【Pytest】基础到高级功能的理解使用
文章目录
- 第一部分:Pytest 简介
- 1.1 什么是 Pytest?
- 1.2 Pytest 的历史
- 1.3 Pytest 的核心概念
- 1.4 Pytest 的特点
- 1.5 为什么选择 Pytest?
- 第二部分:Pytest 的基本使用
- 2.1 安装 Pytest
- 2.2 编写第一个测试用例
- 2.2.1 创建一个简单的测试函数
- 2.2.2 运行测试
- 2.3 测试报告和输出
- 2.3.1 简单输出
- 2.3.2 显示详细的失败信息
- 2.3.3 生成 HTML 报告
- 2.4 组织和运行多个测试
- 2.4.1 测试文件和测试函数命名约定
- 2.4.2 运行特定的测试用例
- 2.5 断言与调试
- 2.5.1 常见断言示例
- 2.5.2 调试断言失败
- 2.6 夹具(Fixtures)介绍
- 2.6.1 创建一个夹具
- 2.6.2 夹具的作用范围
- 第三部分:Pytest的高级功能
- 3.1 参数化测试(Parametrized Tests)
- 3.1.1 使用 @pytest.mark.parametrize 进行测试
- 3.1.2 参数化测试的使用场景
- 3.2 模拟与测试(Mocking)
- 3.2.1 使用 unittest.mock 模块
- 3.2.2 使用 pytest-mock 插件
- 3.3 测试配置(Configuration)
- 3.3.1 配置文件 pytest.ini
- 3.3.2 使用命令行选项
- 3.4 并行测试(Parallel Testing)
- 3.4.1 使用 pytest-xdist 插件
- 3.4.2 并行测试的配置与使用
- 第四部分:Pytest 插件
- 4.1 自定义插件
- 4.1.1 创建自己的 pytest 插件
- 插件创建步骤:
- 示例:创建一个简单的插件,添加一个命令行选项
- 4.1.2 插件的安装与使用
- 4.2 常用插件介绍
- 4.2.1 pytest-cov:代码覆盖率报告
- 4.2.2 pytest-html:生成 HTML 格式的测试报告
- 4.2.3 pytest-flake8:集成 flake8 代码检查
- 第五部分:Pytest 与持续集成(CI)
- 5.1 Jenkins 集成
- 5.1.1 使用 Jenkins 运行 pytest 测试
- 5.1.2 Jenkins 中配置 pytest 插件
- 5.2 GitHub Actions 集成
- 5.2.1 在 GitHub Actions 中设置 pytest 测试
- 5.2.2 自动化测试报告
- 第六部分:Pytest 常见问题解答
- 6.1 如何处理测试超时
- 6.1.1 使用 pytest-timeout 插件
- 6.2 如何跳过测试
- 6.2.1 使用 @pytest.mark.skip 和 @pytest.mark.skipif
- 6.3 如何收集测试数据
- 6.3.1 使用 pytest-cov 生成测试覆盖率报告
- 附件
- pytest 命令行参数
第一部分:Pytest 简介
1.1 什么是 Pytest?
pytest
是一个功能强大的 Python 测试框架,专为编写简单、可扩展的测试而设计。它是 Python 中最受欢迎的测试工具之一,广泛应用于单元测试、集成测试以及功能测试等领域。pytest
提供了清晰易懂的语法,并且可以轻松与其他测试框架(如 unittest
)兼容使用。
1.2 Pytest 的历史
pytest
由 Holger Krekel 于 2004 年首次发布,它的起源可以追溯到其前身 py.test
。pytest
在最初发布时就力图通过简化测试代码,使其易于使用,并且随着时间的推移,逐渐添加了大量功能和优化。
- 2004:
py.test
项目发布,提供了基础的测试框架。 - 2010:项目更名为
pytest
,并开始引入插件支持。 - 2015:
pytest
开始成为 Python 测试领域的领先工具,并逐渐广泛应用于工业界和开源项目中。
通过不断更新和增加特性,pytest
逐步成为 Python 最常用的测试框架之一,并且被许多开发者和团队广泛采用。
1.3 Pytest 的核心概念
在使用 pytest
进行测试时,我们需要理解几个核心概念:
1. 测试函数与测试类
- 测试函数:
pytest
会自动识别以test_
开头的函数,并将它们视为测试用例。我们可以直接使用 Python 内建的assert
语句来验证某些条件。 - 测试类:可以通过在类中定义以
test_
开头的方法来组织测试用例。类本身可以没有初始化方法或有必要的设置和清理工作。
2. 断言(Assertions)
断言是 pytest
测试框架的核心。我们通过 assert
语句来验证一个表达式是否成立。例如:
def test_addition():result = 2 + 3assert result == 5 # 如果结果不等于5,测试会失败
在 pytest
中,断言语法非常简单直接,并且可以非常清晰地显示出失败的原因,便于调试。
3. 夹具(Fixtures)
pytest
中的夹具(Fixtures)是用来准备和清理测试所需资源的组件。它可以自动处理一些资源的初始化和销毁,比如数据库连接、文件操作等。夹具可以在多个测试函数之间共享,从而减少代码的重复。
4. 参数化(Parametrization)
通过 参数化测试,可以用不同的输入数据执行同一测试方法。pytest
支持通过 @pytest.mark.parametrize
装饰器将参数化的测试逻辑应用到函数中,这在处理需要多次执行的相似测试时非常有用。
1.4 Pytest 的特点
pytest
拥有许多使其成为开发者首选测试框架的特性:
简单易用
pytest
的最大特点之一是它的简洁性。通过仅使用 Python 内建的 assert
语法,可以编写简单的测试用例。同时,它不需要复杂的配置和设置,可以立即开始编写和执行测试。
自动化测试发现
pytest
会自动发现符合命名规则的测试文件和测试函数。默认情况下,pytest
会查找以 test_
开头的函数,并执行其中的代码。
- 测试文件:以
test_
开头,或者以_test.py
结尾的 Python 文件。 - 测试函数:以
test_
开头的函数。
例如,pytest
会自动发现并执行以下文件中的测试:
test_example.py
test_calculator.py
丰富的插件支持
pytest
有一个强大的插件系统,可以扩展其功能。例如,pytest-html
可以生成 HTML 格式的测试报告,pytest-xdist
可以并行运行测试用例,pytest-cov
可以进行代码覆盖率报告等。
高度可扩展
pytest
支持通过 夹具(Fixtures)、标记(Marks)、插件(Plugins) 等方式扩展框架功能。它能够处理复杂的测试场景,满足各种不同的需求。
支持并行测试
pytest
可以通过插件支持并行执行测试用例,从而显著提高大规模测试的效率。例如,使用 pytest-xdist
插件,可以将测试分发到多个 CPU 核心进行并行执行。
与其他测试框架兼容
pytest
可以兼容 unittest
测试框架,即可以在使用 pytest
的同时继续使用旧有的 unittest
测试用例。pytest
还提供了适配器,以便将其他测试框架(如 nose
)的测试迁移到 pytest
中。
高质量的测试报告
pytest
默认会以简单的文本格式显示测试结果,但它还可以生成更详细的报告,包括失败的详细信息、调试提示等。如果我们希望生成 HTML 格式的报告,也可以使用插件来实现。
1.5 为什么选择 Pytest?
以下是一些开发者选择 pytest
的常见原因:
- 简洁和易学:由于
pytest
使用标准的 Python 断言语法,学习曲线非常平缓。开发者可以快速上手并编写有效的测试。 - 强大的功能:即使是最复杂的测试需求,
pytest
也能够处理。通过插件、夹具等特性,pytest
支持多种高级用法。 - 良好的社区支持:
pytest
拥有一个活跃的社区,几乎任何问题都有现成的解决方案或资源。 - 提高开发效率:通过自动化测试和集成工具,
pytest
能够帮助开发者更快地定位问题,并提高软件开发效率。
第二部分:Pytest 的基本使用
2.1 安装 Pytest
在开始使用 pytest
之前,首先需要安装它。可以通过 Python 的包管理工具 pip
来安装:
pip install pytest
安装完成后,可以通过以下命令验证 pytest
是否安装成功:
pytest --version
如果安装成功,会显示 pytest
的版本信息。
2.2 编写第一个测试用例
安装好 pytest
,我们就可以开始编写测试用例。pytest
会自动识别所有以 test_
开头的函数或文件,并将其视为测试用例。
2.2.1 创建一个简单的测试函数
首先,在一个新的 Python 文件中(例如 test_sample.py
),编写一个简单的测试函数:
# test_sample.pydef test_addition():assert 2 + 3 == 5def test_subtraction():assert 114514 - 1919 == 112595
在这个例子中,我们创建了两个测试函数 test_addition
和 test_subtraction
,并在其中使用了 assert
语句来验证基本的数学运算。
2.2.2 运行测试
通过命令行运行 pytest
,它会自动识别并执行以 test_
开头的测试函数。
pytest test_sample.py
运行后,pytest
会列出所有测试的结果。例如:
=========================== test session starts ============================
collected 2 itemstest_sample.py .. [100%]============================ 2 passed in 0.03 seconds =====================
这里的 ..
表示两个测试都通过了。测试通过后,pytest
会输出相关的通过信息,并且可以选择性地生成更详细的报告。
2.3 测试报告和输出
默认情况下,pytest
输出测试结果到控制台,包括测试是否通过、失败以及跳过的测试等。我们还可以使用以下选项来修改输出的详细程度:
2.3.1 简单输出
运行 pytest
时,添加 -q
参数可以减少输出的详细程度,输出更为简洁:
pytest -q test_sample.py
这将只显示测试的摘要信息,如下所示:
.. [100%]
2.3.2 显示详细的失败信息
当测试失败时,pytest
会自动显示失败的详细信息。例如,如果在 test_addition
中断言失败,pytest
会给出详细的错误信息和调试提示,帮助开发者快速定位问题。
> assert 2 + 3 == 6
E assert 5 == 6
2.3.3 生成 HTML 报告
还可以通过 pytest
插件生成 HTML 格式的报告。首先,安装 pytest-html
插件:
pip install pytest-html
然后,运行 pytest
并指定生成报告的输出文件:
pytest --html=report.html
这样,测试结果将保存在 report.html
文件中,并可以通过浏览器查看详细的测试报告。
2.4 组织和运行多个测试
2.4.1 测试文件和测试函数命名约定
pytest
会自动发现符合一定命名规则的测试用例。默认的命名规则是:
- 测试文件:以
test_
开头,或者以_test
结尾的 Python 文件。 - 测试函数:以
test_
开头的函数。
例如,以下文件和函数会被 pytest
自动发现并运行:
- 文件:
test_example.py
,example_test.py
- 函数:
test_addition()
,test_subtraction()
2.4.2 运行特定的测试用例
通过文件名或函数名可以指定运行特定的测试,类似cpp命名空间的用法。例如,运行 test_addition
函数:
pytest test_sample.py::test_addition
这样,pytest
只会执行 test_addition
函数,而不会执行文件中的其他测试函数。
2.5 断言与调试
pytest
默认使用 Python 内建的 assert
语句来进行断言,这使得测试代码非常简洁。通过断言,pytest
可以验证期望的结果是否与实际结果一致。
2.5.1 常见断言示例
-
比较数字:
def test_addition():assert 2 + 3 == 5
-
比较字符串:
def test_string():assert "Hello" == "Hello"
-
检查是否抛出异常:
pytest
允许检查某个操作是否会抛出异常。例如,验证除以零时是否抛出ZeroDivisionError
:import pytestdef test_zero_division():with pytest.raises(ZeroDivisionError):1 / 0
2.5.2 调试断言失败
当 assert
语句失败时,pytest
会显示失败的断言表达式,并给出失败的提示。为了调试失败的测试,还可以在运行时使用 pytest
的 -s
选项,这样就可以在失败的地方查看输出或交互式调试。
pytest -s test_sample.py
2.6 夹具(Fixtures)介绍
pytest
的夹具是用来在测试运行之前或之后执行某些准备工作和清理工作的。通过夹具,可以实现数据库连接、文件创建等操作,并在多个测试之间共享这些资源。
2.6.1 创建一个夹具
夹具通过 @pytest.fixture
装饰器创建。以下是一个简单的夹具示例:
import pytest@pytest.fixture
def setup_data():data = {"name": "Alice", "age": 30}return datadef test_name(setup_data):assert setup_data["name"] == "Alice"def test_age(setup_data):assert setup_data["age"] == 30
在上面的示例中,setup_data
是一个夹具,它会在每个测试函数运行之前自动提供数据。
2.6.2 夹具的作用范围
夹具的作用范围(scope)可以通过 scope
参数来设置,常见的范围有:
function
:每个测试函数都会创建新的夹具实例(默认)。module
:每个模块只会创建一次夹具实例。session
:在整个测试会话期间只会创建一个夹具实例。
例如,创建一个模块级别的夹具:
@pytest.fixture(scope="module")
def setup_database():# 设置数据库连接db = create_db_connection()yield db # 测试执行完毕后关闭数据库连接db.close()
第三部分:Pytest的高级功能
3.1 参数化测试(Parametrized Tests)
3.1.1 使用 @pytest.mark.parametrize 进行测试
@pytest.mark.parametrize
是 Pytest 提供的一个装饰器,用于实现参数化测试。通过它,我们可以对同一个测试用例提供多个不同的输入数据,这样每次运行测试时都会用不同的参数执行,避免重复编写多个测试函数。
import pytest# 参数化测试,test_addition 会分别用 (1, 2, 3) 和 (4, 5, 9) 这两个数据集来执行
@pytest.mark.parametrize("a, b, expected", [(1, 2, 3), (4, 5, 9), (7, 8, 15)])
def test_addition(a, b, expected):assert a + b == expected
上面的代码中,@pytest.mark.parametrize
使得 test_addition
测试函数能够接受三个参数 a
, b
和 expected
,并且每个参数集分别对应 (1, 2, 3)
、(4, 5, 9)
和 (7, 8, 15)
。运行时,Pytest 会为每组输入值自动执行该测试。
3.1.2 参数化测试的使用场景
参数化测试通常适用于以下几种场景:
-
多组输入输出验证:当我们需要验证函数或方法的多个输入和输出时,可以使用参数化来减少代码重复。例如,测试一个加法函数对于多个输入的行为。
-
多种边界条件的测试:测试时需要覆盖多个边界条件(如最大值、最小值、负值等),使用参数化可以很容易地针对每个边界值进行验证。
-
提升测试效率:当测试数据量大时,参数化可以将相似的测试代码合并成一个测试用例,提高测试的效率与可读性。
3.2 模拟与测试(Mocking)
3.2.1 使用 unittest.mock 模块
在进行单元测试时,我们可能会遇到外部依赖的情况(例如数据库查询、API 请求等),为了避免这些外部依赖影响测试的独立性,我们通常需要模拟这些外部依赖。
Python 提供了 unittest.mock
模块来创建模拟对象,并替代真正的外部依赖。下面是一个使用 unittest.mock
模块的示例:
from unittest.mock import MagicMock
import requestsdef fetch_data(url):response = requests.get(url)return response.json()def test_fetch_data():mock_response = MagicMock()mock_response.json.return_value = {"key": "value"}# 模拟 requests.get 返回模拟的响应对象with patch('requests.get', return_value=mock_response):result = fetch_data('http://example.com')assert result == {"key": "value"}
在上面的代码中,patch
用来模拟 requests.get
方法,使得 fetch_data
方法使用的是模拟的响应对象,而不是实际进行网络请求。
3.2.2 使用 pytest-mock 插件
pytest-mock
是一个为 Pytest 提供更友好接口的插件,它基于 unittest.mock
,但更加简化了模拟操作。使用 pytest-mock
,可以直接在测试函数中通过 mocker
fixture 来进行模拟。
import requestsdef fetch_data(url):response = requests.get(url)return response.json()def test_fetch_data(mocker):mock_response = mocker.Mock()mock_response.json.return_value = {"key": "value"}# 使用 mocker 模拟 requests.getmocker.patch('requests.get', return_value=mock_response)result = fetch_data('http://example.com')assert result == {"key": "value"}
在这个示例中,mocker.patch
替代了 requests.get
方法并返回模拟的响应对象,整个过程更加简洁和易读。
3.3 测试配置(Configuration)
3.3.1 配置文件 pytest.ini
pytest.ini
是一个配置文件,允许我们在项目根目录下定义一些 Pytest 的全局配置选项,比如测试时使用的标记、日志级别、插件等。一个常见的 pytest.ini
配置文件如下:
[pytest]
# 定义自定义标记
markers =slow: 标记为慢速测试smoke: 标记为冒烟测试# 设置默认的日志级别
log_cli_level = INFO# 配置插件
addopts = --maxfail=1 --disable-warnings
在上面的示例中,我们定义了两种标记 slow
和 smoke
,同时设置了日志级别和命令行选项。
3.3.2 使用命令行选项
Pytest 提供了多个命令行选项,方便我们在运行测试时指定一些配置参数。下面列举几个常用的命令行选项:
-v
:显示详细的测试输出。-k
:根据表达式过滤测试函数名。--maxfail
:指定最大失败次数,超过该次数后停止运行。--disable-warnings
:禁用警告信息。
例如:
pytest -v --maxfail=2 --disable-warnings
此命令会运行所有测试,并且如果有超过两次失败就停止,且不显示警告信息。
详细的pytest命令行选项
3.4 并行测试(Parallel Testing)
3.4.1 使用 pytest-xdist 插件
pytest-xdist
插件允许我们在多个 CPU 核心上并行运行测试,从而提高测试效率。通过安装并配置 pytest-xdist
,我们可以使用命令行选项 -n
来指定并行测试的数量。
首先,安装插件:
pip install pytest-xdist
然后,使用以下命令来运行并行测试:
pytest -n 4
这条命令会在 4 个并行进程中执行测试,从而提高运行速度。
3.4.2 并行测试的配置与使用
在并行测试时,我们可以通过 pytest-xdist
来进一步配置,如控制测试的并发数、并行运行时避免共享状态等。
例如,运行时,如果需要隔离测试的状态,可以使用 --dist
和 --tx
选项来进行更多控制:
pytest -n 4 --dist=loadscope --tx ssh=remotehost//python=python3
这个命令表示使用 4 个进程来运行测试,并将每个进程的负载均匀分配到每个核心。通过 --tx
选项,可以将测试分发到远程主机上进行并行运行。
第四部分:Pytest 插件
4.1 自定义插件
4.1.1 创建自己的 pytest 插件
创建 Pytest 插件可以帮助扩展 Pytest 的功能,例如自定义命令行选项、配置、测试钩子等。Pytest 插件一般由两个部分组成:一个是定义插件行为的 Python 代码,另一个是一个配置文件(通常是 pytest.ini
或其他配置文件)。
插件创建步骤:
- 创建一个 Python 文件:在项目根目录或
conftest.py
中编写插件代码。 - 实现钩子函数:Pytest 插件通过钩子函数(hook functions)来定制功能。常见的钩子函数包括
pytest_runtest_protocol
、pytest_configure
等。 - 注册插件:插件通过
pytest_plugins
在conftest.py
或pytest.ini
中进行注册。
示例:创建一个简单的插件,添加一个命令行选项
- 创建一个 Python 文件
myplugin.py
,并实现一个命令行选项:
# myplugin.py
import pytestdef pytest_addoption(parser):parser.addoption("--myoption", action="store", default="default_value", help="Custom option")@pytest.fixture
def myoption(request):return request.config.getoption("--myoption")
- 在测试文件中使用这个选项:
def test_with_option(myoption):assert myoption == "default_value"
- 使用
pytest.ini
来注册插件:
# pytest.ini
[pytest]
plugins =myplugin
通过上面的步骤,创建了一个简单的插件,它为 Pytest 添加了一个名为 --myoption
的命令行选项。
4.1.2 插件的安装与使用
自定义插件可以通过 Pytest 配置文件进行注册,或者直接安装并在测试运行时启用。如果开发了一个插件并想要安装和使用它(nb),可以将插件发布到 PyPI(Python 包索引)中,然后通过 pip install
安装。以下是安装和使用插件的基本步骤:
-
安装插件:
pip install pytest-myplugin
-
启用插件:在
pytest.ini
或conftest.py
中注册插件,或在命令行通过-p
选项指定插件。pytest -p myplugin
这样,就可以在 Pytest 中使用自定义插件了。
4.2 常用插件介绍
4.2.1 pytest-cov:代码覆盖率报告
pytest-cov
插件用于生成代码覆盖率报告,帮助开发者了解代码的测试覆盖情况。它集成了 coverage.py
,并能够输出多种格式的报告,如终端输出、HTML 或 XML。
安装:
pip install pytest-cov
使用:
-
命令行选项:可以通过
--cov
选项来指定要进行覆盖率检查的模块或包。pytest --cov=my_module
这条命令会运行
my_module
的测试并生成代码覆盖率报告。 -
生成 HTML 报告:
可以通过
--cov-report
选项指定生成的报告格式。例如,生成 HTML 格式的覆盖率报告:pytest --cov=my_module --cov-report html
这会在当前目录下生成一个
htmlcov
文件夹,其中包含了 HTML 格式的代码覆盖率报告。 -
多项覆盖率报告:还可以同时输出多种格式的报告:
pytest --cov=my_module --cov-report html --cov-report term
这将同时生成 HTML 和终端格式的报告。
4.2.2 pytest-html:生成 HTML 格式的测试报告
pytest-html
插件用于生成漂亮的 HTML 测试报告,包含测试结果的详细信息,如每个测试用例的执行状态、日志、截图等。
安装:
pip install pytest-html
使用:
-
生成 HTML 测试报告:
运行测试并生成一个
report.html
文件:pytest --html=report.html
-
自定义报告标题和描述:
可以通过
--self-contained-html
选项生成一个独立的 HTML 文件,其中包含所有的资源(如 CSS 和 JavaScript),使报告文件更具可移植性:pytest --html=report.html --self-contained-html
-
自定义报告内容:
pytest-html
允许在报告中加入自定义的内容(如测试前后的钩子):# conftest.py def pytest_html_report_title(report):report.title = "Custom Test Report"
这样,生成的报告标题会被替换为 “Custom Test Report”。
4.2.3 pytest-flake8:集成 flake8 代码检查
pytest-flake8
插件集成了 flake8
工具,允许运行 Pytest 测试时自动检查代码的样式问题(如 PEP 8 规范)。如果代码违反了样式规则,Pytest 会报告出错的地方。
安装:
pip install pytest-flake8
使用:
-
运行 Flake8 检查:
在运行测试时,Pytest 会自动执行
flake8
检查:pytest --flake8
-
配置 Flake8 选项:可以通过在项目根目录下创建
.flake8
配置文件来调整 Flake8 的行为:# .flake8 [flake8] max-line-length = 120
通过这个配置文件,可以调整行长度限制或其他
flake8
的设置。
第五部分:Pytest 与持续集成(CI)
在持续集成(CI)流程中,Pytest 可与 Jenkins、GitHub Actions 等工具集成,自动化执行测试并生成报告,帮助团队确保代码质量和快速发现潜在问题。
5.1 Jenkins 集成
Jenkins 是一款广泛使用的自动化服务器,支持构建、部署、测试等各种自动化任务。通过在 Jenkins 中集成 Pytest,可以实现自动化测试,确保代码在每次更改后都经过验证。
5.1.1 使用 Jenkins 运行 pytest 测试
-
安装 Jenkins 和必要的插件
- 安装 Jenkins 服务器,并确保已经安装了必要的插件,如 Pipeline、Git 等。
- 如果要使用 Pytest 的代码覆盖率插件,可以安装 Coverage 插件。
-
设置 Jenkins 任务
可以通过创建一个新任务或配置现有任务来运行 Pytest 测试。假设已经有一个 Git 仓库,并且测试代码存在于该仓库中。
- 在 Jenkins 中,点击 新建任务,然后选择 自由风格项目。
- 在 构建触发器 部分,可以选择例如 GitHub webhook,以便每次代码更改时自动触发构建。
-
配置构建步骤
在 构建 部分,可以添加一个执行 Shell 或批处理命令的步骤来运行 Pytest。
如果要使用虚拟环境,可以通过以下命令在构建中运行 Pytest:
# 激活虚拟环境 source venv/bin/activate # 或者其他合适的命令# 安装依赖 pip install -r requirements.txt# 运行 pytest pytest --maxfail=1 --disable-warnings -q
还可以根据需要修改
pytest
命令,如生成 HTML 或 JUnit 格式的报告。 -
运行构建
保存并启动构建,Jenkins 将会自动执行测试,并在控制台输出测试结果。
5.1.2 Jenkins 中配置 pytest 插件
-
安装 Pytest 插件
Jenkins 提供了一些插件,可以与 Pytest 集成,特别是 JUnit 插件,它可以解析 Pytest 生成的 JUnit 格式的测试结果,并在 Jenkins 中展示。可以通过以下步骤来配置:
-
在 Jenkins 上的任务配置界面,选择 构建后操作。
-
添加 发布JUnit测试报告 步骤。
-
在测试报告 XML 文件路径中,填入 Pytest 生成的 JUnit 格式报告路径。例如:
pytest --junitxml=report.xml
这将生成一个
report.xml
文件,其中包含测试的详细信息,Jenkins 可以解析这个文件并在界面上展示测试结果。
-
-
配置 HTML 报告
如果希望生成更美观的 HTML 测试报告,可以使用
pytest-html
插件,并将生成的 HTML 文件发布到 Jenkins:-
使用以下命令生成 HTML 格式的报告:
pytest --html=report.html
-
然后,可以将 HTML 文件通过 Jenkins 任务的 构建后操作 上传并作为构建的输出文件查看。
-
5.2 GitHub Actions 集成
GitHub Actions 是 GitHub 提供的一种自动化 CI/CD 服务,能够在代码提交时自动运行测试、部署应用等。它能够无缝集成 Pytest,以确保每次提交都经过测试验证。
5.2.1 在 GitHub Actions 中设置 pytest 测试
-
创建 GitHub Actions 配置文件
GitHub Actions 的配置文件是 YAML 格式,通常存放在项目中的
.github/workflows
文件夹下。创建一个新的文件pytest.yml
,并添加以下内容:name: Run Pyteston:push:branches:- mainpull_request:branches:- mainjobs:test:runs-on: ubuntu-lateststeps:- name: Check out the repositoryuses: actions/checkout@v2- name: Set up Pythonuses: actions/setup-python@v2with:python-version: '3.8'- name: Install dependenciesrun: |python -m pip install --upgrade pippip install -r requirements.txt- name: Run Pytestrun: |pytest --maxfail=1 --disable-warnings -q
这个配置会在代码推送或拉取请求时,自动在 GitHub Actions 上运行 Pytest 测试。
-
解析测试结果
如果希望 GitHub Actions 在每次运行后报告测试结果,可以配置 Pytest 生成 JUnit 格式的报告并使用 GitHub Actions 的 JUnit 测试结果解析器:
在
pytest.yml
中添加以下步骤:- name: Run Pytest and generate JUnit reportrun: |pytest --junitxml=test_results.xml- name: Upload JUnit test resultsuses: actions/upload-artifact@v2with:name: pytest-resultspath: test_results.xml
这样,测试结果将被上传为构建工件,可以在 GitHub Actions 界面上查看。
5.2.2 自动化测试报告
-
生成并上传 HTML 报告
如果希望生成更详细和美观的 HTML 格式测试报告,可以使用
pytest-html
插件,并将报告作为构建工件上传:- name: Install pytest-htmlrun: pip install pytest-html- name: Run Pytest with HTML reportrun: pytest --html=report.html- name: Upload HTML reportuses: actions/upload-artifact@v2with:name: pytest-html-reportpath: report.html
这样,每次运行测试后都能获取一个详细的 HTML 测试报告,并且可以通过 GitHub Actions 界面下载和查看该报告。
-
可视化测试结果
如果想将 Pytest 结果直接以图形化的方式显示在 GitHub Actions 界面上,可以使用第三方工具或插件(如 pytest-azure-pipelines)来集成更丰富的报告和通知功能,提供更加可视化的测试反馈。
通过将 Pytest 集成到持续集成系统中(如 Jenkins 或 GitHub Actions),可以在每次代码变更后自动执行测试,并生成详细的报告,从而确保软件质量。自动化测试能够帮助团队快速发现并修复问题,从而提高开发效率。
第六部分:Pytest 常见问题解答
在使用 Pytest 进行自动化测试时,开发人员可能会遇到一些常见问题,如测试超时、跳过某些测试和收集测试覆盖率等。以下是解决这些问题的一些方法。
6.1 如何处理测试超时
有时候,某些测试可能会因某些原因超时(如依赖外部服务或执行较复杂的操作)。为了解决这个问题,可以使用 pytest-timeout
插件来设置测试的超时时间。
6.1.1 使用 pytest-timeout 插件
pytest-timeout
插件可以为每个测试设置超时时间,并在超时后强制终止该测试。
-
安装插件
要使用
pytest-timeout
插件,首先需要通过 pip 安装:pip install pytest-timeout
-
配置超时设置
可以在命令行中设置超时,也可以使用装饰器在测试函数中配置超时。
-
在命令行中设置超时:
可以通过
--timeout
参数为所有测试设置超时。例如,设置每个测试的超时时间为 10 秒:pytest --timeout=10
-
使用装饰器设置超时:
还可以使用
@pytest.mark.timeout
装饰器为单个测试或测试类设置超时时间。例如,设置某个特定测试的超时时间为 5 秒:import pytest@pytest.mark.timeout(5) def test_example():# 测试逻辑assert True
-
-
处理超时异常
默认情况下,当超时发生时,
pytest-timeout
会抛出一个TimeoutError
,并将该测试标记为失败。可以通过--timeout-method
参数设置超时处理方式:exit
: 在超时后立刻终止测试。signal
: 使用操作系统信号终止超时测试。thread
: 通过线程来中止测试。
示例:
pytest --timeout=10 --timeout-method=exit
6.2 如何跳过测试
在某些情况下,可能希望跳过某些测试,或者根据条件决定是否执行某些测试。Pytest 提供了两种常见的跳过方法:@pytest.mark.skip
和 @pytest.mark.skipif
。
6.2.1 使用 @pytest.mark.skip 和 @pytest.mark.skipif
-
使用
@pytest.mark.skip
跳过测试如果希望强制跳过某个测试,可以使用
@pytest.mark.skip
装饰器。被装饰的测试将始终跳过,不会被执行。import pytest@pytest.mark.skip(reason="暂时跳过这个测试") def test_example():assert 1 == 1
在上面的例子中,
test_example
测试会被跳过,并且在测试报告中显示跳过的原因。 -
使用
@pytest.mark.skipif
根据条件跳过测试如果只希望在特定条件下跳过测试,可以使用
@pytest.mark.skipif
装饰器。该装饰器接受一个条件表达式,只有当该条件为真时,测试才会被跳过。例如,假设希望仅在 Python 版本低于 3.7 时跳过某个测试:
import pytest@pytest.mark.skipif(pytest.__version__ < "3.7", reason="Python 版本低于 3.7,跳过测试" ) def test_example():assert 1 == 1
在这个例子中,如果 pytest 版本低于 3.7,
test_example
测试将被跳过。
6.3 如何收集测试数据
测试数据的收集对确保代码覆盖率以及了解测试的执行情况至关重要。Pytest 提供了多种方法来收集和分析测试数据。
6.3.1 使用 pytest-cov 生成测试覆盖率报告
pytest-cov
插件用于收集代码覆盖率数据,并生成相应的报告。它允许查看测试执行期间代码的覆盖情况,帮助我们发现未被测试到的代码部分。
-
安装 pytest-cov 插件
首先,需要安装
pytest-cov
插件:pip install pytest-cov
-
运行测试并生成覆盖率报告
运行 Pytest 时,可以通过
--cov
参数指定希望收集覆盖率的代码文件或模块。例如,收集my_module
模块的代码覆盖率:pytest --cov=my_module
该命令会执行测试,并在控制台输出覆盖率报告。
-
生成详细的覆盖率报告
如果希望将覆盖率报告输出为 HTML 格式,可以使用
--cov-report
参数:pytest --cov=my_module --cov-report=html
这将生成一个
htmlcov
目录,其中包含一个详细的 HTML 格式的覆盖率报告。 -
生成其他格式的报告
除了 HTML 格式,还可以生成其他格式的报告(如
xml
或term
),以便于进一步的分析或与其他工具集成:-
生成 XML 格式的报告:
pytest --cov=my_module --cov-report=xml
-
在终端中输出覆盖率统计信息:
pytest --cov=my_module --cov-report=term
-
-
配置覆盖率的阈值
可以配置覆盖率阈值,确保覆盖率达到预期。例如,设置最低的覆盖率为 80%:
pytest --cov=my_module --cov-fail-under=80
如果覆盖率低于 80%,测试将失败。
附件
pytest 命令行参数
参数 | 描述 |
---|---|
-q 或 --quiet | 简化输出,显示最简洁的测试结果。 |
-v 或 --verbose | 显示详细输出,包括每个测试用例的名称和状态。 |
-k | 选择性运行匹配特定表达式的测试,如 -k "test_name" 。 |
-x 或 --exitfirst | 第一个测试失败时立即停止执行。 |
--maxfail=num | 设置最大失败次数,超过后停止执行,如 --maxfail=3 。 |
-s | 显示标准输出和错误输出。 |
--disable-warnings | 禁用警告信息的显示。 |
--tb=short 或 --tb=long | 设置错误回溯信息的显示方式,short 显示简洁回溯,long 显示详细回溯。 |
--html=report.html | 生成 HTML 格式的测试报告,保存为 report.html 。 |
--maxfail=NUM | 设置最大失败数,达到时停止测试。 |
--capture=no | 禁止捕获测试输出,显示实时输出。 |
--runxfail | 即使标记为“预期失败”的测试失败,也将其视为成功。 |
--tb=auto | 根据测试结果自动选择回溯信息的展示方式。 |
--junitxml=path | 输出 JUnit 风格的 XML 测试报告到指定路径。 |
--pdb | 测试失败时启用 Python 调试器 (pdb),可以进行交互式调试。 |
相关文章:

【Pytest】基础到高级功能的理解使用
文章目录 第一部分:Pytest 简介1.1 什么是 Pytest?1.2 Pytest 的历史1.3 Pytest 的核心概念1.4 Pytest 的特点1.5 为什么选择 Pytest? 第二部分:Pytest 的基本使用2.1 安装 Pytest2.2 编写第一个测试用例2.2.1 创建一个简单的测试…...

RHCE实验详解
目录 实验分析 环境拓扑结构 项目需求 主机环境描述 实验步骤 一、密钥互信和主机名更改 二、DNS 三、NGINX 四、MARIADB 五、NFS 六、NTP 七、论坛服务 结果展示及痛点解答 实验分析 环境拓扑结构 项目需求 1. 172.25.250.101 主机上的 Web 服务要求提供 www.ex…...

备赛蓝桥杯之第十五届职业院校组省赛第二题:分享点滴
提示:本篇文章仅仅是作者自己目前在备赛蓝桥杯中,自己学习与刷题的学习笔记,写的不好,欢迎大家批评与建议 由于个别题目代码量与题目量偏大,请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题࿰…...

MyBatis 注解开发详解
MyBatis 注解开发详解 MyBatis 支持使用注解来进行数据库操作。注解方式将 SQL 语句直接写在 Java 接口中,通过注解来完成 CRUD(增删改查)操作,省去了使用 XML 配置的繁琐步骤。这种方式适合简单项目或快速原型开发,因…...

Kivy App开发之UX控件VideoPlayer视频播放
kivy使用VideoPlayer控件实现视频播放,可以控制视频的播放,暂停,音量调节等功能。 在使用VideoPlayer视频播放器时,可以参考下表属性来设置其样式和触发事件。 属性说明source视频路径,默认为空state视频状态,值play,pause,stop,默认为stopthumbnail显示视频的缩略图…...

简单排序算法
异或运算及异或运算实现的swap方法 ^(异或): ^运算是计算机中的位运算,运算规则为相同为0,不同为1(也被称为无进位相加)。位运算处理效率比常规运算符效率更高。 异或运算遵循的法则: 0^N N N^N 0 异或运算…...

C语言初阶牛客网刷题——JZ17 打印从1到最大的n位数【难度:入门】
1.题目描述 牛客网OJ题链接 题目描述: 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。 用返回一个整数列表来代替打印n 为正整数,0 < n < 5 示例1 输入&…...

基于springboot+vue的校园二手物品交易系统的设计与实现
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

开发环境搭建-2:配置 python 运行环境(使用 uv 管理 python 项目)
在 WSL 环境中配置:WSL2 (2.3.26.0) Oracle Linux 8.7 官方镜像 UV 介绍 uv软件官网(github 需要梯子,没错这个软件的官网真就是 github 页面):https://github.com/astral-sh/uv 中文官网(github 需要梯…...

STM32 ST7735 128*160
ST7735 接口和 STM32 SPI 引脚连接 ST7735 引脚功能描述STM32 引脚连接(示例,使用 SPI1)SCLSPI 时钟信号 (SCK)PA0(SPI1_SCK)SDASPI 数据信号 (MOSI)PA1 (SPI1_MOSI)RST复位信号 (Reset)PA2(GPIO 手动控制)DC数据/命令选择 (D/C)PA3 (GPIO 手…...

【面试总结】FFN(前馈神经网络)在Transformer模型中先升维再降维的原因
FFN(前馈神经网络)在Transformer模型中先升维再降维的设计具有多方面的重要原因,以下是对这些原因的总结: 1.目标与动机 高维映射空间:FFN的设计目的是通过一系列线性变换来拟合一个高维的映射空间,而不仅…...

VB读写ini配置文件将运行文件放入任务计划程序设置为开机自启动
本示例使用设备: https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1bWmhJZJ&ftt&id562957272162 Public Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpAppl…...

Java基础 (一)
基础概念及运算符、判断、循环 基础概念 关键字 数据类型 分为两种 基本数据类型 标识符 运算符 运算符 算术运算符 隐式转换 小 ------>>> 大 强制转换 字符串 拼接符号 字符 运算 自增自减运算符 ii赋值运算符 赋值运算符 包括 强制转换 关系运算符 逻辑运算符 …...

数据结构——实验六·散列表
嗨~~欢迎来到Tubishu的博客🌸如果你也是一名在校大学生,正在寻找各种编程资源,那么你就来对地方啦🌟 Tubishu是一名计算机本科生,会不定期整理和分享学习中的优质资源,希望能为你的编程之路添砖加瓦⭐&…...

springboot网上书城
摘 要 在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括网上书城管理系统的网络应用,在国外网上书城管理系统已经是很普遍的方式,不过国内的书城管理系统可能还处于起步阶段。网上书城管理系统具有网上…...

如何在 Pytest 中使用命令行界面和标记运行测试
关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 在前文你已经初步尝试编写了代码和单元测试,并且想要确保它能正常运行。…...

不建模,无代码,如何构建一个3D虚拟展厅?
在数字化浪潮的推动下,众多企业正积极探索线上3D虚拟展厅这一新型展示平台,旨在以更加生动、直观的方式呈现其产品、环境与综合实力。然而,构建一个既专业又吸引人的3D虚拟展厅并非易事,它不仅需要深厚的技术支持,还需…...

github汉化
本文主要讲述了github如何汉化的方法。 目录 问题描述汉化步骤1.打开github,搜索github-chinese2.打开项目,打开README.md3.下载安装脚本管理器3.1 在README.md中往下滑动,找到浏览器与脚本管理器3.2 选择浏览器对应的脚本管理器3.2.1 点击去…...

Unity Line Renderer Component入门
Overview Line Renderer 组件是 Unity 中用于绘制连续线段的工具。它通过在三维空间中的两个或两个以上的点的数组,并在每个点之间绘制一条直线。可以绘制从简单的直线到复杂的螺旋线等各种图形。 1. 连续性和独立线条 连续性:Line Renderer 绘制的线条…...

数据库的三级模式结构与两级映像
三级模式结构与两级映像 什么是数据库的三级模式结构?1. 模式(Conceptual Schema,概念模式)定义特点作用示例 2. 外模式(External Schema,外部模式)定义特点作用举例 3. 内模式(Inte…...

TCP断开通信前的四次挥手(为啥不是三次?)
1.四次握手的过程 客户端A发送 FIN(终止连接请求) A:我要断开连接了(FIN)。A进入FIN_WAIT_1状态,表示请求断开,等待对方确认。 服务器B回复 ACK(确认断开请求,但还未准备…...

win32汇编环境,按字节、双字等复制字符的操作
;运行效果 ;win32汇编环境,按字节、双字等复制字符的操作 ;这是汇编的优点之一。我们可以按字节、双字、四字、八字节等复制或挨个检查字符。 ;有时候,在接收到的一串信息中,比如访问网站时,返回的字串里,有很多0值存在࿰…...

.net 项目引用与 .NET Framework 项目引用之间的区别和相同
在 .NET 和 .NET Framework 项目中,引用其他库或项目的方式有一些区别和相同之处。以下是详细的对比: 相同点 引用目的: 目的:无论是 .NET 还是 .NET Framework 项目,引用其他库或项目的主要目的是为了使用这些库或项…...

RabbitMQ--延迟队列
(一)延迟队列 1.概念 延迟队列是一种特殊的队列,消息被发送后,消费者并不会立刻拿到消息,而是等待一段时间后,消费者才可以从这个队列中拿到消息进行消费 2.应用场景 延迟队列的应用场景很多,…...

使用pyboard、micropython和tja1050进行can通信
单片机和can收发器之间tx、rx不需要交叉接线!!! tja1050的rx接Y3、tx接Y4 from pyb import CANcan CAN(1) can.init(modecan.NORMAL, prescaler6, sjw1, bs14, bs22, auto_restartTrue) # 1Mbps的配置,本文使用的micropython1.…...

JS学习之JavaScript模块化规范进化论
前言 JavaScript 语言诞生至今,模块规范化之路曲曲折折。 前言 JavaScript 语言诞生至今,模块规范化之路曲曲折折。社区先后出现了各种解决方案,包括 AMD、CMD、CommonJS 等,而后 ECMA 组织在 JavaScript 语言标准层面࿰…...

亚博microros小车-原生ubuntu支持系列:7-脸部检测
背景知识 官网介绍: Face Mesh - mediapipe mpFaceMesh.FaceMesh() 类的参数有:self.staticMode, self.maxFaces, self.minDetectionCon, self.minTrackCon staticMode:是否将每帧图像作为静态图像处理。如果为 True,每帧都会进行人脸检测…...

第二届国赛铁三wp
第二届国赛 缺东西去我blog找👇 第二届长城杯/铁三 | DDLS BLOG web Safe_Proxy 源码题目 from flask import Flask, request, render_template_stringimport socketimport threadingimport htmlapp Flask(__name__)app.route(/, methods"GET"])de…...

缓存商品、购物车(day07)
缓存菜品 问题说明 问题说明:用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大。 结果: 系统响应慢、用户体验差 实现思路 通过Redis来缓存菜品数据,减少数据库查询…...

4【编程语言的鄙视链原因解析】
在编程行业中,是存在鄙视链的,技术越好的圈子越不明显,技术越差的圈子越明显,很多时候为新人营造了错误的观点,我们来针对此类现象为新人们讲解原因 ①心里落差:比如你是学厨师的 你经过过年努力练…...