Запуск тестов pytest в другом пакете Python

Прямо сейчас у меня есть пакет Python (назовем его mypackage) с кучей тестов, которые я запускаю с помощью pytest. У одной конкретной функции может быть много возможных реализаций, поэтому я использовал механизм funcarg для запуска этих тестов с эталонной реализацией.

# In mypackage/tests/conftest.py
def pytest_funcarg__Feature(request):
    return mypackage.ReferenceImplementation

# In mypackage/tests/test_stuff.py
def test_something(Feature):
    assert Feature(1).works

Теперь я создаю отдельный пакет Python с более сложной реализацией (fancypackage). Можно ли запустить все тесты в mypackage, содержащие funcarg Feature, только с разными реализациями?

Я хотел бы избежать необходимости изменять fancypackage, если я добавлю новые тесты в mypackage, поэтому явный импорт не идеален. Я знаю, что могу запустить все тесты с помощью pytest.main(), но поскольку у меня есть несколько реализаций моей функции, я не хочу вызывать pytest.main() несколько раз. В идеале это должно выглядеть примерно так:

# In fancypackage/tests/test_impl1.py
def pytest_funcarg__Feature(request):
    return fancypackage.Implementation1
## XXX: Do pytest collection on mypackage.tests, but don't run them

# In fancypackage/tests/test_impl2.py
def pytest_funcarg__Feature(request):
    return fancypackage.Implementation2
## XXX: Do pytest collection on mypackage.tests, but don't run them

Затем, когда я запускаю pytest в fancypackage, он собирает каждый из тестов mypackage.tests дважды, по одному разу для каждой реализации функции. Я пытался сделать это с явным импортом, и, кажется, он работает нормально, но я не хочу явно импортировать все.

Бонус

Дополнительным приятным бонусом будет сбор только тех тестов, которые содержат Feature funcarg. Это возможно?

Пример с юниттестом

Прежде чем перейти на py.test, я сделал это со стандартной библиотекой unittest. Функция для этого следующая:

def mypackage_test_suite(Feature):
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()
    mypackage_tests = loader.discover('mypackage.tests')
    for test in all_testcases(mypackage_tests):
        if hasattr(test, 'Feature'):
            test.Feature = Feature
            suite.addTest(test)
    return suite

def all_testcases(test_suite_or_case):
    try:
        suite = iter(test_suite_or_case)
    except TypeError:
        yield test_suite_or_case
    else:
        for test in suite:
            for subtest in all_testcases(test):
                yield subtest

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


person tbekolay    schedule 09.01.2014    source источник


Ответы (1)


Вы можете параметризовать свой прибор Feature:

@pytest.fixture(params=['ref', 'fancy'])
def Feature(request):
    if request.param == 'ref':
        return mypackage.ReferenceImplementation
    else:
        return fancypackage.Implementation1

Теперь, если вы запустите py.test, он проверит оба.

Выбор тестов на используемом приспособлении невозможен, AFAIK, вы, вероятно, могли бы собрать что-то вместе, используя request.applymarker() и -m. Однако.

person flub    schedule 10.01.2014
comment
В идеале fancypackage не будет запускать эталонные тесты реализации, но вы правы, что параметризация функции может быть полезной, если я смогу хотя бы один раз загрузить все тесты из mypackage. Я обновил вопрос фрагментом unittest, который делает то, что я ищу, на случай, если это будет полезно. - person tbekolay; 12.01.2014
comment
способ сказать, что pytest дает мне коллекцию всех тестов, начинающихся ЗДЕСЬ, а затем добавить их в мою тестовую коллекцию, было бы неплохой функцией. Требуется некоторая работа по разработке точного пользовательского интерфейса и реализации, но, безусловно, выполнимая, возможно, путем добавления нового хука. - person hpk42; 12.01.2014
comment
Я рад помочь с реализацией этой функции @hpk42! Я создал проблему обсудить идею и интерфейс. - person tbekolay; 12.01.2014
comment
Другая возможность, которая может сработать прямо сейчас, — это добавить параметр командной строки, чтобы выбрать, какой прибор и поднять pytest.Skip в приборе, если параметр командной строки отключает его. Таким образом, вы можете использовать параметризацию и выполнять тесты только для одного прибора. - person flub; 14.01.2014