需要安装的包
allure-pytest 生成测试报告
pytest 测试
pytest-dependency 测试之间的依赖
pytest-ordering 测试排序
pytest-xdist 多进程测试
pytest-result-log 自动记录测试报告的日志
faker 生成moker数据
pytest-benchmark 基准测试
pytest.ini
[pytest]
# --dist=loadscope 是将同一个模块 (module) 或同一个测试类 (class) 下的测试分组,并将每个组发送给一个 worker。
# 这对于处理有依赖关系的测试(如使用 pytest-dependency )很有用,因为它确保同一个组的测试在同一个进程中执行
addopts = --alluredir=allure-results -n auto --dist=loadscope -v
testpaths = tests
python_files = test_*.py
log_cli = true
log_cli_level = INFO
# 避免中文输出乱码
console_output_style = classic
markers =
slow: mark标记
# 自动记录日志,配置
log_file = ./logs/pytest.log
log_file_level = info
log_file_format = %(levelname)-8s %(asctime)s [%(name)s:%(lineno)s] : %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S
# 设置打印日志的级别
result_log_level_verbose = info
conftest.py
import shutil
import pytest
#每次启动前 先把报告的目录清了
@pytest.hookimpl(tryfirst=True)
def pytest_configure():
shutil.rmtree("allure-results", ignore_errors=True)
test_pytest01.py
import pytest
import allure
def create_db_connection():
print("我是模块级别")
## 优先级 session_fixture → (module_fixture → class_fixture → function_fixture) × N → session_fixture清理
# session级别的不会自动执行,要么加上autouse,要么在下面的方法内传参
@pytest.fixture(scope="session", autouse=True)
def session_fixture():
print("\n===== 会话级前置操作 =====")
yield "shared_data"
print("\n===== 会话级清理操作 =====")
# 模块级别的fixture
@pytest.fixture(scope="module")
def db_connection():
conn = create_db_connection()
yield conn
# class级别的fixture
@pytest.fixture(scope="class")
def test_data(db_connection): # 依赖模块级fixture
print("我是class级别")
# 方法级别的fixture
@pytest.fixture(scope="function")
def test_method():
print("我是方法级别-前")
yield
print("我是方法级别-后")
# 测试类
# 可以在class层面使用fixture数据
@pytest.mark.usefixtures("test_data")
@allure.severity(allure.severity_level.CRITICAL) # 严重等级
@allure.tag("核心功能", "支付") # 标签
@allure.link("https://example.com/api-docs", name="接口文档") # 文档链接
@allure.issue("BUG-1234", "问题") # 关联的问题单
@allure.testcase("TC-001", "测试用例") # 关联的测试用例
@allure.epic("示例项目") # 系统级别分类
@allure.feature("计算功能") # 功能模块分类
@allure.story("加法场景") # 具体用户故事
@allure.title("加法用例 - 正常情况") # 测试用例标题
@allure.description("""### 描述内容-md""")
class TestIntegration:
@pytest.mark.dependency(name="count_test") # 设置这个函数是被依赖的函数
@pytest.mark.run(order=1) # 设置这个函数最先执行,可以用 pytest-ordering 也可以用dependency这个插件,order更简单,直接
def test_count(self, test_method):
assert 0 < 1
@pytest.mark.dependency(depends=["count_test"]) # 配置依赖其他函数
def test_content(self, test_method, test_data):
assert "SELECT" in "SELECT * FROM test_table"
@pytest.mark.parametrize(
["a", "b", "result"],
[
[1, 2, 5],
[2, 3, 5],
[5, 3, 8],
],
)
def test_foo(self, a, b, result, session_fixture):
assert foo(a, b) == result
@allure.title("加法测试 - 正常情况")
def test_add(self):
"""加法测试:1 + 1 = 2"""
with allure.step("步骤1:计算 1 + 1"):
result = 1 + 1
with allure.step("步骤2:断言结果等于2"):
assert result == 2, "加法结果应为2"
@allure.title("除法用例 - 异常情况")
def test_divide_zero(self):
"""除法测试:1 / 0 应抛出异常"""
with allure.step("步骤1:尝试计算 1 / 0"):
with pytest.raises(ZeroDivisionError):
_ = 1 / 0
with allure.step("步骤2:断言抛出 ZeroDivisionError"):
assert True
# 加法,模拟测试方法
def foo(a, b):
return a + b
if __name__ == '__main__':
pytest.main(["test_pytest01.py", "-s"])
压力测试,类似go的testing.B
def pytest_generate_tests(metafunc):
if "iter_count" in metafunc.fixturenames:
metafunc.parametrize("iter_count", [10, 100, 1000], indirect=True)
def test_benchmark(iter_count):
for _ in range(iter_count):
# 被测逻辑
assert sum(range(10)) == 45