MaartenB
MaartenB

Reputation: 475

Parameterized fixture with pytest-datafiles

I have a Python function that processes different types of files for which I want set up a testing scheme. For each of the different file types it can handle I have a test file. I'd like to use pytest-datafiles so the tests automatically get performed on copies in a tmpdir. I'm trying to setup a parameterized fixture, similar to @pytest.fixture(params=[...]), so that the test function automatically gets invoked for each test file. How do I achieve this?

I tried the code below, but my datafiles are not copied to the tmpdir, and the test collection fails, because the test_files() fixture does not yield any output. I'm quite new to pytest, so possibly I don't fully understand how it works.

@pytest.fixture(params = [1,2])
@pytest.mark.datafiles('file1.txt','file1.txt')
def test_files(request,datafiles):
    for testfile in datafiles.listdir():
        yield testfile

@pytest.fixture(params = ['expected_output1','expected_output2'])
def expected_output(request):
    return request.param

def my_test_function(test_files,expected_output):
    assert myFcn(test_files) == expected_output

Upvotes: 1

Views: 1369

Answers (2)

Jylpah
Jylpah

Reputation: 373

If I understood correctly you want to use pytest-datafiles with parametrized input so that the params define how each file is handled. I do not get fully how exactly you want to use the params, but I give an example how I have managed to use those:

from pathlib import Path
import pytest  # type: ignore

FIXTURE_DIR = Path(__file__).parent

FILES= pytest.mark.datafiles(
    FIXTURE_DIR / "file1.txt",
    FIXTURE_DIR / "file2.txt",
    FIXTURE_DIR / "file3.txt",
)


@pytest.mark.parametrize(
    "file,size",
    [("file1.txt", 345), ("file2.txt", 1024), ("file3.txt", 3465)],
)
@FILES
def test_1_files(
    datafiles: Path, tmp_path: Path, file: str, size: int
) -> None:
    fn : Path = tmp_path / file
    with open(fn, "r") as f:
        content = f.read()
    assert len(content) == size, f"unexpected file size: {len(content)} != {size}"

Was this what you tried to achieve? ... 2+ years ago :-)

Upvotes: 0

MaartenB
MaartenB

Reputation: 475

After reading up on fixtures and marks I conclude that the way I tried to use pytest.mark.datafiles is probably not possible. Instead I used the built-in tmpdir functionality in pytest, as demonstrated below. (Also, the fact that I named my fixture function test_files() may have messed things up since pytest would recognize it as a test function.)

testFileNames = {1:'file1.txt', 2:'file2.txt'}
expectedOutputs = {1:'expected_output1', 2:'expected_output2'}

@pytest.fixture(params = [1,2])
def testfiles(request,tmpdir):
    shutil.copy(testFileNames[request.param],tmpdir)
    return os.path.join(tmpdir,testFileNames[request.param])

@pytest.fixture(params = [1,2])
def expected_output(request):
    return expectedOutputs[request.param]

def my_test_function(testfiles,expected_output):
    assert myFcn(testfiles) == expected_output

Upvotes: 1

Related Questions