Skip to content

when @parametrize finds a fixture_ref in its argvalues, the parameter is not anymore accessible through request.getfixturevalue #146

Closed

Description

@TheCaffinatedDeveloper

Hi again @smarie!

Trying to figure out how to maintain the return values from cases that use a fixture as their own fixture name.

Example

conftest.py

@pytest.fixture
def some_fixture():
       return 1

@pytest.fixture(scope='function', autouse=True)
def some_other_fixture(request):
       # ouput will contain test_some_test_important_value_other_important_value as the fixture name
       print('fixturenames: ' + str(request.node.fixturenames))
       # hoping for important_value and other_important_value to be listed as fixtures

def case_some_case(some_fixture):
      important_value = some_fixture
      other_important_value = 2
      return important_value, other_important_value

mock_test.py

@parametrize_with_cases("important_value, other_important_value", cases='.')
def test_some_test(important_value, other_important_value):
       # important_value and other_important_value are here no problem
       assert important_value == 1
       assert other_important_value == 2

expected: [request, ..., ..., important_value, other_important_value, ...]
actual: [request, ..., ..., test_some_test_important_value_other_important_value, ...]

Note: this only happens when I use a fixture on the case.

Activity

  1. TheCaffinatedDeveloper commented on Nov 14, 2020

    @TheCaffinatedDeveloper
    Author

    I should note that I was able to use the follow to accomplish what I was looking for:

    @fixture_plus
    @parametrize_with_cases("important_value,other_important_value", cases='.')
    def prepare_test_cases(important_value, other_important_value):
        return important_value, other_important_value
    
    important_value, other_important_value = unpack_fixture("important_value,other_important_value", prepare_test_cases)
    

    I didn't change anything in the case_ functions. While this works, it would be cool to have similar functionality for @parametrize_with_cases by having an option to prevent packing or union etc.

  2. smarie commented on Nov 15, 2020

    @smarie
    Owner

    Hi @TheCaffinatedDeveloper , I am not sure to understand what the actual issue is.
    All fixture names are preserved. However additional new fixtures are created automatically behind the scenes by @parametrize when there is at least a fixture_ref in the parameters. This happens when @parametrize_with_cases finds a case that relies on a fixture: it creates a fixture for the case, and then creates a fixture_ref pointing to it in the generated @parametrize.

    So that is why you have for example test_some_test_important_value_other_important_value in the list.

    If you compare the lists you should see that no name disappeared, only new names appeared. Let me know if this is not the case.

  3. TheCaffinatedDeveloper commented on Nov 16, 2020

    @TheCaffinatedDeveloper
    Author

    Hi @TheCaffinatedDeveloper , I am not sure to understand what the actual issue is.
    All fixture names are preserved. However additional new fixtures are created automatically behind the scenes by @parametrize when there is at least a fixture_ref in the parameters. This happens when @parametrize_with_cases finds a case that relies on a fixture: it creates a fixture for the case, and then creates a fixture_ref pointing to it in the generated @parametrize.

    So that is why you have for example test_some_test_important_value_other_important_value in the list.

    If you compare the lists you should see that no name disappeared, only new names appeared. Let me know if this is not the case.

    @smarie Thank you for your reply. That definitely makes sense. To clarify my example, if you print a list of fixtures using request.node.fixturenames the names do appear to be preserved here.

    Even further, if you were use request.getfixturevalue('important_value') it would say that the fixture does not exist.

    Again, this is only when a case_ is using a fixture_ref.

  4. TheCaffinatedDeveloper commented on Nov 17, 2020

    @TheCaffinatedDeveloper
    Author

    @smarie I know you are busy so I created a repl to demonstrate the issue:
    Example

  5. smarie commented on Nov 18, 2020

    @smarie
    Owner

    Thanks @TheCaffinatedDeveloper for this example ! I did not know about repl.it, quite cool :)

    I copy the examples here for reproducibility

    from pytest_cases import parametrize_with_cases
    
    def case_without_fixture():
      important_value = 1
      other_important_value = 2
      return important_value, other_important_value 
    
    
    @parametrize_with_cases("important_value,other_important_value", cases='.')
    def test_case_without_fixture(request, important_value, other_important_value):
      # important_value and other_important_value are here no problem
      value = request.getfixturevalue('important_value').get()
      
      assert value == 1
      assert other_important_value == 2

    and

    from pytest_cases import parametrize_with_cases
    
    def case_with_fixture(some_fixture):
      important_value = some_fixture
      other_important_value = 2
      return important_value, other_important_value
    
    @parametrize_with_cases("important_value,other_important_value", cases='.')
    def test_case_with_fixture(request, important_value, other_important_value):
      value = None
      try:
        value = request.getfixturevalue('important_value').get()
      except:
        print('Fixture not found :(')
      
      assert value == important_value
      assert important_value == 1
      assert other_important_value == 2

    I think that there is a small misunderstanding here: important_value is not a fixture, this is a parameter. But since the pytest api is misleadingly named getfixturevalue it is quite normal to do the mistake :)
    Ok I see the issue, and I'm afraid that this might be extremely difficult to fix. That being said, I'll have a look when I'm back to normal activity. Thanks !

  6. TheCaffinatedDeveloper commented on Nov 18, 2020

    @TheCaffinatedDeveloper
    Author

    @smarie Thanks, glad you found REPL.it useful 👍

  7. smarie commented on Dec 16, 2020

    @smarie
    Owner

    Trying to reformulate this ticket in order to leave it open: when @parametrize finds a fixture_ref in its argvalues, the parameter is not anymore accessible through request.getfixturevalue.

    Minimal example:

    from pytest_cases import parametrize, fixture, fixture_ref
    
    @parametrize("a", [1])
    def test_without_fixture_ref(request, a):
        print(request._fixture_defs)
        assert request.getfixturevalue('a') == 1
    
    @fixture
    def some_fixture():
        return 1
    
    @parametrize("a", [fixture_ref(some_fixture)])
    def test_with_fixture_ref(request, a):
        print(request._fixture_defs)
        assert request.getfixturevalue('a') == 1

    This is due to the fact that a does not exist as a parameter in the second case. Indeed @parametrize replaces test_with_fixture_ref with a wrapper function, depending on a newly generated fixture named test_with_fixture_ref_a. We can look at the console prints above to see it in request._fixture_defs.

    So the second test is equivalent to

    @fixture
    def some_fixture():
        return 1
    
    @fixture
    def test_with_fixture_ref_a(some_fixture):
        return some_fixture
    
    def test_with_fixture_ref(request, test_with_fixture_ref_a):
        a = test_with_fixture_ref_a
        print(request._fixture_defs)
        assert request.getfixturevalue('a') == 1

    I'm afraid there is no simple solution to this problem... I suggest to close as "won't fix" except if you feel that this should be tackled. In that case we'll leave it open for community support

  8. changed the title [-]cases with fixture change fixturenames[/-] [+]when @parametrize finds a fixture_ref in its argvalues, the parameter is not anymore accessible through request.getfixturevalue[/+] on Dec 16, 2020
  9. changed the title [-]when @parametrize finds a fixture_ref in its argvalues, the parameter is not anymore accessible through request.getfixturevalue[/-] [+]when @parametrize finds a fixture_ref in its argvalues, the parameter is not anymore accessible through `request.getfixturevalue`[/+] on Dec 16, 2020
  10. added a commit that references this issue on Jan 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    wontfixThis will not be worked on

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions