基于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
上课!全体起立~ 大家好,欢迎观看蛙色官方系列全景摄影课程! 正式开讲之前需要先引出一个概念:到底什么是调色? 比如说上面这张照片,你可能会具体的指出照片中的元素有天空、山脉、草地等…… 如果我们跳出我们的固…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
