Open Tishka17 opened 5 months ago
im one of the pytest maintainers, im very curious about enabling this as i want to start using dishka more in a number of projects that have some needs and we will need pytest fixtures
we are plying with ideas on how to repressent pytest fixtures in a more interoperable manner and would love to get input on both - making pytest fixutres more easy to integrate as well as easing other di tools to cooperate with pytest nicely
a key pain point is probably that pytest currently works name based instead of type based
I though about several approaches here:
Generate fixures manually. So the code will be like
x = dishka_fixture("x", Class)
which will be transformed to
def x(dishka_container):
return dishka_container.get(Class)
Decorate tests and fixtures using @inject
decorator as in all integrations. So it will erase all FromDishka
arguments and add dishka_container
@inject
def test(a, x: FromDishka[Class]):
...
will be transofmed to something similar to
def test(a, dishka_container):
_real_test(a, dishka_container.get(Class))
Another task here is pytest_asyncio
integration
As a PoC
def dishka_fixture(cls: Any):
def temp_fixture(dishka_container):
return dishka_container.get(cls)
return pytest.fixture(temp_fixture)
@pytest.fixture
def dishka_container():
p = Provider(scope=Scope.APP)
p.provide(lambda: 12, provides=int)
return make_container(p)
someint = dishka_fixture(int)
def test_x(someint):
assert someint == 12
It's critical to set the name, else thing's will turn bleak
@RonnyPfannschmidt is it? I did only small test and that code looks working. I would prefer not to set name twice for same fixture
I may be missremember the exact factory parsing behavior
I'll validate later
@RonnyPfannschmidt is there any hook to modify any fixture/test?
There's no hook to modify dependency injection yet
Same goes for discovery of fixtures
I'd like a discussion on enabling discovery of more fixtures and matching them to parameters
@RonnyPfannschmidt a) we can patch fixtures and tests so they will call container by themselves. It doesn't require modification of pytest DI engine. But it requires some kind middlewares/hooks which will be applied to any created test/fixture. I showed prototype for wrapping tests here https://github.com/reagento/dishka/commit/dc8c8a099dd1079a248205c6e383aabc606723dd
b) probably pytest can be modified to lookup fixtures not only by name, but by types. In this case we need some fixture factory protocol in pytest implemented by pytest plugin (dishka). This looks much more complicated for me. We need to keep in mind here, that there will be multiple containers in different packages/modules
not to mention that pytest has own fixture scopes
instead of patching tests and fixtures, i'd like to have a way to be a intermediate between the container and the pytest system (so the normal fill fixture mechanisms can be used)
my current impression is that in the case of pytest, a certain focus on controlling the call signatures from the test framework is necessary
Regarding scopes my point is that main logic of scopes is related to application running inside test, so here we do not need anything. If user needs some logic on synchronizing container scope (e.g, Scope.RUNTIME=="session"
and Scope.APP=="funcion"
) it can be implemented in his dishka_container
fixture
On topic of container managements I am interested in implementing integration which will be available on current versions of pytest, but it will be manual (using @inject
or dishka_fixture
as shown above). But for autoinjected I definitely need changes in pytest logic.
Do you have any issues/plans for this in pytest repo?
No plans or issues yet, the pre planning stage is literally starting now (in part because dishka is nicely inspiring)
Another open question here is pytest-asyncio support. We have 2 versions of container now: sync and async. I guess, user might want to use async container to get fixtures for non-async test. And vice versa.
thats one of the reasons why the full-fillment of the injection needs to be able to be deferred to some kind of controller - in particualr since pytest is absolutlely unable to re-color test nodes in any sensible amount of time
https://github.com/pytest-dev/pytest/pull/12473 is working on replacing fixtures with a more specific object
i believe that can be a starting point for more
Allow using dishka container to provide fixtures