背景介绍

按照组织上的安排,咱游击到了S产品(一个快速成长中的Web产品)开搞持续集成。

考虑到S产品核心业务单一明确,前端功能简单,业务逻辑主要在后端的特点,制定了持续集成的实施策略:

  • UI自动化为辅,用例少一点,精一点,降低维护成本,用例设计以冒烟和页面跳转,走通业务流程为主,目的是保障一个高可测性的测试环境;
  • 单元测试重点跟进,自顶向下逐步覆盖各层接口,多覆盖各种分支路径,与UI自动化形成互补。

这里有个小插曲,我和S产品的测试负责人关于UI自动化用例的粒度和覆盖度有一些歧义,测试负责人坚持UI自动化要尽量覆盖大大小小各种流程与细节,接近于手工测试。最后,咱还是坚持了己见 🙂

虽然,实施策略中设计了以单元测试(这里必须澄清一下,此处的单元测试实为集成测试/接口测试,没有完善的mock,仍有一些外部依赖;但是考虑到使用了JUnit/TestNg,一般也就笼统地称之为单元测试了)为主,后续工作中确实也在这方面寄予厚望,投入较多,但由于种种原因,颇有鸡肋之感,此处暂时按下不表。

框架选择

网易杭州研究院开源的,简单易用的,结实耐操的Dagger框架(https://github.com/NetEase/Dagger)成为不二的选择(嗯,因为咱就是Dagger的主开发呵 >_< )

而且,S产品的童鞋也已经基于Dagger陆陆续续写过一些UI自动化用例了,有一定基础。

这里插播小广告,网易杭州研究院质量保障部在自动化方面的积累颇为丰富,其中不乏精品;我的旧博客中也有一些这方面的博文。

用例建模

考虑到UI自动化在S产品中的预定角色,我们将用例分成三大类:

  • UserStory,产品的核心业务流程,一个用例包括一系列步骤,模拟用户在S产品网站的真实运动;这些用例如果失败将明显干扰QA正常测试,一旦上线,将是严重故障;
  • Topic,包括一些冗长的特定业务(例如,下图所示的Topic 1:团购超市卡),以及对UI自动化所依赖的外部环境的检测(例如,Topic 2:与供应商保持联系);
  • BugCover,出现过线上Bug的功能点补充用例。
Step 1 Step 2 Step 3 Step 4 Step 5
UserStory 1 从车库进超市 取手推车 买水果 买牛奶 现金结账
UserStory 2 从正门进超市 取购物篮 啥都不买就逛逛 离开
UserStory 3 选购牛奶 选购面包 购物卡充值 购物卡结账
Topic 1 团购超市卡
Topic 2 与X供货方保持实时联系
BugCover 1 央视报道Y牛奶
没有及时下架
导致用户投诉

这里必须要特别指出的是,不同UserStory的步骤之间尽量正交,减少重复 ,这样一来:

  • 在实际编写用例代码时,基本不必考虑是否须要把哪些操作抽象成API,哪些XPath封装起来,完全脚本化写用例;
  • 相应的,由于用例与用例之间重复代码少,也鲜有共同依赖的API,就可以很放心地将用例责任到人,实现真正的谁写谁负责;
  • 而对于持续集成来讲,责任到人,及时响应是其能否成功的关键之一。

另外,我认为这种用例模型仅适合小规模的UI自动化用例 ,用例数量上去以后,很难实现用例之间的正交。所以,其背后必须有充分的其它类型测试,例如:单元测试/接口测试,作为依托。

典型的用例结构如下所示(基于TestNgDagger

public class Demo {

    BrowserEmulator be;

    @BeforeClass
    public void doBeforeClass() {
    	be = new BrowserEmulator();
    }

    @Test(description = "从车库进入超市")
    public void step_1() {
    }

    @Test(description = "买牛奶", dependsOnMethods = "step_1")
    public void step_2() {
    }

    @Test(description = "买水果", dependsOnMethods = "step_2")
    public void step_3() {
    }

    @Test(description = "现金付款", dependsOnMethods = "step_3")
    public void step_4() {
    }

    @Test(description = "开车离开", dependsOnMethods = "step_4")
    public void step_5() {
    }

    @AfterClass(alwaysRun = true)
    public void doAfterClass() {
        be.quit();
    }

}

实战与效果

由于对UI自动化及Jenkins轻车熟路,在极短的时间内就完成了一套简易的UI自动化持续集成,整套流程的执行时间严格控制在15分钟 以内(可开启用例并发执行模式),并且每隔30分钟执行一次:

工程代码构建 -> 测试环境部署 -> 执行UI自动化

最初,一共只有10个左右的UI自动化用例,但已经基本覆盖了产品的核心功能点(没考虑各种流程的排列组合),正是这只有区区几个UI自动化用例的持续集成却发挥了不小的作用:

  • 不少的各种低级错误(低级,不解释!)在构建阶段被拦截,并以邮件形式知会开发团队;
  • 引起QA测试工作Block的严重问题(不一定是Bug,也可能是环境配置,脏数据,等)被及时发现;
  • 用例数量确实不多,大家都乐意在第一时间去处理失败用例。

所以,正如古人云:银子钞票,多多益善;持续集成,愈早愈好 ,还是尽早写几个UI自动化,配置持续集成跑起来吧,它能够发现和预防的问题比你预计的多得多!而且,只要这套持续集成跑起来了,往里面添砖加瓦就轻松得多了,不再会有畏惧感,信心也会逐步增强。

现在,每次产品迭代结束之后,测试团队就会及时整理一份类似上述的表格,大家一起参详下,分工下,补充用例,逐步完善。

一些结论

S产品的UI自动化是小而美 的典型:

  • 用例不多,维护/补充很及时;
  • 代码冗余度很小,结构清晰;
  • 运行稳定且快速,深合持续集成的 字诀。

2 thoughts on “持续集成回顾暨点滴分享[2] – UI自动化,靠谱!”

  1. Dagger Framework中暗藏了“彩蛋”啊。BrowserEmulator be;be.open(url)。url要是没有http://就是直接跳网易163首页了

发表评论

电子邮件地址不会被公开。 必填项已用*标注