hi,你好!欢迎访问本站!登录
本站由简数采集腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

10、pytest -- skip和xfail标记

2019-11-18杂谈搜奇网45°c
A+ A-

目次

  • 1. 跳过测试用例的实行
    • 1.1. @pytest.mark.skip装潢器
    • 1.2. pytest.skip要领
    • 1.3. @pytest.mark.skipif装潢器
    • 1.4. pytest.importorskip要领
    • 1.5. 跳过测试类
    • 1.6. 跳过测试模块
    • 1.7. 跳过指定文件或目次
    • 1.8. 总结
  • 2. 标记用例为预期失利的
    • 2.1. 去使能xfail标记
  • 3. 连系pytest.param要领

往期索引:https://www.cnblogs.com/luizyao/p/11771740.html

现实工作中,测试用例的实行可能会依赖于一些外部前提,比方:只能运行在某个特定的操作体系(Windows),或许我们自身希冀它们测试失利,比方:被某个已知的Bug所壅塞;假如我们能为这些用例提早打上标记,那末pytest就响应地预处理它们,并供应一个越发正确的测试报告;

在这类场景下,经常运用的标记有:

  • skip:只要当某些前提获得满足时,才实行测试用例,不然跳过全部测试用例的实行;比方,在非Windows平台上跳过只支撑Windows体系的用例;
  • xfail:由于一个确实的缘由,我们晓得这个用例会失利;比方,对某个未完成的功用的测试,或许壅塞于某个已知Bug的测试;

pytest默许不显现skipxfail用例的详细信息,我们能够经由过程-r选项来自定义这类行动;

平常,我们运用一个字母作为一种范例的代表,详细的划定规矩以下:

(f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed(p/P), or (A)ll

比方,显现结果为XFAILXPASSSKIPPED的用例:

pytest -rxXs

更多细节能够参考:2、运用和挪用 -- 总结报告

1. 跳过测试用例的实行

1.1. @pytest.mark.skip装潢器

跳过实行某个用例最简朴的体式格局就是运用@pytest.mark.skip装潢器,而且能够设置一个可选参数reason,表明跳过的缘由;

@pytest.mark.skip(reason="no way of currently testing this")
def test_the_unknown():
    ...

1.2. pytest.skip要领

假如我们想在测试实行时期(也能够在SetUp/TearDown时期)强迫跳过后续的步骤,能够斟酌pytest.skip()要领,它一样能够设置一个参数msg,表明跳过的缘由;

def test_function():
    if not valid_config():
        pytest.skip("unsupported configuration")

别的,我们还能够为其设置一个布尔型的参数allow_module_level(默许是False),表明是不是许可在模块中挪用这个要领,假如置为True,则跳过模块中盈余的部份;

比方,在Windows平台下,不测试这个模块:

import sys
import pytest

if not sys.platform.startswith("win"):
    pytest.skip("skipping windows-only tests", allow_module_level=True)

注重:

当在用例中设置allow_module_level参数时,并不会见效;

def test_one():
    pytest.skip("跳出", allow_module_level=True)


def test_two():
    assert 1

也就是说,在上述示例中,并不会跳过test_two用例;

1.3. @pytest.mark.skipif装潢器

假如我们想有前提的跳过某些测试用例的实行,能够运用@pytest.mark.skipif装潢器;

比方,当python的版本小于3.6时,跳过用例:

import sys


@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_function():
    ...

我们也能够在两个模块之间同享pytest.mark.skipif标记;

比方,我们在test_module.py中定义了minversion,表明当python的最低支撑版本:

# src/chapter-10/test_module.py

import sys

import pytest

minversion = pytest.mark.skipif(sys.version_info < (3, 8),
                                reason='请运用 python 3.8 或许更高的版本。')


@minversion
def test_one():
    assert True

而且,在test_other_module.py中引入了minversion

# src/chapter-10/test_other_module.py

from test_module import minversion


@minversion
def test_two():
    assert True

如今,我们来实行这两个用例(当前虚拟环境的python版本为3.7.3):

λ pipenv run pytest -rs -k 'module' src/chapter-10/
================================ test session starts ================================= 
platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: D:\Personal Files\Projects\pytest-chinese-doc
collected 2 items

src\chapter-10\test_module.py s                                                 [ 50%] 
src\chapter-10\test_other_module.py s                                           [100%]

============================== short test summary info =============================== 
SKIPPED [1] src\chapter-10\test_module.py:29: 请运用 python 3.8 或许更高的版本。
SKIPPED [1] src\chapter-10\test_other_module.py:26: 请运用 python 3.8 或许更高的版本。
================================= 2 skipped in 0.03s =================================

能够看到,minversion在两个测试模块中都见效了;

因而,在大型的测试项目中,能够在一个文件中定义一切的实行前提,须要时再引入到模块中;

别的,须要注重的是,当一个用例指定了多个skipif前提时,只需满足个中一个,就能够跳过这个用例的实行;

注重:不存在pytest.skipif()的要领;

1.4. pytest.importorskip要领

当引入某个模块失利时,我们一样能够跳过后续部份的实行;

docutils = pytest.importorskip("docutils")

我们也能够为其指定一个最低满足要求的版本,推断的根据是搜检引入模块的__version__属性:

docutils = pytest.importorskip("docutils", minversion="0.3") 

我们还能够再为其指定一个reason参数,表明跳过的缘由;

我们注重到pytest.importorskippytest.skip(allow_module_level=True)都能够在模块的引入阶段跳过盈余部份;现实上,在源码中它们抛出的都是一样的非常:

# pytest.skip(allow_module_level=True)

raise Skipped(msg=msg, allow_module_level=allow_module_level)
# pytest.importorskip()

raise Skipped(reason, allow_module_level=True) from None

只是importorskip分外增加了minversion参数:

# _pytest/outcomes.py
 
if minversion is None:
        return mod
    verattr = getattr(mod, "__version__", None)
    if minversion is not None:
        if verattr is None or Version(verattr) < Version(minversion):
            raise Skipped(
                "module %r has __version__ %r, required is: %r"
                % (modname, verattr, minversion),
                allow_module_level=True,
            )

从中我们也证明了,它现实搜检的是模块的__version__属性;

所以,关于平常场景下,运用下面的要领能够完成一样的结果:

try:
    import docutils
except ImportError:
    pytest.skip("could not import 'docutils': No module named 'docutils'",
                allow_module_level=True)

1.5. 跳过测试类

在类上运用@pytest.mark.skip@pytest.mark.skipif

# src/chapter-10/test_skip_class.py

import pytest


@pytest.mark.skip("作用于类中的每个用例,所以 pytest 共网络到两个 SKIPPED 的用例。")
class TestMyClass():
    def test_one(self):
        assert True

    def test_two(self):
        assert True

1.6. 跳过测试模块

在模块中定义pytestmark变量(引荐):

# src/chapter-10/test_skip_module.py

import pytest

pytestmark = pytest.mark.skip('作用于模块中的每个用例,所以 pytest 共网络到两个 SKIPPED 的用例。')


def test_one():
    assert True


def test_two():
    assert True

或许,在模块中挪用pytest.skip要领,并设置allow_module_level=True

# src/chapter-10/test_skip_module.py

import pytest

pytest.skip('在用例网络阶段就已跳出了,所以不会网络就任何用例。', allow_module_level=True)


def test_one():
    assert True


def test_two():
    assert True

1.7. 跳过指定文件或目次

经由过程在conftest.py中设置collect_ignore_glob项,能够在用例的网络阶段跳过指定的文件和目次;

比方,跳过当前测试目次中文件名婚配test_*.py划定规矩的文件和config的子文件夹sub中的文件:

collect_ignore_glob = ['test*.py', 'config/sub']

更多细节能够参考:https://docs.pytest.org/en/5.1.3/example/pythoncollection.html#customizing-test-collection

1.8. 总结

pytest.mark.skip pytest.mark.skipif pytest.skip pytest.importorskip conftest.py
用例 @pytest.mark.skip() @pytest.mark.skipif() pytest.skip(msg='') / /
@pytest.mark.skip() @pytest.mark.skipif() / / /
模块 pytestmark = pytest.mark.skip() pytestmark = pytest.mark.skipif() pytest.skip(allow_module_level=True) pytestmark = pytest.importorskip() /
文件或目次 / / / / collect_ignore_glob

2. 标记用例为预期失利的

我们能够运用@pytest.mark.xfail标记用例,示意希冀这个用例实行失利;

用例会一般实行,只是失利时不再显现客栈信息,终究的结果有两个:用例实行失利时(XFAIL:相符预期的失利)、用例实行胜利时(XPASS:不相符预期的胜利)

别的,我们也能够经由过程pytest.xfail要领在用例实行过程当中直接标记用例结果为XFAIL,并跳过盈余的部份:

def test_function():
    if not valid_config():
        pytest.xfail("failing configuration (but should work)")

一样能够为pytest.xfail指定一个reason参数,表明缘由;

下面我们来重点看一下@pytest.mark.xfail的用法:

  • condition位置参数,默许值为None

    @pytest.mark.skipif一样,它也能够吸收一个python表达式,表明只要满足前提时才标记用例;

    比方,只在pytest 3.6版本以上标记用例:

    @pytest.mark.xfail(sys.version_info >= (3, 6), reason="python3.6 api changes")
    def test_function():
        ...
  • reason关键字参数,默许值为None

    能够指定一个字符串,表明标记用例的缘由;

  • strict关键字参数,默许值为False

    strict=False时,假如用例实行失利,结果标记为XFAIL,示意相符预期的失利;假如用例实行胜利,结果标记为XPASS,示意不相符预期的胜利;

    strict=True时,假如用例实行胜利,结果将标记为FAILED,而不再是XPASS了;

    我们也能够在pytest.ini文件中设置:

    [pytest]
    xfail_strict=true
  • raises关键字参数,默许值为None

    能够指定为一个非常类或许多个非常类的元组,表明我们希冀用例上报指定的非常;

    假如用例的失利不是由于所希冀的非常致使的,pytest将会把测试结果标记为FAILED;

  • run关键字参数,默许值为True:

    run=False时,pytest不会再实行测试用例,直接将结果标记为XFAIL

我们以下表来总结差别参数组合对测试结果的影响(个中xfail = pytest.mark.xfail):

@xfail() @xfail(strict=True) @xfail(raises=IndexError) @xfail(strict=True, raises=IndexError) @xfail(..., run=False)
用例测试胜利 XPASS FAILED XPASS FAILED XFAIL
用例测试失利,上报AssertionError XFAIL XFAIL FAILED FAILED XFAIL
用例上报IndexError XFAIL XFAIL XFAIL XFAIL XFAIL

2.1. 去使能xfail标记

我们能够经由过程命令行选项pytest --runxfail往来来往使能xfail标记,使这些用例变成一般实行的用例,似乎没有被标记过一样:

一样,pytest.xfail()要领也将会失效;

3. 连系pytest.param要领

pytest.param要领可用于为@pytest.mark.parametrize或许参数化的fixture指定一个详细的实参,它有一个关键字参数marks,能够吸收一个或一组标记,用于标记这轮测试的用例;

我们以下面的例子来申明:

# src/chapter-10/test_params.py

import pytest
import sys


@pytest.mark.parametrize(
    ('n', 'expected'),
    [(2, 1),
     pytest.param(2, 1, marks=pytest.mark.xfail(), id='XPASS'),
     pytest.param(0, 1, marks=pytest.mark.xfail(raises=ZeroDivisionError), id='XFAIL'),
     pytest.param(1, 2, marks=pytest.mark.skip(reason='无效的参数,跳过实行')),
     pytest.param(1, 2, marks=pytest.mark.skipif(sys.version_info <= (3, 8), reason='请运用3.8及以上版本的python。'))])
def test_params(n, expected):
    assert 2 / n == expected

实行:

λ pipenv run pytest -rA src/chapter-10/test_params.py
================================ test session starts ================================= 
platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0
rootdir: D:\Personal Files\Projects\pytest-chinese-doc
collected 5 items

src\chapter-10\test_params.py .Xxss                                             [100%]

======================================= PASSES ======================================= 
============================== short test summary info =============================== 
PASSED src/chapter-10/test_params.py::test_params[2-1]
SKIPPED [1] src\chapter-10\test_params.py:26: 无效的参数,跳过实行
SKIPPED [1] src\chapter-10\test_params.py:26: 请运用3.8及以上版本的python。
XFAIL src/chapter-10/test_params.py::test_params[XFAIL]
XPASS src/chapter-10/test_params.py::test_params[XPASS]
================= 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.08s =================

关于参数化的fixture的细节能够参考:4、fixtures:明白的、模块化的和可扩大的 -- 在参数化的fixture中标记用例

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
10、pytest -- skip和xfail标记

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282399.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>