在Pytest中捕获断言消息

时间:2020-04-07 07:09:30

标签: python unit-testing pytest python-unittest

我正在尝试捕获PyTest的返回值。我正在以编程方式运行这些测试,当测试失败时,我想返回相关信息。

我认为我也许可以按以下方式返回kernel的值,以便以后列出失败的测试时可以打印该信息:

def test_eval(test_input, expected):
    kernel = os.system("uname -r")
    assert eval(test_input) == expected, kernel

这不起作用。当我以后遍历生成的TestReport时,无法访问任何返回信息。 TestReport中唯一可用的信息是测试的名称和True / False

例如,其中一份测试报告如下所示:

<TestReport 'test_simulation.py::test_host_has_correct_kernel_version[simulation-host]' when='call' outcome='failed'>

有一种方法可以在断言失败后返回一个值,返回到TestReport?我尝试使用PyTest插件执行此操作,但未成功。

这是我用来以编程方式运行测试的代码。您可以看到我要在哪里访问返回值。

import pytest
from util import bcolors

class Plugin:
    def __init__(self):
        self.passed_tests = set()
        self.skipped_tests = set()
        self.failed_tests = set()
        self.unknown_tests = set()
    def pytest_runtest_logreport(self, report):
        print(report)
        if report.passed:
            self.passed_tests.add(report)
        elif report.skipped:
            self.skipped_tests.add(report)
        elif report.failed:
            self.failed_tests.add(report)
        else:
            self.unknown_tests.add(report)

if __name__ == "__main__":
    plugin = Plugin()
    pytest.main(["-s", "-p", "no:terminal"], plugins=[plugin])
    for passed in plugin.passed_tests:
        result = passed.nodeid
        print(bcolors.OKGREEN + "[OK]\t" + bcolors.ENDC + result)
    for skipped in plugin.skipped_tests:
        result = skipped.nodeid
        print(bcolors.OKBLUE + "[SKIPPED]\t" + bcolors.ENDC + result)
    for failed in plugin.failed_tests:
        result = failed.nodeid
        print(bcolors.FAIL + "[FAIL]\t" + bcolors.ENDC + result)
    for unknown in plugin.unknown_tests:
        result = unknown.nodeid
        print(bcolors.FAIL + "[FAIL]\t" + bcolors.ENDC + result)

目标是在打印FAILED测试时能够打印出“额外的上下文信息”,以便立即有信息可用于调试测试失败的原因。

1 个答案:

答案 0 :(得分:0)

您可以在自定义pytest_exception_interact hookimpl中从凸起的AssertionError中提取故障详细信息。示例:

# conftest.py
def pytest_exception_interact(node, call, report):
    # assertion message should be parsed here
    # because pytest rewrites assert statements in bytecode
    message = call.excinfo.value.args[0]
    lines = message.split()
    kernel = lines[0]
    report.sections.append((
        'Kernels reported in assert failures:',
        f'{report.nodeid} reported {kernel}'
    ))

运行测试模块

import subprocess

def test_bacon():
    assert True

def test_eggs():
    kernel = subprocess.run(
        ["uname", "-r"],
        stdout=subprocess.PIPE,
        text=True
    ).stdout
    assert 0 == 1, kernel

产量:

test_spam.py::test_bacon PASSED                                          [ 50%]
test_spam.py::test_eggs FAILED                                           [100%]

=================================== FAILURES ===================================
__________________________________ test_eggs ___________________________________

    def test_eggs():
        kernel = subprocess.run(
            ["uname", "-r"],
            stdout=subprocess.PIPE,
            text=True
        ).stdout
>       assert 0 == 1, kernel
E       AssertionError: 5.5.15-200.fc31.x86_64
E         
E       assert 0 == 1
E         +0
E         -1

test_spam.py:12: AssertionError
--------------------- Kernels reported in assert failures: ---------------------
test_spam.py::test_eggs reported 5.5.15-200.fc31.x86_64
=========================== short test summary info ============================
FAILED test_spam.py::test_eggs - AssertionError: 5.5.15-200.fc31.x86_64
========================= 1 failed, 1 passed in 0.05s ==========================
相关问题