Pytest - run same tests for different sets of input data

Viewed 2466

I have a number of functions that I want to test using pytest.

Throughout my testing, I use several input files that I specify at the top of the script:

import pytest
from mymodule.mymodule import *

test_bam = 'bam/test/test_reads_pb.bwa.bam'
sample_mapping_file = 'tests/test_sample_mapping.txt'
pb_errors_file = 'tests/data/pb_test_out.json'
pb_stats = 'tests/data/pb_stats.json'

I am then running several tests using this input:

@pytest.fixture
def options():
    o, a = get_args()

    return o

@pytest.fixture
def samples_dict():
    d = get_sample_mapping(sample_mapping_file)

    return d


@pytest.fixture
def read_stats(options, samples_dict):
    stats, bam = clean_reads(options, test_bam, samples_dict)

    return stats


@pytest.fixture
def clean_bam(options, samples_dict):
    stats, bam = clean_reads(options, test_bam, samples_dict)

    return bam


def test_errors(options, samples_dict, clean_bam):
    """Test successful return from find_errors"""
    sample, genome, chrom = set_genome(options, test_bam, samples_dict)

    base_data = find_errors(options, chrom, sample, clean_bam)

    assert base_data

I would like to be able to run the same tests on multiple different sets of input, where test_bam, sample_mapping_file, pb_errors_file and pb_stats will all be different.

What's the best way of running the same tests on different sets of input data?

I've played around with using marks to run input-specific functions:

@pytest.mark.pd
def get_pb_data():
    """Read in all pb-related files"""

@pytest.mark.ab
def get_ab_data():
    """Read in all ab-related files"""

But this doesn't work with the fixtures that I have set up (unless I'm missing something).

Any advice would be great!

2 Answers

use pytest parametrize wrapper.

test_bam = 'bam/test/test_reads_pb.bwa.bam'
sample_mapping_file = 'tests/test_sample_mapping.txt'
pb_errors_file = 'tests/data/pb_test_out.json'
pb_stats = 'tests/data/pb_stats.json'

@pytest.mark.parametrize("config", [test_bam, sample_mapping_file, pb_errors_file, pb_stats])
def do_something(config):
   #

It will create multiple test on every config test input and assign to config variable.

@pytest.mark.pd doesn't specify an input type, it adds pd marker to the test which can be used when running the tests, for example running all the tests marked with pd

pytest TestsFolder -m pd

If you want to run the tests on different sets of files you can store the files names in a csv for example and read the sets from there in the test parametrized marker

def data_source():
    for files in read_files_groups_from_csv():
        yield files

@pytest.mark.parametrize('files', data_source())
def test_errors(options, samples_dict, clean_bam, files):
    """for example, files parameter will be ['bam/test/test_reads_pb.bwa.bam', 'tests/test_sample_mapping.txt', 'tests/data/pb_test_out.json', 'tests/data/pb_stats.json']"""

mark.parametrize will run before the fixtures, so you can send files as a parameter to them as well

@pytest.fixture
def options(files):
    d = samples_dict(files[1])
    return d

If you don't want to rely on index create a class with files names as attributes and return it from data_source().

Related