当前位置: 首页>数据库>正文

自动化测试框架pytest教程4-内置Fixture(夹具)

pytest的开发者在pytest中包含了一些常用的Fixture。pytest预包装的Fixture可以帮助你在测试中轻松而一致地做一些非常有用的事情。例如pytest包含的内置Fixture可以处理临时目录和文件,访问命令行选项,在测试会话之间通信,验证输出流,修改环境变量,以及询问警告。内置固定程序是对pytest的核心功能的扩展。

tmp_path和tmp_path_factory

tmp_path 和 tmp_path_factory Fixture用于创建临时目录。tmp_path返回一个pathlib.Path实例,该实例指向一个临时目录,在你的测试期间和更长的时间内一直存在。tmp_path_factory session-scope fixture返回一个TempPathFactory对象。这个对象有一个mktemp()函数来返回Path对象。你可以使用mktemp()来创建多个临时目录。

ch4/test_tmp.py

def test_tmp_path(tmp_path):
    file = tmp_path / "file.txt"
    file.write_text("Hello")
    assert file.read_text() == "Hello"


def test_tmp_path_factory(tmp_path_factory):
    path = tmp_path_factory.mktemp("sub")
    file = path / "file.txt"
    file.write_text("Hello")
    assert file.read_text() == "Hello"

使用tmp_path_factory,你必须调用mktemp()来获得一个目录。tmp_path_factory是session 范围。tmp_path是function 范围。

在上一章中,我们使用标准库中的tempfile.TemporaryDirectory作为我们的db夹具。

import cards
import pytest


@pytest.fixture(scope="session")
def db(tmp_path_factory):
    """CardsDB object connected to a temporary database"""
    db_path = tmp_path_factory.mktemp("cards_db")
    db_ = cards.CardsDB(db_path)
    yield db_
    db_.close()

很好。注意,这也允许我们删除两个导入语句,因为我们不需要导入 pathlib 或 tempfile。

下面是两个相关的内置固定程序。

*tmpdir-类似于tmp_path,但返回一个py.path.local对象。py.path.local比pathlib更早,pathlib是在Python 3.4中加入的。py.path.local在pytest中被慢慢淘汰,而采用pathlib版本。因此,我推荐使用 tmp_path。

tmpdir_factory-类似于tmp_path_factory,只是它的mktemp函数返回py.path.local对象而不是pathlib.Path对象。

所有pytest临时目录固定的基础目录是由系统和用户决定的,包括一个pytest-NUM部分,其中NUM在每个会话中递增。基准目录在会话结束后立即保持原样,以便在测试失败时进行检查。pytest最终会对其进行清理。只有最近的几个临时基础目录被留在系统中。

如果需要,你也可以用pytest --basetemp=mydir指定你自己的基础目录。

使用capsys

有时应用程序代码向stdout、stderr等输出一些东西。

$ cards version
1.0.0
$ python -i
>>> import cards
>>> cards.__version__
'1.0.0'

测试的一个方法是用subprocess.run()实际运行命令,抓取输出,并与API中的版本进行比较。

import subprocess


def test_version_v1():
    process = subprocess.run(
        ["cards", "version"], capture_output=True, text=True
    )
    output = process.stdout.rstrip()
    assert output == cards.__version__

def test_version_v2(capsys):
    cards.cli.version()
    output = capsys.readouterr().out.rstrip()
    assert output == cards.__version__

capsys能够捕获写到stdout和stderr的数据。我们可以直接调用CLI中实现这一功能的方法,并使用capsys来读取输出。

capsys的另一个特点是能够暂时禁用pytest的正常输出捕获。pytest通常捕获你的测试和应用程序代码的输出。这包括打印语句。

ch4/test_print.py

def test_normal():
    print("\nnormal print")


def test_fail():
    print("\nprint in failing test")
    assert False

# 另一种总是包括输出的方法是使用 capsys.disabled()
def test_disabled(capsys):
    with capsys.disabled():
        print("\ncapsys disabled print")

如果我们运行它,没有看到任何输出。

# pytest捕获了所有的输出。这有助于保持命令行会话的清洁。
$ pytest test_print.py::test_normal
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0
rootdir: D:\code\pytest_quick, configfile: pytest.ini
plugins: allure-pytest-2.12.0, Faker-4.18.0, tep-0.8.2, anyio-3.5.0
collected 1 item

test_print.py .                                                          [100%]

============================== 1 passed in 0.10s ==============================

# 有时我们希望看到所有的输出,即使是在通过测试时。我们可以使用-s或-capture=no标志来实现。

$ pytest -s test_print.py::test_normal
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0
rootdir: D:\code\pytest_quick, configfile: pytest.ini
plugins: allure-pytest-2.12.0, Faker-4.18.0, tep-0.8.2, anyio-3.5.0
collected 1 item

test_print.py
normal print
.

============================== 1 passed in 0.07s ==============================

$ pytest test_print.py::test_fail
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0
rootdir: D:\code\pytest_quick, configfile: pytest.ini
plugins: allure-pytest-2.12.0, Faker-4.18.0, tep-0.8.2, anyio-3.5.0
collected 1 item

test_print.py F                                                          [100%]

================================== FAILURES ===================================
__________________________________ test_fail __________________________________

    def test_fail():
        print("\nprint in failing test")
>       assert False
E       assert False

test_print.py:7: AssertionError
---------------------------- Captured stdout call -----------------------------

print in failing test
=========================== short test summary info ===========================
FAILED test_print.py::test_fail - assert False
============================== 1 failed in 0.13s ==============================

$ pytest test_print.py::test_disabled
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0
rootdir: D:\code\pytest_quick, configfile: pytest.ini
plugins: allure-pytest-2.12.0, Faker-4.18.0, tep-0.8.2, anyio-3.5.0
collected 1 item

test_print.py
capsys disabled print
.                                                          [100%]

============================== 1 passed in 0.08s ==============================


以下是相关的内置Fixture。

  • capfd-类似于capsys,但捕获文件描述符1和2,通常与stdout和stderr相同。
  • capsysbinary- capsys捕捉文本,capsysbinary捕捉字节。
  • capfdbinary-捕获文件描述符1和2上的字节。
  • caplog-捕获用日志包编写的输出。

https://www.xamrdz.com/database/6h21886127.html

相关文章: