自动化测试框架pytest教程6-标签(标记)

标签简介

在pytest中,标记是一种告诉pytest某个特定测试有什么特别之处的方式。你可以把它们看成是标记或标识。如果有些测试很慢,你可以用@pytest.mark.slow标记它们,当你赶时间时,可以让pytest跳过这些测试。你可以从测试套件中挑选一些测试,用@pytest.mark.smoke标记它们,然后在持续集成系统中作为测试管道的第一阶段运行。

pytest包括内置的标记,可以修改测试运行的行为。我们已经使用了@pytest.mark.parametrize,在Parametrizing Functions中。除了我们可以创建并添加到我们的测试中的类似标签的标记外,内置标记告诉pytest对标记的测试做一些特殊处理。

内置标记

  • @pytest.mark.filterwarnings(warning)。

为给定的测试添加警告过滤器。

  • @pytest.mark.skip(reason=None):

跳过测试。

  • @pytest.mark.skipif(condition, ..., *, reason):

如果条件为 "真"跳过测试。

  • @pytest.mark.xfail(condition, ..., *, reason, run=True, raises=None, strict=xfail_strict)

希望测试失败。

  • @pytest.mark.parametrize(argnames, argvalues, indirect, ids, scope)。

多次调用测试函数,依次传入不同的参数。

  • @pytest.mark.usefixtures(fixturename1, fixturename2, ...)

将测试标记为需要所有指定的固定装置。

用pytest.mark.skip跳过测试

skip标记允许我们跳过测试。比方说,我们正在考虑在未来版本的Cards应用程序中增加排序的功能,所以我们想让Card类支持比较。我们用<这样写一个测试来比较Card对象。

ch6/builtins/test_skip.py

from cards import Card

import pytest


@pytest.mark.skip(reason="Card doesn't support < comparison yet")
def test_less_than():
    c1 = Card("a task")
    c2 = Card("b task")
    assert c1 < c2


def test_equality():
    c1 = Card("a task")
    c2 = Card("a task")
    assert c1 == c2

@pytest.mark.skip()标记告诉pytest跳过该测试。原因是可选的,但列出原因很重要,有助于以后的维护。

$ pytest test_skip.py
============================= 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 2 items

test_skip.py s.                                                          [100%]

======================== 1 passed, 1 skipped in 0.15s =========================

$ pytest -v -ra test_skip.py
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0 -- D:\ProgramData\Anaconda3\python.exe
cachedir: .pytest_cache
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
collecting ... collected 2 items

test_skip.py::test_less_than SKIPPED (Card doesn't support < compari...) [ 50%]
test_skip.py::test_equality PASSED                                       [100%]

=========================== short test summary info ===========================
SKIPPED [1] test_skip.py:6: Card doesn't support < comparison yet
======================== 1 passed, 1 skipped in 0.11s =========================

-r标志告诉pytest在会议结束时报告不同测试结果的原因。你给它一个单一的字符,代表你想要更多的信息的那种结果。默认的显示方式与输入-rfE相同:f表示测试失败;E表示错误。你可以用pytest --help查看整个列表。

-ra中的a代表 "除通过外的所有"。因此,-ra标志是最有用的,因为我们几乎总是想知道为什么某些测试没有通过的原因。

用pytest.mark.skipif有条件地跳过测试

假设我们知道在1.x.x版本的Cards应用程序中不支持排序,但在2.x.x版本中会支持。我们可以告诉pytest跳过所有低于2.x.x版本的Cards测试,就像这样。

ch6/builtins/test_skipif.py

import pytest
from cards import Card


import cards
from packaging.version import parse


@pytest.mark.skipif(
    parse(cards.__version__).major < 2,
    reason="Card < comparison not supported in 1.x",
)
def test_less_than():
    c1 = Card("a task")
    c2 = Card("b task")
    assert c1 < c2

skipif标记允许你传入任意多的条件,如果其中任何一个条件为真,则跳过测试。在我们的例子中,我们使用packaging.version.parse来让我们分离出主要版本,并与数字2进行比较。

这个例子使用了名为packaging的第三方包。如果你想尝试这个例子,先用管道安装packaging。version.parse只是其中众多方便的工具之一。更多信息见packaging文档。

有了skip和skipif标记,测试就不会实际运行。如果我们想运行这个测试,我们可以使用xfail。

用pytest.mark.xfail期望测试失败

  • @pytest.mark.xfail(condition, ..., *, reason, run=True,
    raises=None, strict=xfail_strict)

默认情况下,测试会运行,但run参数可以用来告诉pytest通过设置run=False来不运行测试。raises参数允许你提供异常类型或异常类型的元组,你希望导致xfail。strict告诉pytest,如果通过的测试应该被标记为XPASS(strict=False)或FAIL,strict=True。

让我们看一个例子。

ch6/builtins/test_xfail.py

import pytest
import cards
from cards import Card
from packaging.version import parse


@pytest.mark.xfail(
    parse(cards.__version__).major < 2,
    reason="Card < comparison not supported in 1.x",
)
def test_less_than():
    c1 = Card("a task")
    c2 = Card("b task")
    assert c1 < c2


@pytest.mark.xfail(reason="XPASS demo")
def test_xpass():
    c1 = Card("a task")
    c2 = Card("a task")
    assert c1 == c2


@pytest.mark.xfail(reason="strict demo", strict=True)
def test_xfail_strict():
    c1 = Card("a task")
    c2 = Card("a task")
    assert c1 == c2

我们在这里有三个测试:一个我们知道会失败,两个我们知道会通过。这些测试展示了使用xfail的失败和通过情况以及使用strict的效果。第一个例子也使用了可选的条件参数,其作用类似于 skipif 的条件。

$ pytest -v -ra test_xfail.py
============================= test session starts =============================
platform win32 -- Python 3.9.13, pytest-7.1.2, pluggy-1.0.0 -- D:\ProgramData\Anaconda3\python.exe
cachedir: .pytest_cache
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
collecting ... collected 3 items

test_xfail.py::test_less_than XFAIL (Card < comparison not supported...) [ 33%]
test_xfail.py::test_xpass XPASS (XPASS demo)                             [ 66%]
test_xfail.py::test_xfail_strict FAILED                                  [100%]

================================== FAILURES ===================================
______________________________ test_xfail_strict ______________________________
[XPASS(strict)] strict demo
=========================== short test summary info ===========================
XFAIL test_xfail.py::test_less_than
  Card < comparison not supported in 1.x
XPASS test_xfail.py::test_xpass XPASS demo
FAILED test_xfail.py::test_xfail_strict
=================== 1 failed, 1 xfailed, 1 xpassed in 0.17s ===================

标记为xfail的测试失败时,pytest确切地知道应该告诉你什么。"你是对的,它确实失败了,"这就是它对XFAIL的评价。对于标记为xfail但实际通过的测试,pytest并不十分确定该怎么说。它的结果可能是XPASSED,大概的意思是,"好消息,你认为会失败的测试已经通过了"。或者它的结果是FAILED,或者,"你认为它会失败,但它没有。你错了。"

如果你希望它们是FAILED,那么就设置strict。你可以像本例中那样,将strict设置为xfail标记的一个选项,或者在pytest.ini(pytest的主要配置文件)中通过xfail_strict=true设置全局设置。

始终使用xfail_strict的一个务实的原因是,我们倾向于仔细观察所有失败的测试。设置strict使你能够研究你的测试期望与代码行为不一致的情况。

你可能感兴趣的:(自动化测试框架pytest教程6-标签(标记))