这是我在从事网站自动化测试的工作当中构建出的一个“生态系统”。“生态系统”这个概念是我从公司的前辈身上学到的,他一直以来都认为自动化测试人员不应仅仅局限于编写测试代码,还应该让整个自动化测试的过程(测试代码的持续集成、分发、执行等)都自动化,形成一个“系统”,这个系统的自动化程度越高,自动化测试人员就越省力。
一、概念
这里我画了一张示意图:
之所以称之为“生态系统”,是因为建成之后需要的人为干涉很少,其余的时间都是系统内部循环运作。作为自动化测试人员的你只需要提交代码,之后便可以在AutomationDashboard上看到运行的结果了,其余的事情都由系统内部消化。当然,结果的分析还是需要人来完成,机器还没有聪明到可以灵活分析出各种各样让case fail掉的原因。
我们可以把整个系统看作一个黑盒子,那么上面的图可以变成:
实际上这里画的人不仅限于自动化测试人员,也可以是:
(1)产品的管理者,比如产品经理需要从自动化回归测试知道这次release有无推迟风险;
(2)团队的管理者,比如开发经理、QA经理需要从自动化的daily/weekly regression知道最近的代码质量如何;
(3)开发人员,他们也许会想通过quick regression(提交的产品代码被部署到测试环境之后运行的测试)知道自己刚提交的代码有没有破坏系统的基本功能;
(4)其他帮忙做自动化测试的开发人员、刚刚开始学习编写自动化测试代码的手动测试人员,他们不必关心生态系统的内部实现。
二、实现
说完概念,接下来该说说具体实现了。我这里讲的是我认为最适合我所测试的产品的实现,工具不止一种,方式不止一种。Jenkins可以用TeamCity或其它CI替换,git也可以是svn或tfs,AutomationDahsboard可以用.NET、SpringMVC、ROR等等实现,运行测试的slave可以是Windows/Linux/Mac(土豪!),总之选择一种最适合你所测试的产品的实现。还有一点就是自动化测试代码是用关键字驱动思想实现的,这是另外一个话题了,有时间另外写篇文。
好,进入正题。依次说说系统的每个重要组成部分吧:
1、SCM(Source Code Management)。我选的是git,可以是git服务器(公司自己搭建了一个git server),也可以是一个bare repo(http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/) 。
2、CI(continuous integration)。我选的是部署方便、插件丰富的Jenkins。
它的职责是:
(1)从git上取出代码,build(.NET对应msbuild,如果是ruby则不用build了,直接部署即可);
(2)把build好的*.dll部署(这里即是拷贝)到所有的slave上;
(3)启动或停止所有slave上的AutomationService(后面还会讲到AutomationService),从而控制测试的执行。我在Jenkins的这些个job配置起来还是比较繁琐的,要细讲又可以另外写一篇文了。这里就特别提到两个很实用的插件吧:
(1)Parameterized Trigger Plugin(https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin):可以在一个build step中触发其它project的build。
它最有用的就是这个“Block until the triggered projects finish their builds”选项,勾上的话Jenkins就能在所有trigger的project完成build之后(而非仅仅trigger其它project的build,不等它们完成就继续下一个build step)再继续下一个build step,做到真正的依次执行每个build step。
(2)NodeLabel Parameter Plugin(https://wiki.jenkins-ci.org/display/JENKINS/NodeLabel+Parameter+Plugin):在所有“Possible nodes”标有指定标签(“Label”)的Jenkins节点(就是Jenkins master或Jenkins slave)上触发指定project(被触发的project是参数化的)。
比如我有一个project叫“StartClassicROLATServiceOnAllNodes”,它有一个build step是这样设定的:
再来看看“StartClassicROLATServiceOnASingleNode”这个project的设定:
这个project有一个Node类型的参数,参数名“NodeX”与之前Label Factory中的“NodeX”对应,“Possible nodes”选的是“ALL”,那么列出的所有node(master、10.107.122.152、10.107.122.153、10.107.122.154)都在判断范围之内(判断其是否有“Node”标签,有则执行project)。
另外,列出的所有node我都为其加了一个“Node”标签。
这样,当我trigger “StartClassicROLATServiceOnAllNodes”之后,就会在master、10.107.122.152、10.107.122.153、10.107.122.154这4个node上同时执行“StartClassicROLATServiceOnASingleNode”。
3、AutomationDashboard,这里姑且译作“自动化测试控制面板”吧。实际上它应该和Jenkins一起并称控制面板,不过因为Jenkins有API可以调用,所以想做的画两者也是可以统一成一个web界面的。这个dashboard完全是用.NET+IIS+SQLServer一点点从数据库设计构建、数据访问层、业务层、表现层做起来的,要细讲……额……又会是另外一篇文了(Oh man, not again!)。反正我觉得,虽然我是做自动化测试工作的,但不应该把自己局限于测试。为了更好地进行自动化测试,开发网站、安装配置虚拟机以及其它要用到的工具,都应该抽时间去学习、掌握。
好,来说说这个dashboard。这里只讲两个主要组成部分,一个网站(以下简称dashboard)、一个Windows Service(以下简称ATService)和一个console application(以下称ConsoleRunner):
(1)dashboard,它的主要功能:
a、展示测试的运行状况:有多少正在运行/执行完毕,分别在哪台slave上执行等等。
b、通过call Jenkins的API来trigger Jenkins的job,间接控制测试的执行。
c、展示测试的结果:发生错误的是哪个case、出错时间、错误信息、代码回溯(stack trace)、甚至可以包含一张出错时的截图。
主要界面如下:
a、Summary,顾名思义是汇总信息,case有多少pass多少fail、case按分类每一类有多少等等。(其实这里我少做了一张很重要的图,就是coverage饼状图)
b、Queue,测试队列,包含当前正在运行的、运行完的、等待运行的test fixture或test case(依据测试工具的不同,NUnit、JUnit、RSpec等,fixture的叫法可能不同,总之就是包含多个test case的集合)。可以启动、停止、终止(终止之后可以清空)测试执行或清空当前队列。
c、TestCase,生态系统中的所有测试用例会展示在这里,可以看到它们最后一次执行的时间和状态(pass/fail),点击某条case可以跳转到该条case的所有test result。可以按状态(pass/fail/other)筛选用例,可以勾选部分用例重新执行、或重新执行所有fail的case。“Reload Test Cases”主要是考虑到*.dll文件中的test case可能会在某次部署之后发生变化,需要重新加载。不过后来我修改了Jenkins里的job在每次部署之后都自动重新加载,所以这个按钮其实没什么用了。
d、TestSuite,包含多个fixture的集合是一个suite。勾选多个suite点击“Run Suite”即可把这些suite中包含的fixture添加到Queue。
这里的suite是对NUnit中的Category的一个补充,点击“New Suite”你可以任意选择fixture来组成自己想要的suite:
e、TestResult,展示所有test case的运行结果,可以按test case id进行筛选,点击TC#这一列的id就只显示这条case的结果。
点右边的蓝色“i”图标可以跳到这条结果的详细页面,截图功能暂未启用,根据RunnerMessage和RunnerStackTrace可以知道报错的代码位置,进而尝试重现问题。