概述
Cucumber 用于执行基于 Gherkin 场景描述的自动化测试。它的核心是让自然语言写的测试步骤找到对应的代码并执行。
步骤参数与数据传递
1. 步骤参数
在步骤定义中,Cucumber 可以从步骤描述中提取数据,并自动转换成合适的类型,传给方法。
-
数量必须匹配:方法参数个数必须与表达式中的捕获组数量一致,否则会报错。
-
自动类型转换 :例如
{int}会把"48"自动转换为整数48。
2. 数据表
Gherkin 中的表格可以通过 DataTable 对象传给步骤定义,也支持自动转换为各种集合类型,用起来更方便:
R
假设有以下动物:
| 奶牛 |
| 马 |
| 绵羊 |
java
// 方法一:使用 List<String>
@Given("有以下动物:")
public void the_following_animals(List<String> animals) {
// animals 包含:["奶牛", "马", "绵羊"]
}
// 方法二:使用 DataTable(更灵活,可处理复杂表格)
@Given("有以下动物:")
public void the_following_animals(DataTable table) {
// 可以调用 table.asLists()、table.asMaps() 等方法处理
}
支持的集合类型 :除了 List<String>,还支持 List<Map<String, String>>、Map<String, List<String>> 等复杂结构,以及 Integer、Float 等数字类型。
步骤的执行与结果
1. 什么是步骤?
一个步骤就像一次函数调用。例如,Given I have 93 cucumbers in my belly 就是在"调用"对应的步骤定义,并传入参数 93。
2. 匹配流程
-
Cucumber 将步骤文本与步骤定义的表达式(正则或 Cucumber 表达式)进行匹配。
-
提取捕获的变量或组。
-
将变量传给步骤定义方法并执行。
注意 :步骤定义前的 Given、When、Then 等关键词仅用于提高可读性,Cucumber 在匹配时并不区分它们。
3. 步骤执行结果
每个步骤执行后都有一个状态:
| 状态 | 说明 | 颜色 |
|---|---|---|
| 成功 | 找到匹配定义且执行无错误。 | 绿色 |
| 未定义 | 未找到匹配的步骤定义。后续步骤会被跳过。 | 黄色 |
| 待完成 | 步骤定义中主动标记为"待实现"(如调用 pending())。 |
黄色 |
| 失败 | 步骤定义执行时抛出异常或错误。 | 红色 |
| 跳过 | 因前面的步骤未定义、待完成或失败,而未被执行的步骤。 | 青色 |
| 歧义 | 多个步骤定义匹配了同一个步骤,Cucumber 无法决定用哪个,会抛出异常。 | - |
重要:步骤定义方法的返回值不会影响成功与否,只有是否抛出异常才会导致失败。
钩子:测试的"幕布"控制
钩子是在 Cucumber 执行周期的特定点运行的代码块,常用于测试环境的搭建和清理。
1. 场景钩子
-
@Before:在每个场景的第一个步骤之前运行。-
慎用 :钩子里的逻辑对只看
.feature文件的人来说是不可见的。对于重要的、应被理解的设置步骤,更推荐使用Background。@Before更适合底层操作(如启动浏览器、清理数据库)。 -
可以指定顺序 :
@Before(order = 10)
-
-
@After:在每个场景的最后一个步骤之后 运行,无论场景成功与否都会执行。- 可以接收
Scenario参数,用于根据场景状态做处理(例如:失败时截图)。
- 可以接收
-
@Around(仅Ruby):可以包裹整个场景的执行,用于控制超时等。
2. 步骤钩子
-
@BeforeStep/@AfterStep:在每个步骤执行之前/之后运行。- 它们具有"环绕"语义:只要执行了
@BeforeStep,无论步骤结果如何,对应的@AfterStep都会执行。
- 它们具有"环绕"语义:只要执行了
3. 条件钩子
可以通过标签表达式,让钩子只对特定场景生效:
java
@After("@browser and not @headless")
// 仅对带有 @browser 标签但不带 @headless 标签的场景生效
public void takeScreenshot(Scenario scenario) {
// ...
}
4. 全局钩子
@BeforeAll/@AfterAll:在所有场景开始前/结束后各运行一次(静态方法)。
标签:灵活的分类与筛选工具
标签是组织场景和功能、控制执行范围的强大工具。
1. 基本用法
在 Feature、Scenario 等上方用 @ 符号定义,一个元素可以有多个标签。
java
@billing @重要
功能:验证计费
@smoke
场景:新用户订阅
当 ...
2. 标签继承
子元素会继承父元素的标签。例如,Feature 上的标签会被其下的所有 Scenario 继承。
3. 运行指定标签的场景
-
命令行/Maven :
mvn test -Dcucumber.filter.tags="@smoke and @fast" -
JUnit Runner 配置 :
@CucumberOptions(tags = "@smoke and not @slow")
4. 标签表达式
使用逻辑运算符组合标签,实现精细筛选:
| 表达式 | 描述 |
|---|---|
@fast |
所有带 @fast 标签的场景 |
@wip and not @slow |
带 @wip 但不带 @slow 的场景 |
@smoke and @fast |
同时带有 @smoke 和 @fast 的场景 |
@gui or @database |
带有 @gui 或 @database 标签的场景 |
(@smoke or @ui) and (not @slow) |
使用括号控制优先级 |
5. 其他创意用途
-
链接外部文档 :
@REQ-123可被插件转换为指向需求管理系统的链接。 -
跟踪开发流程 :使用如
@dev_complete、@qa_ready等标签标识功能状态。
运行与配置
1. 如何运行
Cucumber 本身是一个 Java 库,可以通过多种方式启动:
-
命令行 :
java io.cucumber.core.cli.Main /path/to/features --glue com.example.steps -
JUnit 4 Runner :创建一个使用
@RunWith(Cucumber.class)注解的空类。 -
构建工具/IDE:通过 Maven、Gradle 或 IntelliJ IDEA 等运行。
2. 常用配置选项(通过 @CucumberOptions 或属性文件)
-
plugin:指定输出格式和报告插件(如"pretty","html:target/report.html","json:target/cucumber.json")。 -
dryRun:设置为true可快速检查是否有步骤缺少定义,而不真正执行。 -
monochrome:让控制台输出更简洁(无彩色)。 -
tags:指定要运行的场景标签表达式。 -
snippets:指定为未定义步骤生成代码片段时的命名风格(UNDERSCORE或CAMELCASE)。 -
glue:指定步骤定义等代码所在的包路径。
3. 通过系统属性/环境变量配置
可以在命令行动态覆盖配置:
bash
mvn test -Dcucumber.filter.tags="@smoke" -Dcucumber.plugin="pretty, html:target/cucumber.html"
主要配置属性表:
| 属性 | 示例 | 说明 |
|---|---|---|
cucumber.filter.tags |
@smoke and not @slow |
标签过滤器 |
cucumber.glue |
com.example.steps |
步骤定义位置 |
cucumber.plugin |
pretty, html:report.html |
插件与报告 |
cucumber.execution.dry-run |
true |
干跑模式 |
cucumber.snippet-type |
camelcase |
代码片段风格 |
通过灵活组合这些功能,你可以构建出结构清晰、易于维护且执行高效的自动化测试套件。