Skip to content

Commit 3650436

Browse files
committed
fix: pytest-django no longer being optional
This makes the workaround from 06db7b8 work against installations that do not use `pytest-django` as our plugin does not require users to install it.
1 parent 06db7b8 commit 3650436

File tree

8 files changed

+177
-29
lines changed

8 files changed

+177
-29
lines changed

.github/workflows/test.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ jobs:
7575
run: |
7676
coverage run -m pytest
7777
78+
- name: Test Example Project
79+
env:
80+
DJANGO_VERSION: ${{ matrix.django }}
81+
working-directory: example/
82+
run: |
83+
uv pip install "django~=${DJANGO_VERSION}"
84+
uv sync --locked --inexact --group dev
85+
coverage run --append -m pytest
86+
7887
# Converts the binary `.coverage` file to a XML file
7988
# that codecov can understand
8089
- name: Export Coverage

example/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ description = "Example Django project that uses pytest-django-queries"
99
readme = "README.md"
1010
requires-python = ">=3.10"
1111
dependencies = [
12-
"django",
12+
"django>=4.2.0",
1313
]
1414
package = true
1515

1616
[dependency-groups]
1717
dev = [
18-
"pytest>=9.0.2",
18+
"pytest>=7.2.0",
1919
"pytest-django>=4.12.0",
2020
"pytest-django-queries",
2121
]

pyproject.toml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ dev = [
6060
]
6161
test = [
6262
"coverage",
63+
"pytest-django",
6364
"pytest-xdist",
6465
]
6566

@@ -143,7 +144,16 @@ members = [
143144
".",
144145
]
145146

146-
[tool.pytest.ini_options]
147+
[tool.pytest]
148+
addopts = [
149+
# Prevents autoloading plugins as they could impact the test
150+
# results, e.g., we could fail to detect that the plugin
151+
# doesn't work if pytest-django isn't installed (as it's an
152+
# optional plugin)
153+
"--disable-plugin-autoload",
154+
"-p", "xdist",
155+
"-p", "django_queries",
156+
]
147157
testpaths = [
148158
"tests",
149159
]

src/pytest_django_queries/plugin.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
import pytest
1010
from django.test.utils import CaptureQueriesContext
1111

12-
# Defines the plugin marker name
1312
from pytest_django_queries.utils import create_backup
1413

14+
# Defines the plugin marker name
1515
PYTEST_QUERY_COUNT_MARKER = "count_queries"
1616
PYTEST_QUERY_COUNT_FIXTURE_NAME = "count_queries"
1717
DEFAULT_RESULT_FILENAME = ".pytest-queries"
@@ -29,11 +29,11 @@ def get_worker_input(node):
2929
return workerinput
3030

3131

32-
def is_worker(config):
32+
def is_worker(config: pytest.Config):
3333
return hasattr(config, "workerinput") or hasattr(config, "slaveinput")
3434

3535

36-
def get_workerid(config):
36+
def get_workerid(config: pytest.Config):
3737
if hasattr(config, "workerinput"):
3838
return config.workerinput["workerid"]
3939
elif hasattr(config, "slaveinput"):
@@ -51,7 +51,7 @@ def save_results_to_json(save_path, backup_path, data):
5151
json.dump(data, fp, indent=2)
5252

5353

54-
def add_entry(request, queries, dirout):
54+
def add_entry(request: pytest.FixtureRequest, queries, dirout):
5555
module_name = request.node.module.__name__
5656
test_name = request.node.name
5757
queries = queries[:]
@@ -119,14 +119,19 @@ def pytest_load_initial_conftests(early_config, parser, args):
119119
early_config.known_args_namespace.queries_backup_results = backup_path
120120

121121

122-
def _process_query_count_marker(request, *_args, **kwargs):
122+
def _process_query_count_marker(
123+
config: pytest.Config, request: pytest.FixtureRequest, *_args, **kwargs
124+
):
123125
autouse = kwargs.setdefault("autouse", True)
124126
if autouse:
127+
# Force load
128+
if config.dj_queries_has_django_plugin is True:
129+
request.getfixturevalue("_django_db_marker")
125130
request.getfixturevalue(PYTEST_QUERY_COUNT_FIXTURE_NAME)
126131

127132

128133
@pytest.fixture(autouse=True)
129-
def _pytest_query_marker(request):
134+
def _pytest_query_marker(request: pytest.FixtureRequest):
130135
"""Use the fixture to count the queries on the current node if it's
131136
marked with 'count_queries'.
132137
@@ -138,16 +143,25 @@ def _pytest_query_marker(request):
138143
but place the fixture manually."""
139144
marker = request.node.get_closest_marker(PYTEST_QUERY_COUNT_MARKER)
140145
if marker:
141-
_process_query_count_marker(request, *marker.args, **marker.kwargs)
146+
_process_query_count_marker(
147+
request.config, request, *marker.args, **marker.kwargs
148+
)
142149

143150

144-
def pytest_configure(config):
151+
def pytest_configure(config: pytest.Config) -> None:
145152
config.django_queries_shared_directory = tempfile.mkdtemp(
146153
prefix="pytest-django-queries"
147154
)
148155

156+
# Stores whether the pytest-django plugin is installed
157+
# Note: both names are valid, 'django' is an alias for 'pytest_django.plugin'
158+
# (https://github.com/pytest-dev/pytest-django/blob/3955b1826f396cecd01d1c059e7703769ad94d81/pyproject.toml#L77-L78)
159+
config.dj_queries_has_django_plugin = config.pluginmanager.hasplugin(
160+
"django"
161+
) or config.pluginmanager.hasplugin("pytest_django.plugin")
162+
149163

150-
def pytest_unconfigure(config):
164+
def pytest_unconfigure(config: pytest.Config):
151165
results_path = config.django_queries_shared_directory
152166
test_results = {}
153167

@@ -188,7 +202,7 @@ def pytest_configure_node(node):
188202
)
189203

190204

191-
def get_shared_directory(request):
205+
def get_shared_directory(request: pytest.FixtureRequest):
192206
"""Returns a unique and temporary directory which can be shared by
193207
master or worker nodes in xdist runs.
194208
"""
@@ -199,7 +213,7 @@ def get_shared_directory(request):
199213

200214

201215
@pytest.fixture
202-
def count_queries(db, request):
216+
def count_queries(request: pytest.FixtureRequest):
203217
"""Wrap a test to count the number of performed queries."""
204218
from django.db import connection
205219

tests/conftest.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
pytest_plugins = "pytester"
44

5+
# Prevents autoloading plugins as they could impact the test results,
6+
# e.g., we could fail to detect that the plugin doesn't work if
7+
# pytest-django isn't installed (as it's an optional plugin)
8+
DEFAULT_PYTEST_FLAGS = [
9+
"--disable-plugin-autoload",
10+
"-p",
11+
"xdist",
12+
"-p",
13+
"django_queries",
14+
]
15+
516

617
@pytest.fixture
718
def valid_comparison_entries():

tests/test_plugin.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import mock
77
import pytest
88

9+
from tests.conftest import DEFAULT_PYTEST_FLAGS
10+
911
DUMMY_TEST_QUERY = """
1012
import pytest
1113
@@ -32,7 +34,9 @@ def test_fixture_is_invoked_when_marked(testdir):
3234
# Run a dummy test that performs queries
3335
# and triggers a counting of the query number
3436
testdir.makepyfile(test_file=DUMMY_TEST_QUERY)
35-
results = testdir.runpytest("--django-db-bench", results_path)
37+
results = testdir.runpytest(
38+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
39+
)
3640

3741
# Ensure the tests have passed
3842
results.assert_outcomes(1, 0, 0)
@@ -56,7 +60,9 @@ def test_plugin_exports_nothing_if_empty(testdir):
5660
def test_nothing():
5761
pass
5862
""")
59-
results = testdir.runpytest("--django-db-bench", results_path)
63+
results = testdir.runpytest(
64+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
65+
)
6066

6167
# Ensure the tests have passed
6268
results.assert_outcomes(1, 0, 0)
@@ -80,7 +86,9 @@ def test_plugin_exports_results_even_when_test_fails(testdir):
8086
def test_failure():
8187
assert 0
8288
""")
83-
results = testdir.runpytest("--django-db-bench", results_path)
89+
results = testdir.runpytest(
90+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
91+
)
8492

8593
# Ensure the tests have failed
8694
results.assert_outcomes(0, 0, 1)
@@ -114,7 +122,9 @@ def fixture_with_db_queries():
114122
def test_with_side_effects(fixture_with_db_queries, count_queries):
115123
pass
116124
""")
117-
results = testdir.runpytest("--django-db-bench", results_path)
125+
results = testdir.runpytest(
126+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
127+
)
118128

119129
# Ensure the tests have passed
120130
results.assert_outcomes(1, 0, 0)
@@ -140,7 +150,9 @@ def test_plugin_marker_without_autouse_disabled(testdir):
140150
def test_without_autouse():
141151
pass
142152
""")
143-
results = testdir.runpytest("--django-db-bench", results_path)
153+
results = testdir.runpytest(
154+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
155+
)
144156

145157
# Ensure the tests have passed
146158
results.assert_outcomes(1, 0, 0)
@@ -159,7 +171,11 @@ def test_fixture_is_backing_up_old_results(testdir):
159171
testdir.makepyfile(test_file=DUMMY_TEST_QUERY)
160172

161173
results = testdir.runpytest(
162-
"--django-db-bench", results_path, "--django-backup-queries", old_results_path
174+
*DEFAULT_PYTEST_FLAGS,
175+
"--django-db-bench",
176+
results_path,
177+
"--django-backup-queries",
178+
old_results_path,
163179
)
164180

165181
# Ensure the tests have passed
@@ -177,7 +193,11 @@ def test_fixture_is_backing_up_old_results(testdir):
177193

178194
# Run again the tests
179195
results = testdir.runpytest(
180-
"--django-db-bench", results_path, "--django-backup-queries", old_results_path
196+
*DEFAULT_PYTEST_FLAGS,
197+
"--django-db-bench",
198+
results_path,
199+
"--django-backup-queries",
200+
old_results_path,
181201
)
182202

183203
# Ensure the tests have passed
@@ -211,7 +231,9 @@ def test_fixture_is_not_backing_up_if_not_asked_to(testdir):
211231
testdir.makepyfile(test_file=DUMMY_TEST_QUERY)
212232

213233
with mock.patch("pytest_django_queries.plugin.create_backup") as mocked_backup:
214-
results = testdir.runpytest("--django-db-bench", results_path)
234+
results = testdir.runpytest(
235+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path
236+
)
215237
assert mocked_backup.call_count == 0
216238

217239
# Ensure the tests have passed
@@ -232,7 +254,10 @@ def test_fixture_is_backing_up_old_results_to_default_path_if_no_path_provided(t
232254
from pytest_django_queries.plugin import DEFAULT_OLD_RESULT_FILENAME
233255

234256
results = testdir.runpytest(
235-
"--django-db-bench", results_path, "--django-backup-queries"
257+
*DEFAULT_PYTEST_FLAGS,
258+
"--django-db-bench",
259+
results_path,
260+
"--django-backup-queries",
236261
)
237262
mocked_backup.assert_called_with(str(results_path), DEFAULT_OLD_RESULT_FILENAME)
238263

@@ -243,7 +268,7 @@ def test_fixture_is_backing_up_old_results_to_default_path_if_no_path_provided(t
243268

244269
def test_marker_message(testdir):
245270
"""Ensure the custom markers configuration is added to pytest."""
246-
result = testdir.runpytest("--markers")
271+
result = testdir.runpytest(*DEFAULT_PYTEST_FLAGS, "--markers")
247272
result.stdout.fnmatch_lines(
248273
[
249274
"@pytest.mark.count_queries: "
@@ -254,7 +279,7 @@ def test_marker_message(testdir):
254279

255280
def test_implements_custom_options(testdir):
256281
"""Ensure the custom options are added to pytest."""
257-
result = testdir.runpytest("--help")
282+
result = testdir.runpytest(*DEFAULT_PYTEST_FLAGS, "--help")
258283
result.stdout.fnmatch_lines(
259284
[
260285
"django-queries:",
@@ -286,7 +311,9 @@ def test_foo():
286311
cursor.execute("SELECT 1;")
287312
cursor.fetchone()""")
288313

289-
results = testdir.runpytest("--django-db-bench", results_path, script)
314+
results = testdir.runpytest(
315+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path, script
316+
)
290317

291318
# Ensure the tests have passed
292319
results.assert_outcomes(1, 0, 0)
@@ -324,7 +351,9 @@ def test_foo(foo):
324351
# Append current test files into the temporary test directory in order
325352
# to have settings.py available for PyPi packages
326353
shutil.copytree(os.path.dirname(__file__), os.path.join(str(testdir) + "/tests"))
327-
results = testdir.runpytest("--django-db-bench", results_path, "-n", "5", script)
354+
results = testdir.runpytest(
355+
*DEFAULT_PYTEST_FLAGS, "--django-db-bench", results_path, "-n", "5", script
356+
)
328357

329358
# Ensure the tests have passed
330359
results.assert_outcomes(500, 0, 0)

0 commit comments

Comments
 (0)