【自动化测试】Pytest框架详细使用指南,附实际案例及代码
Pytest 框架详细使用指南
一、 Pytest 是什么?为什么选择它?
Pytest 是一个基于 Python 的成熟、功能丰富的测试框架。它几乎可以用于所有类型和级别的软件测试。
核心优势:
-
简单易上手:用例编写简单,断言使用标准的
assert语句,无需学习更多 API。 -
功能强大:支持参数化、Fixture(夹具)、重运行失败用例、分布式执行等高级功能。
-
丰富的插件生态:拥有庞大的插件系统(如
pytest-html生成报告,pytest-xdist并行执行,pytest-rerunfailures重试失败用例等)。 -
兼容性好:可以运行 unittest, nose 等传统测试框架的用例。
二、 环境搭建与安装
在开始之前,请确保你的系统已安装 Python。然后通过 pip 安装 Pytest。
bash
# 安装 pytest pip install pytest # 验证安装,查看版本 pytest --version
三、 第一个测试用例:从编写到运行
1. 创建项目结构
创建一个清晰的目录结构是良好实践的开始。
text
my_pytest_project/ ├── tests/ # 专门存放测试用例的目录 │ └── test_sample.py └── README.md
2. 编写第一个测试用例
在 tests/test_sample.py 中编写以下代码:
python
# 待测试的函数(通常放在另一个文件,这里为了演示方便)
def add(a, b):
return a + b
# Pytest 测试用例
# 规则1:测试文件以 `test_` 开头或结尾
# 规则2:测试类以 `Test` 开头
# 规则3:测试函数/方法以 `test_` 开头
def test_add():
# 使用简单的 assert 语句进行断言
assert add(1, 2) == 3
assert add(-1, 1) == 0
assert add(0, 0) == 0
# 一个预期会失败的用例
def test_add_fail():
assert add(1, 1) == 3 # 这个断言会失败
3. 运行测试
在项目根目录 my_pytest_project/ 下打开终端/命令行。
bash
# 最基本运行方式:运行当前目录及子目录所有 test_*.py 文件里的所有 test_* 函数 pytest # 运行指定文件 pytest tests/test_sample.py # 运行指定文件中的指定用例(通过函数名匹配) pytest tests/test_sample.py::test_add # verbose 模式,输出更详细信息 pytest -v # 运行后,你会看到输出结果,清晰地显示通过、失败、错误的状态。
运行 pytest -v 后,你将看到类似如下输出:
text
========================= test session starts =========================
collected 2 items
tests/test_sample.py::test_add PASSED [ 50%]
tests/test_sample.py::test_add_fail FAILED [100%]
============================== FAILURES ===============================
_____________________________ test_add_fail ____________________________
def test_add_fail():
> assert add(1, 1) == 3 # 这个断言会失败
E assert 2 == 3
E + where 2 = add(1, 1)
tests/test_sample.py:15: AssertionError
======================= short test summary info =======================
FAILED tests/test_sample.py::test_add_fail - assert 2 == 3
===================== 1 failed, 1 passed in 0.10s =====================
四、 核心功能详解与实战
1. Fixture(夹具):测试的“基石”
Fixture 是 Pytest 最核心的功能。它用于为测试用例提供预置环境(如数据库连接、测试数据)和清理工作。
-
使用
@pytest.fixture装饰器定义 -
通过在测试函数参数列表中声明夹具名称来使用
python
# tests/test_fixture.py
import pytest
# 定义一个简单的 Fixture,返回一个列表
@pytest.fixture
def my_list():
print("\n(Setting up the list fixture)") # setup 部分
yield [1, 2, 3] # 这是测试用例实际拿到的值
print("\n(Tearing down the list fixture)") # 可选的 teardown 部分
# 使用 Fixture:只需将夹具函数名作为参数传入
def test_list_length(my_list):
assert len(my_list) == 3
def test_list_sum(my_list):
assert sum(my_list) == 6
运行 pytest -v -s tests/test_fixture.py (-s 用于显示 print 语句的输出)。
-
autouse参数:让夹具自动执行,无需显示声明。python
@pytest.fixture(autouse=True) def auto_fixture(): print("\nThis runs automatically for every test in this module!") -
scope参数:控制夹具的作用域(function(默认),class,module,package,session)。python
@pytest.fixture(scope="module") # 整个模块只执行一次 def db_connection(): conn = create_expensive_connection() yield conn conn.close() -
conftest.py:一个神奇的配置文件,用于存放全局共享的 Fixture。Pytest 会自动发现它。-
在项目根目录或任何子目录创建
conftest.py -
将 Fixture 移入其中,所有同级及子目录的测试文件均可直接使用,无需导入。
-
2. 参数化测试:一个用例,多组数据
使用 @pytest.mark.parametrize 装饰器,避免写大量重复代码来测试不同输入。
python
# tests/test_parametrize.py
import pytest
# 待测试函数
def is_even(n):
return n % 2 == 0
# 参数化:第一个参数是字符串,表示参数名;第二个参数是数据列表
@pytest.mark.parametrize("number, expected", [
(2, True),
(1, False),
(0, True),
(-1, False),
(-2, True),
])
def test_is_even(number, expected):
assert is_even(number) == expected
运行后,Pytest 会将这组数据展开成 5 个独立的测试用例执行。
3. Mark(标记):对测试用例进行分类
Mark 可以用来做跳过(skip)、预期失败(xfail)、自定义分组等。
python
# tests/test_mark.py
import pytest
import sys
@pytest.mark.skip(reason="This feature is broken, skipping for now.")
def test_skipped():
assert False
@pytest.mark.skipif(sys.version_info < (3, 8), reason="Requires Python 3.8+")
def test_skipif():
assert True
# 预期会失败,如果测试通过了,报告为 XPASS;失败了,报告为 XFAIL
@pytest.mark.xfail
def test_expected_to_fail():
assert False
# 自定义标记,比如标记为“慢测试”
@pytest.mark.slow
def test_slow_integration():
# ... some slow code ...
assert True
运行特定标记的用例:pytest -v -m slow tests/test_mark.py
4. 断言细节:Pytest 会告诉你为什么失败
Pytest 重写了断言,提供了极其清晰的失败信息。对于复杂数据结构(如列表、字典)的对比,效果尤其明显。
python
def test_complex_assertion():
actual_result = {"name": "Alice", "age": 30, "hobbies": ["coding", "hiking"]}
expected_result = {"name": "Bob", "age": 30, "hobbies": ["reading", "hiking"]}
assert actual_result == expected_result
运行这个用例,Pytest 会高亮显示字典中不匹配的键值对,非常利于调试。
五、 实战:搭建一个简单的 Web UI 自动化测试(以 Selenium 为例)
让我们把上面的知识用起来,模拟一个真实场景。
1. 安装依赖
bash
pip install pytest selenium # 记得下载对应的浏览器驱动(如 chromedriver)并放到 PATH 下
2. 项目结构
text
my_web_test_project/ ├── conftest.py # 全局 Fixture ├── tests/ │ ├── __init__.py │ └── test_google_search.py └── requirements.txt
3. 编写 conftest.py(共享浏览器驱动)
python
# conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture(scope="session") # 整个测试会话只启动一次浏览器
def browser():
options = Options()
options.headless = True # 无头模式,不打开浏览器UI
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
yield driver
# Teardown:所有测试结束后,关闭浏览器
driver.quit()
4. 编写测试用例 test_google_search.py
python
# tests/test_google_search.py
import pytest
# 使用 conftest.py 中定义的 browser fixture
def test_google_search_title(browser):
browser.get("https://www.google.com")
assert "Google" in browser.title
# 参数化搜索关键词
@pytest.mark.parametrize("keyword", ["pytest", "selenium", "python"])
def test_google_search(browser, keyword):
browser.get("https://www.google.com")
search_box = browser.find_element_by_name("q")
search_box.send_keys(keyword)
search_box.submit()
# 简单断言搜索结果页面标题包含关键词
assert keyword in browser.title
5. 运行并生成报告
bash
# 运行所有测试 pytest -v # 安装 html 报告插件后运行 pip install pytest-html pytest --html=report.html
六、 常用配置与命令
-
配置文件
pytest.ini:放在项目根目录,用于配置默认行为。ini
# pytest.ini [pytest] addopts = -v --html=report.html # 默认命令行参数 testpaths = tests # 测试目录 markers = slow: marks tests as slow (deselect with '-m "not slow"') -
常用命令:
-
pytest -k "add":运行名称中包含 "add" 的用例。 -
pytest --maxfail=2:失败2个用例后停止测试。 -
pytest -x:遇到第一个失败就停止。 -
pytest --tb=short:简化错误回溯信息。
-
总结与下一步
恭喜!你现在已经掌握了 Pytest 的核心概念:
-
基础:用例编写规则、断言、运行命令。
-
核心:Fixture(
conftest.py,scope,autouse)和参数化。 -
进阶:Mark 标记、插件系统、配置文件。
给你的学习建议:
-
动手:把上面的例子全部敲一遍,并确保能运行成功。
-
改造:尝试用 Pytest 去改写你之前用 unittest 或自己写的测试脚本。
-
探索插件:尝试使用
pytest-html,pytest-xdist(并行测试),pytest-rerunfailures(失败重试)等常用插件。 -
集成:学习如何将 Pytest 集成到 CI/CD 工具(如 Jenkins, GitLab CI)中。
Pytest 的生态系统非常丰富,官方文档是最好的朋友:pytest documentation
更多推荐
所有评论(0)