Pytest学习教程_基础知识(一)

前言

pytest是一个用于编写和执行Python单元测试的框架。它提供了丰富的功能和灵活性,使得编写和运行测试变得简单而高效。

  pytest的一些主要特点和解释如下:

  • 自动发现测试:pytest会自动查找以"test_"开头的文件、类和函数,并将其识别为测试用例。这样可以避免手动编写复杂的测试套件。
  • 参数化测试:pytest支持使用@pytest.mark.parametrize装饰器来定义参数化测试。通过将不同的参数传递给测试函数,可以轻松地执行多次测试并检查不同输入组合的结果。
  • 断言支持:pytest提供了丰富而灵活的断言库,用于验证预期结果与实际结果是否一致。这些断言函数可以处理各种数据类型和比较逻辑,使编写断言语句变得更简单和直观。
  • 夹具(Fixture):夹具是pytest的一个强大特性,用于在测试之前准备环境并在测试之后进行清理工作。夹具可以帮助您创建和管理共享的测试资源,例如数据库连接、临时文件等。
  • 插件系统:pytest具有可扩展的插件系统,可以根据需要添加各种插件来扩展其功能。这些插件可以用于生成测试报告、集成其他测试工具、修改测试执行流程等。

总结来说,pytest是一个功能强大且易于使用的Python单元测试框架,它提供了丰富的特性和灵活的配置选项,使开发人员能够高效地进行测试驱动的开发,并保证代码质量和可靠性。

一、安装

1、pytest 安装

python 复制代码
安装命令: pip install -U pytest
查看版本: pytest --version

2、pytest 扩展插件

bash 复制代码
pip install pytest-cov
pip install pytest-html
pip install pytest-xdist
pip install pytest-repeat
pip install pytest-mock
pip install pytest-selenium
pip install pytest-timeout
pip install pytest-django
pip install pytest-flask
pip install pytest-bdd
pip install pytest-datadir
pip install pytest-ordering
pip install pytest-rerunfailures
pip install pytest-base-url
pip install allure-pytest
pip install pytest-randomly
pip install pytest-asyncio
  • pytest-cov: 生成测试覆盖报告,显示代码中被测试覆盖的部分
  • pytest-html: 生成漂亮的 HTML 报告,以可视化形式展示测试结果
  • pytest-xdist: 在多个进程或主机上并行执行测试,提高测试速度
  • pytest-repeat: 重复运行测试用例,用于检测稳定性和偶发性错误
  • pytest-mock: 使用 Mock 对象轻松地进行模拟和断言
  • pytest-selenium: 在 Selenium 中运行测试,用于自动化 Web 应用程序的端到端测试
  • pytest-timeout: 设置测试运行的超时时间,避免由于长时间运行而导致的阻塞
  • pytest-django: 对 Django 项目的测试提供支持和增强功能
  • pytest-flask: 对 Flask 应用程序的测试提供支持和增强功能
  • pytest-bdd: 使用行为驱动开发(BDD)方法编写测试,结合 Gherkin 语法
  • pytest-datadir: 在测试运行时访问测试数据目录
  • pytest-ordering: 控制测试函数的执行顺序
  • pytest-rerunfailures: 重新运行失败的测试用例,用于处理偶发性失败
  • pytest-base-url: 设置基本的 URL,用于在 Web 应用程序的测试中引用
  • allure-pytest: 生成 Allure 报告,提供详细和交互式的测试结果
  • pytest-randomly: 随机化测试用例的执行顺序,帮助发现不确定性问题
  • pytest-asyncio: 支持异步测试,用于编写基于 asyncio 的异步代码的测试

二、用例设计原则

  • 文件名要求: 通常 pytest 会自动发现以 test_ 开头或 _test 结尾的文件作为测试文件,但也可以通过配置进行自定义。例如 test_example.py 或 example_test.py 都符合命名约定。

  • 以 test_ 开头的函数: pytest 将识别以 test_ 开头的函数作为测试用例,这些函数应该包含您要测试的特定行为或功能。例如 def test_addition(): 是一个以 test_ 开头的测试用例函数。

  • 以 Test 开头的类和以 test_ 开头的方法: pytest 另一个常见的约定是,以 Test 开头的类用于组织相关的测试用例,并且类中以 test_ 开头的方法被识别为独立的测试用例。请注意,这些方法不能包含 __ init __ 方法。

  • 使用 assert 进行断言: 在 pytest 中,使用 assert 语句进行断言是推荐的做法。例如 assert add(2, 3) == 5 可以用于断言 add() 函数的结果是否符合预期。

三、代码示例

1、测试函数和测试类

python 复制代码
# content of test_sample.py
# 测试函数
def func(x):
    return x + 1

def test_answer():
    assert func(3) == 4
# 可以看到pytest自动地运行了test_answer函数,同时提示测试通过,因为func函数的返回值是4


# 测试类,把多条用例放到一个类中
class TestClass:
    def func(self, x):
        return x + 1

    def test_B(self):
        assert self.func(3) == 6, '结果不符合预期'

    def test_A(self):
        assert self.func(3) == 5
# 可以看到,pytest自动地运行了test_B和test_A函数,同时都提示测试失败,\
# 因为TestClass类中的func方法的返回值是4,而不是6和5,所以assert语句报错

2、参数化测试

python 复制代码
# content of test_sample.py
import pytest

@pytest.mark.parametrize("a, b, expected", [
    (2, 3, 5),
    (4, 5, 9),
    (6, 7, 13)
])
def test_addition(a, b, expected):
    assert a + b == expected

通过 @pytest.mark.parametrize 装饰器,指定了要传入 test_addition 函数的参数和预期结果。在这个例子中,我们定义了三组参数 (2, 3, 5)、(4, 5, 9) 和 (6, 7, 13)。

然后,test_addition 函数会依次接收每组参数,并执行断言语句 assert a + b == expected 进行验证。如果断言条件成立,即两数相加等于预期结果,那么测试通过;否则,会触发断言错误,测试失败。

3、跳过测试

python 复制代码
# content of test_sample.py
import pytest

@pytest.mark.skip(reason="Not implemented yet")
def test_multiply():
    assert 3 * 4 == 12

使用@pytest.mark.skip装饰器将其标记为跳过的测试,并提供了一个说明信息"Not implemented yet"

由于该测试函数被标记为跳过,因此在运行测试套件时,这个测试不会被执行。这可以作为一个占位符,表示该测试还没有实现。一旦实现了相应的功能,可以删除@pytest.mark.skip行或注释掉它,以便让测试函数正常运行。

4、分组和标记

python 复制代码
# content of test_sample.py
import pytest

@pytest.mark.group1
def test_addition():
    assert (1 + 2) == 3

@pytest.mark.group1
def test_subtraction():
    assert (5 - 3) == 2

@pytest.mark.group2
@pytest.mark.skip(reason="Not implemented yet")
def test_multiplication():
    assert (2 * 3) == 6

@pytest.mark.group2
def test_division():
    assert (10 / 2) == 5

@pytest.mark.group1和@pytest.mark.group2是自定义标记,可以用来对测试函数进行分组或分类。通过在运行测试时指定标记,可以选择性地运行特定的测试组

例如,可以使用以下命令只运行被标记为group1的测试:

python 复制代码
pytest -m group1

这样只会执行test_addition()和test_subtraction()函数,而跳过test_multiplication()和test_division()函数

  • 运行以上示例会有警告信息,这时我们需要把group1 和group2 注册到 pytest 中,在项目目录中创建一个pytest.ini(如果你尚未创建),并在其中定义自定义标记。下面是在pytest.ini 中注册 group1和group2 标记的示例:
bash 复制代码
[pytest]
markers =
    group1: group1 测试的描述
    group2: group2 测试的描述

5、异常处理

python 复制代码
# content of test_sample.py
import pytest


def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return a / b


def test_divide():
    with pytest.raises(ZeroDivisionError) as exc_info:
        divide(10, 0)

    assert str(exc_info.value) == "Cannot divide by zero"

在上面的示例中,divide 函数用于执行除法运算。如果除数 b 为零,则会抛出 ZeroDivisionError 异常。在测试函数 test_divide 中,我们使用 pytest.raises 上下文管理器捕获该异常,并断言其异常信息是否与预期相符。

当运行 pytest 命令来执行测试时,它将检测到 divide 函数引发了 ZeroDivisionError 异常,并且断言通过。这表明异常处理机制正常工作。

四、常用的断言方法

python 复制代码
assert x == y:判断x是否等于y
assert x != y:判断x是否不等于y
assert x > y:判断x是否大于y
assert x < y:判断x是否小于y
assert x >= y:判断x是否大于等于y
assert x <= y:判断x是否小于等于y
assert x 判断x为真
assert not x 判断x不为真
assert item in collection:判断item是否在collection中
assert item not in collection:判断item是否不在collection中

五、执行命令

1、Pytest执行命令

python 复制代码
pytest: 运行所有以test_*.py或*_test.py命名的文件中的测试函数。
pytest test_sample.py: 运行指定的test_sample.py文件中的测试函数。
pytest testing/: 运行指定目录下所有以test_*.py命名的文件中的测试函数。
pytest -k "test_B": 按关键字匹配运行包含test_B关键字的测试函数。
pytest test_sample.py::test_B: 运行指定的test_sample.py文件中的test_B函数。
pytest test_sample.py::TestClass::test_B: 运行指定的test_sample.py文件中的TestClass测试类中的test_B方法。

2、其他执行命令

python 复制代码
pytest -q: 使用-q/--quiet标志可以使输出保持简短。
pytest -v: 显示每个测试用例的执行结果。
pytest -s: 用于显示测试函数中的print()函数输出。
pytest -x: 第一次遇到错误后停止测试。
pytest --maxfail=2: 遇到两次错误后停止测试。
pytest -rs: -rs选项可以显示测试报告的摘要,包括已跳过的测试、错误和失败的数量以及原因。

六、目录结构组织

在使用 Pytest 进行单元测试时,你可以按照以下目录结构组织你的测试用例:

python 复制代码
project/
├── src/
│   ├── module1.py
│   └── module2.py
└── tests/
    ├── test_module1.py
    └── test_module2.py
  • project/ 是你的项目根目录
  • src/ 目录存放你的源代码文件
  • module1.pymodule2.py 是你要测试的模块或功能的源代码文件
  • tests/ 目录存放测试用例文件
  • test_module1.py 和 test_module2.py 是用于测试 module1.pymodule2.py
    的测试用例文件

你可以根据需要在 tests/ 目录下创建更多的测试用例文件,每个文件可以包含多个测试函数。在测试用例文件中,你可以使用 Pytest 提供的各种断言和装饰器来编写测试逻辑。

请注意,这只是一种常见的组织结构示例,你可以根据自己的项目需要进行调整和扩展。

相关推荐
青 春 记 忆5 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO35 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO7 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白7 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲9 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)10 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机10 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69211 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy12 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽12 小时前
真实即粗糙,光滑是伪造
人工智能·python