来源:https://cucumber.io/docs/guides/overview/
作为QA,可能我们在迭代中总会遇到这样一些问题:
- 开发进行重构影响范围大,每次都需要进行大量的回归测试耗时耗力
- 一些技术卡如果测试又不知道具体影响范围,不测试又总是觉得不安心
- 一些客户会要求提供一些类似测试用例或者是测试报告之类的测试成果物,但是在敏捷流程中这些可能不是必需品,如果单独准备会很麻烦
这些问题Cucumber测试实践都会提供一些解决思路,并且还远不仅限于此。
一、思路转变
1、培养CICD意识
CICD,持续集成持续部署/交付不是什么新概念,但是时至今日对于测试者来说很少有人对于测试有这个意识。敏捷流程中的测试者还是按部就班的根据Issue卡的内容构思测试范围、设计测试场景、执行测试用例,如果做的好一点可能会在之后补充一下简单的自动化测试。于是会出现的一种节奏上的偏差,敏捷流程中往往伴随着大量的、短时间内的变化,如果测试者依照上面的流程应对这些变化,这就意味着大量的重复工作。举一个最简单的例子,一个有鉴权的系统光登录就是每次测试必要执行的。于是,当大量的变化、大规模的重构在迭代中发生时,这就意味着测试者的工作量会是之前涉及到的Issue卡的总和,可能就需要为了妥协而采取减少一些测试场景等等措施。
试想一下如果把我们的测试工作也做成一个持续集成的产品呢?把我们所做的测试工作全部有计划、有规律的拓印下来。对于之前执行过的测试,之后只需要one click即能执行,对于拓展的业务需求,只需要在已有的语法上进行拓展。交付产品不断迭代,测试集也在不断迭代。这样不仅节省测试工作量同样也会让QA对于整个产品质量框架有一个整体的把控。
2、尽量减少“徒手”测试
当我们有意识的去让我们的测试持续集成持续执行的时候,我们就会意识到“徒手”测试需要减少(但是在某些场景也是必须的)。因为徒手测试意味着一次性且相对低效,即便拓印下来这些徒手测试也是没有规律的无法拓展的。
3、行为与断言需要闭环,测试场景需要幂等
如同开发完成的功能都需要有Issue记录一样,QA的测试行为也需要尽可能全量的拓印下来。然而并不是所有的行为都能够称之为行为,其中需要意识到行为和实现是有区别的,我们希望记录的是具体的用户行为而不是这个行为中的每一步实践。同时尽量保证每个行为都能够自我验证,其中合适的断言是重中之重,我们需要记录我们目之所及尽可能多的能够确定的断言,让记录下的行为和我们徒手测试的验证项尽可能的一致。
当我们记录下一条条测试行为,形成测试场景。这些场景需要满足幂等性。这也是我们测试集能够持续集成持续执行的前提。
二、Cucumber测试实践
1、并不是BDD
根据维基百科,BDD是一种对于TDD在敏捷软件开发中的改进尝试,主要目的在用自然语言让DEV、QA、BA、PO对于程序如何运行形成一种共同理解。目前我们的Issue卡基本是类似BDD Gherkin的语法,而kick off 和 desk check这两个环节需要DEV、QA、BA等不同角色一起参加完成,这就类似于一种BDD闭环验证的实践。
然而,我们的目的是为了将我们在测试过程中的所有行为、断言利用程序记录下来,所以Cucumber是作为一种脚本工具来完成测试实践。在这个场景下我们测试的是一个已经开发完成的代码,这不是一种BDD。使用Cucumber并不意味着使用BDD。所以不需要给Cucumber测试别扭地加上一层BDD的外衣,而是将其作为一种脚本工具来统一实现测试执行行为,形成类似一种测试行为字典。
2、写好Gherkin
Cucumber执行流程如下
来源:https://cucumber.io/docs/guides/overview/
终于来到了Cucumber的实践操作,首先我们需要写好Gherkin,这也是我觉得Cucumber中最难的一块。我个人写Gherkin Feature文件的风格从刚开始接触Cucumber到现在有很大的区别。Gherkin的编写是整个Cucumber脚本程序可维护、可拓展、易理解、可复用的关键,也是避免Cucumber goes bad的关键。具体可以参考:https://cucumber.io/docs/bdd/better-gherkin/和https://cucumber.io/docs/guides/overview/。
3、Step Definitions断言很重要
至于Step Definitions就是和coding能力相关联,但是作为一个脚本工具需要尽量将项目轻量化、可移植化。我的做法是无论是Cucumber-jvm还是Cucumber-js都是会根据项目涉及到的数据库、后台或者是大数据组件来编写一些工具类,通过这些来组装Step Definitions。为了防止Cucumber goes bad,每个Step Definition需要尽可能简洁不要包含太多逻辑,但是需要体现我们设计的测试逻辑。因而在断言粒度上一定要贴近我们人工测试,这样才能让我们足够信任我们的脚本,这样脚本才能真正的起到作用。
断言的设计基本上是努力拷贝人眼,所见即所得,所见即是我们要断言的地方。但同时也不局限于此,对于很多场景来说人眼的观察是有限的,比如大量数据的比对、各种随机场景的模拟,这些脚本往往可以编写的超越人眼。
总而言之Step Definitions需要遵循的原则就是轻量、可维护但是要尽可能细腻的完成我们的行为和断言。这听起来好像有些悖论感,但是确实是我们的目标。
4、两种测试场景构建思路
如果阅读了“思路转变”这一章节,那么我们可能会有一种感觉这和我们平时测试时候设计测试思路或者测试用例感觉没什么区别,只是加了一些限制。这种感觉其实是很正确的。我们基于Gherkin的Feature文件实际上就是一个个测试用例集。同时我一直认为使用Cucumber或是其他工具来进行测试,都是需要基于QA的测试设计。测试设计是我们在执行测试工作的核心,于是,第一种测试场景的构建思路就自然而然的产生:通过测试思路或者测试用例来改写成基于Gherkin语言的Feature文件,转换方式如下图所示:
当我们按照上面那种构建思路组建了一些测试场景得到了一些Steps之后,我们很自然的会有这样一种想法:如果我们抛开测试设计和测试用例,从实际应用场景出发,利用Steps组建成一个真实可能发生的场景形成测试的Feature文件。因为我们在设计编写Steps的时候遵行了行为的原则,并且实现了每个行为的自我验证,那是不是就可以证明当我组建的这个Feature文件跑通那么整个场景我就已经验证完毕了,如下图所示:
三、关于E2E测试
1、Cucumber与E2E结合不是好的实践
在github上搜索Cucumber相关的开源项目,95%以上的都是将Cucumber和E2E测试工具相结合使用。从Cucumber WebdriverIO到最近的Cucumber Cypress和Cucumber Testcafe。以实现的角度来说,这样的组合看起来没有什么问题,甚至在刚刚开始还比较好用。然而会存在以下几个问题:
(1)不是好的Gherkin写法如下图所示,这是官网对于Gherkin写法的一个范例,这也是前面所提到的Gherkin应该记录行为而不是行为对应的实践。然而几乎所有的Cucumber E2E项目都是下面这种写法。这样的做法可能从实现上讲差别不到甚至更优,但是表意上已经无法完成原有的意图。举一个例子,在登录场景中,Gherkin Steps应该这样写:When "Bob" logs in
而不是:
Given I visit "/login"
When I enter "Bob" in the "user name" field
And I enter "tester" in the "password" field
And I press the "login" button
Then I should see the "welcome" page
(2)与PageModel或者PageObject不能很好的结合Cucumber E2E其中很核心的思路是将各种操作行为、断言抽象出来形成Steps。但是当这些成为Steps之后就很难成为某个Page的属性。其中很关键的问题在于,PageObject已经将页面定义为了主体,也就是Gherkin中的Given,不同的测试内容的Description就可以看成不同Scenarios,所以完全不需要Cucumber再进行一层包装,函数进行语义化命名就能完全表达意思。
(3)通常耗时耗力从原则上我总是这样认为,应该编写更少的 E2E 测试。端到端测试本质上是缓慢的,因此测试的数量应该大大低于其他测试的数量。Cucumber通常需要行为进行大量的兼容和适配,这些会消耗很多的精力。同时UI测试由于大量的智能缺失,很难匹配上人眼测试的粒度和效果,所以可以看到大量的UI测试都是固定化流程的不断重复,很多报错也是来自脚本本身而不是产品本身。整体来说无论怎么做UI测试性价比很低。
2、个人的解决方案
针对有Browser或者其他Client的项目,我会采用分离测试的方案。首先将自己模拟成各端触点来访问对应的后端,用Cucumber单独对后端进行测试,这一块会进行细粒度测试,保证功能和数据的准确性。
对于Browser和Client端采用轻量化的E2E脚本进行操作主要确认主要功能可用、控制台无异常、简单弹窗断言,这些是脚本能搞定的。当然人工测试是必不可少的,因为在Browser和Client的维度,从目前技术来看人眼的断言和人脑的判断是远超过脚本的。另外Bug Bash等等方案也是对于Browser和Client展示测试很好的解决方案。
四、Cucumber相关资料
书籍:《The cucumber book》官方文档:https://cucumber.io/docs/cucumber/Cucumber-js: https://github.com/cucumber/cucumber-jsCucumber-jvm: https://github.com/cucumber/cucumber-jvm一个简单上手的IDE:http://cuketest.com/
本文版权属Thoughtworks公司所有,如需转载请在后台留言联系。