敏捷测试价值观、方法和实践读书笔记(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 测试,优化自动化测试的分层结构

目录
相关文章
|
11月前
|
人工智能 自然语言处理 测试技术
从人工到AI驱动:天猫测试全流程自动化变革实践
天猫技术质量团队探索AI在测试全流程的落地应用,覆盖需求解析、用例生成、数据构造、执行验证等核心环节。通过AI+自然语言驱动,实现测试自动化、可溯化与可管理化,在用例生成、数据构造和执行校验中显著提效,推动测试体系从人工迈向AI全流程自动化,提升效率40%以上,用例覆盖超70%,并构建行业级知识资产沉淀平台。
从人工到AI驱动:天猫测试全流程自动化变革实践
|
11月前
|
数据采集 存储 人工智能
从0到1:天猫AI测试用例生成的实践与突破
本文系统阐述了天猫技术团队在AI赋能测试领域的深度实践与探索,讲述了智能测试用例生成的落地路径。
从0到1:天猫AI测试用例生成的实践与突破
|
12月前
|
测试技术 开发者 Python
Python单元测试入门:3个核心断言方法,帮你快速定位代码bug
本文介绍Python单元测试基础,详解`unittest`框架中的三大核心断言方法:`assertEqual`验证值相等,`assertTrue`和`assertFalse`判断条件真假。通过实例演示其用法,帮助开发者自动化检测代码逻辑,提升测试效率与可靠性。
676 1
|
12月前
|
机器学习/深度学习 人工智能 自然语言处理
如何让AI更“聪明”?VLM模型的优化策略与测试方法全解析​
本文系统解析视觉语言模型(VLM)的核心机制、推理优化、评测方法与挑战。涵盖多模态对齐、KV Cache优化、性能测试及主流基准,助你全面掌握VLM技术前沿。建议点赞收藏,深入学习。
3481 8
|
12月前
|
Java 测试技术 API
自动化测试工具集成及实践
自动化测试用例的覆盖度及关键点最佳实践、自动化测试工具、集成方法、自动化脚本编写等(兼容多语言(Java、Python、Go、C++、C#等)、多框架(Spring、React、Vue等))
862 6
|
12月前
|
人工智能 边缘计算 搜索推荐
AI产品测试学习路径全解析:从业务场景到代码实践
本文深入解析AI测试的核心技能与学习路径,涵盖业务理解、模型指标计算与性能测试三大阶段,助力掌握分类、推荐系统、计算机视觉等多场景测试方法,提升AI产品质量保障能力。
|
12月前
|
人工智能 自然语言处理 测试技术
AI测试平台的用例管理实践:写得清晰,管得高效,执行更智能
在测试过程中,用例分散、步骤模糊、回归测试效率低等问题常困扰团队。霍格沃兹测试开发学社推出的AI测试平台,打通“用例编写—集中管理—智能执行”全流程,提升测试效率与覆盖率。平台支持标准化用例编写、统一管理操作及智能执行,助力测试团队高效协作,释放更多精力优化测试策略。目前平台已开放内测,欢迎试用体验!
|
人工智能 资源调度 jenkins
精准化回归测试:大厂实践与技术落地解析
在高频迭代时代,全量回归测试成本高、效率低,常导致关键 bug 漏测。精准化测试通过代码变更影响分析,智能筛选高价值用例,显著提升测试效率与缺陷捕获率,实现降本增效。已被阿里、京东、腾讯等大厂成功落地,成为质量保障的新趋势。
|
搜索推荐 Devops 测试技术
避免无效回归!基于MCP协议的精准测试影响分析实践
本文揭示传统测试的"孤岛困境",提出MCP(Model Context Protocol)测试新范式,通过模型抽象业务、上下文感知环境和协议规范协作,实现从机械执行到智能测试的转变。剖析MCP如何颠覆测试流程,展示典型应用场景,并提供团队落地实践路径,助力测试工程师把握质量效率革命的新机遇。
|
人工智能 缓存 自然语言处理
大模型性能测试完全指南:从原理到实践
本文介绍了大模型性能测试的核心价值与方法,涵盖流式响应机制、PD分离架构、五大关键指标(如首Token延迟、吐字率等),并通过实战演示如何使用Locust进行压力测试。同时探讨了多模态测试的挑战与优化方向,帮助测试工程师成长为AI系统性能的“诊断专家”。