【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 的历史

pytestHolger Krekel 于 2004 年首次发布,它的起源可以追溯到其前身 py.testpytest 在最初发布时就力图通过简化测试代码,使其易于使用,并且随着时间的推移,逐渐添加了大量功能和优化。

  • 2004py.test 项目发布,提供了基础的测试框架。
  • 2010:项目更名为 pytest,并开始引入插件支持。
  • 2015pytest 开始成为 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_additiontest_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, bexpected,并且每个参数集分别对应 (1, 2, 3)(4, 5, 9)(7, 8, 15)。运行时,Pytest 会为每组输入值自动执行该测试。

3.1.2 参数化测试的使用场景

参数化测试通常适用于以下几种场景:

  1. 多组输入输出验证:当我们需要验证函数或方法的多个输入和输出时,可以使用参数化来减少代码重复。例如,测试一个加法函数对于多个输入的行为。

  2. 多种边界条件的测试:测试时需要覆盖多个边界条件(如最大值、最小值、负值等),使用参数化可以很容易地针对每个边界值进行验证。

  3. 提升测试效率:当测试数据量大时,参数化可以将相似的测试代码合并成一个测试用例,提高测试的效率与可读性。


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

在上面的示例中,我们定义了两种标记 slowsmoke,同时设置了日志级别和命令行选项。

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 或其他配置文件)。

插件创建步骤:
  1. 创建一个 Python 文件:在项目根目录或 conftest.py 中编写插件代码。
  2. 实现钩子函数:Pytest 插件通过钩子函数(hook functions)来定制功能。常见的钩子函数包括 pytest_runtest_protocolpytest_configure 等。
  3. 注册插件:插件通过 pytest_pluginsconftest.pypytest.ini 中进行注册。
示例:创建一个简单的插件,添加一个命令行选项
  1. 创建一个 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")
  1. 在测试文件中使用这个选项:
def test_with_option(myoption):assert myoption == "default_value"
  1. 使用 pytest.ini 来注册插件:
# pytest.ini
[pytest]
plugins =myplugin

通过上面的步骤,创建了一个简单的插件,它为 Pytest 添加了一个名为 --myoption 的命令行选项。

4.1.2 插件的安装与使用

自定义插件可以通过 Pytest 配置文件进行注册,或者直接安装并在测试运行时启用。如果开发了一个插件并想要安装和使用它(nb),可以将插件发布到 PyPI(Python 包索引)中,然后通过 pip install 安装。以下是安装和使用插件的基本步骤:

  1. 安装插件

    pip install pytest-myplugin
    
  2. 启用插件:在 pytest.iniconftest.py 中注册插件,或在命令行通过 -p 选项指定插件。

    pytest -p myplugin
    

这样,就可以在 Pytest 中使用自定义插件了。


4.2 常用插件介绍

4.2.1 pytest-cov:代码覆盖率报告

pytest-cov 插件用于生成代码覆盖率报告,帮助开发者了解代码的测试覆盖情况。它集成了 coverage.py,并能够输出多种格式的报告,如终端输出、HTML 或 XML。

安装:

pip install pytest-cov

使用:

  1. 命令行选项:可以通过 --cov 选项来指定要进行覆盖率检查的模块或包。

    pytest --cov=my_module
    

    这条命令会运行 my_module 的测试并生成代码覆盖率报告。

  2. 生成 HTML 报告

    可以通过 --cov-report 选项指定生成的报告格式。例如,生成 HTML 格式的覆盖率报告:

    pytest --cov=my_module --cov-report html
    

    这会在当前目录下生成一个 htmlcov 文件夹,其中包含了 HTML 格式的代码覆盖率报告。

  3. 多项覆盖率报告:还可以同时输出多种格式的报告:

    pytest --cov=my_module --cov-report html --cov-report term
    

    这将同时生成 HTML 和终端格式的报告。

4.2.2 pytest-html:生成 HTML 格式的测试报告

pytest-html 插件用于生成漂亮的 HTML 测试报告,包含测试结果的详细信息,如每个测试用例的执行状态、日志、截图等。

安装:

pip install pytest-html

使用:

  1. 生成 HTML 测试报告

    运行测试并生成一个 report.html 文件:

    pytest --html=report.html
    
  2. 自定义报告标题和描述

    可以通过 --self-contained-html 选项生成一个独立的 HTML 文件,其中包含所有的资源(如 CSS 和 JavaScript),使报告文件更具可移植性:

    pytest --html=report.html --self-contained-html
    
  3. 自定义报告内容

    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

使用:

  1. 运行 Flake8 检查

    在运行测试时,Pytest 会自动执行 flake8 检查:

    pytest --flake8
    
  2. 配置 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 测试
  1. 安装 Jenkins 和必要的插件

    • 安装 Jenkins 服务器,并确保已经安装了必要的插件,如 PipelineGit 等。
    • 如果要使用 Pytest 的代码覆盖率插件,可以安装 Coverage 插件。
  2. 设置 Jenkins 任务

    可以通过创建一个新任务或配置现有任务来运行 Pytest 测试。假设已经有一个 Git 仓库,并且测试代码存在于该仓库中。

    • 在 Jenkins 中,点击 新建任务,然后选择 自由风格项目
    • 构建触发器 部分,可以选择例如 GitHub webhook,以便每次代码更改时自动触发构建。
  3. 配置构建步骤

    构建 部分,可以添加一个执行 Shell 或批处理命令的步骤来运行 Pytest。

    如果要使用虚拟环境,可以通过以下命令在构建中运行 Pytest:

    # 激活虚拟环境
    source venv/bin/activate  # 或者其他合适的命令# 安装依赖
    pip install -r requirements.txt# 运行 pytest
    pytest --maxfail=1 --disable-warnings -q
    

    还可以根据需要修改 pytest 命令,如生成 HTML 或 JUnit 格式的报告。

  4. 运行构建

    保存并启动构建,Jenkins 将会自动执行测试,并在控制台输出测试结果。

5.1.2 Jenkins 中配置 pytest 插件
  1. 安装 Pytest 插件

    Jenkins 提供了一些插件,可以与 Pytest 集成,特别是 JUnit 插件,它可以解析 Pytest 生成的 JUnit 格式的测试结果,并在 Jenkins 中展示。可以通过以下步骤来配置:

    • 在 Jenkins 上的任务配置界面,选择 构建后操作

    • 添加 发布JUnit测试报告 步骤。

    • 在测试报告 XML 文件路径中,填入 Pytest 生成的 JUnit 格式报告路径。例如:

      pytest --junitxml=report.xml
      

      这将生成一个 report.xml 文件,其中包含测试的详细信息,Jenkins 可以解析这个文件并在界面上展示测试结果。

  2. 配置 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 测试
  1. 创建 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 测试。

  2. 解析测试结果

    如果希望 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 自动化测试报告
  1. 生成并上传 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 界面下载和查看该报告。

  2. 可视化测试结果

    如果想将 Pytest 结果直接以图形化的方式显示在 GitHub Actions 界面上,可以使用第三方工具或插件(如 pytest-azure-pipelines)来集成更丰富的报告和通知功能,提供更加可视化的测试反馈。


通过将 Pytest 集成到持续集成系统中(如 Jenkins 或 GitHub Actions),可以在每次代码变更后自动执行测试,并生成详细的报告,从而确保软件质量。自动化测试能够帮助团队快速发现并修复问题,从而提高开发效率。



第六部分:Pytest 常见问题解答

在使用 Pytest 进行自动化测试时,开发人员可能会遇到一些常见问题,如测试超时、跳过某些测试和收集测试覆盖率等。以下是解决这些问题的一些方法。

6.1 如何处理测试超时

有时候,某些测试可能会因某些原因超时(如依赖外部服务或执行较复杂的操作)。为了解决这个问题,可以使用 pytest-timeout 插件来设置测试的超时时间。

6.1.1 使用 pytest-timeout 插件

pytest-timeout 插件可以为每个测试设置超时时间,并在超时后强制终止该测试。

  1. 安装插件

    要使用 pytest-timeout 插件,首先需要通过 pip 安装:

    pip install pytest-timeout
    
  2. 配置超时设置

    可以在命令行中设置超时,也可以使用装饰器在测试函数中配置超时。

    • 在命令行中设置超时:

      可以通过 --timeout 参数为所有测试设置超时。例如,设置每个测试的超时时间为 10 秒:

      pytest --timeout=10
      
    • 使用装饰器设置超时:

      还可以使用 @pytest.mark.timeout 装饰器为单个测试或测试类设置超时时间。例如,设置某个特定测试的超时时间为 5 秒:

      import pytest@pytest.mark.timeout(5)
      def test_example():# 测试逻辑assert True
      
  3. 处理超时异常

    默认情况下,当超时发生时,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
  1. 使用 @pytest.mark.skip 跳过测试

    如果希望强制跳过某个测试,可以使用 @pytest.mark.skip 装饰器。被装饰的测试将始终跳过,不会被执行。

    import pytest@pytest.mark.skip(reason="暂时跳过这个测试")
    def test_example():assert 1 == 1
    

    在上面的例子中,test_example 测试会被跳过,并且在测试报告中显示跳过的原因。

  2. 使用 @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 插件用于收集代码覆盖率数据,并生成相应的报告。它允许查看测试执行期间代码的覆盖情况,帮助我们发现未被测试到的代码部分。

  1. 安装 pytest-cov 插件

    首先,需要安装 pytest-cov 插件:

    pip install pytest-cov
    
  2. 运行测试并生成覆盖率报告

    运行 Pytest 时,可以通过 --cov 参数指定希望收集覆盖率的代码文件或模块。例如,收集 my_module 模块的代码覆盖率:

    pytest --cov=my_module
    

    该命令会执行测试,并在控制台输出覆盖率报告。

  3. 生成详细的覆盖率报告

    如果希望将覆盖率报告输出为 HTML 格式,可以使用 --cov-report 参数:

    pytest --cov=my_module --cov-report=html
    

    这将生成一个 htmlcov 目录,其中包含一个详细的 HTML 格式的覆盖率报告。

  4. 生成其他格式的报告

    除了 HTML 格式,还可以生成其他格式的报告(如 xmlterm),以便于进一步的分析或与其他工具集成:

    • 生成 XML 格式的报告:

      pytest --cov=my_module --cov-report=xml
      
    • 在终端中输出覆盖率统计信息:

      pytest --cov=my_module --cov-report=term
      
  5. 配置覆盖率的阈值

    可以配置覆盖率阈值,确保覆盖率达到预期。例如,设置最低的覆盖率为 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),可以进行交互式调试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/67710.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GS论文阅读--GeoTexDensifier

前言 本文是一个关于高斯致密化策略对高斯地图进行优化&#xff0c;他主要关注了几何结构和纹理信息。我最近对于高斯点的分布比较感兴趣&#xff0c;因为高斯点的分布决定了之后重建质量的好坏&#xff0c;初始化高斯很重要&#xff0c;但之后的维护需要致密化与修建策略&…

支持大功率输出高速频闪的图像处理用光源控制器

机器视觉系统中的光源控制器在确保图像质量、提高系统稳定性、降低能耗以及方便系统扩展和升级等方面发挥着重要作用。它可提供稳定光源&#xff0c;调节参数&#xff0c;另外具有操作便捷性。 下面我们来看Gardasoft的光源控制器&#xff0c;Gardasoft拥有作为图像处理用LED光…

Excel 技巧17 - 如何计算倒计时,以及数据条(★)

本文讲如何计算倒计时&#xff0c;以及加数据条。 1&#xff0c;如何计算倒计时 这里也要用公式 D3 - TODAY() 显示为下面这个样子的 然后右键该单元格&#xff0c;选 设置单元格格式 然后点 常规 这样就能显示出还书倒计时的日数了。 下拉适用到其他单元格。 2&#xff0c;…

springboot整合modbus实现通讯

springboot整合modbus4j实现tcp通讯 前言 本文基于springboot和modbus4j进行简单封装&#xff0c;达到开箱即用的目的&#xff0c;目前本方案仅实现了tcp通讯。代码会放在最后&#xff0c;按照使用方法操作后就可以直接使用 介绍 在使用本方案之前&#xff0c;有必要对modb…

iOS-YModel

YModel 是一个高效的 iOS/OSX 的模型转换框架&#xff0c;可以轻松地将 JSON 转换成 Model&#xff0c;或者将 Model 转换成 JSON。以下是详细的使用指南&#xff1a; 导入 YYModel: 确保在你的项目中导入了 YYModel。使用 CocoaPods 的话可以在 Podfile 中加入以下代码&#…

PhyCAGE:符合物理规律的图像到 3D 生成

Paper: Yan H, Zhang M, Li Y, et al. PhyCAGE: Physically Plausible Compositional 3D Asset Generation from a Single Image[J]. arXiv preprint arXiv:2411.18548, 2024. Introduction: https://wolfball.github.io/phycage/ Code: Unreleased PhyCAGE 是一种 image-to-3D…

麒麟操作系统服务架构保姆级教程(十三)tomcat环境安装以及LNMT架构

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 之前咱们学习了LNMP架构&#xff0c;但是PHP对于技术来说确实是老掉牙了&#xff0c;PHP的市场占有量越来越少了&#xff0c;我认识一个10年的PHP开发工程师&#xff0c;十年工资从15k到今天的6k&am…

网站HTTP改成HTTPS

您不仅需要知道如何将HTTP转换为HTTPS&#xff0c;还必须在不妨碍您的网站自成立以来建立的任何搜索排名权限的情况下进行切换。 为什么应该从HTTP转换为HTTPS&#xff1f; 与非安全HTTP于不同&#xff0c;安全域使用SSL&#xff08;安全套接字层&#xff09;服务器上的加密代…

大模型GUI系列论文阅读 DAY1:《基于大型语言模型的图形用户界面智能体:综述》(6.6W 字长文)

摘要 图形用户界面&#xff08;Graphical User Interfaces, GUIs&#xff09;长期以来一直是人机交互的核心&#xff0c;为用户提供了直观且以视觉为驱动的方式来访问和操作数字系统。传统上&#xff0c;GUI交互的自动化依赖于基于脚本或规则的方法&#xff0c;这些方法在固定…

实战经验:使用 Python 的 PyPDF 进行 PDF 操作

文章目录 1. 为什么选择 PyPDF&#xff1f;2. 安装 PyPDF3. PDF 文件的合并与拆分3.1 合并 PDF 文件3.2 拆分 PDF 文件 4. 提取 PDF 文本5. 修改 PDF 元信息6. PDF 加密与解密6.1 加密 PDF6.2 解密 PDF 7. 页面旋转与裁剪7.1 旋转页面7.2 裁剪页面 8. 实战经验总结 PDF 是一种非…

MySQL 安装配置(完整教程)

文章目录 一、MySQL 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL5.1 初始化 MySQL5.2 启动 MySQL 服务 六、修改 MySQL 密码七、卸载 MySQL八、结语 一、MySQL 简介 MySQL 是一款广泛使用的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#…

PostgreSQL的学习心得和知识总结(一百六十六)|深入理解PostgreSQL数据库之\watch元命令的实现原理

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

当当网书籍信息爬虫

1.基本理论 1.1概念体系 网络爬虫又称网络蜘蛛、网络蚂蚁、网络机器人等&#xff0c;可以按照我们设置的规则自动化爬取网络上的信息&#xff0c;这些规则被称为爬虫算法。是一种自动化程序&#xff0c;用于从互联网上抓取数据。爬虫通过模拟浏览器的行为&#xff0c;访问网页…

计算机网络 (50)两类密码体制

前言 计算机网络中的两类密码体制主要包括对称密钥密码体制&#xff08;也称为私钥密码体制、对称密码体制&#xff09;和公钥密码体制&#xff08;也称为非对称密码体制、公开密钥加密技术&#xff09;。 一、对称密钥密码体制 定义&#xff1a; 对称密钥密码体制是一种传…

【PowerQuery专栏】实现JSON数据的导入

Json 格式数据是在互联网数据格式传输使用的非常频繁的一类数据,图7.44为Json数据格式中比较典型的数据格式。 PowerQuery进行Json数据解析使用的是Json.Document进行数据解析,Json.Document目前有2个参数。 参数1为内容数据,数据类型为二进制类型,值为需要解析的Json数据参…

软件授权管理中的软件激活向导示例

软件激活向导示例 在软件许可中&#xff0c;提供许可应该是简单和安全的。这适用于想要在中央许可证服务器上创建新许可证的软件开发人员&#xff0c;也适用于需要在其设备上获得许可证的最终用户。如果所讨论的系统有互联网连接&#xff0c;或是暂时的连接&#xff0c;就可以…

模型部署工具01:Docker || 用Docker打包模型 Build Once Run Anywhere

Docker 是一个开源的容器化平台&#xff0c;可以让开发者和运维人员轻松构建、发布和运行应用程序。Docker 的核心概念是通过容器技术隔离应用及其依赖项&#xff0c;使得软件在不同的环境中运行时具有一致性。无论是开发环境、测试环境&#xff0c;还是生产环境&#xff0c;Do…

【云岚到家】-day03-门户缓存方案选择

【云岚到家】-day03-门户缓存方案选择 1.门户常用的技术方案 什么是门户 说到门户马上会想到门户网站&#xff0c;中国比较早的门户网站有新浪、网易、搜狐、腾讯等&#xff0c;门户网站为用户提供一个集中的、易于访问的平台&#xff0c;使他们能够方便地获取各种信息和服务…

网络安全VS数据安全

关于网络安全和数据安全&#xff0c;我们常听到如下两种不同声音&#xff1a; 观点一&#xff1a;网络安全是数据安全的基础&#xff0c;把当年做网络安全的那一套用数据安全再做一遍。 观点二&#xff1a;数据安全如今普遍以为是网络安全的延伸&#xff0c;实际情况是忽略数据…

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )

一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化&#xff1a; 文件是存储数据的一种非常基本且重要的方式。通过文件&#xff0c;我们可 以将程序运行时产生的数据永久保存下来&#xff0c;以便将来使用。 跨平台兼容性&#xff1a; 文件是一种通用…