2015-04-20 3 views
2

Я пишу функциональные тесты, используя pytest для программного обеспечения, которое может работать локально и в облаке. Я хочу создать 2 модулей, каждый из которых с теми же именами модулей/арматуре и иметь pytest нагрузку одну или другую сторону в зависимости, если я бегу тестов локально или в облаке:Модули Pytest и Dynamic fixture

/fixtures 
/fixtures/__init__.py 
/fixtures/local_hybrids 
/fixtures/local_hybrids/__init__.py 
/fixtures/local_hybrids/foo.py 
/fixtures/cloud_hybrids 
/fixtures/cloud_hybrids/__init__.py 
/fixtures/cloud_hybrids/foo.py 
/test_hybrids/test_hybrids.py 

foo.py (оба из них) :

import pytest 
@pytest.fixture() 
def my_fixture(): 
    return True 

/fixtures/__init__.py:

if True: 
    import local_hybrids as hybrids 
else: 
    import cloud_hybrids as hybrids 

/test_hybrids/test_hybrids.py:

from fixtures.hybrids.foo import my_fixture 

def test_hybrid(my_fixture): 
    assert my_fixture 

Последний блок кода не работает, конечно, потому что import fixtures.hybrids смотрит на файловой системе, а не „фальшивый“ пространства имен __init__.py «s, который не любит from fixtures import hybrids, который работает (но тогда вы не можете использовать светильники поскольку имена будут включать точечную нотацию).

Я понимаю, что я могу играть с pytest_generate_test, чтобы динамически изменять прибор (может быть?), Но я бы очень не хотел управлять каждым прибором вручную изнутри этой функции ... Я надеялся на динамический импорт (если x, импортируйте это , иначе импорт, который) был стандартный Python, к сожалению, он сталкивается с механизмом светильников:

import fixtures 
def test(fixtures.hybrids.my_fixture): # of course it doesn't work :) 
    ... 

Я мог бы также импортировать каждую функцию арматуре один за другим в INIT; но все же жизнеспособный вариант, чтобы обмануть pytest и получить имена приборов без точек.

Показать мне черную магию. :) Можно ли это сделать?

ответ

1

Я думаю, что в вашем случае лучше определить светильник - environment или другое приятное имя.

Это приспособление может быть только геттер из os.environ [ «KEY»] или вы можете добавить свой аргумент командной строки, как here затем использовать его как here и окончательное использование here.

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

+0

Да, я знаю об этой возможности (так я и делал это изначально), но я действительно хочу избежать импорта модулей облака, если я запускаю локальные тесты и наоборот. Из-за этого импортирование каждого символа один за другим (более интересное предложение в моем оригинальном посте) более оптимально для меня. Спасибо, что нашли время ответить хотя;) – Joe

0

Вы можете упустить что-то здесь: Если вы хотите повторно использовать те приборы, нужно сказать, что это явно:

from fixtures.hybrids.foo import my_fixture 

@pytest.mark.usefixtures('my_fixture') 
def test_hybrid(my_fixture): 
    assert my_fixture 

В этом случае вы можете настроить pytest следующим образом:

from local_hybrids import local_hybrids_fixture 
from cloud_hybrids import cloud_hybrids_fixture 

fixtures_to_test = { 
    "local":None, 
    "cloud":None 
} 

@pytest.mark.usefixtures("local_hybrids_fixture") 
def test_add_local_fixture(local_hybrids_fixture): 
    fixtures_to_test["local"] = local_hybrids_fixture 

@pytest.mark.usefixtures("cloud_hybrids_fixture") 
def test_add_local_fixture(cloud_hybrids_fixture): 
    fixtures_to_test["cloud"] = cloud_hybrids_fixture 

def test_on_fixtures(): 
    if cloud_enabled: 
     fixture = fixtures_to_test["cloud"] 
    else: 
     fixture = fixtures_to_test["local"] 
    ... 

Если меня интересуют лучшие решения;)

0

Я действительно не думаю, что в питоне есть «хороший способ», но все же это возможно с небольшим количеством хаки нг. Вы можете обновить sys.path для подпапки с помощью приборов, которые вы хотели бы использовать и импортировать светильники напрямую. В грязном корпусе это выглядит так:

для ваших светильников/__ init__.р:

if True: 
    import local as hybrids 
else: 
    import cloud as hybrids 

def update_path(module): 
    from sys import path 
    from os.path import join, pardir, abspath 
    mod_dir = abspath(join(module.__file__, pardir)) 
    path.insert(0, mod_dir) 

update_path(hybrids) 

и в коде клиента (test_hybrids/test_hybrids.py):

import fixtures 
from foo import spam 

spam() 

В других случаях вы можете использовать гораздо более сложные действия, чтобы выполнить поддельное движение всех модулей/пакетов/functions и т. д. из вашей облачной/локальной папки непосредственно в файл __init__.py. Тем не менее, я думаю - это не стоит попробовать.

Еще одна вещь - черная магия - не самая лучшая вещь для использования, я бы порекомендовал вам использовать пунктирную нотацию с «import X from Y» - это гораздо более стабильное решение.

Смежные вопросы