независимый от pytest импорт одного и того же модуля из разных тестовых файлов - PullRequest
0 голосов
/ 18 марта 2019

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

mod.py:

def global_setter():
    global x
    x = 123
    print("setter x:", x)


def global_getter():
    print("getter x:", x)

Для каждой функции есть тестовый файл.

test_1.py

import pytest

import mod


def test_set_x():
    mod.global_setter()
    assert mod.x == 123

test_2.py

import pytest

import mod


def test_get_x():
    with pytest.raises(NameError):
        mod.global_getter()

Эти тесты проходят, если они выполняются отдельно

$ pytest -s -v test_1.py
========================== test session starts ==========================
platform linux -- Python 3.6.7, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /mnt/temp/test, inifile:
collected 1 item

test_1.py::test_set_x setter x: 123
PASSED

-

======================= 1 passed in 0.03 seconds ========================
$ pytest -s -v test_2.py
========================== test session starts ==========================
platform linux -- Python 3.6.7, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /mnt/temp/test, inifile:
collected 1 item

test_2.py::test_get_x PASSED

======================= 1 passed in 0.02 seconds ========================

Если запустить вместе, второй тест не пройден.

$ pytest -s -v test_1.py test_2.py
========================== test session starts ==========================
platform linux -- Python 3.6.7, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /mnt/temp/test, inifile:
collected 2 items

test_1.py::test_set_x setter x: 123
PASSED
test_2.py::test_get_x getter x: 123
FAILED

=============================== FAILURES ================================
______________________________ test_get_x _______________________________

    def test_get_x():
        with pytest.raises(NameError):
>           mod.global_getter()
E           Failed: DID NOT RAISE <class 'NameError'>

test_2.py:8: Failed
================== 1 failed, 1 passed in 0.08 seconds ===================

Похоже, что состояние импортированного модуля кровоточит между тестами и тестовыми файлами.

Почему это происходит, и есть ли способ указать pytest импортировать модули независимо для каждого тестового файла? Если это так, как можно это сделать с минимальными изменениями в функциях test_? Приведенный выше пример с игрушкой иллюстрирует проблему, которая возникает у меня с большей базой кода со многими тестами.

1 Ответ

1 голос
/ 18 марта 2019

Это ожидается, потому что все тесты, запускаемые с помощью pytest, выполняются в одном процессе, и ваш первый тест изменяет глобальное состояние, добавляя x в глобальное пространство имен.

У вас есть несколько вариантов.

  1. Рефакторинг вашего кода, чтобы не использовать глобальные переменные. Или, по крайней мере, заключить его в класс, который позволяет легко высмеивать.
  2. Используйте структуру, подобную pytest-xdist (см. Запуск теста py.test в другом процессе ), который обеспечивает выполнение ваших тестов в разных процессах.
  3. Добавьте прибор перед вашим вторым тестом, который явно сбрасывает глобальную переменную x.
...