Pytest-BDD 行为驱动开发测试

文章目录

    • 01 BDD
    • 02 pytest-BDD
    • 03 安装pytest-BDD
    • 04 pytest-bdd的框架结构
    • 05 pytest-bdd基础使用
      • 5.1 第一步:添加需求描述/用户场景
        • 5.1.1 BDD的表达语法
        • 5.1.2 创建`.feature`文件
      • 5.2 第二步:实现用户场景
        • 5.2.1 用户场景的解析/实现
        • 5.2.2 使用`scenarios`或`@scenario`关联用户场景和步骤函数
          • 1. `scenarios`
          • 2. `@scenario`
      • 5.3 第三步:运行测试
    • 06 pytest-bdd扩展使用
      • 6.1 步骤参数
        • 6.1.1 默认是String
        • 6.1.2 parse (基于pypi_parse)
        • 6.1.3 cfparse (pypi_parse的扩展,基于 pypi_parse_type)
        • 6.1.4 re
      • 6.2 给定测试步骤覆盖fixture
      • 6.3 多行步骤
      • 6.4 解析测试步骤中的表格
      • 6.5 场景大纲
      • 6.6 pytest-bdd标记
        • 6.6.1 pytest-bdd标记的基础使用
        • 6.6.2 pytest_bdd_apply_tag钩子函数
      • 6.7 背景Backgrounds
      • 6.8 重用fixtures (Reusing fixtures)
      • 6.9 重用测试步骤 (Reusing steps)
      • 6.10 配置Feature的基础路径
        • 6.10.1 没有配置Feature的基础路径
        • 6.10.2 配置Feature的基础路径
    • 07 pytest-bdd钩子函数
      • 7.1 pytest_bdd_before_scenario
      • 7.2 pytest_bdd_after_scenario
      • 7.3 pytest_bdd_before_step
      • 7.4 pytest_bdd_before_step_call
      • 7.5 pytest_bdd_after_step
      • 7.6 pytest_bdd_step_error
      • 7.7 pytest_bdd_step_func_lookup_error

01 BDD

BDD 即 Behavior-driven development,行为驱动开发。
在软件工程中, BDD是一种敏捷开发流程。减少传统测试过程中由于技术背景能力,非技术与商业参与者之间业务理解不同而导致的问题。BDD它关注的核心是设计,其要求在设计测试用例的时候对系统进行定义,倡导使用通用的语言将系统的行为描述出来,将系统设计和测试用例结合起来,从而以此为驱动进行开发工作。
BDD行为驱动是一种敏捷开发模式, 重点在于消除开发/测试对需求了解的歧义及用户场景的验证。
BDD 使用自然语言Gherkin来描述系统功能和场景,根据这些描述步骤进行系统自动化的测试。

02 pytest-BDD

官方文档地址: https://pytest-bdd.readthedocs.io/en/latest/
Git仓库地址:https://gitlink.org.cn/test_framework/pytest-bdd

pytest-bdd 是一个BDD测试框架,类似于behave, cucumber。与许多其他传统框架pytest, unittest不同,BDD框架-pytest-bdd 不需要单独的运行程序,它可以统一单元测试和功能测试,减轻连续集成服务器配置的负担,并允许重用测试。
pytest-bdd作为pytest的一个插件,所有pytest的功能和插件都可以用于pytest-bdd!
为单元测试编写的pytest固定装置可以通过依赖项注入重新用于功能步骤中提到的设置和操作。允许对需求进行真正的BDD说明,而无需维护任何包含Gherkin命令性声明的上下文对象。

03 安装pytest-BDD

使用如下命令可以安装:pip install pytest-bdd

04 pytest-bdd的框架结构

我们先大概介绍以下框架结构,大家可以先有一个概念。了解了框架结构后,我们再详细介绍pytest-bdd的使用。
正常情况下,我们需要有一个目录features来管理测试用例(.feature文件),一个目录step_defs来管理测试步骤(test_*.py文件)。

  • 其中目录features可以自定义名称,以及自定义位置。只需要在测试步骤(test_*.py文件)中引用正确即可。
  • 目录step_defs也可以自定义名称以及自定义位置。

以下是示例:

# 第一种
├────features/   # 用户场景
│    ├────projects/
│    │    ├────create_project.features
│    ├────login.features
├────step_defs/  # 步骤函数和测试场景
│    ├────projects/
│    │    ├────test_create_project.py
│    └────test_login.py
# 第二种
├────cases/  # 用户场景
│    ├────projects/
│    │    ├────create_project.features
│    ├────login.features
├────test_cases/  # 步骤函数和测试场景
│    ├────projects/
│    │    ├────test_create_project.py
│    └────test_login.py
# 第三种
├────test_cases/  # 测试用例
│    ├────features/  # 用户场景
│    │    ├────login.features
│    ├────step_defs/  # 步骤函数和测试场景
│    │    ├────test_login.py
# 第四种
├────features/   # 用户场景
│    ├────projects/
│    │    ├────create_project.features
│    ├────login.features
├────step_defs/  # 步骤函数
│    ├────projects/
│    │    ├────create_project_steps.py
│    └────login_steps.py
├────test_case/  # 测试场景
│    ├────test_projects/
│    │    ├────test_create_project.py
│    └────test_login.py

05 pytest-bdd基础使用

5.1 第一步:添加需求描述/用户场景

5.1.1 BDD的表达语法

BDD提供一套标准的需求及用户场景表达语法, 使用文件后缀为.feature的文件进行管理。

BDD分如下几部分:

  • Fixture(特性):是向最终用户或其他涉众提供的一项功能,以支持他们实现业务目标所需的功能。
  • Background(背景):是所有场景公共的部分。在所有场景运行前会运行的部分。
  • Scenario(场景):用户在访问应用时,用户和应用之间有多种条件需要满足,每一种不同的情况都对应不同的场景,简短的声明性句子来总结这个例子的特别之处
  • Given(前置条件):在测试操作前有哪些先决条件?应该定义出所有的但不场景该场景要求范围的先决条件,given主要为后面的测试主体服务
  • When (用户操作):用户做了哪个操作,输入了哪些数据
  • Then (预期结果):回应行操作的预期结果,用户做了操作后会触发系统产生什么样的变化、输出的数据是什么

注意:

  • 一个需求文件中只能有一个Feature字段,可以包含多个Scenario(用户场景)。
  • Given->When->Then类似与准备->执行->验证/清理的流程。
  • Given:一般可以用来做预置条件/数据准备,下面第一个And也属于Given。
  • When下面的量And都属于When, 一般是操作步骤。
  • Then: 一般用于验证结果(断言),也可以进行清理数据。

5.1.2 创建.feature文件

如下所示是一个示例(文件名:login.feature):

Feature: 登录模块需求描述: 用户进入登录页面/弹窗登录页面,使用正确用户名以及密码可以登录成功Background: 清除浏览器缓存,避免缓存影响用例Given 清除浏览器缓存Scenario: 弹窗登录: 正确用户名和密码登录成功Given 打开浏览器,访问项目首页When 点击:登录按钮,打开登录弹窗And 弹窗中,输入用户:xxxxxx, 密码:12345678And 弹窗中,点击: 登录按钮, 提交登录表单Then 当前页面的url地址应该是:https://www.gitlink.org.cn/exploreAnd 右上角显示的用户昵称应该是:xxxxxxScenario: 网页登录: 正确用户名和密码登录成功Given 打开浏览器,访问GitLink首页When 点击:登录按钮,进入登录页面And 登录页面中,输入用户:xxxxxx, 密码:12345678And 登录页面中,点击: 登录按钮, 提交登录表单Then 当前页面的url地址应该是:https://www.gitlink.org.cn/xxxxxxAnd 右上角显示的用户昵称应该是:xxxxxx

5.2 第二步:实现用户场景

在前面的章节我们已经实现了测试场景,但是单单是靠测试场景是无法运行测试的。 我们还需要将每个场景文件.feature中的描述翻译成具体的页面操作, 每一句对应一个步骤函数。

5.2.1 用户场景的解析/实现

我们需要从pytest_bdd中导入given, when, then, parsers,帮助我们实现用户场景中的每一个步骤。

注意:我这里只摘取了上述部分步骤进行实现展示。方法都是类似的。

比如我们实现given中步骤,只需要写一个步骤函数,使用@given("步骤名称")装饰器即可。

@given("打开浏览器,访问项目首页")
def visit_projects_home(driver, host):driver.get(host)

同时,一个步骤函数是可以添加多个步骤的,例如:

@when("点击:登录按钮,进入登录页面")
@when("点击:登录按钮,打开登录弹窗")
def click_login_button(driver):login_button = driver.find_element(By.XPATH, "//a[text()='登录']")login_button.click()

如果我们需要从测试步骤弹窗中,输入用户:xxxxxx, 密码:12345678 中提取用户名和密码的具体值,我们可以使用parsers来解析语句中的参数。例如:

@when(parsers.parse("弹窗中,输入用户:{username}, 密码:{password}"))
def input_login_info_on_pop(driver, username, password):# 这里通过parsers.parse解析到username=xxxxxx, password=12345678username_input = driver.find_element(By.XPATH, "//input[@name='username']")password_input = driver.find_element(By.XPATH, "//input[@name='password']")username_input.send_keys(username)password_input.send_keys(password)

而且在步骤函数中,我们可以直接使用pytest的fixture。

# conftest.py 中定义了一个fixture
@pytest.fixture(scope="session")
def host():return GLOBAL_VARS.get("host")# --------------------------------------------------------------#
# test_*.py 测试方法中直接传入fixture的名称作为参数使用即可。
# 这里直接传入了fixture的名称: host, 作为测试方法:visit_projects_home的入参使用。
@given("打开浏览器,访问项目首页")
def visit_projects_home(driver, host):driver.get(host)

特别注意:步骤函数中的步骤描述,需要于.feature中的保持完全一致,否则可能会报错。

5.2.2 使用scenarios@scenario关联用户场景和步骤函数

前面我们已经分别使用.feature文件以及.py文件分别实现了用户场景以及步骤函数。 我们需要将这两者关联起来。
假如我们的步骤函数是放在test_开头的.py文件中,我们可以直接在该文件中使用scenarios@scenario关联用户场景和步骤函数。
假如我们的步骤函数不是放在test_开头的.py文件中,我们可以新建一个test_开头的.py来管理测试场景,但是我们需要导入该测试场景中所需要相关的步骤函数。

我这里是直接在test_开头的.py文件中放置步骤函数以及测试场景。

下面我将分别介绍scenarios@scenario装饰器,这两种不同的方法来定义和标记 BDD 场景。

1. scenarios

scenarios,用于将多个 BDD 场景与步骤函数关联起来。它可以接受一个或多个参数,每个参数代表一个 BDD 场景。通过 scenarios,可以将多个场景组织在一起,并且可以在步骤函数中使用场景名称进行条件判断或其它处理。

我们可以使用scenarios的方式建立,参考如下:

# test_login.pyfr

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/18280.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 测试磁盘读写速度和内存读写速度.

import time import os # from SpeedTest import perform_default_speedtest# 测试硬盘读写速度 def test_disk_speed():filename "./testfile.bin"# 生成一个1GB大小的测试文件with open(filename, "wb") as f:f.write(os.urandom(1024*1024*1024))# 从…

C语言手撕单链表

一、链表的概念 链表是一种物理存储结构上非连续、非顺序的存储结构,也就是内存存储不是像顺序表那么连续存储,而是以结点的形式一块一块存储在堆上的(用动态内存开辟)。 既然在内存上不是连续存储,那我们如何将这一…

Qt/C++音视频开发50-不同ffmpeg版本之间的差异处理

一、前言 ffmpeg的版本众多,从2010年开始计算的项目的话,基本上还在使用的有ffmpeg2/3/4/5/6,最近几年版本彪的比较厉害,直接4/5/6,大版本之间接口有一些变化,特别是一些废弃接口被彻底删除了,…

浙大数据结构第六周之Saving James Bond - Easy Version

题目详情: This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the worlds most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake f…

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查

Django学习记录:使用ORM操作MySQL数据库并完成数据的增删改查 数据库操作 MySQL数据库pymysql Django开发操作数据库更简单,内部提供了ORM框架。 安装第三方模块 pip install mysqlclientORM可以做的事: 1、创建、修改、删除数据库中的…

【腾讯云 Cloud studio 实战训练营】搭建Next框架博客——抛开电脑性能在云端编程(沉浸式体验)

文章目录 ⭐前言⭐进入cloud studio工作区指引💖 注册coding账号💖 选择cloud studio💖 cloud studio选择next.js💖 安装react的ui框架(tDesign)💖 安装axios💖 代理请求跨域&#x…

动态爬虫IP与反爬虫技术的博弈:揭秘真实反爬虫事例引发的思考

作为一名长期从事爬虫行业动态IP解决方案服务商,我们深知动态IP代理在抗击反爬虫方面的重要性。在当今数字化时代,互联网数据的爆炸性增长让数据采集变得前所未有的重要。然而,随着数据价值的不断提升,反爬虫技术也日益增强&#…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(一)

说明:请先自行安装好docker再来看本篇文章,本篇文章主要实现通过使用docker部署mysql实现读写分离,并连接数据库测试。第二篇将实现使用Shardingjdbc实现springboot的读写分离实现。 基于Docker去创建Mysql的主从架构 #创建主从数据库文件夹…

Ubuntu 20.04 系统或图像界面卡死或完全无响应处理方法

Ubuntu 20.04 系统或图像界面卡死或完全无响应处理方法 问题背景无需重启方法安全重启方法 问题背景 Ubuntu 20.04在安装驱动程序时系统突然无响应,终端也无法运行;考虑到尽量不破坏系统,不希望强制上下电重启机器,以免损坏文件系…

版本控制和团队协作:前端工程化的关键要素

文章目录 版本控制系统介绍(如 Git)1. 分布式系统2. 分支管理3. 版本控制4. 快速和高效5. 社区和生态系统 分支管理和团队协作流程1. 主分支2. 功能分支3. 开发工作4. 合并到develop5. 发布准备6. 发布 持续集成与持续部署实践持续集成(CI&am…

【前端知识】React 基础巩固(三十七)——自定义connect高阶组件

React 基础巩固(三十七)——自定义connect高阶组件 一、手撸一个自定义connect高阶组件 import { PureComponent } from "react"; import store from "../store";/*** connect的参数:* 参数一: 函数* 参数二: 函数* 返…

lc1074.元素和为目标值的子矩阵数量

创建二维前缀和数组 两个for循环,外循环表示子矩阵的左上角(x1,y1),内循环表示子矩阵的右下角(x2,y2) 两个for循环遍历,计算子矩阵的元素总和 四个变量,暴力破解的时间复杂度为O(…

ChatGPT安全技术

前言 近期,Twitter 博主 lauriewired 声称他发现了一种新的 ChatGPT"越狱"技术,可以绕过 OpenAI 的审查过滤系统,让 ChatGPT 干坏事,如生成勒索软件、键盘记录器等恶意软件。 他利用了人脑的一种"Typoglycemia&q…

MySQL 5.7版本不支持ROW_NUMBER()函数

MySQL 5.7版本不支持ROW_NUMBER()函数。但是,你可以使用变量来手动实现这个功能。以下是一个示例查询语句: SELECT row_number:row_number1 AS row_num,column1, column2, ... FROM (SELECT row_number:0) AS t,your_table ORDER BY column1;在这个语句…

web3行业有哪些职业发展路径?

Web3 是一个相对较新的概念,因此其职业发展路径也在不断演变。一般来说,Web3 职业发展路径可以分为以下几个方向: 区块链开发工程师:区块链开发工程师需要掌握 Solidity 等语言和智能合约开发技能,负责开发和维护区块…

Vue.js2+Cesium 四、模型对比

Vue.js2Cesium 四、模型对比 Cesium 版本 1.103.0&#xff0c;低版本 Cesium 不支持 Compare 对比功能。 Demo 同一区域的两套模型&#xff0c;实现对比功能 <template><div style"width: 100%; height: 100%;"><divid"cesium-container"…

MTK联发科安卓核心板MT8385(Genio 500)规格参数资料_性能介绍

简介 MT8385安卓核心板 是一个高度集成且功能强大的物联网平台&#xff0c;具有以下主要特性&#xff1a; l 四核 Arm Cortex-A73 处理器 l 四核Arm Cortex-A53处理器 l Arm Mali™-G72 MP3 3D 图形加速器 (GPU)&#xff0c;带有 Vulkan 1.0、OpenGL ES 3.2 和 OpenCL™ 2.x …

tinyproxy搭建http代理

安装tinyproxy yum install tinyproxy 修改配置 vim /etc/tinyproxy/tinyproxy.conf # 允许任意ip访问 Allow 0.0.0.0/0 # 指定端口 ​​​​​​​Port 8888 常用配置 User nobody Group nobody# 绑定监听端口号 Port 8608 # 监听的网络接口 默认会监听所有的接口 #Liste…

Linux中的file命令:查看文件类型

2023年8月1日&#xff0c;周二上午 目录 简要说明使用方法MIME类型举例说明 简要说明 在Linux中&#xff0c;file命令用于识别文件类型。 file命令可以识别各种类型的文件&#xff0c;包括普通文件、目录、符号链接、设备文件、压缩文件、二进制可执行文件等。 它是一个非常…

云原生势不可挡,如何跳离云原生深水区?

云原生是云计算领域一大热词&#xff0c;伴随云原生概念而来的是数字产业迎来井喷、数字变革来临、数字化得以破局以及新一波的技术红利等等。云原生即“云”原生&#xff0c;顾名思义是让“应用”最大程度地利用云的能力&#xff0c;发挥云价值的最佳路径。具体来说&#xff0…