начальная настройка
Предположим, у вас есть упрощенный проект с 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
и затем проверьте, завершился ли один тест с ошибкой, а в выводе об ошибке содержится ожидаемое сообщение об ошибке.