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

目录
相关文章
|
30天前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
47 4
|
1月前
|
人工智能 JavaScript 前端开发
自动化测试框架的演进与实践###
本文深入探讨了自动化测试框架从诞生至今的发展历程,重点分析了当前主流框架的优势与局限性,并结合实际案例,阐述了如何根据项目需求选择合适的自动化测试策略。文章还展望了未来自动化测试领域的技术趋势,为读者提供了宝贵的实践经验和前瞻性思考。 ###
|
30天前
|
测试技术 Python
探索软件测试的深度与广度:从理论到实践
在数字化时代,软件已成为我们生活中不可或缺的一部分。随着技术的不断进步和用户需求的多样化,确保软件质量变得尤为重要。本文将深入浅出地介绍软件测试的核心概念、类型及其在软件开发生命周期中的重要性。我们将通过实际案例,展示如何实施有效的测试策略,并探讨自动化测试的未来趋势,旨在为读者提供一套完整的软件测试知识体系,帮助提升软件质量和开发效率。
|
1月前
|
测试技术 Python
探索软件测试的奥秘:从理论到实践
在软件开发的宇宙中,软件测试犹如一颗璀璨的星辰,指引着质量的方向。本文将带你穿梭于软件测试的理论与实践之间,揭示其内在的逻辑和魅力。从测试的重要性出发,我们将探讨不同类型的测试方法,并通过实际案例分析,深入理解测试用例的设计和应用。最后,我们将通过一个代码示例,展示如何将理论知识转化为实际操作,确保软件质量的同时,也提升你的测试技能。让我们一起踏上这段探索之旅,发现软件测试的无限可能。
|
1月前
|
jenkins 测试技术 持续交付
自动化测试框架的搭建与实践
在软件开发领域,自动化测试是提升开发效率、确保软件质量的关键手段。本文将引导读者理解自动化测试的重要性,并介绍如何搭建一个基本的自动化测试框架。通过具体示例和步骤,我们将探索如何有效实施自动化测试策略,以实现软件开发流程的优化。
70 7
|
1月前
|
测试技术
探索软件测试的奥秘:从理论到实践
本文深入探讨了软件测试的基本概念、重要性、主要类型以及实施策略。通过分析不同测试阶段和相应的测试方法,文章旨在为读者提供一套完整的软件测试知识体系,帮助他们更好地理解和应用测试技术,确保软件产品的质量和可靠性。
65 4
|
2月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
52 2
|
29天前
|
监控 搜索推荐 测试技术
电商API的测试与用途:深度解析与实践
在电子商务蓬勃发展的今天,电商API成为连接电商平台、商家、消费者和第三方开发者的重要桥梁。本文深入探讨了电商API的核心功能,包括订单管理、商品管理、用户管理、支付管理和物流管理,并介绍了有效的测试技巧,如理解API文档、设计测试用例、搭建测试环境、自动化测试、压力测试、安全性测试等。文章还详细阐述了电商API的多样化用途,如商品信息获取、订单管理自动化、用户数据管理、库存同步、物流跟踪、支付处理、促销活动管理、评价管理、数据报告和分析、扩展平台功能及跨境电商等,旨在为开发者和电商平台提供有益的参考。
37 0
|
2月前
|
人工智能 数据管理 jenkins
探索软件测试中的自动化框架:从基础到高级实践
在当今快速发展的软件行业中,自动化测试已成为提高开发效率和保障产品质量的关键手段。本文将深入探讨软件测试自动化的各个方面,包括其重要性、主流的自动化测试框架、以及如何有效地实施自动化测试策略。我们还将通过案例分析,展示自动化测试在实际项目中的应用效果,以及面临的挑战和解决方案。无论是软件开发者还是测试工程师,了解并掌握自动化测试技术都将极大提升工作效率和产品质量。
51 0
|
18天前
|
监控 JavaScript 测试技术
postman接口测试工具详解
Postman是一个功能强大且易于使用的API测试工具。通过详细的介绍和实际示例,本文展示了Postman在API测试中的各种应用。无论是简单的请求发送,还是复杂的自动化测试和持续集成,Postman都提供了丰富的功能来满足用户的需求。希望本文能帮助您更好地理解和使用Postman,提高API测试的效率和质量。
70 11