敏捷测试价值观、方法和实践读书笔记(7)

简介: 本文介绍了BDD(行为驱动开发)的Given-When-Then方法,并详细描述了如何在Java环境中使用Cucumber框架实现BDD测试。内容涵盖配置环境、修改POM文件、编写Feature文件及步骤定义文件、运行测试等过程。同时,提供了使用Cucumber和Selenium对Web页面进行测试的具体示例,并探讨了BDD在团队中的实施策略,包括不同角色之间的协作流程与自动化测试框架的选择。

BDD

  • Given - When - Then
  • Given 初始化描述 and 另一个初始化描述
  • When 某个行为 and 另一个行为
  • Then 获得的结果 and 另外一个结果

代码语言:javascript

复制

test.feature
Scenario: As an account owner
Given I have no account
When I open a new account
Then the account balance is 0.00

英文关键词(Keyword)

对应中文关键词(Equivalemt)

feature

功能

background

背景

scenarioOutline

场景大纲、剧本大纲

scenano

场景、剧本

examples

例子

given

假如、假设、假定

when

then

那么

and

而且、并且、同时

but

但是

1. 修改%MVN_HOME%\conf\settings.xml

找到<mirror>处,加入:

代码语言:javascript

复制

<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf> 
</mirror>

2 在工作目录运行

代码语言:javascript

复制

>mvn archetype:generate "-DarchetypeGroupId=io.cucumber" "-DarchetypeArtifactId=cucumber-archetype" "-DarchetypeVersion=4.2.6" "-DgroupId=hellocucumber" "-DartifactId=hellocucumber" "-Dpackage=hellocucumber"   "-Dversion=1.0.0-SNAPSHOT"   "-DinteractiveMode=false" "-DarchetypeCatalog=local"

形成hellocucumber项目。

3 打开Eclipse,“帮助-eclipse市场”,安装cucumber

4 修改pom.xml

代码语言:javascript

复制

<?xml version="1.0"
encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hellocucumber</groupId>
<artifactId>hellocucumber</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<cucumber.version>4.2.6</cucumber.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>5
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
 <configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
 </configuration>
</plugin>
</plugins>
</build>
</project>

5 书写feature文件。test.feature

代码语言:javascript

复制

#language:zh-CN
功能:
  作为一名银行客户
  我想要拥有一个账户
  以便我可以存钱、取钱,并且显示当前余额
 
场景:我没有账户
    假设我没有账户
  当我新建账户的时候    
  那么我的账户余额为0.00元
 
场景:我已经有了账户
  假设我的账户初始余额为0.00元
  当我存入100.00元后
  那么我的账户余额为100.00元
  假设我的账户初始余额为100.00元
  当我存入200.00元后
  那么我的账户余额为300.00元
  假设我的账户初始余额为400.00元
  当我取出300.00元后
  那么我的账户余额为100.00元

#language:zh-CN 表示用中文写

6 根据test.feature写步骤文件Stepdefs.java

代码语言:javascript

复制

package hellocucumber;
 
import cucumber.api.java.zh_cn.*;
import static org.junit.Assert.*;
public class Stepdefs {
    private Account account;
    @假如("我没有账户")
    public void 我没有账户() {    
        this.account = null;
    }
    @当("我新建账户的时候")
    public void 我新建账户的时候() {
        this.account = new Account();
    }
    @那么("我的账户余额为{double}元")
    public void 我的账户余额为(Double value) {
        assertEquals(value, this.account.getBalance());
    }
   
    @假设("我的账户初始余额为{double}元")
    public void 我的账户初始余额为_元(Double value) {
        this.account = new Account();
        this.account.deposit(value);
    }
    @当("我存入{double}元后")
    public void 我存入_元后(Double value) {
        this.account.deposit(value);
    }
    @当("我取出{double}元后")
    public void 我取出_元后(Double value) {    
        this.account.withdraw(value);
    }
}

注意,空格都必须一致

7 修改RunCucumberTest.java文件

代码语言:javascript

复制

package hellocucumber;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/java/hellocucumber/test.feature",plugin = {"pretty"})
public class RunCucumberTest {
}

features = "src/test/java/hellocucumber/test.feature"指明feature文件位置

8 修改产品代码

代码语言:javascript

复制

package hellocucumber;
 
public class Account {
    private Double balance = 0.0;
    public Double getBalance(){
        return this.balance;    
    }
    public Double deposit(Double value) {
        return this.balance+=value;
    }
   
    public Double withdraw(Double value) {
        return this.balance-=value;
    }
}

9 运行

代码语言:javascript

复制

[INFO] Scanning for projects...
[INFO]
[INFO] --------------------< hellocucumber:hellocucumber >---------------------
[INFO] Building hellocucumber 1.0.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hellocucumber ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ hellocucumber ---    
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hellocucumber ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ hellocucumber ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hellocucumber ---
[INFO] Surefire report directory: C:\Code\MyJava\JUnit\hellocucumber\target\surefire-reports
 
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running hellocucumber.RunCucumberTest
功能:     
  作为一名银行客户
  我想要拥有一个账户
  以便我可以存钱、取钱,并且显示当前余额
 
  场景: 我没有账户        # src/test/java/hellocucumber/test.feature:7
    假设我没有账户        # Stepdefs.我没有账户()
    当我新建账户的时候      # Stepdefs.我新建账户的时候()
    那么我的账户余额为0.00元 # Stepdefs.我的账户余额为(Double)
 
  场景: 我已经有了账户          # src/test/java/hellocucumber/test.feature:12
    假设我的账户初始余额为0.00元   # Stepdefs.我的账户初始余额为_元(Double)
    当我存入100.00元后       # Stepdefs.我存入_元后(Double)
    那么我的账户余额为100.00元   # Stepdefs.我的账户余额为(Double)
    假设我的账户初始余额为100.00元 # Stepdefs.我的账户初始余额为_元(Double)
    当我存入200.00元后       # Stepdefs.我存入_元后(Double)
    那么我的账户余额为300.00元   # Stepdefs.我的账户余额为(Double)
    假设我的账户初始余额为400.00元 # Stepdefs.我的账户初始余额为_元(Double)
    当我取出300.00元后       # Stepdefs.我取出_元后(Double)
    那么我的账户余额为100.00元   # Stepdefs.我的账户余额为(Double)
 
2 Scenarios (2 passed)
12 Steps (12 passed)    
0m0.100s
 
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.237 sec
 
Results :
 
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.700 s
[INFO] Finished at: 2024-02-01T17:13:15+08:00
[INFO] ------------------------------------------------------------------------
 
场景:余额不足
  假设我的账户初始余额为600.00元
  当我取出300.00元后
  那么我的账户余额为300.00元
  当我取出300.00元后
  那么我的账户显示余额不足
@那么("我的账户显示余额不足")    
public void 我的账户显示余额不足() {
    // Write code here that turns the phrase above into concrete actions
    throw new cucumber.api.PendingException();
}
 
Tests run: 3, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.259 sec

代码语言:javascript

复制

@当("我取出{double}元后")
public void 我取出_元后(Double value) throws Throwable {
this.account.withdraw(value);
}
 
@当("我取出{double}元后,显示余额不足")
public void 我取出_元后_显示余额不足(Double value) {
assertThrows(Throwable.class,()->this.account.withdraw(value));
}
 
public Double withdraw(Double value) throws Throwable {
if (value>this.balance)
throw new Throwable("余额不足");
else
return this.balance-=value;    
}

代码语言:javascript

复制

#language:zh-CN
功能:
  作为一名银行客户
  我想要拥有一个账户
  以便我可以存钱、取钱,并且显示当前余额
 
场景大纲:我已经有了账户-表格
  假设我的账户初始余额为<初始余额>元
  当我存入<存入额>元后
  那么我的账户余额为<账户余额>元
 
例子:
| 初始余额| 存入额| 账户余额|
| 0.00 |5.0|5.0|
| 20.00|2.2|22.2|

在pom.xml加入:

代码语言:javascript

复制

<plugin>
<groupId>com.trivago.rta</groupId>
<artifactId>cluecumber-report-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>report</id>
<phase>post-integration-test</phase>
<goals>
<goal>reporting</goal>
</goals>
</execution>
</executions>
<configuration>
<sourceJsonReportDirectory>
${project.build.directory}/cucumber-report
</sourceJsonReportDirectory>
<generatedHtmlReportDirectory>
${project.build.directory}/generated-report
</generatedHtmlReportDirectory>
</configuration>
</plugin>

运行 mvn verify

使用 Cucumber 和 Selenium 对 Web 页面的行为进行测试

代码语言:javascript

复制

# language: zh-CN
功能:
作为一名天猫网的 Web 端用户
我想要搜索到世界上最贵的东西
以便我可以购买世界上最贵的东西

代码语言:javascript

复制

mvn archetype:generate "-DarchetypeGroupId=io.cucumber" "-DarchetypeArtifactId=cucumber-archetype" "-DarchetypeVersion=4.2.6" "-DgroupId=tmall.bdd" "-DartifactId=selenium-bdd" "-Dpackage=selenium.bdd" "-Dversion=1.0.0-SNAPSHOT" "-DinteractiveMode=false" "-DarchetypeCatalog=local"

代码语言:javascript

复制

# language: zh-CN
功能:
作为一名天猫网的 Web 端用户
我想要搜索到世界上最贵的东西    
以便我可以购买世界上最贵的东西
场景:打开浏览器,进入天猫网首页假设我没有打开浏览器当打开浏览器并输入“https://www.tmall.com/”的时候那么我可以进入天猫网首页

代码语言:javascript

复制

package tmall.bdd;
import io.cucumber.java.zh cn.*;
public class StepDefnitions {
@假设("我没有打开浏览器")
public void 我没有打开浏览器(){
  // Write code here that turns the phrase above into concrete actions
  throw new io.cucumber.java.PendingException();
@当("打开浏览器并输入 http:\\/\\www.tmall.com的时候")
public void 打开浏览器并输入天猫网首页的时候(){
  // Write code here that turns the phrase above into concrete actions
  throw new io.cucumber.java.PendingException();
@那么("我可以进入天猫网首页")
public void 我可以进入天猫网首页(){
  // Write code here that turns the phrase above into concrete actions
  throw new io.cucumber.java.PendingException();
}
}

BDD落地

1与团队确定BDD模式

方案1

产品负责人/业务分析师与客户讨论需求,确认用户故事。

产品负责人/业务分析师在迭代计划会上解释用户故事和验收标准。

在迭代计划会上,敏捷软件开发团队根据验收标准承诺交付。

产品负责人/业务分析师与客户进一步沟通交流,确认敏捷软件开发团队提问题,达成验收标准,或展示设计方案以获取进一步反馈。

重复第2 3 4步,直至敏捷软件开发团队能够承诺交付,在这一过程中可分出多个用户故事。

方案2

产品负责人/业务分析师与客户讨论需求,确认用户故事、验收场景和验收标准。

测试人员与产品负责人/业务分析师和敏捷软件开发团队确认验收标准。

测试团队以 Given-When-Then 的方式编写自动化的测试用例。

产品负责人/业务分析师与客户确认以 Given-When-Then 方式编写的验收标准。

确认完毕后,在迭代计划会上,敏捷软件开发团队根据验收标准承诺交付。

重复第2、 3 、4步,直至敏捷软件开发团队能够承诺交付,在这一过程中可能会拆分出多个用户故事。

敏捷软件开发团队根据客户最终确认的 Given-When-Then 测试用例编写自动化验收测试,并完成敏捷软件开发。

方案3

产品负责人/业务分析师和客户讨论需求,确认用户故事、验收场景和验收标准

测试团队以 Given-When-Then 的方式编写自动化的测试用例。

测试团队与产品负责人/业务分析师和敏捷软件开发团队确认验收标准。

产品负责人/业务分析师与客户进一步沟通交流,确认以 Given-When-Then方:号的验收标准。

确认完毕后,在迭代计划会上,开发团队根据验收标准承诺交付。

重复第2、 3、4步,直至敏捷软件开发团队能够承诺交付,在这一进程中可能会拆分出多个用户故事。

敏捷软件开发团队以通过测试人员编写的自动化测试为完成条件,完成敏捷软开发。

2.选择一个适合当前技术栈的 BDD 自动化框架

3.建立基础的.feature文件

(1)使用通用语言(Ubiquitous Language)编写用户故事和验收测试。

(2)一个没有统一领域语言导致年收入减少 10%的 Bug。

4.在持续集成的任务中运行 BDD 的自动化测试

5.重构 BDD 测试,优化自动化测试的分层结构

目录
相关文章
|
8天前
|
测试技术
软件测试的艺术:探索式测试的实践与思考
在软件开发的广阔海洋中,测试是确保航船稳健行驶的关键。本文将带你领略探索式测试的魅力,一种结合创造性思维和严格方法论的测试方式。我们将一起揭开探索式测试的神秘面纱,了解其核心概念、实施步骤和带来的效益。通过实际代码示例,你将学会如何将探索式测试融入日常的软件质量保证流程中,提升测试效率与质量。
|
15天前
|
敏捷开发 人工智能 Devops
探索自动化测试的高效策略与实践###
当今软件开发生命周期中,自动化测试已成为提升效率、保障质量的关键工具。本文深入剖析了自动化测试的核心价值,探讨了一系列高效策略,包括选择合适的自动化框架、设计可维护的测试脚本、集成持续集成/持续部署(CI/CD)流程,以及有效管理和维护测试用例库。通过具体案例分析,揭示了这些策略在实际应用中的成效,为软件测试人员提供了宝贵的经验分享和实践指导。 ###
|
15天前
|
机器学习/深度学习 人工智能 jenkins
软件测试中的自动化与持续集成实践
在快速迭代的软件开发过程中,自动化测试和持续集成(CI)是确保代码质量和加速产品上市的关键。本文探讨了自动化测试的重要性、常见的自动化测试工具以及如何将自动化测试整合到持续集成流程中,以提高软件测试的效率和可靠性。通过案例分析,展示了自动化测试和持续集成在实际项目中的应用效果,并提供了实施建议。
|
15天前
|
Java 测试技术 持续交付
探索自动化测试在软件开发中的关键作用与实践
在现代软件开发流程中,自动化测试已成为提升产品质量、加速交付速度的不可或缺的一环。本文深入探讨了自动化测试的重要性,分析了其在不同阶段的应用价值,并结合实际案例阐述了如何有效实施自动化测试策略,以期为读者提供一套可操作的实践指南。
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
智能化软件测试:AI驱动的自动化测试策略与实践####
本文深入探讨了人工智能(AI)在软件测试领域的创新应用,通过分析AI技术如何优化测试流程、提升测试效率及质量,阐述了智能化软件测试的核心价值。文章首先概述了传统软件测试面临的挑战,随后详细介绍了AI驱动的自动化测试工具与框架,包括自然语言处理(NLP)、机器学习(ML)算法在缺陷预测、测试用例生成及自动化回归测试中的应用实例。最后,文章展望了智能化软件测试的未来发展趋势,强调了持续学习与适应能力对于保持测试策略有效性的重要性。 ####
|
5天前
|
敏捷开发 前端开发 Java
软件测试中的自动化测试框架选择与实践
在当今软件开发生命周期中,自动化测试已成为提升软件质量和开发效率的关键手段。本文旨在探讨自动化测试框架的选择标准及其在实际项目中的应用实践。通过对主流自动化测试框架的分析比较,结合具体案例,本文将阐述如何根据项目需求和团队特点选择合适的自动化测试工具,并分享实施过程中的经验教训。
14 1
|
15天前
|
Web App开发 敏捷开发 测试技术
探索自动化测试的奥秘:从理论到实践
【10月更文挑战第39天】在软件质量保障的战场上,自动化测试是提升效率和准确性的利器。本文将深入浅出地介绍自动化测试的基本概念、必要性以及如何实施自动化测试。我们将通过一个实际案例,展示如何利用流行的自动化测试工具Selenium进行网页测试,并分享一些实用的技巧和最佳实践。无论你是新手还是有经验的测试工程师,这篇文章都将为你提供宝贵的知识,帮助你在自动化测试的道路上更进一步。
|
15天前
|
敏捷开发 Java 测试技术
探索自动化测试:从理论到实践
【10月更文挑战第39天】在软件开发的海洋中,自动化测试是一艘能够带领团队高效航行的船只。本文将作为你的航海图,指引你理解自动化测试的核心概念,并分享一段实际的代码旅程,让你领略自动化测试的魅力和力量。准备好了吗?让我们启航!
|
20天前
|
测试技术 API Android开发
探索软件测试中的自动化框架选择与实践####
本文深入探讨了软件测试领域内,面对众多自动化测试框架时,如何依据项目特性和团队需求做出明智选择,并分享了实践中的有效策略与技巧。不同于传统摘要的概述方式,本文将直接以一段实践指南的形式,简述在选择自动化测试框架时应考虑的核心要素及推荐路径,旨在为读者提供即时可用的参考。 ####
|
25天前
|
NoSQL 测试技术 Go
自动化测试在 Go 开源库中的应用与实践
本文介绍了 Go 语言的自动化测试及其在 `go mongox` 库中的实践。Go 语言通过 `testing` 库和 `go test` 命令提供了简洁高效的测试框架,支持单元测试、集成测试和基准测试。`go mongox` 库通过单元测试和集成测试确保与 MongoDB 交互的正确性和稳定性,使用 Docker Compose 快速搭建测试环境。文章还探讨了表驱动测试、覆盖率检查和 Mock 工具的使用,强调了自动化测试在开源库中的重要性。