简介
cucumber是BDD(Behavior-driven development,行为驱动开发)的一个自动化测试的副产品。它使用自然语言来描述测试,使得非程序员可以理解他们。Gherkin是这种自然语言测试的简单语法,而Cucumber是可以执行它们的工具。关于BDD有兴趣自行了解。附cucumber官网链接,里面也有关于BDD的信息。
cucumber本质上是使用根据正则表达式匹配自然语言,然后依次执行对应的方法,以达到测试的目的。
本文基本上只是官网的搬运工,摘要了部分信息,最好还是看官网文档。
Gherkin
Gherkin是自然语言测试的简单语法。
一个完整的测试是由多个step组成的,step即最小单元,如何复用step是非常关键的问题。多个step组成一个Scenario,即一个完整的测试case。多个Scenario组成一个Feature,即一组相关的测试case。
关键字
- Feature
- Example(or Scenario)
- Given,When,Then,And,But(steps)
- Background
- Scenario Outline (or Scenario Template)
- Examples (or Scenarios)
一个简单的例子
Feature: Is it friday yet?
this is a descriptions
Everybody want to know when it's Friday
Scenario: Sunday isn't Friday
Given today is Sunday
When I ask whether it's Friday yet
Then I should be told "Nope"
Scenario: Friday is Friday
Given today is Friday
When I ask whether it's Friday yet
Then I should be told "TGIF"
Feature
Feature是所有测试的开头。后面跟一段描述性的文字,表明这个测试文件是干什么的。
description
description是一段扩展性的文字描述,可以跟在Feature、Example、Background、Scenario、Scenario Outline下面。
Example和Scenario
Example和Scenario是一对同义词,是一个具体的测试case,包含了多个step。一般情况下,都是由Given(给定一个初始条件),When(发生了什么),Then(结果是什么)组成的。
Steps
step是cucubmer的最小单元,每个step是由Given, When, Then, And, 或者But开头的。如果关键词后面的内容是完全一样的话,那么cucumber会认为这两句话是重复的,哪怕前面的关键词不一样,如
Given there is money in my account
Then there is money in my account
这种限制也促使我们使用更加准确的语言去描述
Given my account has a balance of £430
Then my account should have a balance of £430
Given
Given一般用于在Scenario中描述系统的初始状态。它的目的是使系统在使用前处于一个已只的状态,要避免在Given中谈论交互上的事情。
When
When描述一个事件或者动作。他可以是与系统间的交互,也可以是由另一个系统触发的事件。cucumber强烈推荐每个Scenario只有一个When,当你觉得需要加更多的When的时候,通常就是需要拆分成多个Scenario的信号。
Then
Then描述期望的输出或者结果。对Then的step definition应该使用断言去比较期望值和实际值,就和单元测试差不多。
But和And
当有几个Given,When,Then的时候,可以写成
Example: Multiple Givens
Given one thing
Given another thing
Given yet another thing
When I open my eyes
Then I should see something
Then I shouldn't see something else
也可以用And和But增加其可读性
Example: Multiple Givens
Given one thing
And another thing
And yet another thing
When I open my eyes
Then I should see something
But I shouldn't see something else
step definition里个人并不建议使用@And和@But,只使用@Given,@When,@Then,这样语言更加明确,因为And和But都可以在Given,When,Then的下面使用。
Background
当在同一个Feature里有多个Scenario有相同Given的时候,可以使用Background将这些Given抽到一起。这样这个Feature的每个Scenario在运行的时候,都会先运行一次Background。每个Feature里只能有一个Background。
tips
- 不要设置复杂的状态,除非该状态实际上是客户需要知道的
- 保持background简短,因为在阅读Scenario的时候,是需要记住background的。最好不要超过4行
- 一个feature只能有一个background,如果需要不同的background针对不同的方案,就需要分拆成不同的feature
Scenario Outline
Scenario Outline即Scenario的模板,也可写作Scenario Template。它可运行相同的Scenario多次。
Scenario: eat 5 out of 12
Given there are 12 cucumbers
When I eat 5 cucumbers
Then I should have 7 cucumbers
Scenario: eat 5 out of 20
Given there are 20 cucumbers
When I eat 5 cucumbers
Then I should have 15 cucumbers
可用Scenario Outline简化
Scenario Outline: eating
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |
DataTable
Gherkin可以传递List,Map,称为DataTable,具体例子查看该github上的文档
方言
Gherkin支持多种方言,对应关键字转换查看该文档
状态共享
不同step里定义的变量,可以通过java类的成员变量达到共享上下文变量的目的。如上例子的today和actualAnswer。
而状态泄露会使得scenarios变得脆弱和难以维护。详细信息查看该文档
注释
Gherkin使用#作为注释符号
step definition
step definition是指通过正则表达式对应到一个或多个Gherkin step的java方法。如下例子是上面例子对应的step definition
public class FridayYet {
private String today;
private String actualAnswer;
@Given("^today is (.*)$")
public void todayIsSunday(String day) {
this.today = day;
}
@When("^I ask whether it's Friday yet$")
public void iAskWhetherItsFridayYet() {
if (this.today.equals("Friday")) {
this.actualAnswer = "TGIF";
} else {
this.actualAnswer = "Nope";
}
}
@Then("^I should be told \"(.*)\"$")
public void iShouldBeToldNope(String expectedAnswer) {
Assert.assertEquals(expectedAnswer, actualAnswer);
}
}
替代文本
使用/作为替代文本。如下例子可匹配I have {int} cucumber(s) in my belly和I have {int} cucumber(s) in my stomach
I have {int} cucumber(s) in my belly/stomach
3.0.1版本前,无法转义/,始终被解释为替代文本,3.0.1后用\/转义/
附github版本变更记录
tag
tag提供2个作用
- 提供@before和@after的钩子(tagged-hooks)
- 运行时只运行指定tag的用例
tag具有继承特性,即在Feature上标记tag,该Feature下的Scenario,step会继承该tag。
@simpleDemo
Feature: Is it friday yet?
@RunWith(Cucumber.class)
@CucumberOptions(tags = "@simpleDemo")// 指定只运行代用@simpleDemo的
public class CucumberTest {
}
@Before("@simpleDemo")
public void beforeOperation() {
}
@After("@simpleDemo")
public void afterOperation() {
}
测试过写两个tag,两个都会生效
结合Background具体的运行顺序是 before tag -> Background -> Scenario -> after tag
- 以上2点是官网提出的,个人认为还有第三点作用:生成report的时候提供分类作用
update at 2019年03月25日
tips: cucumber.api.spring.SpringTransactionHooks(cucmber-spring包)提供了一个spring事务的钩子@txn,提供回滚功能。
IDE插件
IDEA Cucumber for Java
report
具体没看,有兴趣可以自行了解
自动化测试之cucumber(四)