Vladimir Yahello
Vladimir Yahello

Reputation: 291

Pytest: run teardown once for all workers using pytest-xdist

I have a pytest fixture that I need to run only once across all pytest workers.

@pytest.fixture(scope="session")
@shared  # this will call setup once for all processes
def cache(request):
    acc = Account(id=10)
    acc.create()
    request.addfinilizer(acc.delete)
    return acc


def shared(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        request = kwargs['request']
        root = request.config._tmp_path_factory.getbasetemp().parent
        filepath = root / "shared"

        with filelock.FileLock(f'{filepath}.lock'):
            if filepath.is_file():
                result = json.loads(filepath.read_text())
            else:
                result = func(*args, **kwargs)
                filepath.write_text(json.dumps(result.id))

        return result
    return wrapper

I use the solution from https://pytest-xdist.readthedocs.io/en/latest/how-to.html?highlight=only%20once#making-session-scoped-fixtures-execute-only-once and it works fine for the pytest setup part, but the teardown part is called on every pytest process.

It is possible to lock pytest-xdist teardown to run it only once after all pytest sessions are finished? I want to run teardown once for all workers.

Upvotes: 8

Views: 2786

Answers (1)

Justin Furuness
Justin Furuness

Reputation: 986

Not sure if this answers your question or is the most optimal method (I'm not quite sure what you want the teardown to look like), but the pytest_sessionfinish function runs at the end of all tests. If you check for the worker input attribute, it will run in the master thread after all other processes have finished testing

def pytest_sessionfinish(session, exitstatus):
    """Insert teardown that you want to occur only once here"""
    if not hasattr(session.config, "workerinput"):
        pass

Source: https://github.com/pytest-dev/pytest-xdist/issues/271#issuecomment-826396320

Upvotes: 3

Related Questions