Search code examples
pythonpytestlazy-evaluationparametrize

How to avoid parametrization of a Pytest class when skipping it?


I have two Pytest classes: one test class is very fast and the other is slower, parametrizing itself with a function call and reusing that resource across multiple tests.

My problem is that, when running the quicker test via pytest test.py -k "Quick", I have to wait for the slower test to be parametrized before the specified test will be run.

class TestQuick:
    def test_quick(self): pass

@pytest.mark.parametrize('num', get_nums())
class TestSlow
    def test_1(self, num): pass
    def test_2(self, num): pass

def get_nums():
    inputs = range(100)
    with multiprocess.Pool(10) as pool:
        return list(pool.map(IO_fn, # takes a lot of time
                             inputs))

I have tried using @pytest.mark.parametrize('num', get_nums(), indirect=True), but I couldn't get this to work.

I also tried using @pytest.fixture(scope='class') on IO_fn, which is almost there except for:

  1. I lose the crucial ability to speed up collection of nums using multiprocessing.
  2. I want my test output to be grouped by TestSlow/num/test rather than just a flat directory of TestSlow/test.

Solution

  • A bit "dirty" hack to parse input arguments and stop executing long process when it meets Quick tag:

    import sys
    import pytest
    
    
    def get_nums():
        if sys.argv[-1] == 'Quick':
            return []
        inputs = range(100)
        with multiprocess.Pool(10) as pool:
            return list(pool.map(IO_fn, inputs))
    
    
    class TestQuick:
        def test_quick(self): pass
    
    
    @pytest.mark.parametrize('num', get_nums())
    class TestSlow:
        def test_1(self, num): pass
    
        def test_2(self, num): pass
    

    Testing:

    pytest test.py -k "Quick" — runs fast

    pytest test.py -k "Slow" — runs slow