Failure using --fixtures flag with pytest
gudjonragnar opened this issue · 5 comments
I have a conftest.py
file that is loading an image and creating a container using this plugin. It looks something like this:
image = fetch("image-name")
my_container = container(...)
@pytest.fixture
def some_other_fixture():
...
When I run pytest --fixtures <test-path>
it fails showing this error:
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR> File "/var/as/venvs/callback/lib/python3.8/site-packages/_pytest/main.py", line 269, in wrap_session
INTERNALERROR> session.exitstatus = doit(config, session) or 0
INTERNALERROR> File "/var/as/venvs/callback/lib/python3.8/site-packages/_pytest/python.py", line 1497, in _showfixtures_main
INTERNALERROR> available.sort()
INTERNALERROR> TypeError: '<' not supported between instances of 'NoneType' and 'str'
When i looked into the code and check this available list that is being sorted I see this:
(5, 'tests.conftest', 'tests/conftest.py:88', 'hostname', <FixtureDef argname='hostname' scope='module' baseid='tests'>)
(5, None, '<string>:5', 'image', <FixtureDef argname='image' scope='session' baseid='tests'>)
(5, 'tests.conftest', 'tests/conftest.py:98', 'rabbit_connections', <FixtureDef argname='rabbit_connections' scope='module' baseid='tests'>)
(5, None, '<string>:5', 'my_container', <FixtureDef argname='my_container' scope='package' baseid='tests'>)
As you can see the two lines containing image
and my_container
have None as their second value and the location is also weird.
The available
list is being created here: https://github.com/pytest-dev/pytest/blob/master/src/_pytest/python.py#L1471
I think the issue might be related to the decorator handling in the plugin, but I haven't investigated it.
That kind of makes sense. The current method for generating fixtures relies on some grim eval to make some other part of pytest function correctly so it's location won't be a file. I guess that code needs amending to set some properties that a normal fixture would have...
I guess you are referencing the build_fixture_function
function in builder.py
?
Yeah. So i had hoped it would be enough to make sure that that returns something with .__module__
set, but so far in my tests pytest still thinks its None regardless.
Sigh. pytest captures a copy of the fixture, so you can't mutate it after calling the pytest decorator.
So something like this fixes it for me:
diff --git a/pytest_docker_tools/builder.py b/pytest_docker_tools/builder.py
index bdb3a70..2bc959c 100644
--- a/pytest_docker_tools/builder.py
+++ b/pytest_docker_tools/builder.py
@@ -5,7 +5,7 @@ from .templates import find_fixtures_in_params, resolve_fixtures_in_params
def build_fixture_function(callable, scope, wrapper_class, kwargs):
name = callable.__name__
- docstring = "Docker image"
+ docstring = name
if "path" in kwargs:
docstring = getattr(callable, "__doc__", "").format(**kwargs)
fixtures = find_fixtures_in_params(kwargs).union({"request", "docker_client"})
@@ -15,13 +15,15 @@ def build_fixture_function(callable, scope, wrapper_class, kwargs):
f"""
import pytest
- @pytest.fixture(scope=scope)
def {name}({fixtures_str}):
\'\'\'
{docstring}
\'\'\'
real_kwargs = resolve_fixtures_in_params(request, kwargs)
return _{name}(request, docker_client, wrapper_class=wrapper_class, **real_kwargs)
+
+ {name}.__module__ = callable.__module__
+ {name} = pytest.fixture(scope=scope)({name})
"""
)
globals = {