详解如何使用Pytest进行自动化测试

叶初
叶初
发布时间:2026-10-14| 5人浏览过
原创

本文深入解析Python中Pytest框架的自动化测试应用。内容涵盖Pytest的核心特性、自动发现机制、Fixture的高级用法及参数化测试,并演示如何结合Selenium和API测试构建结构化项目。此外,还介绍了利用pytest-xdist插件实现并行执行以缩短测试时间,以及生成CI兼容的测试报告的方法。

为什么需要自动化测试

自动化测试具有诸多优势,主要体现为以下三个方面:

  • 可重用性:无需频繁编写新脚本,即使面对新的操作系统版本,通常也无需重新编写测试代码。
  • 可靠性:人工操作易出错,而机器执行更为稳定;在运行不可跳过的重复步骤或测试时,机器执行速度更快。
  • 全天候运行:支持在任何时间或远程启动测试任务,例如在夜间自动运行测试,即使开发者处于离线状态,软件也能持续被验证。

成熟的、功能齐全的Python测试工具——pytest

目前市场上存在多种测试框架和工具,它们遵循不同的风格,如数据驱动、关键字驱动、混合模式或行为驱动开发(BDD)等。用户可根据具体需求选择最合适的框架。

在各类测试框架中,Python及其生态占据了重要地位。Python及相关工具之所以被广泛采用,部分原因在于其门槛较低,即使缺乏深厚编程经验的人员也能轻松上手。

pytest框架不仅便于编写小型测试用例,还能扩展支持应用程序和库的复杂功能测试。

Pytest具备以下核心特性:

  • 自动发现测试模块和功能
  • 提供高效的命令行接口(CLI),便于精确控制要运行或跳过的测试内容
  • 拥有庞大的第三方插件生态系统
  • 支持多种类型和不同作用域的固定装置(Fixture)
  • 兼容传统的单元测试框架
  • 如何使用Pytest进行自动化测试

自动和可配置的测试发现

默认情况下,pytest会在名称以test_开头或以test.py结尾的Python模块中查找测试。同时,它期望测试函数名以test_开头。不过,用户可以通过在pytest配置文件(如pytest.ini、tox.ini或setup.cfg)中添加自定义配置来修改这一发现协议。


# content of pytest.ini
# Example 1: have pytest look for "check" instead of "test"
# can also be defined in tox.ini or setup.cfg file, although the section
# name in setup.cfg files should be "tool:pytest"
[pytest]
python_files = check_*.py
python_classes = Check
python_functions = *_check

让我们观察一个非常基础的测试函数示例。


class CheckClass(object):
  def one_check(self):
    x = "this"
    assert 'h' in x

  def two_check(self):
    x = "hello"
    assert hasattr(x, 'check')

注意,这里没有使用花哨的assertEqual或assertDictEqual等特定断言方法,而是使用了简单直接的assert语句。对于比较两个对象的简单操作,无需导入额外的断言函数。因为assert是Python语言内置的功能,无需重新发明轮子。

固定装置(Fixture)在此过程中发挥关键作用

查看测试功能,测试钱包软件的基本操作,例如:


// test_wallet.py
from wallet import Walletdef test_default_initial_amount():
  wallet = Wallet()
  assert wallet.balance == 0
  wallet.close()def test_setting_initial_amount():
  wallet = Wallet(initial_amount=100)
  assert wallet.balance == 100
  wallet.close()def test_wallet_add_cash():
  wallet = Wallet(initial_amount=10)
  wallet.add_cash(amount=90)
  assert wallet.balance == 100
  wallet.close()def test_wallet_spend_cash():
  wallet = Wallet(initial_amount=20)
  wallet.spend_cash(amount=10)
  assert wallet.balance == 10
  wallet.close()

注意,这里存在大量样板代码。此外,测试函数不仅执行测试逻辑,还负责实例化钱包对象并调用Wallet.close()进行清理,这种耦合增加了维护成本。

现在让我们看看如何使用pytest fixture去除样板代码


import pytest
from _pytest.fixtures import SubRequest
from wallet import Wallet#==================== fixtures
@pytest.fixture
def wallet(request: SubRequest):
  param = getattr(request, ‘param', None)
  if param:
   prepared_wallet = Wallet(initial_amount=param[0])
  else:
   prepared_wallet = Wallet()
  yield prepared_wallet
  prepared_wallet.close()#==================== testsdef test_default_initial_amount(wallet):
  assert wallet.balance == 0@pytest.mark.parametrize(‘wallet', [(100,)], indirect=True)
def test_setting_initial_amount(wallet):
  assert wallet.balance == 100@pytest.mark.parametrize(‘wallet', [(10,)], indirect=True)
def test_wallet_add_cash(wallet):
  wallet.add_cash(amount=90)
  assert wallet.balance == 100@pytest.mark.parametrize(‘wallet', [(20,)], indirect=True)
def test_wallet_spend_cash(wallet):
  wallet.spend_cash(amount=10)
  assert wallet.balance == 10

代码变得整洁了许多。测试函数非常简洁,仅执行其预期的测试逻辑。Fixture(如wallet)负责设置和拆卸、实例化和关闭钱包对象。这不仅有助于编写可重用的代码,还实现了数据与测试逻辑的分离。仔细观察可以发现,钱包初始金额是作为测试数据在测试逻辑之外提供的,而非硬编码在测试函数内部。


@pytest.mark.parametrize(‘wallet', [(10,)], indirect=True)

在更可控的环境中,您可以在存储库中放置一个测试数据文件(例如test-data.ini),并编写读取该文件的包装器。测试函数可以调用该包装器的接口来获取测试数据。

建议将Fixture定义在conftest.py文件中。这是pytest中的特殊文件,允许测试发现全局可用的Fixture。

如果存在针对许多不同数据集执行的测试用例呢?

无需担心,pytest提供了强大的参数化Fixture功能。让我们通过一个示例来了解它。

假设您的产品公开CLI接口以在本地管理它。此外,产品在启动时设置了许多默认参数,您需要验证所有这些参数的默认值。

我们可以考虑为每个设置编写一个单独的测试用例,但是使用pytest就显得容易得多。


@pytest.mark.parametrize(“setting_name, setting_value”, [(‘qdb_mem_usage', ‘low'),
(‘report_crashes', ‘yes'),
(‘stop_download_on_hang', ‘no'),
(‘stop_download_on_disconnect', ‘no'),
(‘reduce_connections_on_congestion', ‘no'),
(‘global.max_web_users', ‘1024'),
(‘global.max_downloads', ‘5'),
(‘use_kernel_congestion_detection', ‘no'),
(‘log_type', ‘normal'),
(‘no_signature_check', ‘no'),
(‘disable_xmlrpc', ‘no'),
(‘disable_ntp', ‘yes'),
(‘ssl_mode', ‘tls_1_2'),])def test_settings_defaults(self, setting_name, setting_value):
  assert product_shell.run_command(setting_name) == \
   self.”The current value for \'{0}\' is   \'{1}\'.”.format(setting_name, setting_value), \
 ‘The {} default should be {}'.format(preference_name, preference_value)

效果显著,不是吗?您只需编写13个测试用例(每个不同的setting_value对应一个)。未来如果向产品添加新设置,只需在参数列表中添加一个新的元组即可。

它是如何与selenium和API测试的UI测试集成的

产品可能拥有多种界面,包括我们上面讨论的CLI,以及GUI和API。在部署软件之前,对所有组件进行测试至关重要。在多个组件相互依赖和耦合的企业软件中,某一部分的更改可能会影响其他部分,因此全面测试不可或缺。

请记住,pytest只是一个促进“测试”执行的框架,而非特定类型的测试工具。因此,您可以使用Selenium构建GUI测试,或使用Python的requests库构建API测试,然后使用pytest来运行它们。

例如,在高层次上,这可能是您的测试存储库结构。


正如您在上面看到的,这种结构能够很好地分离组件。

  • apiobjects:为调用API端点创建包装器的理想位置。您可以使用BaseAPIObject及其派生类来满足需求。
  • helper:用于编写辅助方法。
  • 库文件:可被不同组件使用,例如您的Fixture(在conftest中)、PageObjects等。
  • pageobjects:PageObjects设计模式可用于创建代表不同GUI页面的类。我们在站得住使
  • 用Webium,它是Python的一个页面对象模式实现库。
  • 套件:您可以在这里编写pylint代码验证套件,这将有助于您对代码质量有信心。
  • 测试:可以根据测试的风格对测试目录进行分类。它使管理和研究您的测试变得容易。

这仅作为参考,存储库的结构和依赖关系可以按照您的需要进行布局。

我有足够的测试用例,想并行运行它们

您的测试套件中可能有大量的测试用例,并且有时您可能想并行地运行测试用例,以减少总体测试执行时间。

Pytest提供了一个很棒的并行运行测试的插件,名为Pytest -xdist,它用一些独特的执行模式扩展了Pytest。使用pip安装此插件


pip install pytest-xdist

让我们通过一个示例来快速研究它。

我有一个自动化测试存储库CloudApp,用于使用selenium进行GUI测试。此外,它还随着新的测试用例不断增长,现在已经有了数百个测试。我想做的是并行运行它们,并减少测试执行时间。

在终端中,只需在项目根文件夹/ tests文件夹中键入pytest。这将执行所有测试。


pytest -s -v -n=2


并行运行测试的pytest-xdist

这还可以帮助您在多个浏览器上并行运行测试。

报告

Pytest内置支持创建结果文件,可由Jenkins、Bamboo或其他持续集成服务器读取,使用如下调用:


pytest test/file/path — junitxml=path

这可以生成很好的XML风格的输出,可以由许多CI系统解析器解释。

结论

Pytest的受欢迎程度逐年上升。此外,它还拥有广泛的社区支持,这让您可以访问很多扩展,比如pytest-django,它可以帮助您为Django web应用程序集成编写测试。记住,pytest支持运行unittest测试用例,所以如果您正在使用unittest, pytest是值得考虑的。

到此这篇关于详解如何使用Pytest进行自动化测试的文章就介绍到这了,更多相关Pytest 自动化测试内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。