首先抽象地描述一下项目背景,这个项目是一个面向消费者的Web系统(以下简称系统A)。用户访问系统A,输入数据,系统A 接收数据,然后调用系统B 的REST接口返回处理过的数据给用户。其中系统B 是由另一个团队开发和维护的。描述地够抽象的吧,不过你可以想象,比如一个电商网站。
该项目采用Java,框架是Spring,构建工具是Maven,技术不算很新啦。
好了,要说到自动化测试,肯定得先说说我们是如何按照需求进行开发的。
首先,我们不是按照一份全面的12页的需求说明文档来开发,那样的话,无休止的前期的设计讨论会、数据库设计、代码框架设计、架构讨论会,再加上编码和测试的时间,等全部功能都开发出来都已经是一个月以后了。对我们这个面向消费者的互联网应用来说,一个月太长了。等到一个月以后,这些一个月以前收集的需求和实现的功能,对消费者还有没有价值,都不一定呢。
我们的工作是价值拉动的,所以我们要快速响应变化,我们的哲学是:“先把应用跑起来,完成一小部分可以使用的业务功能,看看反馈再说”。
所以我们按照故事点来划分需求,比如这三天我们就开发”登录功能“,这里面包括页面的登录框,页面JS校验,后台逻辑校验,数据库表字段调整,调用系统B 的验证接口等。这样,三天以后,团队就能给产品经理/Boss演示“登录功能”,接受产品经理/Boss的反馈,并在第四天就开始改进,第五天就可以再给产品经理/Boss演示改进后的“登录功能”了。
而不像传统的软件开发方式,团队跟产品经理/Boss说,“一个月以后你才能看到全部功能中的登录功能,到时候你要是不满意,走需求变更流程,需要再等一个月!”。
那么,这个“登录功能”包括页面的登录框,页面JS校验,后台逻辑校验,数据库表字段调整,调用系统B 的验证接口,这些都是可以自动化验证的。页面的登录框我们用Selenium验证,JS校验逻辑我们用Jasmine验证,后台逻辑校验我们用JUnit验证,数据库表字段调整,我们用DBUnit验证,调用系统B 的接口,我们用Mockito来mock接口调用验证。
当开发人员对测试人员说,我们已经开发完成了“登录功能”,测试人员会问,“如何证明你们已经开发完成了登录功能?给我看下你们的自动化测试代码!”
是的,只有通过自动化测试的代码,才能证明功能是正确开发完成的。因为如果没有这些自动化测试,两个星期之后,代码被多处修改,当时写的代码还能不能工作,都不一定呢。
没错,这些自动化测试代码都是开发人员写的。我们的哲学是:“You build it, You test it!”
看到这里,你可能会问,Selenium 验证,Jasmine 验证,JUnit验证, DBUnit和 Mockito 验证,写了这么多的自动化测试代码,该怎么运行呢?
没问题,我们的构建工具是用的Maven嘛,这些测试都有对应的Maven插件,我们把这些测试都集成到了Maven的构建脚本里,这样,在本地命令行,仅仅运行 “mvn clean install” 就能挨个运行这些测试了,当运行到Selenium测试时,我们的脚本还会在本地把Jetty服务器运行起来,打开本地的Firefox进行Web UI测试,运行完毕后退出Firefox,关闭Jett服务器。如果中途有测试失败的话,脚本就会给出失败提示。
下面是我们项目中实际的自动化测试代码,在powershell中的运行截图:
上图是我们项目目前总共的532个JUnit测试运行结果。
上图是76个Jasmine测试运行结果
那么测试人员如何做测试?
开发人员都开始写自动化测试代码了,那么测试人员干什么呢?
我们是这么做的,测试人员负责故事点的测试策略分析,比如“登录功能”有一个要求是:“密码必须包含字母和数字”。
那么测试人员会事先设计至少三个测试用例:
1)密码全部是字母,不通过
2)密码全部是数字,不通过
3)密码有部分字母,部分数字,通过
当开发人员开始开发“登录功能”时,测试人员会和他说,这里有三个测试用例,你的开发完成时,我需要看到至少三个自动化测试覆盖这三种情况。开发人员说,没问题。
当开发人员开发完毕,测试人员看到了这三个自动化测试用例后,测试人员说,“可以了,我再进行一些登录的手工测试和探索性测试,你给我一个测试环境吧。”
那么开发人员如何给测试人员准备测试环境呢?
这也好办,我们不是有持续集成服务器(以下简称CI)嘛,开发人员提交代码到SVN后,CI检测到有代码提交,会自动运行一遍“mvn clean install”, 如果结果是Success,CI会生成一个构建号码,比如“1292”。
开发人员会对测试人员说,“我的功能代码对应的CI构建号是1292,你去把1292号版本发布到测试环境吧。”
这里先说明一下,我们的环境分为DEV,SYS,UAT等。这几个环境的配置大都是一样的,只是给不同的人使用。其中,DEV是给开发人员开发用的,SYS是给测试人员测试用的,UAT是给产品经理和BOSS演示用的。
这时候,就是自动化带来的威力了。
如上图,测试人员访问CI服务器,会看到这样的构建流水线,1292号版本已经在CI上运行通过(第一个绿色),并且被部署到DEV环境中(第二个绿色),SYS和UAT还没有部署1292号版本(蓝色)。
由于我们事先已经在CI上配置好了把代码部署到测试环境的脚本,用Groovy写的,所以测试人员只需要在“1292”号版本的sys环境上点击一个按钮(上图中红色框所示),就能把代码发布到测试环境了。
上图就是一个已经发布到测试环境的版本。我们也可以用同样的办法发布某个特定版本到UAT环境,随时给BOSS做演示。
几分钟之后,测试人员就开始Happy地进行手工测试和探索性测试了。
新功能发布到测试环境后,如果测试人员发现功能不对,想手工验证下当前测试环境的版本,也是可以的。只需要在浏览器输入“http://应用地址/appcheck.jsp”,就能得到如下页面,
其中的信息包括:应用的maven版本号,CI服务器(我们用的是免费的Jenkins)构建号码,SVN提交版本号,构建时间等信息。
如果测试人员又发现了一些Bug,就会和开发人员一起尝试着再写一些自动化测试代码,以此保证一些重复的验证都由便宜又听话的机器去做,测试人员则抽出他们宝贵的精力来关注测试策略和探索性测试。
好了,三天以后,具有自动化测试代码的“登录功能”OK了,产品经理/Boss看后非常满意,说可以发布到产品环境了。
那么,我们是怎么发布到产品环境,我们的上线流程是怎么样的呢?
还有和系统B 的联调,我们是怎么做的呢?
未完待续,敬请期待。。。