Как я могу проверить, вызывает ли устройство Pytest исключение? - PullRequest
0 голосов
/ 14 мая 2018

Вариант использования: в pytest тестовом наборе у меня есть @fixture, который вызывает исключения, если параметры командной строки для его конфигурации отсутствуют. Я написал тест для этого прибора, используя xfail:

import pytest
from <module> import <exception>

@pytest.mark.xfail(raises=<exception>)
def test_fixture_with_missing_options_raises_exception(rc_visard):
    pass

Однако выходные данные после запуска тестов не показывают тест как пройденный, а вместо этого "xfailed":

============================== 1 xfailed in 0.15 seconds ========================

Кроме того, я не могу проверить, вызывает ли fixture исключение для определенных отсутствующих параметров командной строки.

Есть ли лучший подход для этого? Могу ли я каким-то образом высмеивать параметры командной строки pytest, чтобы мне не нужно было вызывать определенные тесты через pytest --<commandline-option-a> <test-file-name>::<test-name>.

1 Ответ

0 голосов
/ 14 мая 2018

начальная настройка

Предположим, у вас есть упрощенный проект с conftest.py, содержащий следующий код:

import pytest


def pytest_addoption(parser):
    parser.addoption('--foo', action='store', dest='foo', default='bar',
                     help='--foo should be always bar!')

@pytest.fixture
def foo(request):
    fooval = request.config.getoption('foo')
    if fooval != 'bar':
        raise ValueError('expected foo to be "bar"; "{}" provided'.format(fooval))

Он добавляет новую командную строку arg --foo и фиксатор foo возвращает переданный аргумент или bar, если не указан.Если что-то еще, кроме bar прошло через --foo, прибор поднимает ValueError.

Вы используете прибор как обычно, например

def test_something(foo):
    assert foo == 'bar'

Теперь давайте проверим этот прибор.

подготовка

В этом примере сначала нужно выполнить простой рефакторинг.Переместите прибор и связанный с ним код в какой-то файл, называемый чем-то другим, чем conftest.py, например, my_plugin.py:

# my_plugin.py

import pytest


def pytest_addoption(parser):
    parser.addoption('--foo', action='store', dest='foo', default='bar',
                     help='--foo should be always bar!')

@pytest.fixture
def foo(request):
    fooval = request.config.getoption('foo')
    if fooval != 'bar':
        raise ValueError('expected foo to be "bar"; "{}" provided'.format(fooval))

В conftest.py, убедитесь, что новый плагин загружен:

# conftest.py

pytest_plugins = ['my_plugin']

Запустите существующий набор тестов, чтобы убедиться, что мы ничего не сломали, все тесты все равно должны пройти.

activ pytester

pytest предоставляет дополнительный плагин для написания плагинатесты под названием pytester.Он не активирован по умолчанию, поэтому вы должны сделать это вручную.В conftest.py, расширьте список плагинов с помощью pytester:

# conftest.py

pytest_plugins = ['my_plugin', 'pytester']

, пишущих тесты

Когда pytester активен, вы получаете новый доступный прибор под названием testdir.Он может генерировать и запускать pytest наборов тестов из кода.Вот как будет выглядеть наш первый тест:

# test_foo_fixture.py

def test_all_ok(testdir):

    testdata = '''
               def test_sample(foo):
                   assert True
               '''

    testconftest = '''
                   pytest_plugins = ['my_plugin']
                   '''

    testdir.makeconftest(testconftest)
    testdir.makepyfile(testdata)
    result = testdir.runpytest()
    result.assert_outcomes(passed=1)

То, что происходит здесь, должно быть довольно очевидным: мы предоставляем тестовый код в виде строки и testdir сгенерирует из него проект pytest в некоторый временный кодкаталог.Чтобы убедиться, что наше foo приспособление доступно в сгенерированном тестовом проекте, мы передаем его в сгенерированном conftest так же, как и в реальном.testdir.runpytest() запускает тестовый прогон, давая результат, который мы можем проверить.

Давайте добавим еще один тест, который проверяет, будет ли foo поднять ValueError:

def test_foo_valueerror_raised(testdir):
    testdata = '''
               def test_sample(foo):
                   assert True
               '''

    testconftest = '''
                   pytest_plugins = ['my_plugin']
                   '''

    testdir.makeconftest(testconftest)
    testdir.makepyfile(testdata)
    result = testdir.runpytest('--foo', 'baz')                                                                                                                                
    result.assert_outcomes(error=1)
    result.stdout.fnmatch_lines([
        '*ValueError: expected foo to be "bar"; "baz" provided'
    ])

Здесь мывыполните сгенерированные тесты с помощью --foo baz и затем проверьте, завершился ли один тест с ошибкой, а в выводе об ошибке содержится ожидаемое сообщение об ошибке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...