目录
- [1 何为测试框架?](#1 何为测试框架?)
- [2 Pytest框架简介](#2 Pytest框架简介)
- [3 快速上手](#3 快速上手)
-
- [3.1 Pytest安装与启动](#3.1 Pytest安装与启动)
- [3.2 读懂Pytest执行结果](#3.2 读懂Pytest执行结果)
-
- [3.2.1 代码示例及结果解读](#3.2.1 代码示例及结果解读)
- [3.2.2 Pytest用例结果](#3.2.2 Pytest用例结果)
- [4 用例规则](#4 用例规则)
-
- [4.1 用例发现规则](#4.1 用例发现规则)
- [4.2 用例内容规则](#4.2 用例内容规则)
- [5 框架配置方法](#5 框架配置方法)
- [6 标记mark](#6 标记mark)
-
- [6.1 用户自定义标记:测试用例分类与分组](#6.1 用户自定义标记:测试用例分类与分组)
- [6.2 框架内置标记](#6.2 框架内置标记)
-
- [6.2.1 parametrize 参数化](#6.2.1 parametrize 参数化)
- [6.2.2 skip 无条件跳过](#6.2.2 skip 无条件跳过)
- [6.2.3 skipif 有条件跳过](#6.2.3 skipif 有条件跳过)
- [6.2.4 xfail 预期失败](#6.2.4 xfail 预期失败)
- [6.2.5 usefixtures:使用fixtures](#6.2.5 usefixtures:使用fixtures)
- [7 数据驱动测试](#7 数据驱动测试)
- [8 夹具fixture](#8 夹具fixture)
-
- [8.1 如何创建fixture](#8.1 如何创建fixture)
- [8.2 如何使用fixture](#8.2 如何使用fixture)
- [8.3 fixture高级用法](#8.3 fixture高级用法)
- 写在最后
1 何为测试框架?
框架指的是抽象出来的工具集合,提供大量的组件、工具、功能,测试框架通常包括如下几种功能:
- 用例发现
- 用例管理
- 环境管理
- 用例执行
- 测试报告
常见的测试框架如下:
- java:junit,testng
- python:unittest,pytest
2 Pytest框架简介
Pytest 是一个成熟的 Python 测试框架,广泛用于单元测试、集成测试和功能测试。它以简单易用、灵活强大著称,能够显著提升测试效率。
主要特点如下:
- 简单易上手: 语法简洁,支持基本断言(assert),无需复杂配置即可快速编写测试用例。
- 强大的插件生态: 可通过插件扩展功能,如生成 HTML 报告(pytest-html)、集成持续工具(如 Jenkins)或支持异步测试。
- 灵活的执行控制: 支持参数化测试、测试跳过、失败重跑(--reruns)以及分组执行(通过 @pytest.mark 标记)。
- 详细报告与集成: 能生成自定义报告(如 Allure 或 XML 格式),便于分析测试结果并与 CI/CD 流程结合。
基本使用规则
- 命名规范:测试文件需以
test_开头或_test结尾;测试类名以 Test 开头且无 init 方法;测试方法名以 test_ 开头。 - 执行方式:可通过命令行直接运行(如 pytest -vs),或通过配置文件(如 pytest.ini)定义默认参数(如测试路径、标记等)

3 快速上手
3.1 Pytest安装与启动
bash
pip install pytest # 安装pytest
pip install pytest -U # 已经安装过pytest,升级到最新版
启动方式有如下三种:
- 命令行方式
bash
pytest # 在文件所在目录命令行执行
- 代码
python
import pytest
pytest.main()
- 鼠标点击Pycharm启动按钮(不推荐)

3.2 读懂Pytest执行结果
3.2.1 代码示例及结果解读
首先我们先编写如下两个用例示例:
python
def test_list():
a = list('aaaaaa')
b = list('aaaabc')
assert a == b
def test_dict():
a = {"a": 1, "b": 2, "c": 3}
b = {"a": 2, "b": 2, "c": 3}
assert a == b
执行后结果如下:
D:\Anaconda3\envs\pytest\python.exe D:/git-code/python/python/my_pytest/main.py
============================= test session starts =============================
platform win32 -- Python 3.8.20, pytest-8.3.5, pluggy-1.5.0
rootdir: D:\git-code\python\python\my_pytest
collected 2 items
test_data.py FF [100%]
================================== FAILURES ===================================
__________________________________ test_list __________________________________
def test_list():
a = list('aaaaaa')
b = list('aaaabc')
> assert a == b
E AssertionError: assert ['a', 'a', 'a', 'a', 'a', 'a'] == ['a', 'a', 'a', 'a', 'b', 'c']
E
E At index 4 diff: 'a' != 'b'
E Use -v to get more diff
test_data.py:4: AssertionError
__________________________________ test_dict __________________________________
def test_dict():
a = {"a": 1, "b": 2, "c": 3}
b = {"a": 2, "b": 2, "c": 3}
> assert a == b
E AssertionError: assert {'a': 1, 'b': 2, 'c': 3} == {'a': 2, 'b': 2, 'c': 3}
E
E Omitting 2 identical items, use -vv to show
E Differing items:
E {'a': 1} != {'a': 2}
E Use -v to get more diff
test_data.py:10: AssertionError
=========================== short test summary info ===========================
FAILED test_data.py::test_list - AssertionError: assert ['a', 'a', 'a', 'a', ...
FAILED test_data.py::test_dict - AssertionError: assert {'a': 1, 'b': 2, 'c':...
============================== 2 failed in 0.08s ==============================
Process finished with exit code 0
- 执行环境:版本、根目录、用例数量

- 执行过程:文件名称、用例执行结果、执行进度

- 失败详情:用例内容、断言提示,描述用例错误原因

- 整体摘要:执行结果、花费时间等

3.2.2 Pytest用例结果
| 缩写 | 单词 | 含义 |
|---|---|---|
| . | passed | 通过 |
| F | failed | 失败(执行用例时报错) |
| E | error | 出错(fixture执行报错) |
| s | skipped | 跳过 |
| X | xpassed | 预期外的通过(不符合预期) |
| x | xfailed | 预期内的失败(符合预期) |
4 用例规则
4.1 用例发现规则
测试框架在识别、加载用例的过程,即为:用例发现
Pytest发现用例的步骤如下:
- 遍历所有目录,除了.开头以及虚拟环境venv的目录
- 打开python文件,识别的python文件需要以 test_ 开头或者以 _test.py 结尾
- 遍历所有以Test开头的类
- 收集所有 test_ 开头的方法
4.2 用例内容规则
文件名规则
文件名需以 test_*.py 或 *_test.py 的格式命名,即要么以 test_ 开头,要么以 _test.py 结尾,例如 test_example.py 或者 example_test.py 这类文件名可以被 Pytest 当作测试用例文件发现
函数名规则
若文件中存在以 test_ 开头的函数,也会被识别为测试用例。比如 test_function() 这样的函数就符合要求
类名规则
类名要以 Test 开头,并且类中不能包含 __init__ 方法。此类下以 test_ 开头的方法也会被当作测试用例。例如 TestClass 类中的 test_method() 方法就会被 Pytest 发现
其他规则
- 所有的包(package)必须要有
__init__.py文件。 - 断言使用 assert 语句
5 框架配置方法
通过配置框架来改变Pytest的默认规则
- 命令参数
- pytest.ini 文件
可以通过命令行的方式,查看如何配置
bash
pytest -h
下面对一些常见的配置简要介绍
常用参数
- -v :增加详细chegndu
- -s :在用例中正常的使用输入和输出
- -x :快速退出,当遇到失败的用例停止执行
- -m :用例筛选
6 标记mark
pytest mark 是 Pytest 框架中一个强大的功能,可用于对测试用例进行分类、分组、参数化、跳过执行等操作,进而实现对测试用例的精细控制与管理。
6.1 用户自定义标记:测试用例分类与分组
使用 @pytest.mark.<your_marker> 可对测试用例进行分类与分组,在运行测试时依据这些分类来选择或排除测试用例。例如,使用 @pytest.mark.smoke 标记的测试用例属于冒烟测试,运行 pytest -m "smoke" 可只运行冒烟测试;运行 pytest -m "not slow" 可排除耗时用例;运行 pytest -m "smoke or slow" 可执行冒烟测试或耗时测试用例
用户自定义标记实现用例筛选的步骤如下:
-
先在 pytest.ini 注册标记
[pytest]
markers =
api: 接口测试
web: UI测试
ut: 单元测试

-
使用
@pytest.mark.<your_marker>标记用例

-
筛选执行
bash
pytest -m api # 只执行api接口用例

6.2 框架内置标记
框架内置标记无需手动注册,按照框架要求使用即可。不同的标记,可以增加不同的特殊效果。
6.2.1 parametrize 参数化
@pytest.mark.parametrize 可使用不同的输入数据多次执行相同的测试逻辑,以扩大测试覆盖范围。
python
import pytest
@pytest.mark.parametrize("username, password, expected", [
("admin", "secret", True), # 有效凭证
("admin", "wrong", False), # 无效密码 (也属于核心流程)
])
def test_admin_login(username, password, expected):
result = login(username, password)
assert result == expected
上述代码中,test_admin_login 测试函数被参数化,使用两组数据覆盖了管理员登录的成功和失败场景。
在第7章节,数据驱动测试我们还会使用到该注解。
6.2.2 skip 无条件跳过
使用 @pytest.mark.skip 可以无条件跳过测试函数。
python
import pytest
@pytest.mark.skip(reason="功能尚未实现,等待后续开发")
def test_new_feature():
# 这个测试会被跳过
assert True
@pytest.mark.skip
def test_deprecated_function():
# 这个测试也会被跳过,没有提供原因
assert False
运行结果示例:
pytest -r s .\test_mark_skip.py # 只运行某个py文件,同时显示跳过的详细信息

6.2.3 skipif 有条件跳过
使用 @pytest.mark.skipif 可以根据条件跳过测试。
python
import pytest
import sys
# 根据Python版本跳过
@pytest.mark.skipif(sys.version_info < (3, 8),
reason="需要Python 3.8或更高版本")
def test_python38_feature():
# 只在Python 3.8+上运行
assert True
# 根据操作系统跳过
@pytest.mark.skipif(sys.platform == "win32",
reason="Windows系统不支持此功能")
def test_unix_only_feature():
# 只在Unix-like系统上运行
assert True
# 根据外部依赖跳过
pytest.importorskip("requests", reason="需要requests库")
@pytest.mark.skipif(not pytest.importorskip("numpy", reason="需要numpy库"),
reason="numpy不可用")
def test_numpy_functionality():
import numpy as np
assert np.array([1, 2, 3]).sum() == 6
# 自定义条件
def is_development_environment():
import os
return os.getenv("ENV") == "development"
@pytest.mark.skipif(not is_development_environment(),
reason="仅在开发环境中运行")
def test_development_only():
assert True
6.2.4 xfail 预期失败
使用 @pytest.mark.xfail标记预期失败的测试。
python
import pytest
# 预期失败但没有提供原因
@pytest.mark.xfail
def test_known_bug():
assert 1 + 1 == 3 # 已知的bug,预期会失败
# 预期失败并说明原因
@pytest.mark.xfail(reason="已知bug:修复中,issue #123")
def test_buggy_function():
# 这个函数有已知问题,预期会失败
result = calculate_something()
assert result == expected_value
def calculate_something():
return 42
# 预期失败但如果通过了则视为失败(严格模式)
@pytest.mark.xfail(strict=True, reason="这个bug肯定没修复")
def test_strict_xfail():
assert False # 如果这个测试意外通过了,会被标记为失败
# 条件性预期失败
@pytest.mark.xfail(sys.version_info < (3, 9),
reason="Python 3.9以下版本有兼容性问题")
def test_version_specific_feature():
# 在某些版本下预期失败
assert True
# 在测试函数内部动态标记为预期失败
def test_runtime_xfail():
try:
result = risky_operation()
assert result is not None
except NotImplementedError:
pytest.xfail("功能尚未实现")
def risky_operation():
raise NotImplementedError("还在开发中")
运行结果示例:
collected 4 items
test_example.py xxxx [100%]
4 xfailed in 0.02s
6.2.5 usefixtures:使用fixtures
使用 @pytest.mark.usefixtures为测试函数指定fixtures,无需在函数参数中声明。以下是代码示例,在第8章节夹具fixture中,将会着重介绍。
python
import pytest
# 定义一些fixtures
@pytest.fixture
def database():
print("\n设置数据库连接")
yield "database_connection"
print("清理数据库连接")
@pytest.fixture
def authenticated_user():
print("\n创建认证用户")
yield {"username": "testuser", "id": 123}
print("清理用户数据")
@pytest.fixture
def temp_file():
import tempfile
import os
fd, path = tempfile.mkstemp()
os.close(fd)
yield path
os.unlink(path)
# 使用单个fixture
@pytest.mark.usefixtures("database")
def test_database_operations():
# 不需要在参数中声明database fixture
# 但可以访问其他fixture
assert True
# 使用多个fixtures
@pytest.mark.usefixtures("database", "authenticated_user")
def test_user_operations():
# 同时使用database和authenticated_user fixtures
assert True
# 在类级别使用fixtures
@pytest.mark.usefixtures("temp_file")
class TestFileOperations:
def test_read_file(self):
# 所有测试方法都会使用temp_file fixture
assert True
def test_write_file(self):
assert True
# 在模块级别使用fixtures(在conftest.py中或文件顶部)
pytestmark = pytest.mark.usefixtures("database")
def test_module_level_test():
# 这个测试也会使用database fixture
assert True
# 混合使用:参数fixtures和标记fixtures
def test_mixed_fixtures(authenticated_user, temp_file):
# authenticated_user通过参数传入
# temp_file通过usefixtures标记使用
assert authenticated_user["username"] == "testuser"
# 也可以在测试函数内部使用其他fixtures
@pytest.mark.usefixtures("database")
def test_with_additional_fixture(authenticated_user):
# database通过标记使用,authenticated_user通过参数使用
assert True
7 数据驱动测试
数据驱动测试 = 参数化测试 + 数据文件,即根据数据文件的内容,动态决定用例的数量、内容。会用到标记中的 @pytest.mark.parametrize 。以下例子将会以一个csv文件格式,演示代码示例。
-
创建一个数据文件,例如 data.csv
a,b,c
1,1,2
2,3,5
3,3,6
4,4,7 -
编写读取csv文件的方法
python
import csv
def read_csv(path):
f = open(path)
try:
reader = csv.reader(f)
data = list(reader)[1:] # 跳过标题行
return data
finally:
f.close()
- 编写用例
python
import pytest
from get_csv import read_csv
def add(a, b):
return int(a) + int(b)
@pytest.mark.parametrize(
"a, b, c",
read_csv("data.csv")
)
def test_add(a, b, c):
res = add(a, b)
assert res == int(c)
- 执行用例,查看结果,csv的4组参数,都被正确执行

8 夹具fixture
夹具,即在用例执行之前或者执行之后,自动运行代码,有如下几种场景示例:
- 之前:加密参数 / 之后:解密结果
- 之前:启动浏览器 / 之后:关闭浏览器
- 之前:构造数据 / 之后:删除数据
8.1 如何创建fixture
- 创建方法/函数
- 添加装饰器
@pytest.fixture - 添加 yield 关键字
python
@pytest.fixture
def method():
# 前置操作
yield # 开始执行用例
# 后置操作
8.2 如何使用fixture
使用fixture有两种方式
方式一:在用例的参数列表中,加入 fixture 的方法名即可
python
import pytest
@pytest.fixture
def f():
# 前置操作
yield # 开始执行用例
# 后置操作
def test_xxx(f):
assert True
方式二:使用 @pytest.mark.usefixtures 为测试函数指定fixtures,无需在函数参数中声明
python
import pytest
@pytest.fixture
def f():
# 前置操作
yield # 开始执行用例
# 后置操作
@pytest.mark.usefixtures('f')
def test_xxx():
assert True
8.3 fixture高级用法
1.自动使用
当多个用例都需要执行fixture时,可以不必每个用例都显示声明usefixtures,可以在编写fixture的时候通过autouse参数实现,示例代码如下:
python
from datetime import datetime
import pytest
@pytest.fixture(autouse=True)
def f():
# 前置操作
print(datetime.now(), "用例开始执行")
yield
# 后置操作
print(datetime.now(), "用例执行完毕")
def test_f1():
assert True
def test_f2():
assert True

2.依赖使用
fixture不仅仅能被用例使用,也可被fixture依赖使用,示例代码如下:
python
import pytest
@pytest.fixture()
def process():
print("处理数据完成")
@pytest.fixture()
def f(process):
print("用例执行前")
yield
print("用例执行后")
@pytest.mark.usefixtures('f')
def test_f():
assert True

3.返回内容
定义的fixture可以有返回内容,被测试用例使用
(1)基本使用方式:
- 将fixture名称作为测试函数的参数
- pytest会自动注入fixture的返回值
- 可以直接在测试函数中使用fixture返回的数据或对象
(2)最佳实践:
- fixture应该返回具体的、可用的数据或对象
- 避免在fixture中执行复杂的业务逻辑
- 使用yield而不是return时,yield后面的代码会在测试结束后执行
- 可以在测试函数中组合使用多个fixture
示例代码如下:
python
import pytest
@pytest.fixture
def sample_data():
"""返回测试数据的fixture"""
return {
"username": "test_user",
"password": "test123",
"email": "test@example.com"
}
@pytest.fixture
def calculator():
"""返回简单计算器对象的fixture"""
class SimpleCalculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def multiply(self, a, b):
return a * b
def divide(self, a, b):
if b == 0:
raise ValueError("除数不能为零")
return a / b
return SimpleCalculator()
@pytest.fixture
def user_list():
"""返回用户列表的fixture"""
return [
{"id": 1, "name": "张三", "age": 25},
{"id": 2, "name": "李四", "age": 30},
{"id": 3, "name": "王五", "age": 28}
]
@pytest.fixture
def database_connection():
"""模拟数据库连接的fixture"""
class MockDatabase:
def __init__(self):
self.connected = True
self.data = {}
def execute(self, query):
return f"执行查询: {query}"
def close(self):
self.connected = False
conn = MockDatabase()
yield conn # 使用yield,测试结束后会执行清理
conn.close()
# 测试函数使用fixture返回的数据
def test_sample_data_fixture(sample_data):
"""测试sample_data fixture返回的数据"""
assert sample_data["username"] == "test_user"
assert sample_data["password"] == "test123"
assert sample_data["email"] == "test@example.com"
print(f"用户名: {sample_data['username']}")
def test_calculator_fixture(calculator):
"""测试calculator fixture返回的计算器对象"""
result_add = calculator.add(5, 3)
assert result_add == 8
result_subtract = calculator.subtract(10, 4)
assert result_subtract == 6
result_multiply = calculator.multiply(3, 7)
assert result_multiply == 21
result_divide = calculator.divide(15, 3)
assert result_divide == 5.0
# 测试除零异常
with pytest.raises(ValueError, match="除数不能为零"):
calculator.divide(10, 0)
def test_user_list_fixture(user_list):
"""测试user_list fixture返回的用户列表"""
assert len(user_list) == 3
assert user_list[0]["name"] == "张三"
assert user_list[1]["age"] == 30
assert user_list[2]["id"] == 3
# 测试查找功能
user = next(u for u in user_list if u["name"] == "李四")
assert user["age"] == 30
def test_database_connection_fixture(database_connection):
"""测试database_connection fixture返回的数据库连接"""
assert database_connection.connected == True
result = database_connection.execute("SELECT * FROM users")
assert "SELECT * FROM users" in result
print(f"数据库查询结果: {result}")
# 测试多个fixture的组合使用
def test_multiple_fixtures(sample_data, calculator, user_list):
"""测试多个fixture的组合使用"""
# 使用sample_data中的数据进行计算
age = sample_data["password"][-3:] # 从密码中提取数字"123"
age_int = int(age)
# 使用calculator进行计算
result = calculator.add(age_int, len(user_list))
assert result == 126 # 123 + 3
print(f"计算结果: {result}")
@pytest.fixture
def config_data():
"""返回配置数据的fixture"""
return {
"database": {
"host": "localhost",
"port": 5432,
"name": "test_db"
},
"api": {
"base_url": "https://api.example.com",
"timeout": 30,
"retries": 3
},
"debug": True
}
def test_config_fixture(config_data):
"""测试配置数据fixture"""
assert config_data["database"]["host"] == "localhost"
assert config_data["database"]["port"] == 5432
assert config_data["api"]["base_url"] == "https://api.example.com"
assert config_data["debug"] == True
# 测试嵌套数据访问
db_config = config_data["database"]
assert f"{db_config['host']}:{db_config['port']}" == "localhost:5432"

4.范围共享
Fixture是pytest提供的一种自动化机制,用于在测试用例执行前后运行特定代码。在UI自动化测试中,如果每个用例都单独执行打开和关闭浏览器的操作,会造成巨大的性能开销。通过将fixture的scope配置为session级别,可以在整个测试会话中共享同一个浏览器实例,所有测试用例复用该前置和后置操作,从而显著提升测试效率。
(1) 作用域类型:
- function(默认):每个测试函数执行一次
- class:每个测试类执行一次
- module:每个模块执行一次
- package:每个包执行一次
- session:整个测试会话执行一次
(2) 使用方式:
python
@pytest.fixture(scope="作用域类型")
def fixture_name():
return 数据或对象
示例代码如下:
python
import pytest
# Function作用域(默认)- 每个测试函数都会重新执行
@pytest.fixture(scope="function")
def function_data():
"""Function作用域的fixture - 每个测试函数都创建新实例"""
print("\n创建function_data")
return {"id": 1, "name": "function测试"}
# Class作用域 - 每个测试类执行一次
@pytest.fixture(scope="class")
def class_data():
"""Class作用域的fixture - 每个测试类执行一次"""
print("\n创建class_data")
return {"id": 2, "name": "class测试"}
# Module作用域 - 每个模块执行一次
@pytest.fixture(scope="module")
def module_data():
"""Module作用域的fixture - 每个模块执行一次"""
print("\n创建module_data")
return {"id": 3, "name": "module测试"}
# Session作用域 - 整个测试会话执行一次
@pytest.fixture(scope="session")
def session_data():
"""Session作用域的fixture - 整个测试会话执行一次"""
print("\n创建session_data")
return {"id": 4, "name": "session测试"}
# 测试function作用域
def test_function_scope_1(function_data):
"""测试function作用域 fixture"""
print(f"test_function_scope_1: {function_data}")
assert function_data["id"] == 1
def test_function_scope_2(function_data):
"""测试function作用域 fixture - 会重新创建"""
print(f"test_function_scope_2: {function_data}")
assert function_data["id"] == 1
# 测试class作用域
class TestClassScope:
def test_class_scope_1(self, class_data):
"""测试class作用域 fixture"""
print(f"test_class_scope_1: {class_data}")
assert class_data["id"] == 2
def test_class_scope_2(self, class_data):
"""测试class作用域 fixture - 共享同一实例"""
print(f"test_class_scope_2: {class_data}")
assert class_data["id"] == 2
class TestClassScope2:
def test_class_scope_3(self, class_data):
"""测试class作用域 fixture - 新类会重新创建"""
print(f"test_class_scope_3: {class_data}")
assert class_data["id"] == 2
# 测试module作用域
def test_module_scope_1(module_data):
"""测试module作用域 fixture"""
print(f"test_module_scope_1: {module_data}")
assert module_data["id"] == 3
def test_module_scope_2(module_data):
"""测试module作用域 fixture - 共享同一实例"""
print(f"test_module_scope_2: {module_data}")
assert module_data["id"] == 3
# 测试session作用域
def test_session_scope_1(session_data):
"""测试session作用域 fixture"""
print(f"test_session_scope_1: {session_data}")
assert session_data["id"] == 4
def test_session_scope_2(session_data):
"""测试session作用域 fixture - 共享同一实例"""
print(f"test_session_scope_2: {session_data}")
assert session_data["id"] == 4
# 混合作用域测试
class TestMixedScopes:
def test_mixed_scopes(self, function_data, class_data, module_data, session_data):
"""测试混合作用域 fixture"""
print(f"混合作用域测试:")
print(f" function: {function_data}")
print(f" class: {class_data}")
print(f" module: {module_data}")
print(f" session: {session_data}")
assert function_data["id"] == 1
assert class_data["id"] == 2
assert module_data["id"] == 3
assert session_data["id"] == 4
# Package作用域示例(需要包结构)
@pytest.fixture(scope="package")
def package_data():
"""Package作用域的fixture - 每个包执行一次"""
print("\n创建package_data")
return {"id": 5, "name": "package测试"}
def test_package_scope(package_data):
"""测试package作用域 fixture"""
print(f"test_package_scope: {package_data}")
assert package_data["id"] == 5
实际使用中,作用域会被命名空间限制,例如在同一目录下不同的py文件定义的fixture可能无法被找到。因此,在实际开发中,我们常常引入第三命名空间,即新建一个conftest.py文件来统一声明fixture
写在最后
以上便是本文的全部内容啦!创作不易,如果你有任何问题,欢迎私信,感谢您的支持!
