2016-09-25 16 views
1

Можно параметризовать тестовые функции из аргументов командной строки. Возможно подключение прибора к классу. Я хочу объединить эти две вещи, так что каждый класс получает параметризованные аргументы, которые присваиваются инструменту внутри класса.Динамически параметризующие приборы уровня класса с pytest

(по существу, за аргумент командной строки мне нужно выполнить одну очень дорогостоящую операцию, а затем выполнить множество дешевых, быстрых тестов против результатов этой операции, и я бы предпочел не повторять дорогостоящую операцию для каждого дешевого теста, так что я хотел бы сохранить его)

Другими словами, я ищу эквивалент pytest_generate_tests (metafunc), который будет работать для динамического параметрирования прибора, а не тестовой функции ,

Одна вещь, которую я уже пробовал необычно, - это чтение параметров запроса и установка тех через крюк pytest_generate_tests.

conftest.py: 
    def pytest_generate_tests(metafunc): 
     metafunc.parametrize("result", [ 
       (1,0),(1,2) 
      ]) 

test_thing.py: 
    class TestThingy: 
     @pytest.fixture(scope="class") 
     def result(self, request): 
      a,b=request.param 
      return a+b 

    #@pytest.mark.parametrize("result", [(0, 1), (1, 2)]) 
    def test_one(self, result): 
     assert result!=2 

Выполнение этого теста вызывает следующее сообщение об ошибке, чтобы поднять (обратите внимание, что тест побежал хорошо, когда я попытался его без conftest крючком и закомментированного линии незакомментированной):

@pytest.fixture(scope="class") 
def result(self, request): 
    a,b=request.param 

AttributeError: 'SubRequest' object has no attribute 'param'

Меня также интересует любой другой альтернативный способ добиться того же результата.

+0

Было бы здорово, если бы команда py.test могла взлететь. Документы не совсем понятны в этом вопросе. –

ответ

2

Я сделал некрасивый-хак-на-работы в параметризующем приспособление на основе командной строки аргументов, как это:

# contents of conftest.py 
import pytest 

def pytest_addoption(parser): 
    parser.addoption("--test-local", action="store_true", default=False) 

def pytest_generate_tests(metafunc): 
    if "dummy" in metafunc.fixturenames: 
     #driverParams sets dummy[0], dummy[1] parametrically (as seen below) 
     if metafunc.config.getoption("--test-local"): 
      driverParams = [(True, None)] 
     else: 
      driverParams = [(False, "seriousface setting 1"), 
          (False, "seriousface setting 2")] 
     metafunc.parametrize("dummy", driverParams) 

#driver can then be used as a standard fixture 
@pytest.fixture(scope="function") 
def driver(dummy): 
    _driver = makeDriverStuff(dummy[0], dummy[1]) 
    yield _driver 
    _driver.cleanup() 

@pytest.fixture(scope="function") 
def dummy(): 
    pass 

По сути то, что происходит здесь в том, что, когда metafunc.parametrize("dummy", driverParams) работает, он подбрасывает driverParams во все, что зависит от фиктивного крепления. Что еще более важно, это означает, что функция фиктивного устройства никогда не выполняет.

Сначала я попытался с помощью metafunc параметризовать мой водитель прибор непосредственно, и заметил, что очистка никогда не происходит, потому что (так), как я делал вещи, прежде чем было metafunc.parametrize с makeDriverStuff(param1, param2) непосредственно, а затем почесать голову интересно, почему driver() никогда не вызывался. Пункт манекена состоит в том, чтобы сказать: «Эй, здесь есть законное приспособление, не жалуйтесь, что вы не можете его найти!», А затем всегда вытесняете его тем, что действительно полезно.

Как я уже сказал, это уродливый хак. Но вы должны уметь адаптировать его.

+0

Я реализовал это предложение. Затем я добавил оператор печати, чтобы проверить, сколько раз вызывался дорогой код. К сожалению, ответ повторяется снова и снова, для каждого теста, который получает параметр. – dWitty

+0

В случае того, что я делаю, это преднамеренно. Мой 'makeDriverStuff()' запускает новый WebDriver (и, следовательно, новый экземпляр браузера), который я специально хочу, чтобы тесты были более изолированы друг от друга. –

+0

Изменил бы декораторы приборов, чтобы иметь 'scope =" session "' (или класс или модуль, если это необходимо) решить его для вас? –