1. BDD 及优势
BDD,行为驱动开发是 敏捷软件开发 的一种技术,鼓励软件项目的所有成员之间的相互协助
传统的软件开发方式主要缺点包含:测试用例比较单一,导致覆盖率不高;业务和产品不能够全面了解产品的行为表现
BDD 的出现主要优势有下面 2 点,主要体现在:
- 可以很好的减少项目成员之间的沟通成本,增加协作
- BDD 能够将上线之后的手工测试转换为自动化测试,提升测试效率
2. 软件开发流程
BDD 一般在产品需求文档审核时就开始介入,产品或业务负责人提供产品需求文档的同时,会提供具体的业务场景行为
开发人员根据定义的行为场景,开发软件,并编写场景下面的测试代码
完成 BDD 先在本地进行自测,没问题之后会提交到代码仓库,最后通过 CI 去持续集成,测试通过之后才能上线
BDD 的软件开发流程图如下:
3. Gherkin 语言及 Features
Gherkin 是 BDD 框架 Cucumber 的功能性语言,能够通过自然语言,支持多国语言,描述一个具体的需求
Gherkin 语言使用的是主要英文关键词包含:Scenario、Given、when 、And、Then 等;这些关键词可以转换成中文关键词,比如:场景、加入、当、那么等。
Features 功能文件一般命名为:*.feature,此文件可以编写具体的需求行为,最后可以支持自动化测试
功能文件的编写规范如下:
- 空格或者制表符用于缩进
- 每一行以 BDD 框架中预设的关键字开头
- 使用 # 符号在文件内进行注释
- 无论是中文或英文编写,「 : 」符号只能用英文格式的冒号,否则运行的时候会报错
下面是一个简单的功能文件,描述的是两个数相加的逻辑:
代码语言:javascript复制# 功能文件(英文)
Feature: Adding
Scenario: Adding two numbers
Given the input "1 1"
When the calculator is run
Then output should be "2"
4. Behave
Behave 是 Python 的 BDD 框架,并且可以使用命令行工具进行测试,使用 pip 可以很方便地进行安装
代码语言:javascript复制# 安装 behave 框架
pip3 install behave
编写完功能文件之后,就可以使用 behave 命令直接运行了
代码语言:javascript复制# 直接运行,控制台查看结果
behave
# 以中文来运行测试
behave --lang=zh-CN
5. 实战一下
下面以自动化测试 Google 搜索为例,来说说具体的使用方式
第 1 步,编写 Features 文件,以中文为例
使用 behave --lang-help zh-CN
命令查看所有的中文关键字:
接着,利用这些关键字结合具体行为,编写的 Feature 文件如下:
代码语言:javascript复制功能: Google搜索模块测试
场景大纲: Google搜索一个关键字功能
假如 搜索框输入一个关键字 <keyword>
当 点击搜索按钮
那么 页面标题应该为 <title>
例子:
| keyword | title |
| Python | Python - Google 搜索 |
| AirPython | AirPython - Google 搜索 |
需要注意的是,文件中定义了两个参数,即:keyword 和 title
实际项目中大部分的自动化测试都是基于数据驱动参数化,因此需要搭配「 场景大纲 例子」一起使用。
第 2 步,编写 step 文件
在 Features 同级目录下新建一个 steps 文件夹,接着,在此文件夹下再新建一个 step.py 文件
然后,就可以对照第 1 步编写的 Features 文件编写测试用例了
借助 @given、@when、@then 装饰器,将文本内容和参数对应上
最后,使用 Selenium 定义的 API 方法操作元素即可
代码语言:javascript复制from time import sleep
from selenium.webdriver.common.keys import Keys
from behave import *
@given(u'搜索框输入一个关键字 {keyword}')
def step_impl(context, keyword):
element_input = context.driver.find_element_by_name('q')
element_input.clear()
print("准备输入")
element_input.send_keys(keyword)
@when(u'点击搜索按钮')
def step_impl(context):
# 模拟Enter键
context.driver.find_element_by_name("q").send_keys(Keys.ENTER)
sleep(1)
@then(u'页面标题应该为 {title}')
def step_impl(context, title):
assert context.driver.title == title
需要指出的是,方法名中的第一个参数 context 是一个全局的字典,可以在步骤方法之间传递数据
第 3 步,编写配置环境文件 environment.py
环境配置文件定义了测试脚本运行过程中,具体步骤、场景之前和之后要执行的内容
比如,我们在 before_feature 方法( 每一个 feature 场景执行之前执行 )前初始化 ChromeDriver,打开目标网站首页;然后在 after_feature 方法( feature 场景测试完成之后执行 )后关闭浏览器
代码语言:javascript复制def before_feature(context, feature):
context.driver = webdriver.Chrome()
context.driver.get("https://www.google.com/")
def after_feature(context, feature):
context.driver.quit()
第 4 步,转换 cucumber 测试报告
为了保证下一步在 Jenkins 中能正常显示测试报告,需要将 behave 生成的测试报告转换为 cucumber 兼容的 json 测试报告
首先,安装依赖 behave2cucumber
代码语言:javascript复制# json测试报告文件转换
pip3 install behave2cucumber
然后,在上一步的环境配置文件中重写 after_all 方法,将 behave 格式的测试报告转换为 cucumber 兼容的测试报告
代码语言:javascript复制def after_all(context):
"""
所有测试完成之后执行
注意:behave1.2.6生成的json没法正常转换为cucumber兼容的json报告,建议降级为:1.2.5
:param context:
:return:
"""
# 转换
with open('./test_report.json',encoding='utf-8') as behave_json:
# 格式转换
cucumberJson = behave2cucumber.convert(json.load(behave_json))
jsonStr = json.dumps(cucumberJson)
# 写入
jsonReport = open(r'./report/jsonReport.json', 'w',encoding='utf-8')
jsonReport.write(jsonStr)
jsonReport.close()
需要注意的是,behave 最新版本转成的 cucumber 测试报告,在 Jenkins 中没法展示出来,建议降低为 1.2.5 版本
第 5 步,本地运行
在 Features 文件同级目录下,执行下面的命令,将在本地生成格式化后 json 格式的测试报告
代码语言:javascript复制# 以中文语言的形式在本地运行
# 在本地产生测试报告
behave --lang=zh-CN -f json.pretty -o './test_report.json'
第 6 步,持续集成
首先搭建 Jenkins 环境,然后安装 Cucumber reports 插件
https://plugins.jenkins.io/cucumber-reports
接着,新建一个 Freestyle project 的任务,添加构建步骤 - Execute Shell,写入要执行的 Python 脚本
代码语言:javascript复制# 打开目标项目位置
cd /Users/xingag/Desktop/xag/git/marks/Python/测试/Demo/feature_chrome
# 执行测试,并生成测试报告
behave --lang=zh-CN -f json.pretty -o './test_report.json'
最后,添加构建后的操作 - Cucumber reports,指向第 4 步转换后的 json 格式的测试报告
第 7 步,构建 构建后,测试脚本会自动进行执行,然后会在结果栏生成可视化测试报告
6. 最后
文章只是通过 Python 中的 Behave 框架来谈 BDD 在实际项目中的用法
如果你想在 Java 或者 Golang 项目中使用,可以直接 JBehave 或者 GoDog 框架来实现,除了语法外,基本操作方法类似。