首页 > 其他分享 >Pytest教程:详解pytest.main()

Pytest教程:详解pytest.main()

时间:2024-03-19 13:58:47浏览次数:15  
标签:__ 插件 自定义 pytest Pytest 测试 main

1.什么是 pytest.main() 函数?


pytest.main() 是 Pytest 测试框架中的一个函数,用于动态地运行测试。通过调用这个函数,可以在代码中以编程方式执行 Pytest 测试集而不是通过命令行。

1.1 pytest.main() 函数的作用和功能:

  • pytest.main() 函数的主要作用是启动 Pytest 测试运行器,它会自动查找和执行当前路径及其子目录中所有符合 Pytest 命名规范的测试文件。
  • 这个函数提供了一种灵活的方式来运行测试,可以在脚本或程序中集成测试执行,方便自动化测试流程和持续集成。

1.2 为什么我们需要使用它来运行 Pytest 测试:

  • 在实际项目开发和测试过程中,通常会有大量的测试用例需要执行,手动逐一执行测试用例效率低下且容易出错。
  • 使用 pytest.main() 函数可以让我们通过编程的方式灵活地控制测试执行,可以根据需要指定特定的测试文件、测试用例或配置选项来运行测试,提高测试效率。
  • 通过将测试执行集成到自动化构建和部署流程中,可以确保每次代码变更后都能够快速、可靠地运行测试,帮助提高代码质量并减少潜在的问题。

2.基本用法


if __name__ == "__main__":
    import pytest
    pytest.main()

在这个基本用法中,我们导入 pytest 模块并调用 pytest.main() 函数来执行测试。

示例代码:在脚本中调用 pytest.main() 来执行测试

import pytest

def test_example():
    assert 1 + 2 == 3

if __name__ == "__main__":
    pytest.main()

上述示例中,我们定义了一个简单的测试函数 test_example(),并在脚本末尾调用了 pytest.main() 函数来执行测试。

3.参数详解


pytest.main() 函数中,有一些常用的参数可以用来控制测试的运行方式。以下是一些常用参数的介绍和说明:

3.1  args 参数:

  • 作用args 参数用于传递命令行参数给 Pytest 运行器。
  • 如何使用:通过将参数以列表形式传递给 pytest.main() 函数,可以实现在命令行中调用 Pytest 时传递的参数。
pytest.main(["-v", "-s", "my_test_file.py"])

3.2 plugins 参数:

  • 作用plugins 参数用于加载指定的 Pytest 插件。
  • 如何使用:通过将插件对象列表传递给 plugins 参数,可以在测试运行过程中使用指定的插件功能。
import my_custom_plugin
pytest.main(plugins=[my_custom_plugin])

3.3 其他常用参数:

  • -v, --verbose:输出详细信息,显示每个测试用例的执行结果。
  • -s, --capture=no:显示测试函数中的打印输出。
  • -k EXPRESSION:只运行包含指定表达式的测试用例。
  • --fixtures:列出所有可用的 fixture。

示例用法:

import pytest

if __name__ == "__main__":
    # 传递参数 args 和 plugins 给 pytest.main()
    pytest.main(args=["-v", "-s", "my_test_file.py"], plugins=[my_custom_plugin])

4.常见示例


当使用 pytest.main() 函数时,可以根据不同的场景和需求来执行测试并输出相应的报告。以下是一些常见用例示例:

4.1 执行指定的测试模块或文件:

pytest.main(["test_file.py"])

 4.2 执行带有特定标记的测试:

pytest.main(["-m", "slow"])

4.3 执行特定的测试函数或类:

pytest.main(["test_file.py::test_function"])
pytest.main(["test_file.py::TestClass::test_method"])

 4.4 输出详细的测试报告:

pytest.main(["-v"])

 完整示例代码:

import pytest

if __name__ == "__main__":
    # 执行指定的测试模块或文件
    pytest.main(["test_file.py"])

    # 执行带有特定标记的测试
    pytest.main(["-m", "slow"])

    # 执行特定的测试函数或类
    pytest.main(["test_file.py::test_function"])
    pytest.main(["test_file.py::TestClass::test_method"])

    # 输出详细的测试报告
    pytest.main(["-v"])

 5.自定义配置


要通过自定义配置来优化 pytest.main() 的行为,可以在调用 pytest.main() 之前设置自定义选项和插件。下面是一个示例,演示如何使用自定义选项和插件来优化 Pytest 测试执行:

自定义配置示例代码:

import pytest

# 自定义插件类
class MyCustomPlugin:
    def pytest_runtest_logreport(self, report):
        print(f"Custom report: {report.nodeid} - {report.outcome}")

# 设置自定义选项
custom_options = [
    "--custom-flag",
    "--custom-value=123"
]

# 添加自定义插件
custom_plugin = MyCustomPlugin()

if __name__ == "__main__":
    # 设置自定义选项并添加自定义插件
    pytest_args = ["-v"] + custom_options
    plugins = [custom_plugin]

    # 调用 pytest.main() 执行测试
    pytest.main(pytest_args, plugins=plugins)

在这个示例中,我们定义了一个名为 MyCustomPlugin 的自定义插件类,该插件类实现了 pytest_runtest_logreport 方法用于自定义测试报告的输出。然后,我们设置了一些自定义选项和添加了自定义插件,最后调用 pytest.main() 函数来执行测试。

通过这种方式,你可以根据需要灵活地定制 Pytest 的行为,并实现更多定制化的功能。记住,在调用 pytest.main() 之前设置自定义选项和插件能够最大程度地优化测试执行过程,使其符合具体项目的需求。

6.错误处理


在使用 pytest.main() 函数时,可能会遇到一些常见的错误和异常情况。以下是一些可能出现的问题以及相应的解决方案和建议:

6.1 无法找到测试模块或文件:

错误描述:在执行 pytest.main() 时,可能会遇到无法找到指定的测试模块或文件的错误。

解决方案:确保指定的测试模块或文件路径是正确的,并且在调用 pytest.main() 之前已经设置了正确的工作目录。可以使用绝对路径或相对路径来指定测试模块或文件的位置。

6.2 无法加载插件或自定义选项不生效:

错误描述:添加了自定义插件或选项,但在执行测试时发现插件未生效或自定义选项未被识别。

解决方案:确保自定义插件类被正确导入并传递给 pytest.main() 函数的 plugins 参数。同时,确保自定义选项以正确的格式传递给了 pytest.main() 函数。

6.3 测试报告输出不符合预期:

错误描述:执行测试后,测试报告的输出结果不符合预期,可能缺少详细信息或包含多余的信息。

解决方案:检查是否正确设置了 -v 等选项来控制测试报告的输出级别。另外,如果需要自定义输出,可以通过编写自定义插件来实现特定的报告格式或内容。

6.4 其他异常情况:

错误描述:可能会遇到其他与环境、配置或代码相关的异常情况,例如依赖库版本不兼容、测试文件中存在语法错误等等。

解决方案:针对具体的异常情况,可以逐一排查并解决。可以通过调试、日志记录以及对比已知正常运行的环境来定位并解决问题。

6.5 建议和注意事项:

  • 在调用 pytest.main() 之前,确保所有必要的配置已经正确设置,包括环境变量、工作目录、插件加载等。
  • 仔细阅读 Pytest 文档,特别是关于 pytest.main() 函数的用法和参数说明部分,以避免常见的错误。
  • 尽量使用相对稳定的 Pytest 版本,并根据需要升级或降级版本以解决可能的兼容性问题。

7.pytest.main()实际使用场景 


当使用 pytest.main() 函数时,以下是一些最佳实践,以便更好地利用它进行测试组织、编写可重复运行的测试用例以及与持续集成工具集成:

7.1 组织测试代码以便更好地利用 pytest.main():

  1. 模块化组织:将测试代码组织成多个模块或包,每个模块负责测试特定功能或模块。

  2. 命名规范:遵循 pytest 的命名规范,使用 test_ 开头定义测试函数,以便 pytest 能够自动识别。

  3. 测试目录结构:按照项目结构组织测试代码,可以使用与源代码相似的目录结构,使得测试代码易于定位和管理。

  4. 共享 fixture:使用 fixture 来共享测试用例之间的初始化和清理逻辑,避免重复代码。

7.2 编写可重复运行的测试用例:

  1. 独立性:确保测试用例之间互相独立,避免依赖关系,每个测试用例应该能够独立执行和验证。

  2. 参数化测试:使用 @pytest.mark.parametrize 装饰器来定义参数化测试,覆盖不同的输入情况,增加测试的覆盖范围。

  3. setup 和 teardown:使用 fixture 的 setupteardown 方法来初始化和清理测试环境,确保每次测试的一致性。

7.3 与持续集成工具集成:

  1. 自动化测试:将 Pytest 测试集成到持续集成工具中,实现自动化测试,并在每次代码提交或合并请求时触发测试。

  2. 测试报告:利用 Pytest 插件生成详细的测试报告和覆盖率报告,帮助及时发现问题并定位 bug。

  3. 版本控制和触发机制:将测试代码与源代码一起纳入版本控制,并设置适当的触发机制来触发测试流程。

示例代码:

下面是一个示例的目录结构和代码组织:

project/
├── src/
│   └── app.py
└── tests/
    ├── test_feature1.py
    ├── test_feature2.py
    ├── conftest.py
    └── fixtures.py

conftest.py 中定义共享的 fixture,而在 fixtures.py 中定义特定的 fixture。

# tests/conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption("--runslow", action="store_true", help="run slow tests")

# tests/fixtures.py
import pytest

@pytest.fixture
def setup_database():
    # 初始化数据库连接等操作
    yield
    # 清理数据库连接等操作

 测试模块中的示例代码:

# tests/test_feature1.py
import pytest

def test_feature1_functionality():
    # 测试 feature 1 的功能
    assert True

# tests/test_feature2.py
import pytest

@pytest.mark.slow
def test_feature2_functionality():
    # 测试 feature 2 的功能
    assert True

 在持续集成工具中,可以根据需要配置触发条件、测试报告输出、覆盖率报告等内容。

8.源码浅析


pytest.main() 函数是 pytest 框架中用于运行测试的入口函数,它的底层原理涉及到 pytest 的插件系统、命令行参数解析、测试文件和函数的收集、fixture 的应用等多个方面。

8.1 源码分析:

  1. 入口函数

    • pytest.main() 函数是 pytest 的入口函数,它在 pytest/__main__.py 模块中定义。
    • 该函数主要负责解析命令行参数,并调用 pytest.core.Main 类的实例来运行测试。
  2. 命令行参数解析

    • pytest.main() 使用 argparse 模块来解析命令行参数,包括常见的选项和标记,如 -k-m--cov 等。
    • 解析后的参数会传递给 pytest.core.Main 类的实例,用于配置测试运行的各种选项。
  3. 测试收集与执行

    • 在 pytest.core.Main 类中,会根据参数配置,进行测试文件和测试函数的收集。
    • pytest 使用插件系统来扩展功能,可以通过插件来修改测试的收集行为、运行行为以及报告生成等过程。
  4. Fixture 的应用

    • 在运行测试时,pytest 会根据 fixture 的定义和使用来动态应用 fixture 到测试用例中。
    • Fixture 可以在测试用例执行前进行初始化操作,并在测试用例执行后进行清理操作,确保测试环境的一致性。
  5. 报告生成

    • 在测试执行完毕后,pytest 负责生成测试报告,包括测试结果、错误信息、覆盖率等内容。
    • pytest 支持多种报告格式,可以生成文本报告、HTML 报告以及 XML 报告,方便查看和分析测试结果。

8.2 底层原理解析:

  • pytest.main() 函数通过解析命令行参数,配置测试的运行选项,然后调用 pytest.core.Main 类的实例来执行测试。
  • pytest.core.Main 类负责测试文件和测试函数的收集、fixture 的应用、测试执行以及报告生成等整个测试流程。
  • pytest 使用插件系统来扩展功能,可以通过编写自定义插件来修改 pytest 的行为,实现定制化需求。
  • 在测试执行过程中,pytest 会利用各个模块之间的协作,包括收集测试、应用 fixture、执行测试用例、生成报告等步骤,最终完成整个测试流程。

更多pytest.main()在实际工作中的使用欢迎私信交流! 

标签:__,插件,自定义,pytest,Pytest,测试,main
From: https://blog.csdn.net/weixin_40025666/article/details/136839489

相关文章

  • CF999D Equalize the Remainders 题解
    题意给定一个长度为\(n\)的序列和一个模数\(m\),记\(c_i\)表示\(\bmodm\)后的结果为\(i\)的数的个数。现在可以使每个数增加\(1\),请问最少要操作多少次才能使所有\(c_i=\frac{n}{m}\)。并输出最后的序列。First.如何最小化操作次数由于每次操作会使\(c_{a_i\bm......
  • pytest+allure生成html报告(入门篇)
    一. 安装pytest库pipinstallpytest代码如下(示例):importpytestclassTestLogin:deftest_login(self):print('---------------login--------------')if__name__=='__main__':pytest.main(['-vs']) 运行结果如下:二、在pyth......
  • python pytest.mark
    pytest.mark是pytest测试框架中的一个功能,它允许你为测试用例和测试夹具(fixtures)添加元数据(或称为“标记”)。这些标记可以用于各种目的,例如选择性地运行特定的测试用例集,跳过某些测试用例,或者为测试用例添加额外的信息。pytest.mark主要有以下几种用法:为测试用例添加标记:你......
  • 如何调用Pytest
    如何调用Pytest在模块中运行测试pytesttest_mod.py在目录中运行测试pytesttesting/通过关键字表达式运行测试pytest-k'MyClassandnotmethod'这将运行包含与给定字符串表达式(不区分大小写)匹配的名称的测试,其中可以包括使用文件名、类名和函数名作为变量的Python......
  • python @pytest.fixture示例及用法
    [email protected]示例及用法@pytest.fixture是pytest测试框架中的一个非常有用的功能,它允许你定义可以在多个测试用例之间共享的设置和清理代码。通过使用fixture,你可以减少重复的代码,并使得测试用例更加清晰和模块化。下面是一个简单的示例,展示了如何使用@pytest.fi......
  • 安装Pytest
    安装Pytest在命令行中运行以下命令pipinstall-Upytest检查是否安装了正确的版本pytest--version创建你的第一个测试创建一个名为test_sample.py的新文件,包含一个函数和一个测试#contentoftest_sample.pydeffunc(x):returnx+1deftest_answer():......
  • [ABC258F] Main Street 题解
    题意:你要在平面直角坐标系中行走,每一步可以上下左右四个方向任意移动$1$,耗时$k$秒。特别地,存在若干条快速通道,若该步起点和终点均满足$x\equiv0\pmod{B}$或$y\equiv0\pmod{B}$,则认为该步是在快速通道上进行,仅需耗时$1$秒。询问从$(S_x,S_y)$到$(G_x,G_y)$最......
  • JAVA面向对象高级:static修饰成员方法 真正搞懂main方法 类方法实例方法应用场景
         真正搞懂main方法    类方法实例方法应用场景类方法最常见的应用场景是做工具类      ......
  • #QT(MainWindow初尝---文本编辑器)
    1.IDE:QTCreator2.实验:使用MainWindow做一个文本编辑器3.记录(1)创建几个功能  (2)为几个功能写实现,这里不能使用转到槽,需要自己用connect函数关联。这里的功能是QAction类,退格搜查其槽函数来进行绑定(3)打开文件操作,主要查看QFileDialog类说明还有QFile类说明,QFileDialog......
  • RAG实战6-如何在LlamaIndex中使用自己搭建的API
    RAG实战6-如何在LlamaIndex使用自己搭建的大模型API在搭建一个大模型API服务中,我们介绍了如何使用SWIFT框架搭建一个大模型API服务。在RAG实战1-5中,我们一直使用的是本地加载大模型的方式来调用大模型,本文将介绍如何在LlamaIndex中使用自己搭建的大模型API。LlamaIndex支持部分......