Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly return a list from a pytest fixture for use in parametrize?

I am attempting to build a little pytest test to ensure all expected keys exist in redis. I have a list of expected keys, that I am storing as a YML file. The test itself will query against redis to ensure each of the expected keys from the list exists.

Initially, I had this set up as a giant list in the test_keys.py file. This was set up like so:

expected_keys = ['key1','key2','key3']
@pytest.mark.parametrize('expected_key', expected_keys)
def test_expected_key(expected_key):
    ...

This works. Since I want to replicate this type of test for a few other checks of the redis environment, I don't want to put multiple lists with a few hundred keys into these files.

I thought I could pull them out into YML files and load the keys via fixtures.

My fixture looks like this:

@pytest.fixture
def expected_keys_fixture():
    with open('expected_keys.yml'), 'r') as f:
        return yaml.safe_load(f)['keys']

The YML looks like this:

keys:
  - key1
  - key2
  - key3

My test decorator changed to this:

@pytest.mark.parametrize("expected_keys", [
    (pytest.lazy_fixture('expected_keys_fixture'))
])
def test_expected_key(expected_key):
    ...

I am using the pytest-lazy-fixture package for this.

The problem I have here is that expected_keys now equals the entire list of expected keys. It's no long each individual key like I had with the static list when it was in my test file.

I attempted to do as Oleh Rybalchenko answer suggested

@pytest.mark.parametrize("expected_keys", pytest.lazy_fixture('expected_keys_fixture')
)
def test_expected_key(expected_key):
    ...

But, this fails with TypeError: 'LazyFixture' object is not iterable.

I understand I only have one argname and that I should have a list, but the example in the documentation is passing the parameters to the fixture() decorator. I am not. My list is being generated by the results of the YML file.


Question: How can I adjust my fixture so that it properly returned a single item at a time for the parametrize decorator?

like image 899
NewGuy Avatar asked Jun 19 '19 16:06

NewGuy


1 Answers

In the same situation and the only way I found is to refuse the fixture and call the function directly.

def expected_keys_fixture():
    with open('expected_keys.yml', 'r') as f:
        return yaml.safe_load(f)['keys']


@pytest.mark.parametrize("expected_key",
                         expected_keys_fixture())
def test_expected_key(expected_key):
    assert expected_key in ['key1', 'key2', 'key3']

like image 127
Roman Sklyarov Avatar answered Nov 14 '22 23:11

Roman Sklyarov