Захват сообщения с подтверждением в Pytest - PullRequest
1 голос
/ 07 апреля 2020

Я пытаюсь получить возвращаемое значение PyTest. Я запускаю эти тесты программным способом и хочу вернуть соответствующую информацию, если тест не пройден.

Я подумал, что, возможно, смогу вернуть значение ядра следующим образом, чтобы я мог распечатать эту информацию позже при выводе списка неудачных тестов:

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

Это не работает. Когда я позже перебираю сгенерированные TestReport s, я не могу получить доступ к какой-либо возвращаемой информации. Единственная информация, доступная в 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 голосов
/ 08 апреля 2020

Вы можете извлечь подробности неисправности из поднятого AssertionError в пользовательском pytest_exception_interact hookimpl. Пример:

# 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
<b>--------------------- Kernels reported in assert failures: ---------------------</b>
<b>test_spam.py::test_eggs reported 5.5.15-200.fc31.x86_64</b>
=========================== 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 ==========================
...