几个月前,LinkedIn推出了在多种平台上一个全新的移动体验,包括本地应用和HTML5的web应用。在后台,我们在客户端大量运用JavaScript和HTML5并在服务器端使用了Node.js。为了能够迅速开发,测试和发布,我们建立了持续集成的自动化流水线。在这篇文章中,我将告诉你LinkedIn的移动CI是如何工作的。
概述
下面是对LinkedIn的移动架构的高度概括:
LinkedIn移动架构
我们支持各种移动平台(iPhone,Android的移动网络)主要包括JavaScript和HTML的应用程序向我们的Node.js的移动服务器发送RESful请求。此服务器,依次通过RESTful对LinkedIn平台的调用来取得数据。你可以通过这两个链接阅读更多关于我们的移动架构。
持续集成流水线
我们的移动CI由5级流水线:
1.单元测试:在不到10秒的运行中测试各模块/单元
2.设备测试:仅在客户端应用程序通过使用静态/模拟数据进行测试
3.布局测试:通过对客户端应用程序的截屏,与基线图像进行比较
4.部署:自动部署到临时环境
5.端到端测试:针对临时环境运行端到端测试
在早期阶段一般比后期阶段更快,同时在下一阶段运行之前每个阶段都必须100%的通过。
单元测试和代码覆盖
我们用 Hudson作为我们持续集成服务器,并让它在每次提交后执行单元测试。我们选择 JsTestDriver,因为它是少数可以支持持续集成的JavaScript的单元测试框架之一。不止如此,它还能计算代码覆盖率:
JsTestDriver代码覆盖
设备测试
客户端可以被配置成向返回静态JSON文件形式的测试配置的nginx服务器发出请求。因为这些测试仅处理模拟数据,任何故障都可以被归类为客户端的错误。除此之外,使用模拟数据还能使这些测试执行速度更快。
我们还可以在此测试阶段配置nginx来看看客户端是如何处理各种HTTP状态代码的。您可以查看一些我们使用的用来确保我们的客户端代码可以正常处理500错误,204等等错误的nginx规则的例子。
布局测试
该装置的环境也使我们能够运行布局测试并自动验证用户界面是否正确呈现,而不需要人为检查。我们使用的WebKit布局和呈现方式并通过无图形用户界面的浏览器进行截图。当UI开发完成后,截图将被标记为基准。在此之后,我们只需比较png文件与基准就可以获得复原。
设备尽量减少可能会导致测试的用户界面的变化的随机数据。在少数情况下,呈现始终是动态的,如时间戳,我们在执行截图之前用自定义JavaScript将动态部分数据更换为静态数据。我们还增加了PNG比较的可容忍误差,因为在某些情况下,WebKit会产生稍微不同的PNG文件。
部署和端到端测试
布局测试100%通过后,生产版本会自动部署到临时环境,然后我们运行端到端测试。这些测试在我们的整个架构中执行完整的代码路径并试图找到前几轮测试中可能漏掉的任何集成问题。我们也在产品环节不断地运行端到端测试,它可以让我们迅速找出任何网络问题,例如服务器关闭或负载均衡问题。
我们使用Selenium webdriver和TestNG创建了一个端到端测试的框架。我们已经使用iPhoneDriver让这些测试针对iPhone模拟器成功运行。我们想用AndroidDriver,但直到最近,我们仍被我们webdriver的团队刚刚修复的CSS选择器的一个问题所困扰。然而Selenium-WebDriver测试可以用各种语言来写,我们选择了最为广泛支持的Java。根据这个要点来看几个Selenium-WebDriver测试的例子:
我们使用JSCoverage来分析端到端测试的代码覆盖率:
JSCoverage:红色标记的部分不能被端到端测试执行
结束语
通过移动CI的所有阶段后,我们已经获得了曾让我们从中找到大量bug的整体代码覆盖率为75%的代码,特别是在开发早期的单元测试和设备测试。这些测试周转速度快:通常在新代码提交不到5分钟内就能找到bug。端到端测试也已经有助于检测出发展的后期阶段,在临时环境和生产环节的漏洞。
今后,作为越来越接近使用测试驱动开发(TDD)的团队,我们应该能够在最后阶段添加最终环节:即部署到生产环境。这将实现闭环,并能够持续部署。
【英文原文:http://engineering.linkedin.com/testing/continuous-integration-mobile】
{测试窝原创译文,译者:大头}