python-pytest-cases icon indicating copy to clipboard operation
python-pytest-cases copied to clipboard

Fixture created for parametrized case not visible to test function in different module

Open plammens opened this issue 4 years ago • 1 comments

As discussed in #158 (in particular https://github.com/smarie/python-pytest-cases/issues/158#issuecomment-747710915 and https://github.com/smarie/python-pytest-cases/issues/158#issuecomment-747942419), when a fixture is created for a parametrized case, if that case is used in a test that lies in a separate module, the fixture won't be visible and test collection will fail.

Related to #170, #169

Example

In the file test_foo_cases.py:

import pytest_cases



class XCases:
    @staticmethod
    def case_foo():
        return 1


class YCases:
    @staticmethod
    @pytest_cases.parametrize_with_cases("x", XCases.case_foo)
    def case_foo(x):
        return x


class ZCases:
    @staticmethod
    @pytest_cases.parametrize_with_cases("y", YCases.case_foo)
    def case_foo(y):
        return y

In test_foo.py:

import pytest_cases
import test_foo_cases


@pytest_cases.parametrize_with_cases("y", test_foo_cases.ZCases.case_foo)
def test_foo(y):
    pass

Trying to run test_foo will result in an error during collection:

_______________________ ERROR at setup of test_foo[foo] _______________________
file .../test_foo.py, line 5: source code not available
file <makefun-gen-14>, line 1: source code not available
file ...
E       fixture 'case_foo_y' not found
>       available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, foo, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, test_foo_y, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
>       use 'pytest --fixtures [testpath]' for help on them.

Workarounds

Possible workarounds are:

  • Import everything from the cases module to ensure all dynamically generated fixtures are visible in the test module too: from test_foo_cases import *
  • Selectively import the dynamically generated fixture in the test module: case_foo_y = test_foo_cases.case_foo_y. This relies on knowing the name of the generated fixture.

Possible solutions

  • Dynamically add the fixture to all modules that reference the case too?
  • Instead of adding the fixture to the cases module, add it to the closest conftest.py available?

plammens avatar Dec 18 '20 09:12 plammens

Nice workaround from test_foo_cases import * ! I did not think it would work but actually there is no reason it shouldnt

Another possible solution is : stop creating hidden fixtures in @parametrize (#170). A bit ambitious/challenging but not impossible.

smarie avatar Dec 18 '20 13:12 smarie