1. BDD
BDD(Behaviour-Driven Development)是軟件團(tuán)隊(duì)縮小業(yè)務(wù)人員和技術(shù)人員之間差距的一種方式,關(guān)注于系統(tǒng)的整體行為,類似我們常說的驗(yàn)收測試。
BDD方式的優(yōu)勢:
鼓勵(lì)跨角色協(xié)作,以建立對要解決的問題的共享理解
通過快速、小的迭代來增加反饋和價(jià)值流
生成針對系統(tǒng)行為自動(dòng)檢查的系統(tǒng)文檔
2. Cucumber
Cucumber是支持BDD方式的一個(gè)工具.
Cucumber讀取以純文本編寫的可執(zhí)行規(guī)范,并驗(yàn)證軟件是否按照這些規(guī)范執(zhí)行。 規(guī)范由多個(gè)示例或場景組成。 例如:
Feature: Login
Scenario: Test login by username and password
Given A register username and it's password
When Input username and password
And Click login button
And Wait the loading dispeare
Then Direct to Home page
And Show login sucessful tips
每個(gè)場景由一系列的步驟組成。Cucumber驗(yàn)證軟件是否符合規(guī)范,并為每個(gè)場景生成使用 ?標(biāo)明成功? 標(biāo)明失敗的報(bào)告。
3. Gherkin
Gherkin是一組語法規(guī)則,它使純文本的結(jié)構(gòu)足以讓Cucumber理解。 上面的場景是用Gherkin寫的。
使用Gherkin的目的:
- 明確的可執(zhí)行的規(guī)范
- 使用Cucumber進(jìn)行自動(dòng)化測試
- 記錄系統(tǒng)的實(shí)際行為

Cucumber語法以不同的形式存在于許多口語中,團(tuán)隊(duì)里可以使用團(tuán)隊(duì)語言中的關(guān)鍵字。
Gherkin 文檔以 .feature文件結(jié)尾,并且通常與軟件一起在源代碼控制中進(jìn)行版本控制。
4. Step 定義
Step 定義把使用Gherkin編寫的step關(guān)聯(lián)到程序代碼中。 步驟定義執(zhí)行應(yīng)該由步驟執(zhí)行的操作。 因此,步驟定義將規(guī)范與實(shí)現(xiàn)連接起來。

5. 代碼
新建maven工程,引入cucumber依賴
<properties>
<cucumber.version>6.8.1</cucumber.version>
</properties>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
定義Feature文件,如分別定義Login.feature 跟Logout.feature文件。
Feature: Login
Scenario: Test login by username and password
Given A register username "testName", and it's password "testPassword"
When Input username and password
And Click login button
And Wait the loading dispeare
Then Direct to Home page
And Show login sucessful tips
Feature: Logout
Scenario: Logout
Given A login user
When Click logout button
Then Direct to login page
And Show logout successful tips
在如IntelliJ Idea中安裝插件,使用Alt+Enter 生成對應(yīng)的Step(Java):


import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.junit.Assert;
public class MyStepdefs {
@Given("A register username {string}, and it's password {string}")
public void aRegisterUsernameAndItSPassword(String testName, String testPassword) {
System.out.println(testName);
System.out.println(testPassword);
}
@When("Input username and password")
public void inputUsernameAndPassword() {
System.out.println("1");
Assert.assertTrue(true);
}
@And("Click login button")
public void clickLoginButton() {
System.out.println("1");
}
@Then("Direct to Home page")
public void directToHomePage() {
System.out.println("1");
}
@And("Show login sucessful tips")
public void showLoginSucessfulTips() {
System.out.println("1");
}
@Given("A login user")
public void aLoginUser() {
}
@When("Click logout button")
public void clickLogoutButton() {
}
@Then("Direct to login page")
public void directToLoginPage() {
}
@And("Show logout successful tips")
public void showLogoutSuccessfulTips() {
}
@And("Wait the loading dispeare")
public void waitTheLoadingDispeare() {
}
}
Run test(使用Junit):
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import java.io.IOException;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
plugin = {
"pretty",
"html:target/cucumber-html-report.html",
"json:target/cucumber-json-report/cucumber.json"
},
features = "src/test/resources",
tags = "not @ignore", monochrome=true)
public class RunTest {
@BeforeClass()
public static void setUp() throws IOException, InterruptedException {
}
}
報(bào)告
跑完:

查看結(jié)果,報(bào)告文件有json跟html格式

還可以集成到CICD工具,如Jenkins,定時(shí)或指定條件下觸發(fā)case并生成報(bào)告。
6. 更多用法
變量
Feature: DataTable
Scenario: Test Datatable
Given a client "clientId"
And I prepare data as input:
|name | testName |
|age | 20 |
|Address | Guangzhou|
And I prepare data as below:
| firstName | lastName | birthDate |
| Annie M. G. | Schmidt | 1911-03-20 |
| Roald | Dahl | 1916-09-13 |
| Astrid | Lindgren | 1907-11-14 |
String入?yún)?/p>
@Given("a client {string}")
public void aClient(String arg0) {
System.out.println(arg0);
}
##輸出:clientId
Map入?yún)?/p>
@And("I prepare data as input:")
public void iPrepareDataAsInput(Map<String,String> tableData) {
System.out.println(tableData);
}
##輸出:{name=testName, age=20, Address=Guangzhou}
Map list入?yún)?/p>
@And("I prepare data as below:")
public void iPrepareDataAsBelow(List<Map<String,String>> tableDataList) {
tableDataList.forEach(t->{
System.out.println(t);
});
}
##輸出:
{firstName=Annie M. G., lastName=Schmidt, birthDate=1911-03-20}
{firstName=Roald, lastName=Dahl, birthDate=1916-09-13}
{firstName=Astrid, lastName=Lindgren, birthDate=1907-11-14}
Scenario Outline
使用Scenario Outline可以使用Examples把類似的Scenario歸在一起,讓Case更簡潔
Feature: Is it Friday yet?
Everybody wants to know when it's Friday
Scenario Outline: Today is or is not Friday
Given today is "<day>"
When I ask whether it's Friday yet
Then I should be told "<answer>"
Examples:
| day | answer |
| Friday | TGIF |
| Sunday | Nope |
| anything else! | Nope |
7. 小結(jié)
介紹了Cucumber工具主要是用來支持BDD方式,Cucumber工具使用Gherkin語法編寫.feature文件,在.feature文件里編寫Step與測試代碼關(guān)聯(lián)起來,這樣把產(chǎn)品需求的user story與user case做了個(gè)很好的關(guān)聯(lián),讓業(yè)務(wù)、開發(fā)、測試對系統(tǒng)的業(yè)務(wù)流程有統(tǒng)一的認(rèn)識(shí)與理解。