基于Cucumber的行为驱动开发(BDD)实例
本篇介绍 Cucumber 的基本使用, 因为Cucumber是BDD的工具, 所以首先需要弄清楚什么是BDD,而在介绍BDD之前,先看看常见的软件开发方法。
常见的软件开发方法
- 面向过程开发(Procedural Development):面向过程开发注重流程和功能的实现,而不是业务需求的实现。
 - 面向对象开发(Object-Oriented Development):面向对象开发注重对象之间的交互和关系,而不是业务需求的实现。
 - 测试驱动开发(Test-Driven Development,TDD):TDD注重测试用例的编写和通过测试用例来驱动代码的实现,而不是业务需求的实现。
 - 行为驱动开发(Behavior-Driven Development,BDD):BDD注重业务需求和行为,并通过测试用例来验证和定义业务需求的实现。
 
BDD的由来
BDD是行为驱动开发的缩写。它是一种软件开发方法,强调开发人员、测试人员和业务利益相关者之间的协作,以确保正在开发的软件与业务目标相一致。
 BDD是在2003年由Dan North首次提出的。他发现在软件开发中,注重测试和自动化并不足以确保软件的质量和正确性。因此,他提出了一种基于“Behavior”(行为)的开发方法,即BDD。BDD旨在通过强调需求和业务价值,更紧密地结合开发和测试团队,提高软件的质量和客户满意度。
 BDD涉及使用自然语言描述或所需系统行为的示例,这些示例被翻译成自动化测试,以确保系统的行为符合预期。这种方法有助于确保软件的开发是在清楚地理解所需的行为和结果的情况下进行的,以满足所有利益相关者的需求。
Cucumber 是什么

Cucumber 是一个行为驱动开发(BDD)工具,用于创建和运行自动化测试,以确保软件系统的行为符合业务需求和用户期望。它用自然语言编写测试用例,这些测试用例可以与开发和业务团队共享和理解。Cucumber支持多种编程语言,并且可以与各种测试框架集成。
Cucumber用于描述应用程序的行为、功能和需求。它的目标是帮助开发人员和非技术人员之间的沟通,以及帮助开发人员编写更易于维护的测试代码。通过使用Cucumber,团队可以创建基于真实场景的自动化测试,这些测试使用了普通语言来描述行为,因此它们对所有团队成员来说都是可理解的。以下是Cucumber的一些特点和用途:
特点:
-  
支持普通语言:Cucumber用于编写测试的语言是Gherkin,这是一种自然语言风格的语言,专门设计用来描述业务行为而不需要注入具体的如何实现。因此,非技术的团队成员(比如产品经理和业务分析师)也能参与测试和开发的过程。
 -  
支持多种语言:尽管Cucumber起初是为用Ruby写的项目设计的,但是现在已经支持多种编程语言,包括Java, JavaScript, .NET,等。
 -  
支持多种测试框架和工具,包括Selenium和Appium。
 -  
可以生成易于阅读的测试报告,并提供了可视化的测试结果。
 -  
整合支持:Cucumber可以和许多流行的持续集成/持续部署工具整合,例如Jenkins和TeamCity。
 -  
可维护性与重用性:Cucumber的测试案例是用普通话写的,所以它们是可理解的,并且可以重复使用。此外,因为测试案例直接对应到需求,所以他们很容易维护。
 
用途:
- 协助团队沟通:Cucumber使用自然语言描述应用程序的需求和功能,可以帮助开发人员和非技术人员之间的沟通。
 - 自动化测试:使用Cucumber可以编写自动化测试用例,这些测试用例模拟了用户使用应用程序的场景,以确保应用程序的正确性。
 - 生成文档:Cucumber测试用例描述了应用程序的行为和需求,可以作为应用程序的文档。
总之,Cucumber是一款功能强大的BDD工具,可以帮助开发团队更好地协作、编写高质量的测试用例和文档。 
基于Java 语言的Cucumber 使用实例
这里使用基于Maven的项目为例, 在Eclipse 上进行开发。
步骤如下:
- 导入依赖
 
需要导入 cucumber-java 和 cucumber-junit , 这里导入当前最新版本 7.14.0。
		<dependency><groupId>io.cucumber</groupId><artifactId>cucumber-java</artifactId><version>7.14.0</version></dependency><dependency><groupId>io.cucumber</groupId><artifactId>cucumber-junit</artifactId><version>7.14.0</version></dependency>
 
- 创建规格文件user.feature, 文件位于 src/test/resources 目录下:
 
Feature: UserScenario: createGiven User 100 not existWhen create User 100Then can query User 100
 
这个文件的解读是:
 系统中User功能的 create场景, 如果ID为100的 User不存在,就创建这个User, 创建完成之后就可以查询到这个User了。
- 根据规格文件完成测试的代码,这里就是根据规格中的步骤定义的, 文件名为StepDefinitions.java。
 
/**
* @Title: StepDefinitions.java
* @Package com.osxm.je.topic.bdd
* @Description: TODO
* @author XM
* @date 2023年10月9日 下午10:03:34
* @Copyright: 2023
* @version V1.0  
*/
package com.osxm.je.topic.bdd;import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;import java.util.HashMap;
import java.util.Map;import com.osxm.je.basic.entity.User;import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;public class StepDefinitions {private Map<Integer, User> userRepo = new HashMap<Integer, User>();private User user;@Given("User {int} not exist")public void user_not_exist(Integer userId) {assertFalse(userRepo.containsKey(userId));}@When("create User {int}")public void create_user(Integer userId) {user = new User(userId);userRepo.put(userId, user);}@Then("can query User {int}")public void query_user(Integer userId) {user = userRepo.get(userId);assertNotNull(user);}
} 
- 注意 @Given 注解中使用 
{int}定义的变量和规格文件user.feature中的对应 
- 编写测试入口类 CucumberTest.java
 
/**
* @Title: CucumberTest.java
* @Package com.osxm.je.topic.bdd
* @Description: TODO
* @author XM
* @date 2023年10月9日 下午10:05:35
* @Copyright: 2023
* @version V1.0  
*/
package com.osxm.je.topic.bdd;import org.junit.runner.RunWith;import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources")  // 要测试的 Feature 文件的位置
public class CucumberTest {}
 
运行测试后的效果如下:
 
如果将规格文件故意修改错误:
Feature: UserScenario: createGiven User 100 not existWhen create User 100Then can query User 200
 
则运行结果就是错误的, 如下图:
 
相关文章:
基于Cucumber的行为驱动开发(BDD)实例
本篇介绍 Cucumber 的基本使用, 因为Cucumber是BDD的工具, 所以首先需要弄清楚什么是BDD,而在介绍BDD之前,先看看常见的软件开发方法。 常见的软件开发方法 面向过程开发(Procedural Development)&#x…...
十六、代码校验(2)
本章概要 前置条件 断言(Assertions)Java 断言语法Guava 断言使用断言进行契约式设计检查指令前置条件后置条件不变性放松 DbC 检查或非常严格的 DbCDbC 单元测试 前置条件 前置条件的概念来自于契约式设计(Design By Contract, DbC), 利用断言机制…...
安卓 kotlin-supportFragmentManager报红
如果你继承baseActivity 请查看 是不是继承 AppCompatActivity...
linux中安装RocketMQ以及dashboard
前提: 需要安装jdk8 上传下面的文件到服务器中 新建目录 mkdir rocketmq 将下载后的压缩包上传到阿里云服务器或者虚拟机中去,并解压 unzip rocketmq-all-4.9.2-bin-release.zip 配置环境变量 vim /etc/profile 配置内容: export NAM…...
Android kotlin内联函数(inline)的详解与原理
一、介绍 在kotlin中,有一种函数叫内联函数,这种函数标识符是inline,但是好多人对这个函数的理解只停留在八股文中,内容函数的用法和普通函数没有区别,但是在编译原理上是有,对程序的性能有一定的影响。 二…...
林沛满---一个面试建议
在应聘一个技术职位之前,做好充分的准备无疑能大大提高成功率。这里所说的准备并不是指押题,因为有经验的面试官往往准备了海量的题库,押中的概率太低。比如我有位同事的题库里有上百道题,内容涵盖了编程、操作系统、网络、存储……...
CMake教程-第 5 步:安装和测试
CMake教程-第 5 步:安装和测试 1 CMake教程介绍2 学习步骤Step 1: A Basic Starting PointStep 2: Adding a LibraryStep 3: Adding Usage Requirements for a LibraryStep 4: Adding Generator ExpressionsStep 5: Installing and TestingStep 6: Adding Support f…...
移动应用-Android开发基础\核心知识点
Android开发基础 知识点 1 介绍了解2 系统体系架构3 四大应用组件4 移动操作系统优缺点5 开发工具6 配置工具7 下载相关资源8JDK下载安装流程9配置好SDK和JDK环境10 第一个Hello word11 AS开发前常用设置12模拟器使用运行13 真机调试14 AndroidUI基础布局15 加载展示XML布局16…...
Java读取并转换字符串中的浮点数
在写Android接收蓝牙数据的时候,由于传过来的蓝牙数据转换后都为字符串格式,但是需要从其中提取出来浮点数,所以通过查阅资料写出了从字符串中提取并转换为浮点数的方法,特记录下来以供参考。 目录 原始数据内容 提取字符串中的…...
SQL: 索引原理与创建索引的规范
SQL 索引是一种数据结构,用于加速数据库查询操作。它通过在表的列上创建索引,提供了一种快速查找数据的方法,减少了数据库的扫描和比较操作,从而提高了查询性能。索引根据其实现方式可以分为多种类型,如 B-树索引、哈希…...
基于STM32_DS18B20单总线传感器驱动
基于STM32_DS18B20单总线传感器驱动 文章目录 基于STM32_DS18B20单总线传感器驱动前言一、BS18B20?二、原理1.复位与检验2.基本命令3.唯一ROM识别码4.温度转换 三、驱动代码四、注意事项 前言 本文以一款典型的单总线传感器及其驱动——DS18B20为例,简单…...
目标识别项目实战:基于Yolov7-LPRNet的动态车牌目标识别算法模型(三)
前言 目标识别如今以及迭代了这么多年,普遍受大家认可和欢迎的目标识别框架就是YOLO了。按照官方描述,YOLOv8 是一个 SOTA 模型,它建立在以前 YOLO 版本的成功基础上,并引入了新的功能和改进,以进一步提升性能和灵活性…...
springboot线程池创建与使用
/*** author: zcs* Title: TaskPoolConfig* Description: 线程池配置* date: 2023/10/11 17:52*/ Component public class TaskPoolConfig {Bean(name "threadPoolTaskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor taskExecutor new ThreadP…...
UDP和TCP特点(部分)对比:
传输层的两个主要协议:TCP 和 UDP UDP和TCP特点(部分)对比: UDP:无连接, 不可靠传输, 面向数据报, 全双工。 TCP:有连接, 可靠传输, 面向字节流…...
PostMan环境变量、全局变量、动态参数使用
一、环境准备 postmanmoco [{"description": "登录认证","request": {"uri": "/login","method": "post","forms": {"user": "admin","password": "a123…...
服务器数据恢复-服务器硬盘指示灯黄灯闪烁的数据恢复案例
服务器数据恢复环境: 服务器面板上的硬盘指示灯显示黄色是一种警告,提示指示灯对应的服务器硬盘已经被服务器识别出存在故障,硬盘即将下线。如果出现这种情况,建议服务器管理员/运维人员及时用完好的硬盘替换显示黄色指示灯对应的…...
ts 分发
在 TypeScript 中,"分发"(distributive)是指在条件类型中的联合类型上自动进行类型推断的机制。当使用条件类型操作联合类型时,TypeScript 会自动将联合类型中的每个成员都应用该条件类型。 下面是一个示例:…...
SQL中的group by使用注意事项
在 SQL 中,GROUP BY 语句用于将查询结果按照指定的列进行分组,并对每个分组计算聚合函数(如 SUM、AVG、COUNT 等)的值。一般情况下,如果查询中包含聚合函数,那么就需要使用 GROUP BY 语句将查询结果按照指定…...
矩阵剪辑系统源码----pc/手机端双开发
剪辑系统,剪辑矩阵系统,剪辑矩阵系统主要是针对抖音、快手、bili平台的一个工具,今天就来给大家交流一下这 个产品的主要功能以及构成。剪辑矩阵系统,矩阵剪辑系统源码-这产品主要功能就是一个视频剪辑功能,这个视频剪…...
0基础学习VR全景平台篇 第106篇:认识调色软件Lightroom
上课!全体起立~ 大家好,欢迎观看蛙色官方系列全景摄影课程! 正式开讲之前需要先引出一个概念:到底什么是调色? 比如说上面这张照片,你可能会具体的指出照片中的元素有天空、山脉、草地等…… 如果我们跳出我们的固…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
