【Pytest】基础到高级功能的理解使用

news2025/1/23 2:02:13

文章目录

    • 第一部分: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 + 3
    assert 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.py

def test_addition():
    assert 2 + 3 == 5

def 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 items

test_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 pytest
    
    def 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 data

def 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 requests

def 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 requests

def 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.get
    mocker.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 pytest

def 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 Pytest
    
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    
    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - name: Check out the repository
            uses: actions/checkout@v2
    
          - name: Set up Python
            uses: actions/setup-python@v2
            with:
              python-version: '3.8'
    
          - name: Install dependencies
            run: |
              python -m pip install --upgrade pip
              pip install -r requirements.txt
    
          - name: Run Pytest
            run: |
              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 report
      run: |
        pytest --junitxml=test_results.xml
    
    - name: Upload JUnit test results
      uses: actions/upload-artifact@v2
      with:
        name: pytest-results
        path: test_results.xml
    

    这样,测试结果将被上传为构建工件,可以在 GitHub Actions 界面上查看。

5.2.2 自动化测试报告
  1. 生成并上传 HTML 报告

    如果希望生成更详细和美观的 HTML 格式测试报告,可以使用 pytest-html 插件,并将报告作为构建工件上传:

    - name: Install pytest-html
      run: pip install pytest-html
    
    - name: Run Pytest with HTML report
      run: pytest --html=report.html
    
    - name: Upload HTML report
      uses: actions/upload-artifact@v2
      with:
        name: pytest-html-report
        path: 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.coloradmin.cn/o/2280644.html

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

相关文章

leetcode 1620. 网络信号最好的坐标

题目如下 数据范围 示例 观察数据范围我们可以看到信号塔最多只有50座而x 与 y范围则是在0到50之间。 如果我们暴力枚举的话计算次数最多51 * 51 * 50时间复杂度即为O&#xff08;n * n * M&#xff09; 显然题目暗示我们使用枚举法通过代码 class Solution { public:vect…

《罗宾逊-旅途VR》Build2108907官方学习版

《罗宾逊-旅途VR》官方版 https://pan.xunlei.com/s/VODiY5gn_fNxKREdVRdwVboCA1?pwdsh3f# 从第一人称的角度进行探索&#xff0c;玩家将遇到一系列恐龙和生物&#xff0c;这些恐龙和生物会对它们在泰森三世生态系统中的存在做出反应。强调与周围环境的互动&#xff0c;鼓励玩…

Leetcode:2239

1&#xff0c;题目 2&#xff0c;思路 循环遍历满足条件就记录&#xff0c;最后返回结果值 3&#xff0c;代码 public class Leetcode2239 {public static void main(String[] args) {System.out.println(new Solution2239().findClosestNumber(new int[]{-4, -2, 1, 4, 8})…

LeetCode:37. 解数独

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;37. 解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff…

FPGA与ASIC:深度解析与职业选择

IC&#xff08;集成电路&#xff09;行业涵盖广泛&#xff0c;涉及数字、模拟等不同研究方向&#xff0c;以及设计、制造、封测等不同产业环节。其中&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;和ASIC&#xff08;专用集成电路&#xff09;是两种重要的芯片类型…

Linux内存管理(Linux内存架构,malloc,slab的实现)

文章目录 前言一、Linux进程空间内存分配二、malloc的实现机理三、物理内存与虚拟内存1.物理内存2.虚拟内存 四、磁盘和物理内存区别五、页页的基本概念&#xff1a;分页管理的核心概念&#xff1a;Linux 中分页的实现&#xff1a;总结&#xff1a; 六、伙伴算法伙伴算法的核心…

GIFT ICA 下载记录

1.帮助文档 Group ICA/IVA Of fMRI Toolbox&#xff1b;【GIFT介绍】 Group ICA of fMRI Toolbox (GIFT) Walk Through&#xff1b;【流程介绍】 GIFT v1.3c Functions Srinivas Rachakonda, Eric Egolf and Vince Calhoun【流程解释】 2.下载记录 从官网下载程序包&#xff0…

PHP礼品兑换系统小程序

&#x1f381; 礼品兑换系统&#xff1a;革新企业礼品管理&#xff0c;专属神器来袭&#xff01; &#x1f4bb; 一款专为追求高效与个性化的现代企业量身打造的礼品兑换系统&#xff0c;它基于强大的ThinkPHP框架与前沿的Uniapp技术栈深度融合&#xff0c;不仅完美适配礼品卡…

kafka学习笔记6 ACL权限 —— 筑梦之路

在Kafka中&#xff0c;ACL&#xff08;Access Control List&#xff09;是用来控制谁可以访问Kafka资源&#xff08;如主题、消费者组等&#xff09;的权限机制。ACL配置基于Kafka的kafka-acls.sh工具&#xff0c;能够管理对资源的读取、写入等操作权限。 ACL介绍 Kafka的ACL是…

webrtc入门系列(五)amazon-kinesis-video-streams-webrtc-sdk-c编译

《webrtc入门系列&#xff08;一&#xff09;easy_webrtc_server 入门环境搭建》 《webrtc入门系列&#xff08;二&#xff09;easy_webrtc_server 入门example测试》 《webrtc入门系列&#xff08;三&#xff09;云服务器coturn环境搭建》 《webrtc入门系列&#xff08;四&…

利用免费GIS工具箱实现高斯泼溅切片,将 PLY 格式转换为 3dtiles

在地理信息系统&#xff08;GIS&#xff09;和三维数据处理领域&#xff0c;不同数据格式有其独特应用场景与优势。PLY&#xff08;Polygon File Format&#xff09;格式常用于存储多边形网格数据&#xff0c;而 3DTiles 格式在 Web 端三维场景展示等方面表现出色。将 PLY 格式…

两天时间!我搞定了Intel显卡(核显)+Windows安装stable-diffusion-AI画画软件

两天时间&#xff01;我搞定了Intel显卡&#xff08;核显&#xff09;Windows安装stable-diffusion-AI画画软件 文章目录 两天时间&#xff01;我搞定了Intel显卡&#xff08;核显&#xff09;Windows安装stable-diffusion-AI画画软件前言一、工具的选择二、工具的熟悉三、硬件…

云计算、AI与国产化浪潮下DBA职业之路风云变幻,如何谋破局启新途?

引言 在近日举办的一场「云和恩墨大讲堂」直播栏目中&#xff0c;云和恩墨联合创始人李轶楠、副总经理熊军和欧冶云商数据库首席薛晓刚共同探讨了DBA的现状与未来发展。三位专家从云计算、人工智能、国产化替代等多个角度进行了深入的分析和探讨&#xff0c;为从业者提供了宝贵…

npm install 报错:Command failed: git checkout 2.2.0-c

[TOC](npm install 报错&#xff1a;Command failed: git checkout 2.2.0-c) npm install 报错&#xff1a;Command failed: git checkout 2.2.0-c export NODE_HOME/usr/local/node-v14.14.0-linux-x64 npm config set registry https://registry.npmmirror.com 使用如上环…

场馆预定平台高并发时间段预定实现V2

&#x1f3af; 本文档介绍了场馆预订系统接口V2的设计与实现&#xff0c;旨在解决V1版本中库存数据不一致及性能瓶颈的问题。通过引入令牌机制确保缓存和数据库库存的最终一致性&#xff0c;避免因服务器故障导致的库存错误占用问题。同时&#xff0c;采用消息队列异步处理库存…

图解Git——分布式Git《Pro Git》

分布式工作流程 Centralized Workflow&#xff08;集中式工作流&#xff09; 所有开发者都与同一个中央仓库同步代码&#xff0c;每个人通过拉取、提交来合作。如果两个开发者同时修改了相同的文件&#xff0c;后一个开发者必须在推送之前合并其他人的更改。 Integration-Mana…

将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(1.标准版)

问题 项目里使用了 AzureBlob 存储了用户上传的各种资源文件&#xff0c;近期 AzureBlob 的流量费用增长很快&#xff0c;想通过分析Blob的日志&#xff0c;获取一些可用的信息&#xff0c;所以有了这个需求&#xff1a;将存储账户的日志&#xff08;读写&#xff0c;审计&…

【json_object】mysql中json_object函数过长,显示不全

问题&#xff1a;json只显示部分 解决&#xff1a; SET GLOBAL group_concat_max_len 1000000; -- 设置为1MB&#xff0c;根据需要调整如果当前在navicat上修改&#xff0c;只有效本次连接和后续会话&#xff0c;重新连接还是会恢复默认值1024 在my.ini配置文件中新增或者修…

Flink底层架构与运行流程

这张图展示了Flink程序的架构和运行流程。 主要组件及功能&#xff1a; Flink Program&#xff08;Flink程序&#xff09;&#xff1a; 包含Program code&#xff08;程序代码&#xff09;&#xff0c;这是用户编写的业务逻辑代码。经过Optimizer / Graph Builder&#xff08…

你还在用idea吗

从VIM、Emacs&#xff0c;到eclipse、Jetbrains, 再到VSCode&#xff0c;过去的三十年时间&#xff0c;出现了这三代IDE产品。现在属于AI的时代来了&#xff0c;最新一代的产品像Cursor、Windsurf&#xff0c;就在昨天&#xff0c;字节跳动发布了最新的IDE&#xff0c;就叫Trae…