В общем, выделил немного времени на то чтобы посмотреть воркараунд, заодно и добавлю практический пример для урока по юнит тестированию Поиск 🔍 организации или лица - Предоставление сведений из ЕГРЮЛ/ЕГРИП в электронном виде.
Заключение, просто это сделать не получиться (может быть и можно как-то, но надо больше времени на эксперименты)
Это больше быстрый костыль нежели решение, но все же лучше иметь что-то чем ничего.
Есть одно ограничение, из-за того что xdist
плагин использует execnet модуль для сериализации, в нем реализовано сериализация только примитивных типов и к сожалению экземпляры объектов не могут быть сериализированны. Т.е. нельзя напрямую присвоить экземпляр класса для нового созданного node node.slaveinput["app"] = node.config.app
потому что при сериализации Вы получите ошибку
raise DumpError("can't serialize %s" % (tp,))
DumpError: can't serialize <class 'conftest.App'>
Для этого я быстро воспользовался pickle
модулем чтобы превратить объект в строку node.slaveinput["app"] = pickle.dumps(node.config.app)
. Т.е данный костыль сработает только если Вы будете инициализировать shared object единожды и вам не нужно потом менять этот объект.
conftest.py
import pytest
from random import randint
import logging
import pickle
logging.basicConfig(filename="log.log", level=logging.INFO)
class App(object):
def __init__(self):
self.a = randint(0, 100)
logging.info("initialized {}".format(self))
def method(self):
logging.info("method in app that print {}".format(self.a))
def pytest_configure(config):
if not hasattr(config, "slaveinput"):
config.app = App()
def pytest_configure_node(node):
node.slaveinput["app"] = pickle.dumps(node.config.app)
@pytest.fixture(scope="session")
def app(request):
return pickle.loads(request.config.slaveinput["app"])
Сам файл с тестами никак не меняется и выглядит точно также.
test_something.py
import pytest
def test_exists(app):
app.method()
def test_exists2(app):
app.method()
def test_exists3(app):
app.method()
И как видно из логов, инициализация происходит один раз и экземпляр класса для каждого потока выдает правильные одинаковые данные (но фактически из-за того что я использовал pickle экземпляры будут разные, хотя поведение у них и будет одинаковым, описал этот момент выше).
log.log
INFO:root:initialized <conftest.App object at 0x02B07470>
INFO:root:method in app that print 46
INFO:root:method in app that print 46
INFO:root:method in app that print 46
Все файлы и логи можно найти здесь:
https://gist.github.com/polusok/4e71f7e3d3dbf437cc25