Skip to content

Commit 7a1b9aa

Browse files
committed
⚡️ improve test performance with pytest-xdist
1 parent 484ca10 commit 7a1b9aa

File tree

9 files changed

+44
-28
lines changed

9 files changed

+44
-28
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
run: pnpm run build
6363
- name: Run tests
6464
run: |
65-
coverage run --branch -m pytest froide/
65+
make test
6666
coverage report --format=markdown >> $GITHUB_STEP_SUMMARY
6767
env:
6868
DATABASE_URL: postgis://postgres:postgres@localhost/froide

Makefile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ export DJANGO_SETTINGS_MODULE=froide.settings
22
export DJANGO_CONFIGURATION=Test
33
export PYTHONWARNINGS=default
44

5+
lint:
6+
pre-commit run --all
7+
58
test:
6-
ruff check
7-
coverage run --branch -m pytest froide/
8-
coverage report
9+
pytest --cov froide -n auto -m "not elasticsearch"
10+
pytest --cov froide --cov-append -m "elasticsearch"
911

1012
testui:
1113
coverage run --branch -m pytest --browser chromium froide/tests/live/

froide/foirequest/tests/test_api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ def test_search(self):
110110
response = self.client.get("/api/v1/request/search/?q=Number")
111111
self.assertEqual(response.status_code, 200)
112112

113+
@pytest.mark.elasticsearch
113114
def test_search_similar(self):
114115
factories.delete_index()
115116
search_url = "/api/v1/request/search/"

froide/foirequest/tests/test_web.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def test_request_prefilled_redirect(world, client):
9494

9595

9696
@pytest.mark.django_db
97+
@pytest.mark.elasticsearch
9798
def test_list_requests(world, client):
9899
factories.rebuild_index()
99100
response = client.get(reverse("foirequest-list"))
@@ -117,6 +118,7 @@ def test_list_requests(world, client):
117118
assert response.status_code == 404
118119

119120

121+
@pytest.mark.elasticsearch
120122
@pytest.mark.django_db
121123
def test_list_jurisdiction_requests(world, client):
122124
factories.rebuild_index()
@@ -151,6 +153,7 @@ def test_list_jurisdiction_requests(world, client):
151153

152154

153155
@pytest.mark.django_db
156+
@pytest.mark.elasticsearch
154157
def test_tagged_requests(world, client):
155158
tag_slug = "awesome"
156159
req = FoiRequest.published.all()[0]
@@ -170,6 +173,7 @@ def test_tagged_requests(world, client):
170173

171174

172175
@pytest.mark.django_db
176+
@pytest.mark.elasticsearch
173177
def test_publicbody_requests(world, client):
174178
factories.rebuild_index()
175179
req = FoiRequest.published.all()[0]
@@ -188,6 +192,7 @@ def test_publicbody_requests(world, client):
188192

189193

190194
@pytest.mark.django_db(transaction=True)
195+
@pytest.mark.elasticsearch
191196
def test_list_no_identical(world, client):
192197
factories.FoiRequestFactory.create(site=world)
193198
factories.rebuild_index()
@@ -277,6 +282,7 @@ def test_auth_links(world, client):
277282

278283

279284
@pytest.mark.django_db
285+
@pytest.mark.elasticsearch
280286
def test_feed(world, client):
281287
factories.rebuild_index()
282288

@@ -673,6 +679,7 @@ def jurisdiction_with_many_requests_slug(request: pytest.FixtureRequest):
673679

674680

675681
@pytest.mark.django_db
682+
@pytest.mark.elasticsearch
676683
@pytest.mark.parametrize(
677684
"filter_field,filter_value,filter_value_function",
678685
[["jurisdiction", None, jurisdiction_with_many_requests_slug], ["q", "*", None]],
@@ -726,6 +733,7 @@ def dict_combinations_all_r(sequence):
726733
yield dict(parts)
727734

728735

736+
@pytest.mark.elasticsearch
729737
@pytest.mark.django_db
730738
def test_request_list_path_filter(
731739
client: Client,

froide/publicbody/tests.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from django.test import TestCase
88
from django.urls import reverse
99

10+
import pytest
11+
1012
from froide.foirequest.tests.factories import make_world, rebuild_index
1113
from froide.georegion.models import GeoRegion
1214
from froide.helper.csv_utils import export_csv_bytes
@@ -25,6 +27,7 @@ class PublicBodyTest(TestCase):
2527
def setUp(self):
2628
self.site = make_world()
2729

30+
@pytest.mark.elasticsearch
2831
def test_web_page(self):
2932
pb = PublicBody.objects.all()[0]
3033
category = CategoryFactory.create(is_topic=True)
@@ -250,6 +253,7 @@ def test_search(self):
250253
response = self.client.get("/api/v1/publicbody/search/?format=json&q=Body")
251254
self.assertEqual(response.status_code, 200)
252255

256+
@pytest.mark.elasticsearch
253257
def test_autocomplete(self):
254258
pb = PublicBody.objects.all()[0]
255259
rebuild_index()

froide/tests/live/test_request.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def do_login(page, live_server, navigate=True):
4242
expect(page.locator("#navbaraccount-link")).to_have_count(1)
4343

4444

45+
@pytest.mark.elasticsearch
4546
@pytest.mark.django_db
4647
def test_make_not_logged_in_request(page, live_server, public_body_with_index):
4748
pb = PublicBody.objects.all().first()
@@ -120,6 +121,7 @@ def test_make_not_logged_in_request_to_public_body(page, live_server, world):
120121
assert req.status == FoiRequest.STATUS.AWAITING_USER_CONFIRMATION
121122

122123

124+
@pytest.mark.elasticsearch
123125
@pytest.mark.django_db
124126
def test_make_logged_in_request(page, live_server, public_body_with_index, dummy_user):
125127
do_login(page, live_server)
@@ -227,6 +229,7 @@ def test_collapsed_menu(page, live_server):
227229

228230

229231
@pytest.mark.django_db
232+
@pytest.mark.elasticsearch
230233
@pytest.mark.parametrize(
231234
"from_resolution, to_resolution",
232235
[("", "successful"), ("successful", "refused")],

pyproject.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,11 @@ test = [
8080
"pre-commit",
8181
"pycodestyle",
8282
"pyflakes",
83+
"pytest-cov",
8384
"pytest-django",
8485
"pytest-factoryboy",
8586
"pytest-playwright",
87+
"pytest-xdist",
8688
"tblib",
8789
"text-unidecode",
8890
"time-machine",
@@ -137,15 +139,18 @@ branch = true
137139

138140
[tool.coverage.report]
139141
show_missing = true
140-
skip_covered = true
142+
skip_covered = false
141143
exclude_lines = ["pragma: no cover"]
142144

145+
[toolcoverage.files]
146+
source = ["froide"]
147+
143148
[tool.pytest.ini_options]
144149
DJANGO_CONFIGURATION = "Test"
145150
DJANGO_SETTINGS_MODULE = "froide.settings"
146151
python_files = ["tests.py", "test_*.py", "*_tests.py"]
147152
addopts = ["--reuse-db"]
148-
markers = ["no_delivery_mock"]
153+
markers = ["no_delivery_mock", "elasticsearch"]
149154

150155
[tool.mypy]
151156
plugins = ["mypy_django_plugin.main"]

requirements-test.txt

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ asgiref==3.8.1
1313
# channels
1414
# django
1515
# django-stubs
16-
async-timeout==4.0.3
17-
# via aiohttp
1816
attrs==24.2.0
1917
# via
2018
# aiohttp
@@ -70,6 +68,7 @@ coverage==7.6.1
7068
# via
7169
# froide (pyproject.toml)
7270
# django-coverage-plugin
71+
# pytest-cov
7372
cron-descriptor==1.4.5
7473
# via django-celery-beat
7574
cryptography==43.0.1
@@ -127,7 +126,7 @@ django-crossdomainmedia==0.0.4
127126
# via froide (pyproject.toml)
128127
django-elasticsearch-dsl==8.0
129128
# via froide (pyproject.toml)
130-
django-filingcabinet @ git+https://github.com/okfde/django-filingcabinet.git@69cde01cf767ebf6447d057b1400b87c32d03803
129+
django-filingcabinet @ git+https://github.com/okfde/django-filingcabinet.git@3e7a8cc61b04cb77f7010d4c878112fc93af4337
131130
# via froide (pyproject.toml)
132131
django-filter==24.3
133132
# via
@@ -191,8 +190,8 @@ elasticsearch-dsl==8.15.2
191190
# via
192191
# froide (pyproject.toml)
193192
# django-elasticsearch-dsl
194-
exceptiongroup==1.2.2
195-
# via pytest
193+
execnet==2.1.1
194+
# via pytest-xdist
196195
factory-boy==3.3.1
197196
# via
198197
# froide (pyproject.toml)
@@ -312,7 +311,7 @@ prompt-toolkit==3.0.47
312311
# via click-repl
313312
psycopg==3.2.3
314313
# via froide (pyproject.toml)
315-
psycopg-binary==3.2.1
314+
psycopg-binary==3.2.3
316315
# via psycopg
317316
pycodestyle==2.12.1
318317
# via froide (pyproject.toml)
@@ -341,17 +340,23 @@ pyphen==0.16.0
341340
pytest==8.3.3
342341
# via
343342
# pytest-base-url
343+
# pytest-cov
344344
# pytest-django
345345
# pytest-factoryboy
346346
# pytest-playwright
347+
# pytest-xdist
347348
pytest-base-url==2.1.0
348349
# via pytest-playwright
350+
pytest-cov==6.0.0
351+
# via froide (pyproject.toml)
349352
pytest-django==4.9.0
350353
# via froide (pyproject.toml)
351354
pytest-factoryboy==2.7.0
352355
# via froide (pyproject.toml)
353356
pytest-playwright==0.5.2
354357
# via froide (pyproject.toml)
358+
pytest-xdist==3.6.1
359+
# via froide (pyproject.toml)
355360
python-crontab==3.2.0
356361
# via django-celery-beat
357362
python-dateutil==2.9.0.post0
@@ -427,12 +432,6 @@ tinycss2==1.3.0
427432
# via
428433
# cssselect2
429434
# weasyprint
430-
tomli==2.0.1
431-
# via
432-
# coverage
433-
# django-stubs
434-
# mypy
435-
# pytest
436435
types-markdown==3.7.0.20240822
437436
# via froide (pyproject.toml)
438437
types-python-dateutil==2.9.0.20240906
@@ -443,22 +442,20 @@ types-requests==2.32.0.20240907
443442
# via froide (pyproject.toml)
444443
typing-extensions==4.12.2
445444
# via
446-
# asgiref
447445
# dj-database-url
448446
# django-stubs
449447
# django-stubs-ext
450448
# elasticsearch-dsl
451449
# jwcrypto
452-
# multidict
453450
# mypy
454451
# psycopg
455452
# pyee
456-
# pypdf
457453
# pytest-factoryboy
458454
tzdata==2024.1
459455
# via
460456
# celery
461457
# django-celery-beat
458+
# kombu
462459
uritemplate==4.1.1
463460
# via
464461
# coreapi

requirements.txt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ asgiref==3.8.1
1212
# via
1313
# channels
1414
# django
15-
async-timeout==4.0.3
16-
# via aiohttp
1715
attrs==24.2.0
1816
# via
1917
# aiohttp
@@ -112,7 +110,7 @@ django-crossdomainmedia==0.0.4
112110
# via froide (pyproject.toml)
113111
django-elasticsearch-dsl==8.0
114112
# via froide (pyproject.toml)
115-
django-filingcabinet @ git+https://github.com/okfde/django-filingcabinet.git@69cde01cf767ebf6447d057b1400b87c32d03803
113+
django-filingcabinet @ git+https://github.com/okfde/django-filingcabinet.git@3e7a8cc61b04cb77f7010d4c878112fc93af4337
116114
# via froide (pyproject.toml)
117115
django-filter==24.3
118116
# via
@@ -248,7 +246,7 @@ prompt-toolkit==3.0.47
248246
# via click-repl
249247
psycopg==3.2.3
250248
# via froide (pyproject.toml)
251-
psycopg-binary==3.2.1
249+
psycopg-binary==3.2.3
252250
# via psycopg
253251
pycparser==2.22
254252
# via cffi
@@ -329,17 +327,15 @@ tinycss2==1.3.0
329327
# weasyprint
330328
typing-extensions==4.12.2
331329
# via
332-
# asgiref
333330
# dj-database-url
334331
# elasticsearch-dsl
335332
# jwcrypto
336-
# multidict
337333
# psycopg
338-
# pypdf
339334
tzdata==2024.1
340335
# via
341336
# celery
342337
# django-celery-beat
338+
# kombu
343339
uritemplate==4.1.1
344340
# via
345341
# coreapi

0 commit comments

Comments
 (0)