pythonpytestfixture

Pytest fixture: setup, teardown and code running between each test


I am trying to use pytest to test a module I am writing. The module is a wrapper of a process with a LONG startup time. I, therefore, want to make sure I have a proper setup/teardown logic to make sure the initialization does not happen more than once.

My current code looks like this:

import pytest
import leelaZeroWrapper

@pytest.fixture(scope='module')
def leela(request):
    leela = leelaZeroWrapper.LeelaWrapper()
    def quit():
        leela.quit()
    request.addfinalizer(quit)
    return leela

def test_single_play(leela):
    leela.reset()
    result = leela.play('b', 'a11')
    assert result == [{'color': 'black', 'loc': 'a11'}]

def test_single_play_uppercase(leela):
    leela.reset()
    result = leela.play('WHITE', 'A11')
    assert result == [{'color': 'white', 'loc': 'a11'}]

def test_reset(leela):
    leela.reset()
    leela.play('b', 'a11')
    leela.play('w', 'a13')
    leela.reset()
    assert leela.current_board == []
    assert leela.current_move == 0

I notice ALL my test will start with the call to reset my module! Is there any way to add this to the fixture, or how would you solve it?

Pseudo code for what I want:

@pytest.fixture(scope='module')
def leela(request):
    leela = leelaZeroWrapper.LeelaWrapper()
    def quit():
        leela.quit()
    def reset():
        leela.reset()
    request.addfinalizer(quit)
    request.add_between_test_resetter(reset)
    return leela

If the initial setup was not so heavy I would just skip this and let the class initialize every test. I have tried to look through the documentation for the request object but cannot find a suitable method. I assume this must be solved some other way. Any idea?


Solution

  • Just introduce another fixture that performs the reset. Make it an autouse fixture so it perfoms automatically before each test:

    @pytest.fixture(scope='module')
    def leela():
        leela = leelaZeroWrapper.LeelaWrapper()
        yield leela
        leela.quit()
    
    @pytest.fixture(autouse=True)
    def reset(leela):
        leela.reset()
    
    
    def test_single_play(leela):
        result = leela.play('b', 'a11')
        assert result == [{'color': 'black', 'loc': 'a11'}]
    

    The default fixture scope is function, so the reset fixture will rerun before each test in module.