Cucumber测试实践
Posted Thoughtworks洞见
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cucumber测试实践相关的知识,希望对你有一定的参考价值。
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展示测试很好的解决方案。
书籍:《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/
测试兵器谱のCucumber-JVM框架篇
测试兵器谱系列全集:
测试兵器谱のCucumber-JVM框架篇(本文)
写在前面
最近业务上使用的自动化测试项目在改进项目执行方案,优化框架,正好结合实践记录一下最近遇到的问题和解决方法,打算从以下几个部分跟大家探讨一下:
认识一下Cucumber-JVM框架
基于Anyproxy代理多端口分发
Appium多端口启动设备
Cucumber分布式执行设备调度和任务分发
Maven的一些配置问题
Pipeline集成Cucumber
关于Cucumber-JVM
项目背景
我们的自动化测试项目是针对Android SDK来做的,因此在一些API调用上优先考虑了java方向的框架,希望能跟被测SDK集成的成本低一些
团队掌握java的同学多一些,上手成本较低
选择Cucumber-JVM框架是想通过BDD的自然语言特性来对SDK的复杂打点字段做一些容易理解的描述,及所谓的“需求及用例”
Cucumber-JVM特点
首先介绍一下框架的特征及项目定位:
Cucumber是一款支持BDD(Behaviour-Driven Development)而编写的框架,它的支撑语言称作Gherkin,能够解析后缀名为.feature和.txt的文本文件。
Cucumber开发语言是ruby,能够运行ruby,java,.NET,python等多种语言的脚本。
Cucumber的文本描述目前支持英、法、中文、日语等30多种语言。
Cucumber 可以和主流的测试框架很好地集成,常见的 TestNG、Selenium、SpringFramework、Ruby on Rails 等,能够方便地引入到您的测试工作中去,几乎没有任何门槛。
我们的SDK项目作为 Java 测试项目,因此使用 Cucumber 的 Java 语言实现版本:Cucumber-JVM
Cucumber-JVM关键字
如上面所说,Cucumber的核心语法是 Gherkin 提供支持的,每个不为空的行必须以 Gherkin 自带关键字开头, 然后跟随有任意的文本。主要的关键字有:
Feature / 功能
Scenario / 场景
Given, When, Then, And, But (Steps/步骤)
Background / 背景
Scenario Outline / 场景大纲**
Examples / 示例
还有其他一些额外的关键字:
""" (文档描述)
| (表格参数分隔符)
@ (Tags标签)
# (注释)
Feature / 功能
"*.feature" 文件通常用来存放一批用例的集合,.feature文件中存放着大量的测试用例,即scenarios。feature有三个基本元素:
Feature: 关键字
name:名称, 在同一行
description:描述, 可选(但是强烈推荐),可以占据多行
如果你需要对当前的用例集合做一个详细的解释,可以直接这样写:
Feature: this is a feature
#这里是feature文件的详细描述
I am a description, blablablablablabla.........
Scenario: just a demo
Given the cow weighs 450 kg
When we calculate the feeding requirements
原因是Cucumber-JVM 不会触发非保留关键字开头的行对应的step, 所以在feature文件开头建议有一个详细的用例集合描述,这是个好习惯。
Scenario / 场景
Scenario 其实就是具体的用例,描述一个用例的summary(标题)。它由若干步骤组成。用例可以有任意多个步骤,但是推荐数量保持在每个场景3-5个步骤。如果太长,他们将丧失作为规范和文档的表单能力。场景遵循同样的模式:
描述一个初始化上下文
描述一个过程
描述一个期望的产出
Given / 假设
Given 步骤用于描述用例的一些前提,包括数据准备、初始化环境等等都可以放在这里来写。当然可以有多个 Given 步骤(推荐使用 And 或者 But 来变的更可读)
When / 当
When 步骤用来描述一个事件, 或者一个动作。如果是连续的动作,推荐使用And提高可读性。通常我们的用例都会有When步骤表示各种操作行为。
Then / 那么
Then 步骤用于描述期望的产出,或者结果。一般断言校验都在这个步骤里体现。
Background / 背景
整个feature文件中的所有用例在执行之前都会执行一次Background中描述的动作,Background中的步骤一般没有Then,用例做一些通用的初始化行为,比如“清空浏览器缓存”,“卸载之前安装的APP”等等。
Scenario Outline / 场景大纲
当有一种用例场景,存在大量重复性的步骤描述,变化的只是输入和输出的时候,非常适合用这个场景大纲结构,举个例子:
Scenario Outline: 这是一个登录的例子
Given 打开 <page> 登录页面
When 输入账户名 <username>
And 输入密码 <password>,点击登录
Then 成功进入 <result> 页面
Examples:
| page| username| password|result |
| 奇虎| test1 | 123456|奇虎欢迎你 |
| 百度| test2 | 123456|百度欢迎你 |
| 网易| test3 | 123456|网易欢迎你 |
| 京东| test4 | 123456|京东欢迎你 |
以上用例也比较适合接口校验类的用例,我们的SDK就使用到了这种描述。
Cucumber-JVM几个例子
一个简单的例子(英文版):
一个简单的例子(中文版):
中英文混合版(为什么会用到这种,后面会提到)
中英文关键字对照
步骤实现
Cucumber-JVM描述的每一个场景(用例),背后都需要一个对于的step步骤来实现这个描述,Cucumber-JVM还不能做到文字自动生成代码的地步,目前很多关键字驱动的框架在做类似的事情。当Cucumber-JVM在解析和执行feature文件时,它将通过正则匹配的方式寻找代码实现的steps。比如这样的:
# 用例描述
Scenario: This is a testcase
Given I have 10 dollor in my wallet
对应的step实现为:
@Given("I have (\d+) dollor in my wallet")
public void I_have_dollor_in_my_wallet(int money){
System.out.println("money: %n
", money);
}
细心的读者应该发现上面有参数传递,那么feature文件是通过什么样的方式把参数传给step的呢?
整型参数
# 用例描述
Scenario: This is a testcase
Given I have 10 dollor in my wallet
这里可以用 (d+) 来捕获:
@Given("I have (\d+) dollor in my wallet")
public void I_have_dollor_in_my_wallet(int money){
}
字符串参数
# 用例描述
Scenario: This is a testcase
Given I have "10" dollor in my wallet
这里可以用"("*)" 来捕获(注意转义符):
@Given("I have "([^"]*)" dollor in my wallet")
public void I_have_dollor_in_my_wallet(String money){
}
布尔类型参数
这种参数通常用在Then步骤里作为校验结果。
# 用例描述
Scenario: This is a testcase
Then 返回检查结果为 false
这里可以用"("*)" 来捕获(注意转义符):
@Then("^返回检查结果为 (true|false)$")
public void verify(boolean expected) {
}
一维数组参数
简单的方式是使用逗号:
# 用例描述
Scenario: This is a testcase
Given the following animals: cow, horse, sheep
将参数定义为List:
@Given("the following animals: (.*)")
public void the_following_animals(List<String> animals) {
}
使用Data Table
# 用例描述
Scenario: This is a testcase
Given the following animals:
| cow |
| horse |
| sheep |
将参数定义为List:
@Given("the following animals: (.*)")
public void the_following_animals(List<String> animals) {
}
Tags(标签)的妙用
Cucumber的标签非常好用,举个应用场景的例子,我们的测试用例会有几种维度,比如
按广告平台分,例如:360,google,gdt
按手机厂商分,例如:apple,xiaomi,huawei
按广告类型分,例如:native,video
我们先给测试用例做了标签分类,可以这样写:
@360
Feature: this is a feature
#这里是feature文件的详细描述
I am a description, blablablablablabla.........
@native
Scenario: just a demo
Given the cow weighs 450 kg
When we calculate the feeding requirements
@video
Scenario: just a demo
Given the cow weighs 450 kg
When we calculate the feeding requirements
@xiaomi @native
Scenario: just a demo
Given the cow weighs 450 kg
When we calculate the feeding requirements
假如我这次只想运行原生广告的用例,我可以在运行命令中这样写:
java cucumber.api.cli.Main --tags @native your_features
假如我这次只想运行除了原生广告的用例,我可以在运行命令中这样写:
java cucumber.api.cli.Main --tags ~@native your_features
各种组合情况,想怎么用就怎么用,我们在项目中针对不同case的归回可以灵活指定测试范围。
按照行号执行测试用例
命令:java cucumber.api.cli.Main E:/codes/cucumber/demo/src/test/features/第一个例子.feature:12:21
可以运行 FixedAmountWithdraw.feature 文件中的第 12 和21 行,如果需要运行更多的行,只需要在 feature 文件名之后加上“:行号”。
按照场景名称执行测试用例
命令:java cucumber.api.cli.Main --name 这是一个原生广告请求有table的例子 features
可以运行名称为“这是一个原生广告请求有table的例子”的 Scenario 或者 Scenario Outline。对于跑单个失败的场景时非常有用。
以上命令行只是例子,缺少本地classpath引入,强烈建议使用maven或者IDEA来运行,避免因环境问题导致的错误
Cucumber-JVM的安装和案例
补充:请确认本地有Android SDK、JDK1.8、Nodejs、NPM环境
方法一:Maven创建Cucumber-JVM项目
步骤一:初始化环境
配置Maven环境(略过)
创建个目录
执行mvn archetype:generate目录
提示输入maven Choose a number or apply filter的时候直接回车
注意:groupId和你的package相关,比如这里输入com.qtest, 而artifactId和项目名称相关,比如我这里叫appiumDemo
步骤二:通过maven的pom在线安装各种依赖
Maven本地安装Cucumber-jvm,需要手动添加很多依赖的jar包,利用maven远程仓库一键安装完成,在创建的maven项目中找到pom.xml,比如增加如下的节点:
步骤三:直接执行feature文件
直接执行feature文件
把提示的代码复制到step文件中
#运行Cucumber-jvm需要用到的命令行:
#简单命令:
java -cp "./jars/*;." cucumber.api.cli.Main -d path/features/test.feature
#命令窗口颜色:
java -cp "./jars/*;." cucumber.api.cli.Main -p pretty features -g step_definitions
#生成测试报告:
java -cp "./jars/*;." cucumber.api.cli.Main -p html:output features -g step_definitions
步骤四:扩展step伪代码
在定义的JAVA类中填充操作步骤,比如我们项目的step实现是类似这样的:
步骤五:执行feature文件生成测试报告
Cucumber-JVM的测试报告比较简陋,后面部分会介绍Jenkins Cucumber插件生成美观的报告,生成的结果如下:
方法二:通过IDEA创建Cucumber-JVM项目
IDEA创建Cucumber-JVM项目
安装IDEA
配置JAVA环境
配置Maven依赖
通过IDEA自动导入依赖
安装Cucumber-JVM的IDEA插件
新建一个feature文件,可以看到关键字已经高亮
创建step definition(一定要注意项目的层级目录)
运行feature文件的configuration
以上为第一节的全部内容,主要是介绍了Cucumber(-JVM)框架的用法。BDD框架的好处在于至少两个方面:
可执行性(Executable):从技术人员的视角来看,可以像执行代码(Java、Ruby...)一样运行这些用例,来验证、验收目标系统。
规范性(Specification):从非技术人员的视角触发,相比验证本身,他们更加关心系统功能的清晰描述:系统在什么场景下能够做什么样的事情。
参考资料:https://skyao.gitbooks.io/learning-cucumber/content/practice/pass_parameters.htmlhttps://docs.cucumber.io/
Qtest是360旗下的专业测试团队!
是WEB平台部测试技术平台化、效率化的先锋力量!
陪伴是最长情的告白
每日为你推送最in的测试技术
以上是关于Cucumber测试实践的主要内容,如果未能解决你的问题,请参考以下文章
集成与验收测试......啥是 Cucumber / Steak?