pytest-4.x.x:如何报告XFAILED之类的SKIPPED测试?

时间:2019-04-23 07:37:05

标签: python python-3.x testing automated-tests pytest

x测试失败时,打印的原因报告有关测试文件,测试类和测试用例的信息,而跳过的测试用例仅报告测试文件和调用跳过的行。

这是一个测试示例:

---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
~/anaconda3/lib/python3.7/site-packages/skimage/_shared/utils.py in safe_as_int(val, atol)
    147     try:
--> 148         np.testing.assert_allclose(mod, 0, atol=atol)
    149     except AssertionError:

~/anaconda3/lib/python3.7/site-packages/numpy/testing/_private/utils.py in assert_allclose(actual, desired, rtol, atol, equal_nan, err_msg, verbose)
   1451     assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
-> 1452                          verbose=verbose, header=header, equal_nan=equal_nan)
   1453 

~/anaconda3/lib/python3.7/site-packages/numpy/testing/_private/utils.py in assert_array_compare(comparison, x, y, err_msg, verbose, header, precision, equal_nan, equal_inf)
    788                                 names=('x', 'y'), precision=precision)
--> 789             raise AssertionError(msg)
    790     except ValueError:

AssertionError: 
Not equal to tolerance rtol=1e-07, atol=0.001

(mismatch 66.66666666666666%)
 x: array([0.25, 0.5 , 0.  ])
 y: array(0)

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-27-754225493c2e> in <module>
      1 for i in range(len(rgb_val)):
      2     downSample.append(resize(rgb_val[i], ((rgb_val[i].shape[0]) / 16, (rgb_val[i].shape[1]) / 16),
----> 3                        anti_aliasing=True))    
      4 
      5 #     downSample.append(resize(i, i.shape[0]/4, i.shape[1]/4), anti_aliasing = True)

~/anaconda3/lib/python3.7/site-packages/skimage/transform/_warps.py in resize(image, output_shape, order, mode, cval, clip, preserve_range, anti_aliasing, anti_aliasing_sigma)
    167         out = warp(image, tform, output_shape=output_shape, order=order,
    168                    mode=mode, cval=cval, clip=clip,
--> 169                    preserve_range=preserve_range)
    170 
    171     else:  # n-dimensional interpolation

~/anaconda3/lib/python3.7/site-packages/skimage/transform/_warps.py in warp(image, inverse_map, map_args, output_shape, order, mode, cval, clip, preserve_range)
    805         output_shape = input_shape
    806     else:
--> 807         output_shape = safe_as_int(output_shape)
    808 
    809     warped = None

~/anaconda3/lib/python3.7/site-packages/skimage/_shared/utils.py in safe_as_int(val, atol)
    149     except AssertionError:
    150         raise ValueError("Integer argument required but received "
--> 151                          "{0}, check inputs.".format(val))
    152 
    153     return np.round(val).astype(np.int64)

ValueError: Integer argument required but received (134.25, 186.5, 3), check inputs.

这是实际结果:

#!/usr/bin/env pytest

import pytest

@pytest.mark.xfail(reason="Reason of failure")
def test_1():
    pytest.fail("This will fail here")

@pytest.mark.skip(reason="Reason of skipping")
def test_2():
    pytest.fail("This will fail here")

但是我希望得到类似的东西

pytest test_file.py -rsx
============================= test session starts =============================
platform linux -- Python 3.5.2, pytest-4.4.1, py-1.7.0, pluggy-0.9.0
rootdir: /home/ashot/questions
collected 2 items                                                             

test_file.py xs                                                         [100%]
=========================== short test summary info ===========================
SKIPPED [1] test_file.py:9: Reason of skipping
XFAIL test_file.py::test_1
  Reason of failure

==================== 1 skipped, 1 xfailed in 0.05 seconds =====================

2 个答案:

答案 0 :(得分:0)

您有两种可能的方法来实现这一目标。快速而肮脏的方法:只需在您的_pytest.skipping.show_xfailed中重新定义test_file.py

import _pytest

def custom_show_xfailed(terminalreporter, lines):
    xfailed = terminalreporter.stats.get("xfailed")
    if xfailed:
        for rep in xfailed:
            pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
            reason = rep.wasxfail
            s = "XFAIL %s" % (pos,)
            if reason:
                s += ": " + str(reason)
            lines.append(s)

# show_xfailed_bkp = _pytest.skipping.show_xfailed
_pytest.skipping.show_xfailed = custom_show_xfailed

... your tests

(不是这样)干净的方法:在conftest.py所在的目录中创建一个test_file.py文件,并添加一个钩子:

import pytest
import _pytest

def custom_show_xfailed(terminalreporter, lines):
    xfailed = terminalreporter.stats.get("xfailed")
    if xfailed:
        for rep in xfailed:
            pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
            reason = rep.wasxfail
            s = "XFAIL %s" % (pos,)
            if reason:
                s += ": " + str(reason)
            lines.append(s)

@pytest.hookimpl(tryfirst=True)
def pytest_terminal_summary(terminalreporter):
    tr = terminalreporter
    if not tr.reportchars:
        return

    lines = []
    for char in tr.reportchars:
        if char == "x":
            custom_show_xfailed(terminalreporter, lines)
        elif char == "X":
            _pytest.skipping.show_xpassed(terminalreporter, lines)
        elif char in "fF":
            _pytest.skipping.show_simple(terminalreporter, lines, 'failed', "FAIL %s")
        elif char in "sS":
            _pytest.skipping.show_skipped(terminalreporter, lines)
        elif char == "E":
            _pytest.skipping.show_simple(terminalreporter, lines, 'error', "ERROR %s")
        elif char == 'p':
            _pytest.skipping.show_simple(terminalreporter, lines, 'passed', "PASSED %s")

    if lines:
        tr._tw.sep("=", "short test summary info")
        for line in lines:
            tr._tw.line(line)

    tr.reportchars = [] # to avoid further output

第二种方法过于矫kill过正,因为您必须重新定义整个pytest_terminal_summary

答案 1 :(得分:0)

感谢this answer,我发现以下最适合我的解决方案。 我已经在测试套件的根目录中创建了conftest.py文件,其内容如下:

import _pytest.skipping as s

def show_xfailed(tr, lines):
    for rep in tr.stats.get("xfailed", []):
        pos = tr.config.cwd_relative_nodeid(rep.nodeid)
        reason = rep.wasxfail
        s = "XFAIL\t%s" % pos
        if reason:
            s += ": " + str(reason)
        lines.append(s)

s.REPORTCHAR_ACTIONS["x"] = show_xfailed

def show_skipped(tr, lines):
    for rep in tr.stats.get("skipped", []):
        pos = tr.config.cwd_relative_nodeid(rep.nodeid)
        reason = rep.longrepr[-1]
        if reason.startswith("Skipped: "):
            reason = reason[9:]
        verbose_word = s._get_report_str(tr.config, report=rep)
        lines.append("%s\t%s: %s" % (verbose_word, pos, reason))

s.REPORTCHAR_ACTIONS["s"] = show_skipped
s.REPORTCHAR_ACTIONS["S"] = show_skipped

现在我要获得以下输出:

./test_file.py -rsx
============================= test session starts =============================
platform linux -- Python 3.5.2, pytest-4.4.1, py-1.7.0, pluggy-0.9.0
rootdir: /home/ashot/questions
collected 2 items                                                             

test_file.py xs                                                         [100%]
=========================== short test summary info ===========================
SKIPPED test_file.py::test_2: Reason of skipping
XFAIL   test_file.py::test_1: Reason of failure

==================== 1 skipped, 1 xfailed in 0.05 seconds =====================
相关问题