Reputation: 291
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
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