2016-09-13 5 views
1

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

В тестах/conftext.py:

import pytest 

@pytest.fixture(scope="module") 
def data_for_a(): 
    return "a_data" 

@pytest.fixture(scope="module") 
def data_for_b(): 
    return "b_data" 

В тестах/tests.py

import pytest 

# this works 
def test_a(data_for_a): 
    assert "a_data" == data_for_a 

# but I want to do this and it fails: 
scenarios = [ 
    { "name": "a", "data": data_for_a }, 
    { "name": "b", "data": data_for_b }, 
] 

for scenario in scenarios: 
    print(scenario.name, scenario.data) 

# desired output: 
# "a a_data" 
# "b b_data" 

я получаю NameError: name 'data_for_a' is not defined исключение. Я пробовал различные подходы, чтобы заставить это работать, но, похоже, нет способа передать прибор в качестве параметра к методу тестирования - так что либо определите кучу тестовых тестов, либо куча операторов if/else в одном тесте и передать каждое устройство в явном виде. Мне не нравится любой из этих вариантов. На данный момент мне кажется, что я должен просто создать свой собственный вспомогательный модуль, чтобы использовать эти тестовые данные, но я предпочел бы использовать встроенный механизм для этого. Есть какой-либо способ сделать это?

ответ

1

Вы можете импортировать из вашего conftest.py так:

from conftest import data_for_a, data_for_b 

или

from conftest import * 

, который позволит вам ссылаться на эту функцию, не передавая его в качестве параметра в функцию проверки.

Edit: Обратите внимание, что это, как правило, не рекомендуемой практики в соответствии с the official pytest documentation

Если у вас есть conftest.py файлы, которые не находятся в директории питон пакета (т.е. один, содержащий __init__. py), тогда «import conftest» может быть неоднозначным, поскольку на вашем PYTHONPATH или sys.path могут быть другие файлы conftest.py. Таким образом, хорошей практикой для проектов является либо поместить conftest.py в область содержимого пакета, либо никогда не импортировать ничего из файла conftest.py.

+0

Спасибо, что ответили. Я только что закончил создание вспомогательного модуля. – lps

0

Прошло некоторое время с тех пор, как вы отправили сообщение, так что есть вероятность, что эта функция не была встроена в pytest на момент публикации.

Я считаю, что вы ищете pytest_generate_tests. Вы можете определить это в модуле conftest.py (помещенном в каталог, содержащий тесты, которые должны быть запущены), который автоматически анализируется до запуска любых тестов через pytest. Эта функция может быть использована для параметрирования ваших тестовых функций или ваших приборов динамически, что позволяет вам определять на ходу множество входов, по которым вы хотите, чтобы тест/приспособление повторялось.

Я привел пример. Рассмотрим следующую структуру каталогов:

tests 
| 
+-- examples.py 
+-- test_examples.py 
+-- conftest.py 

Теперь давайте посмотрим на каждый файл ...

# examples.py 
# ----------- 
example_1 = { 
    "friendship": 0.0, 
    "totes": 0.0, 
} 

example_2 = { 
    "friendship": 0.0, 
    "totes": 0.0, 
} 

dont_use_me = { 
    "friendship": 1.0, 
    "totes": 1.0, 
} 

...

# test_examples.py 
# ---------------- 
def test_answer(pydict_fixture): 
    for k,v in pydict_fixture.items(): 
     assert v==0.0 

...

# conftest.py 
# ----------- 
from os.path import join, dirname, abspath 
import imp 
import re 

def pytest_generate_tests(metafunc): 
    this_dir = dirname(abspath(metafunc.module.__file__)) 
    # 
    if 'pydict_fixture' in metafunc.fixturenames: 
     examples_file= join(this_dir, "examples.py") 
     examples_module = imp.load_source('examples', examples_file) 
     examples_regex = re.compile("example") 
     examples = [] 
     for name, val in examples_module.__dict__.iteritems(): 
      if examples_regex.search(name): 
       examples.append(val) 
     metafunc.parametrize('pydict_fixture', examples) 

В этом конкретном примере, я хотел управлять тестовых случаев в одном, отдельном файле. Итак, я написал функцию pytest_generate_tests, которая, , перед выполнением любых тестов, анализирует examples.py, создает список словарей, имена которых включают слово «пример» и заставляет test_answer запускать каждый словарь в списке. Итак, test_answer будет называться дважды, один раз на example_1 и один раз на example_2. Оба теста пройдут.

Это короткое замыкание. Самое главное, что список входов определяется динамически внутри pytest_generate_tests, и тест запускается один раз для каждого элемента в списке.

Однако, чтобы быть полным в моем описании того, что я написал здесь, моя pytest_generate_tests функции фактически создает список входов для каждого тестовой функции (представленные pytest «s предопределенного metafunc переменных в pytest_generate_tests), который использует мнимую pydict_fixture , и ищет файл examples.pyв каталоге, где metafunc проживает! Таким образом, потенциально это можно было бы расширить, чтобы запустить кучу различных тестов на кучу разных файлов examples.py.