#python-3.x #python-unittest #monkeypatching
#python-3.x #python-unittest #monkeypatching
Вопрос:
Я должен установить разные переменные среды для своих тестовых примеров.
Я предполагал, что после завершения тестового примера monkeypatch удалит переменные env из os.environ. Но это не так. Как установить и отменить переменные среды для каждого теста?
Вот мой упрощенный код тестового примера с библиотекой monkeypatch.
import os
import unittest
import time
from _pytest.monkeypatch import MonkeyPatch
class Test_Monkey_Patch_Env(unittest.TestCase):
def setUp(self):
print("Setup")
def test_1(self):
monkeypatch = MonkeyPatch()
monkeypatch.setenv("TESTVAR1", "This env value is persistent")
def test_2(self):
# I was expected the env TESTVAR1 set in test_1 using monkeypatch
# should not persist across test cases. But it is.
print(os.environ["TESTVAR1"])
def tearDown(self):
print("tearDown")
if __name__ == '__main__':
unittest.main()
Вывод:
Setup
tearDown
.Setup
This env value is persistent
tearDown
.
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
Ответ №1:
Чтобы удалить переменную env, установленную monkeypatch
модулем, кажется, вам нужно вызвать delenv
метод. Вы можете вызвать это delenv
после того, как закончите настройку и тестирование переменной env с помощью setenv
метода, но я думаю tearDown
, что было бы правильным местом для размещения этого вызова delenv.
def tearDown(self):
print("tearDown")
monkeypatch.delenv('TESTVAR1', raising=False)
Я не тестировал код, однако должен дать вам достаточное представление о том, что нужно сделать.
РЕДАКТИРОВАТЬ: улучшен код для более эффективного использования setup * tearDown. test_2
должно вызвать ошибку ОС, поскольку переменная env была удалена
import os
import unittest
import time
from _pytest.monkeypatch import MonkeyPatch
class Test_Monkey_Patch_Env(unittest.TestCase):
def setUp(self):
self.monkeypatch = MonkeyPatch()
print("Setup")
def test_1(self):
self.monkeypatch.setenv("TESTVAR1", "This env value is persistent")
def test_2(self):
# I was expected the env TESTVAR1 set in test_1 using monkeypatch
# should not persist across test cases. But it is.
print(os.environ["TESTVAR1"]) # Should raise OS error
def tearDown(self):
print("tearDown")
self.monkeypatch.delenv("TESTVAR1", raising=False)
if __name__ == '__main__':
unittest.main()
Приветствия!
Ответ №2:
Это немного расширяет (правильный) ответ, данный @MaNKuR.
Причина, по которой он не работает должным образом, заключается в том, что в pytest он не предназначен для использования таким образом — вместо monkeypatch
этого используется приспособление, которое выполняет очистку при выходе из области тестирования. Чтобы выполнить очистку unittest
, вы можете выполнить эту очистку tearDown
, как показано в ответе, хотя я бы использовал менее специфичный undo
для этого:
from _pytest.monkeypatch import MonkeyPatch
class Test_Monkey_Patch_Env(unittest.TestCase):
def setUp(self):
self.monkeypatch = MonkeyPatch()
def tearDown(self):
self.monkeypatch.undo()
Это отменяет любые изменения, внесенные с помощью MonkeyPatch
экземпляра, а не только конкретного setenv
вызова, показанного выше, и поэтому является более безопасным.
Кроме того, есть возможность использовать MonkeyPatch
в качестве контекстного менеджера. Это удобно, если вы хотите использовать его только в одном или нескольких тестах. В этом случае вы можете написать:
...
def test_1(self):
with MonkeyPatch() as mp:
mp.setenv("TESTVAR1", "This env value is not persistent")
do_something()
Очистка в этом случае выполняется при выходе из диспетчера контекста.