-
Notifications
You must be signed in to change notification settings - Fork 16
Use pytest-xdist to run tests #2504
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
7eabf7e
to
6e2c276
Compare
This might need some checking with Playwright too, though in principle we should make those tests run independently too. (Playwright supports xdist; it's a question of us writing our tests to also on separate workers without any interdependencies.) |
For now, it seems that the benefit is with at most two workers, since each worker needs all the `universe` fixture setup. It may improve if we can break out tests into needing specific, finer grained fixtures. So we could revisit this in future.
8427bd8
to
6414fca
Compare
I tried this out with the Playwright tests, and it's highlighted something slightly odd there. They mostly work, but the Traceback (most recent call last):
File "…venv/opencodelists-3.12/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "…venv/opencodelists-3.12/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…venv/opencodelists-3.12/lib/python3.12/site-packages/django/contrib/auth/decorators.py", line 60, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/opencodelists/views/user_create_codelist.py", line 27, in user_create_codelist
return handle_post(request, user, owner_choices)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/opencodelists/views/user_create_codelist.py", line 43, in handle_post
return handle_post_valid(request, form, user, owner_choices)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/opencodelists/views/user_create_codelist.py", line 82, in handle_post_valid
codelist = create_codelist_from_scratch(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…pythons/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/codelists/actions.py", line 198, in create_codelist_from_scratch
cache_hierarchy(version=version)
File "…local/src/github.com/opensafely-core/opencodelists/codelists/actions.py", line 654, in cache_hierarchy
hierarchy = version.calculate_hierarchy()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/codelists/models.py", line 420, in calculate_hierarchy
return self._calculate_new_style_hierarchy()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/codelists/models.py", line 432, in _calculate_new_style_hierarchy
return Hierarchy.from_codes(self.coding_system, list(code_to_status))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/codelists/hierarchy.py", line 44, in from_codes
ancestor_relationships = set(coding_system.ancestor_relationships(codes))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/coding_systems/bnf/coding_system.py", line 68, in ancestor_relationships
return query(sql, codes, database=self.database_alias)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…local/src/github.com/opensafely-core/opencodelists/opencodelists/db_utils.py", line 8, in query
with connections[database].cursor() as c:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "…venv/opencodelists-3.12/lib/python3.12/site-packages/django/test/testcases.py", line 198, in __call__
raise DatabaseOperationForbidden(self.message)
django.test.testcases.DatabaseOperationForbidden: Database queries to 'bnf_test_20200101' are not allowed in this test. Add 'bnf_test_20200101' to pytest_django.fixtures._django_db_helper.<locals>.PytestDjangoTestCase.databases to ensure proper test isolation and silence this failure.
I'm not quite sure why, because at least the BNF fixture being used is listed in the Playwright test (although this is about setting up the fixture, so maybe there's a issue of timing when this applies there?) However, all the tests do run independently: if you assign the same number of workers as tests, so every test runs in a different worker, all the Playwright tests pass. |
Depends on #2495, and should be rebased when #2495 is merged.
It's possible to run the tests with pytest-xdist since each test is now independently runnable. This makes the unit tests run about 10 seconds or so quicker in CI (about 20-30% faster over not running with pytest-xdist). I see a similar improvement locally.