Метаклассы, а также классы, использующие эти метаклассы, создаются при выполнении строк кода, содержащих тело оператора class
.
С учетом этого в тестовых классах нет ничего особенногоили метаклассы - если оператор класса находится на уровне модуля, классы и метаклассы будут создаваться при первом импорте модуля - это означает, что вам придется выйти из своего (или тестового фреймворка) способа, чтобы затем перестроить между тестами.
Но если вы поместите эти элементы в тела функций, они будут перестроены при вызове функций.Если они являются функциями фикстуры, то каждый раз, когда используется фикстура, они перестраиваются (хотя я думаю, что Pytest выполняет некоторое кэширование фикстур - остерегайтесь этого)
С другой стороны, если метаклассы и классы, которые используют затем,находятся в коде приложения, тогда вы не можете поместить их в тела функций для воссоздания.В этом случае вам придется тщательно спроектировать использование функции imp.reload
- это позволит повторно запускать код на уровне модуля при каждом вызове.Вы можете вызывать imp.reload(<module>)
внутри функций своего прибора, но будьте осторожны, чтобы повторно связать любые ссылки на эти метаклассы (и классы, которые их используют) во время работы прибора.
Итак, если код вашего приложения что-то не так:
# module_b
from module_a import SETTING_1, SETTING_2
class Meta(type):
def __init__(mcls, name, bases, ns, **kw):
# code that make use of SETTING_1 and SETTING_2
...
class A(metaclass=Meta):
...
модуль тестовых приборов:
import pytest
from unittest import mock
@pytest.fixture
def recreate_metaclass():
from imp import reload
# Drawback: fixtures file have to know and manually imported here
import test_module_1, ...
import module_b
with mock.patch("module_a.SETTING_1", val_1), mock.patch("module_a.SETTING_2" val_2):
module_b = reload(module_b)
# rebind module_a inside test modules
test_module_1.module_b = module_b
...