Модули pytest с использованием os.environ - как правильно их протестировать?

в настоящее время я пишу какое-то Webapp, но на этот раз я хочу научиться писать для него правильные тесты (используя pytest) :)

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

Я подготовил демо:

./app
./app/conf.py
./conftest.py
./run.py
./tests
./tests/test_demo.py

Мой ./app/conf.py выглядит так:

from os import environ

DEMO = environ.get('DEMO', 'demo')
TEST = environ.get('TEST', 'test')

Запуск ./run.py показывает, что настройки действительно можно изменить:

from os import environ

environ['DEMO'] = 'not a demo'
environ['TEST'] = 'untested'

from app import conf

if __name__ == '__main__':

    print(conf.DEMO)
    print(conf.TEST)

Он распечатывает not a demo и untested - как и ожидалось. Большой. (Обратите внимание, что я установил переменные среды перед импортом conf).

Теперь к тестам: ./conftest.py в настоящее время пуст, он просто помогает pytest находить модули внутри папки приложения.

./tests/test_demo.py содержит следующее:

def test_conf_defaults():
    from app import conf

    assert conf.DEMO == 'demo'
    assert conf.TEST == 'test'


def test_conf_changed(monkeypatch):
    monkeypatch.setenv('DEMO', 'tested demo')
    monkeypatch.setenv('TEST', 'demo test')

    from app import conf

    assert conf.DEMO == 'tested demo'
    assert conf.TEST == 'demo test'

    monkeypatch.undo()

Если я сейчас запущу pytest, test_conf_changed не удастся 'demo' == 'tested demo' -> функция monkeypatch не исправила среду.

Если я поменяю местами обе функции тестирования (так что test_conf_changed запускается первым), test_conf_defaults завершится ошибкой с 'tested demo' == 'demo'.

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

Как я могу указать pytest полностью повторно импортировать conf каждую тестовую функцию после настройки переменных среды?

Я застрял там два дня - и постепенно я сомневаюсь, что тестирование стоит хлопот - пожалуйста, докажите, что я ошибаюсь :)


person spky    schedule 18.06.2015    source источник
comment
Я не уверен, чего вы хотите достичь: если вы хотите запускать тесты, вы запускаете py.test, и он подбирает все test_*.py файлы и запускает тесты в них. Если вы хотите иметь демонстрацию, вы должны создать файл, например ./demos/demo.py, и запустить его в качестве демонстрации. Я не думаю, что ни один из них (конечно, не pytest) должен зависеть от переменных среды.   -  person    schedule 18.06.2015
comment
И да, когда вы импортируете conf, а переменные внутри модуля conf устанавливаются внутри глобального пространства имен, они остаются неизменными: один импорт только во время всего запуска (сеанс python). Если вы хотите продолжить чтение или установить env. переменных, создайте функцию в conf.py, например updateenv(), и запускайте ее каждый раз, когда вам нужно из других функций, чтобы обновить переменные env.   -  person    schedule 18.06.2015
comment
Чего я хочу достичь: config.py содержит настройки по умолчанию, но я хочу сделать их изменяемыми. например Путь для хранения временных файлов и т. д.   -  person spky    schedule 18.06.2015
comment
Теперь я хочу проверить, работает ли назначение правильно - демонстрация, которую я написал, предназначена только для stackoverflow - она ​​не имеет ничего общего с моим настоящим приложением - она ​​просто показывает основные принципы.   -  person spky    schedule 18.06.2015
comment
Конечно, pytest не должен зависеть от переменных среды. Я хочу, чтобы pytest установил некоторые переменные (локально), а затем протестировал мой код (в conf.py), если он правильно ведет себя с использованием этих переменных ...   -  person spky    schedule 18.06.2015


Ответы (1)


Спасибо за подсказку, Evert (переменные внутри модуля conf устанавливаются внутри глобального пространства имен, они остаются здесь) - думаю, теперь я понял.

Чтобы проверить свой код, я должен явно повторно импортировать conf после установки переменных среды. Изменение кода в ./tests/test_demo.py на это дает трюк:

from importlib import reload

from app import conf


def test_conf_changed(monkeypatch):
    monkeypatch.setenv('DEMO', 'tested demo')
    monkeypatch.setenv('TEST', 'demo test')

    reload(conf)

    assert conf.DEMO == 'tested demo'
    assert conf.TEST == 'demo test'


def test_conf_defaults():

    reload(conf)

    assert conf.DEMO == 'demo'
    assert conf.TEST == 'test'

Спасибо.

person spky    schedule 18.06.2015