Search code examples
pythonpytestfixtures

How to use pytest fixture with argument?


I have a pytest fixture:

TEST_DIR_JSON = 'test_data/test_telemetry'

@pytest.fixture
def create_telemetry_fixture():
    """Create and delete .json files"""
    items = [
        {"ts_str": "2021-07-15_10_00_01", "ts": "2021-07-15 10:00:00", "sensor_id": "sensor1", "value": -61.2105297502},
        {"ts_str": "2021-07-15_10_01_02", "ts": "2021-07-15 10:01:00", "sensor_id": "sensor1", "value": -90.9436886104},
    ]
    for item in items:
        data = {
            "timestamp": item["ts"],
            "sensors": [{"sensor_id": item["sensor_id"], "value": item["value"]}]
        }
        with open(f"{TEST_DIR_JSON}/sensors_{item['ts_str']}.json", "w", encoding="UTF-8") as file:
            json.dump(data, file)
    yield
    for file in os.listdir(TEST_DIR_JSON):
        os.remove(os.path.join(TEST_DIR_JSON, file))

And i have test function:

def test_function_1(<fixture_1>, create_telemetry_fixture, <fixture_3>):
    #some code
    assert <sequense>

I want to transfer the items variable to arguments of fixture. How cad i do it?

items1 = [...]
items2 = [...]

@pytest.fixture
def create_telemetry_fixture(items):
    #some code

I read documentation https://docs.pytest.org/en/6.2.x/parametrize.html but i think this is not my case. And this one too Pass a parameter to a fixture function

This code doesn't work

items1 = [
        {"ts_str": "2021-07-15_10_00_01", "ts": "2021-07-15 10:00:00", "sensor_id": "sensor1", "value": -61.2105297502},
        {"ts_str": "2021-07-15_10_01_02", "ts": "2021-07-15 10:01:00", "sensor_id": "sensor1", "value": -90.9436886104},
    ]

@pytest.fixture
def create_telemetry_fixture(items):
    for item in items:
        #some code

@pytest.mark.parametrize("avg_telemetry_fixture", [items1], indirect=True)
def test_agv_value(<fixture_1>, create_telemetry_fixture, <fixture_3>):
    #some_code

Solution

  • The parametrize with indirect=True requires that the argument name of the feature was exactly the "request" and no other word.
    I created a simplified version of your code where I use this approach. You can try it:

    import pytest
    
    items1 = [
            {"ts_str": "item1_ts_str1"},
            {"ts_str": "item1_ts_str2"},
        ]
    items2 = [
            {"ts_str": "item2_ts_str1"},
            {"ts_str": "item2_ts_str2"},
        ]
    
    
    @pytest.fixture
    def create_telemetry_fixture(request):
        text = ''
        for item in request.param:
            text += f'{item["ts_str"]}'
        yield text
    
    
    @pytest.mark.parametrize('create_telemetry_fixture', [items1], indirect=True)
    def test_parameters(create_telemetry_fixture):
        print(create_telemetry_fixture)