Как отключить тест с помощью py.test?
Скажем, у меня есть куча тестов:
def test_func_one():
...
def test_func_two():
...
def test_func_three():
...
Есть ли декоратор или что-то подобное, что я мог бы добавить к функциям, чтобы запретить запуску py.test только этого теста? Результат может выглядеть примерно так...
@pytest.disable()
def test_func_one():
...
def test_func_two():
...
def test_func_three():
...
Я искал что-то подобное в документации по py.test, но думаю, что-то здесь не хватает.
10 ответов
В Pytest есть декораторы пропуска и пропуска, похожие на модуль юнит-теста Python (который использует skip
а также skipIf
), который можно найти в документации здесь.
Примеры по ссылке можно найти здесь:
@pytest.mark.skip(reason="no way of currently testing this")
def test_the_unknown():
...
import sys
@pytest.mark.skipif(sys.version_info < (3,3),
reason="requires python3.3")
def test_function():
...
Первый пример всегда пропускает тест, второй пример позволяет вам условно пропустить тесты (отлично, когда тесты зависят от платформы, исполняемой версии или дополнительных библиотек.
Например, если я хочу проверить, установлена ли у кого-то библиотека панд для теста.
import sys
try:
import pandas as pd
except ImportError:
pass
@pytest.mark.skipif('pandas' not in sys.modules,
reason="requires the Pandas library")
def test_pandas_function():
...
skip
Декоратор сделает работу:
@pytest.mark.skip(reason="no way of currently testing this")
def test_func_one():
# ...
(reason
Аргумент необязателен, но всегда полезно указать, почему тест пропускается).
Существует также skipif()
это позволяет отключить тест, если выполняется какое-то определенное условие.
Эти декораторы могут применяться к методам, функциям или классам.
Чтобы пропустить все тесты в модуле, определите глобальный pytestmark
переменная:
# test_module.py
pytestmark = pytest.mark.skipif(...)
Вы можете отметить тест значком skip
а также skipif
декораторы, если вы хотите пропустить тест в pytest
.
Пропуск теста
@pytest.mark.skip(reason="no way of currently testing this")
def test_func_one():
...
Самый простой способ пропустить тест - это отметить его значком skip
декоратор, которому можно передать необязательный reason
.
Также можно принудительно пропустить во время выполнения теста или настройки, вызвав pytest.skip(reason)
функция. Это полезно, когда невозможно оценить условие пропуска во время импорта.
def test_func_one():
if not valid_config():
pytest.skip("unsupported configuration")
Пропуск теста по условию
@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_func_one():
...
Если вы хотите пропустить на основе условного выражения, вы можете использовать skipif
вместо. В предыдущем примере тестовая функция пропускается при запуске в интерпретаторе более ранней версии, чем Python3.6.
Наконец, если вы хотите пропустить тест, потому что уверены, что он не проходит, вы также можете рассмотреть возможность использования xfail
маркер, указывающий на то, что вы ожидаете неудачного завершения теста.
Если вы хотите пропустить тест, но не жестко запрограммировать маркер, лучше используйте выражение ключевого слова, чтобы избежать его.
pytest test/test_script.py -k 'not test_func_one'
Я не уверен, что это амортизируется, но вы также можете использовать pytest.skip
функция внутри теста:
def test_valid_counting_number():
number = random.randint(1,5)
if number == 5:
pytest.skip('Five is right out')
assert number <= 3
Вы также можете запустить тест, даже если вы подозреваете, что тест не пройден. Для такого сценария https://docs.pytest.org/en/latest/skipping.html предлагает использовать decorator @ pytest.mark.xfail
@pytest.mark.xfail
def test_function():
...
В этом случае Pytest по-прежнему будет запускать ваш тест и сообщать вам сейчас, если он пройдет или сейчас, но не будет жаловаться и нарушать сборку.
Вы можете разделить свои тесты на набор тестовых примеров с помощью настраиваемых маркеров pytest и выполнять только те тестовые примеры, которые вы хотите. Или наоборот, выполняя все тесты, кроме другого набора:
@pytest.mark.my_unit_test
def test_that_unit():
...
@pytest.mark.my_functional_test
def test_that_function():
...
А затем, чтобы запустить только один набор модульных тестов, например:
pytest -m my_unit_test
Обратное, если вы хотите запустить все тесты, кроме одного набора:
pytest -m "not my_unit_test"
Как совместить несколько марок
Больше примеров в официальной документации
Это выглядит удобнее, если у вас есть хорошее логическое разделение тестовых случаев.
Если вы хотите отключить весь тестовый класс, вы можете использовать__test__ = False
Мы используем его в больших наборах тестов для особых тестов, которые мы запускаем только в особых случаях, например, длительные регрессионные тесты или тесты, которые всегда терпят неудачу.
Затем мы устанавливаем переменную среды, например:
SCIM_GROUP_REGRESSION_TEST = False
if os.environ.get('SCIM_GROUP_REGRESSION_TEST'):
SCIM_GROUP_REGRESSION_TEST = True
class TestClass:
__test__ = SCIM_GROUP_REGRESSION_TEST
:
<your tests>
Затем вам явно необходимо установить эту переменную среды для ее запуска, во всех остальных случаях она будет пропущена.
Люди говорили оskip
декоратор. Работает как шарм!
Лучший способ настроить это — использоватьskipif
декоратор, который позволяет условно пропускать определенные тесты.
Эту конструкцию я люблю использовать, особенно для длительных тестов.
import pytest
import os
# your skipif decorator to conditionally skip a test that takes too long
@pytest.mark.skipif("RUNALL" not in os.environ, reason="takes too long")
def test_a_very_long_process():
# Your test code...
Это означает, что он проверит, что переменная средыRUNALL
существует. В противном случае он пропустит эти тесты.
Это означает, что обычныйpytest
команда пропустит эти тесты. Однако, когда придет время запуска всех тестов (например, при переходе в производственный режим), вы можете запуститьRUNALL=true pytest
.
Конечно, вы можете оценить любые другие условия с помощью Skipif :)
Атрибут (задокументированный дляTestXxx
классы здесь ) также работает для функций:
def test_something():
...
test_something.__test__ = False
В журнале изменений Pytest 2.6 говорится:
поддержка носового стиля
__test__
атрибут модулей, классов и функций, включая классы в стиле unittest. Если установлено значение False, тест не будет собран.