Передача параметров из теста в фикстуру pytest (indirect fixture params)

Фикстуры в pytest указываются как параметры функции-теста. Это означает что вы не можете напрямую передать в них параметры.

Но что если в тесте вам необходимо чуть изменить поведение фикстуры?

Ниже я показываю, как это сделть, на примере фикстуры data_path.

Эта фикстура упрощает использование в тестах файлов с данными.

Она берет эти файлы из каталога, имя которого определяется именем модуля с тестом, добавляя к нему _data. И копирует эти файлы во временный каталог, возвращая его имя. Теперь у теста копия данных и он точно их никак не испортит.

К тому же это делает код теста чище - не нужно химичить со всеми этими __file__ или как-то иначе вычислять место файлов с тестовыми данными.

Включите код фикстуры data_path fixture в ваш conftest.py

tests/
    conftest.py     # здесь код фикстуры data_path
    foo_data/       # каталог с файлами для теста 
        my_file.txt
    test_foo.py     # здесь тест `def test_foo` использующий файлы из каталога `foo_data`

И использовать в тесте такой код:

    def test_foo(data_path):
            my_file_path = data_path / "my_file.txt"
            with my_file_path.open() as data:
                ...

Но что если нам хочется в тестах в разных модулях использовать один и тот же каталог с данными? Или мы хотим повторить тест несколько раз для разных каталогов с даннами?

Для этого надо каким-то образом передать в фикстуру эту информацию. Для этого можно использовать pytest indirect parameter

Например, вот так

tests/
    conftest.py         # здесь код фикстуры data_path
    foo/                # каталоги с файлами для теста 
        1/              # каталог с данными для первого прогона теста
            my_file.txt
        2/              # каталог с данными для второго прогона теста
            my_file.txt
    test_foo.py         # здесь тест `def test_foo` использующий файлы из каталогов `foo/1` и `foo/2` 
    @pytest.mark.parametrize('data_path', ['foo/1', 'foo/2'], indirect=['data_path'])
    def test_foo(data_path):
            my_file_path = data_path / "my_file.txt"
            with my_file_path.open() as data:
                ...