## pytest-bdd 的文件的命名规范
pytest-bdd 是基于pytest 之上,所以需要遵循pytest 的命名规则才能进行测试,具体有:
1. 测试文件名必须以*_test.py或者test_*.py命名
2. 测试函数必须以 test_开头
在pytest-bdd中存在两类文件:
1. 以 .feature 结尾的用户场景文件
2. 以 .py 结尾的测试代码。这里又细分为两类:
- 以 `@given`,`@when`,`@then` 注解的步骤函数,这些函数名没有强制限制, 也可以借鉴beheave的写法以 `step_`开头。
- 以 `@scenario` 注解的测试场景函数,这个函数名需要以 `test_` 开头, 因为这样才会被pytest 识别。
举例来看: `@given`,`@when`,`@then` 的步骤函数的示例:
```python
@pytest.fixture
@given("I have a calculator")
def calculator():
return Calculator()
@when(parsers.parse('I enter "{a}" and "{b}"'))
def enter_numbers(calculator, a, b):
calculator.a = int(a)
calculator.b = int(b)
@then(parsers.parse('the result should be "{result}"'))
def verify_result(calculator, result):
assert calculator.add(calculator.a, calculator.b) == int(result)
```
`@scenario` 注解的测试场景函数的示例:
```
@scenario('../features/calculator.feature','Add two numbers')
def test_add():
pass
```
* `@scenario` 本身没有实际的内容,只是一个占位符,关联场景和步骤,但是又不可少
### 关于 `@scenario`
`@scenario`是 pytest-bdd 框架中的一个装饰器,用于标记一个 BDD 场景并将其与编写的测试函数关联起来。
`@scenario`装饰器可以用来定义一个场景,并确定它所属的 feature 和 scenario。其语法如下:
~~~python
@scenario('<feature_file_path>', '<scenario_name>')
def test_my_scenario():
pass
~~~
其中,`<feature_file_path>`是 feature 文件的路径,`<scenario_name>`是场景的名称。在测试方法中不需要任何具体的测试步骤。相反,pytest-bdd 将自动加载与场景匹配的步骤,并在执行测试时逐步执行它们。这意味着测试方法本身只是一个占位符,其定义的唯一目的是将场景与步骤关联起来。
使用`@scenario`装饰器需要遵循一定的规则,如下:
1. 一个`@scenario`装饰器用于定义一个场景。
2. 必须指定该场景所属的 feature 文件的路径和场景名称。
3. 测试函数的名称必须与场景名称匹配。
4. 测试函数的参数必须与场景步骤的参数名称相匹配。
5. 测试函数必须使用 BDD 关键字来编写场景步骤。
6. pytest-bdd 将自动加载与场景匹配的步骤,并在执行测试时逐步执行它们。
7. 可以将多个场景分组在同一个 feature 文件中,并在同一个测试类中执行它们。
## 使用pytest-bdd的项目的目录结构
基于以上,目录的设计如下:
1..feature 场景文件放置在项目根目录的 features目录中。[非强制]
2. 步骤函数和场景函数可以放在一个.py文件中, 也可以放在两个 .py文件中。
3. 包含场景函数的.py 需要以test_ 开头 [强制]
4. 测试步骤的文件放置在项目根目录的steps 或step_defs 目录中[非强制]
5. 场景函数如果分拆出来,放置在根目录的 test_cases目录中[非强制]
6. 在基于面向对象的设计中,可以一个类一个场景文件, 也可以一个功能一个场景文件。[非强制]
基于以上原则,提供的几个目录结构示例如下:
### 目录结构1:
步骤函数和场景函数放在一起,一个功能一个场景文件:
```
├────features/ # 用户场景
│ ├────user/
│ │ ├────create_user.feature
│ ├────login.feature
├────step_defs/ # 步骤函数和测试场景
│ ├────user/
│ │ ├────test_create_user.py
│ └────test_login.py
```
### 目录结构2:
步骤函数和场景函数放在一起,一个类一个场景文件:
```
├────features/ # 用户场景
│ ├────user.feature
│ ├────login.feature
├────step_defs/ # 步骤函数和测试场景
│ ├────user.feature
│ └────test_login.py
```
### 目录结构3:
```
├────features/ # 用户场景
│ ├────user/
│ │ ├────create_user.feature
│ ├────login.feature
├────step_defs/ # 步骤函数
│ ├────user/
│ │ ├────create_user_steps.py
│ └────login_steps.py
├────test_case/ # 测试场景
│ ├────test_user/
│ │ ├────test_create_user.py
│ └────test_login.py
```
其他还可以用 cases和 test_cases 来命名,类似如下:
```
├────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
```
## 以测试角度出发的目录
上面的目录规范是将BDD的规范文件和测试作为独立的部分, 也有的项目从测试角度出发,将BDD的文件作为测试的一部分, 统一放入项目的tests 目录中,
```
|-- tests
| |-- features
| | |-- step_definitions
| | | |-- __init__.py
| | | |-- test_steps.py
| | |-- support
| | | |-- conftest.py
| | | |-- env.py
| | | |-- hooks.py
| | |-- feature1.feature
| | |-- feature2.feature
| |-- unit
| | |-- __init__.py
| | |-- test_module1.py
| | |-- test_module2.py
| |-- __init__.py
| |-- conftest.py
|-- setup.py
|-- requirements.txt
|-- README.md
```
* `tests`目录包含所有测试相关文件,其中`features`目录用于存放 BDD 测试用例和相关文件,`unit`目录用于存放其他类型的测试用例。
* `step_definitions`目录用于存放实现 BDD 测试用例步骤的 Python 脚本。每个 BDD 测试用例的步骤都应该在这里实现
* `support`目录用于存放 BDD 测试用例所需的支持文件,比如环境设置、钩子函数等。
* `conftest.py`文件放在`tests`目录下,用于实现项目级别的配置和夹具设置。
* `setup.py`文件是一个 Python 包的安装脚本。
* `requirements.txt`文件用于存储项目依赖库的清单。
* `README.md`文件是项目的说明文档。
如果从BDD的定义和作用来看的话,这种目录结构就有点混淆了 BDD和测试的概念,因为BDD是有终端用户参与进来的部分, 目录层级较深不利于使用,个人是比较不建议这种方式。
*****
*****
- 前言
- 1.入门篇
- Python介绍
- 安装与使用
- Python开发利器之VS Code
- 模块安装
- 命令行
- 一次Python无法安装模块的问题探索与解决之旅
- 命令运行
- Conda
- 下载地址
- 2.基础篇
- 基础语法
- 输入与输出
- with as的用法
- 注释
- Python命令行参数
- 编码
- 变量类型
- 列表遍历
- 运算符
- 表达式语句
- 条件
- 循环
- 日期和时间
- 函数
- 高级语法
- @符号-装饰器
- 模块和包
- name
- init.py
- 错误和异常
- 面向对象
- 3.专题篇
- 常用功能
- Python 字符串连接
- python web
- Python CGI编程
- Python OAuth2
- 认证 Flask-HTTPAuth
- 常用命令
- 内置函数
- dir()
- print(f)
- 标准模块
- sys
- pickle-数据序列化
- os
- IO(输入输出)
- 键盘输入
- 文件读写
- 测试
- Python测试框架之pytest快速入门
- pytest-bdd快速示例和问题解决
- 基于pytest-bdd的项目目录结构和命名规范
- python BDD 的相关概念
- Behave介绍和快速示例
- Python BDD之Behave测试报告
- Python BDD 框架比较之 pytest-bdd vs behave
- pytest进阶
- Flask + pytest测试
- 参考网址
- pytest-bdd进阶
- hehave进阶
- 测试路径
- python + selunium
- HTML 根据多层CSS 查找元素
- 等待执行
- 使用text 查找 span
- pytest如何在控制台输出
- 4.问题篇
- pip pip3 及区别
- TypeError: can only concatenate str (not "NoneType") to str
- 5.实战篇
- matplotlib-绘图包
- 导入类
- 命名规范
- 模块查找
- 6.进阶篇
- Flask
- Flask介绍
- Flask扩展模块
- Flask-Login
- 问题
- Jinja2
- Flask-RESTful
- Flask-JWT-Extended
- WSGI
- Flask-SQLAlchemy
- 部署
- Flask VS Django
- Flask Web
- Flask + Vue
- Flask实战
- Flask 标准目录结构
- Blueprints
- 参考
- FastAPI 测试
- https 证书 Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate