Более чистый способ сделать параметризацию креплений Pytest на основе ключа командной строки?

Технически я уже решил проблему, над которой работал, но не могу не чувствовать, что мое решение ужасно:

У меня есть пакет pytest, который я могу запустить в двух режимах: локальный режим (для разработки тестов; все просто запускается на моем устройстве dev через Chrome) и режим регрессионного тестирования Seriousface (для CI; пакет запускается на миллионах браузеров). и ОС). У меня есть флаг командной строки для переключения между двумя режимами, --test-local, Если это там, я бегу в локальном режиме. Если его там нет, я бегу в режиме серьезного лица. Вот как я это делаю:

# contents of conftest.py
import pytest

def pytest_addoption(parser):
    parser.addoption("--test-local", action="store_true", default=False, help="run locally instead of in seriousface mode")

def pytest_generate_tests(metafunc):
    if "dummy" in metafunc.fixturenames:
        if metafunc.config.getoption("--test-local"):
            driverParams = [(True, None)]
        else:
            driverParams = [(False, "seriousface setting 1"), (False, "seriousface setting 2")]
        metafunc.parameterize("dummy", driverParams)

@pytest.fixture(scope="function")
def driver(dummy):
    _driver = makeDriverStuff(dummy[0], dummy[1])
    yield _driver
    _driver.cleanup()

@pytest.fixture
def dummy():
    pass

Проблема в том, что dummy крепость отвратительна Я пытался pytest_generate_tests параметризовать driver приспособление напрямую, но в итоге оно заменяет приспособление, а не просто подает в него вещи, так что cleanup() никогда не вызывается, когда тест заканчивается. Использование пустышки позволяет мне заменить пустышку моим кортежем параметров, чтобы он передавался в driver(),

Но, повторюсь, то, что у меня работает, это просто похоже на вздор.

1 ответ

Решение

Вы можете попробовать другой подход: вместо того, чтобы динамически выбирать набор параметров для теста, объявите ВСЕ наборы параметров для него, но отмените несоответствующие наборы во время запуска.

# r.py
import pytest

real = pytest.mark.real
mock = pytest.mark.mock

@pytest.mark.parametrize('a, b', [
    real((True, 'serious 1')),
    real((True, 'serious 2')),
    mock((False, 'fancy mock')),
    (None, 'always unmarked!'),
])
def test_me(a, b):
    print([a, b])

Затем запустите его следующим образом:

pytest -ra -v -s   r.py -m real        # strictly marked sets
pytest -ra -v -s   r.py -m mock        # strictly marked sets
pytest -ra -v -s   r.py -m 'not real'  # incl. non-marked sets
pytest -ra -v -s   r.py -m 'not mock'  # incl. non-marked sets

Также, skipif метки могут использоваться для выбранного набора параметров (отличается от отмены выбора). Они изначально поддерживаются Pytest. Но синтаксис довольно уродливый. Подробнее смотрите в разделе " Пропустить /xfail с параметризацией ".

Официальное руководство также содержит точно такой же случай, как и в вашем вопросе, в пользовательском маркере и параметре командной строки для управления запусками теста. Тем не менее, это также не так элегантно, как -m Отмена выбора теста и больше подходит для сложных условий выполнения, а не для априорной структуры тестов.

Другие вопросы по тегам