Skip to content

Commit b2128b2

Browse files
authored
Add zeal to pytest (#2605)
1 parent 1cafec1 commit b2128b2

File tree

14 files changed

+78
-2
lines changed

14 files changed

+78
-2
lines changed

channels/views_test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
User = get_user_model()
3131

3232

33+
@pytest.mark.skip_nplusone_check
3334
def test_list_channels(user_client):
3435
"""Test that all channels are returned"""
3536
ChannelFactory.create_batch(2, published=False) # should be filtered out
@@ -119,6 +120,7 @@ def test_partial_update_channel_featured_list_only_learning_path(
119120
assert response.status_code == status
120121

121122

123+
@pytest.mark.skip_nplusone_check
122124
@pytest.mark.parametrize("resource_type", LearningResourceType)
123125
def test_create_channel_lists_only_learning_path(admin_client, resource_type):
124126
"""Only learning_paths may be used as one of lists"""
@@ -449,6 +451,7 @@ def test_channel_configuration_is_not_editable(client, channel):
449451
assert channel.configuration == initial_config
450452

451453

454+
@pytest.mark.skip_nplusone_check
452455
def test_channel_counts_view(client):
453456
"""Test the channel counts view returns counts for resources"""
454457
url = reverse(
@@ -486,6 +489,7 @@ def test_channel_counts_view(client):
486489
)
487490

488491

492+
@pytest.mark.skip_nplusone_check
489493
def test_channel_counts_view_is_cached_for_anonymous_users(client, settings):
490494
"""Test the channel counts view is cached for anonymous users"""
491495
settings.CACHES["redis"] = {
@@ -508,6 +512,7 @@ def test_channel_counts_view_is_cached_for_anonymous_users(client, settings):
508512
assert len(response) == channel_count
509513

510514

515+
@pytest.mark.skip_nplusone_check
511516
def test_channel_counts_view_is_cached_for_authenticated_users(client, settings):
512517
"""Test the channel counts view is cached for authenticated users"""
513518
settings.CACHES["redis"] = {

fixtures/common.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import responses
1111
from pytest_mock import PytestMockWarning
1212
from urllib3.exceptions import InsecureRequestWarning
13+
from zeal import zeal_ignore
1314

1415
from channels.factories import ChannelUnitDetailFactory
1516
from learning_resources.constants import LearningResourceRelationTypes, OfferedBy
@@ -122,3 +123,13 @@ def offeror_featured_lists():
122123
channel = ChannelUnitDetailFactory.create(unit=offeror).channel
123124
channel.featured_list = featured_path
124125
channel.save()
126+
127+
128+
@pytest.fixture(autouse=True)
129+
def check_nplusone(request):
130+
"""Raise nplusone errors"""
131+
if request.node.get_closest_marker("skip_nplusone_check"):
132+
with zeal_ignore():
133+
yield
134+
else:
135+
yield

learning_resources/filters_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ def test_learning_resource_filter_delivery(mock_courses, client):
534534
)
535535

536536

537+
@pytest.mark.skip_nplusone_check
537538
def test_content_file_filter_run_id(mock_content_files, client):
538539
"""Test that the run_id filter works for contentfiles"""
539540

@@ -553,6 +554,7 @@ def test_content_file_filter_run_id(mock_content_files, client):
553554
)
554555

555556

557+
@pytest.mark.skip_nplusone_check
556558
def test_content_file_filter_resource_id(mock_content_files, client):
557559
"""Test that the resource_id filter works for contentfiles"""
558560

@@ -575,6 +577,7 @@ def test_content_file_filter_resource_id(mock_content_files, client):
575577
)
576578

577579

580+
@pytest.mark.skip_nplusone_check
578581
def test_content_file_filter_edx_module_id(mock_content_files, client):
579582
"""Test that the resource_id filter works for contentfiles"""
580583
assert mock_content_files[0].edx_module_id is None
@@ -597,6 +600,7 @@ def test_content_file_filter_edx_module_id(mock_content_files, client):
597600
]
598601

599602

603+
@pytest.mark.skip_nplusone_check
600604
def test_content_file_filter_platform(mock_content_files, client):
601605
"""Test that the platform filter works"""
602606

@@ -614,6 +618,7 @@ def test_content_file_filter_platform(mock_content_files, client):
614618
)
615619

616620

621+
@pytest.mark.skip_nplusone_check
617622
def test_content_file_filter_offered_by(mock_content_files, client):
618623
"""Test that the offered_by filter works for contentfiles"""
619624

@@ -631,6 +636,7 @@ def test_content_file_filter_offered_by(mock_content_files, client):
631636
)
632637

633638

639+
@pytest.mark.skip_nplusone_check
634640
def test_learning_resource_filter_content_feature_type(client):
635641
"""Test that the resource_content_tag filter works"""
636642

learning_resources/views_learningpath_test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def mock_opensearch(mocker):
3232
)
3333

3434

35+
@pytest.mark.skip_nplusone_check
3536
@pytest.mark.parametrize("is_public", [True, False])
3637
@pytest.mark.parametrize("is_editor", [True, False])
3738
@pytest.mark.parametrize("has_image", [True, False])
@@ -135,6 +136,7 @@ def test_learning_path_endpoint_create( # pylint: disable=too-many-arguments #
135136
assert resp.data.get("description") == resp.data.get("description")
136137

137138

139+
@pytest.mark.skip_nplusone_check
138140
@pytest.mark.parametrize("is_public", [True, False])
139141
@pytest.mark.parametrize("is_editor", [True, False])
140142
@pytest.mark.parametrize("update_topics", [True, False])
@@ -175,6 +177,7 @@ def test_learning_path_endpoint_patch(client, update_topics, is_public, is_edito
175177
)
176178

177179

180+
@pytest.mark.skip_nplusone_check
178181
@pytest.mark.parametrize("is_editor", [True, False])
179182
def test_learning_path_items_endpoint_create_item(client, user, is_editor):
180183
"""Test lr_learningpathitems_api endpoint for creating a LearningPath item"""
@@ -232,6 +235,7 @@ def test_learning_path_items_endpoint_create_item_bad_data(client, user):
232235
}
233236

234237

238+
@pytest.mark.skip_nplusone_check
235239
@pytest.mark.parametrize(
236240
("is_editor", "position"),
237241
[[True, 0], [True, 2], [False, 1]], # noqa: PT007
@@ -301,6 +305,7 @@ def test_learning_path_items_endpoint_update_items_wrong_list(client, user):
301305
assert resp.status_code == 404
302306

303307

308+
@pytest.mark.skip_nplusone_check
304309
@pytest.mark.parametrize("num_items", [2, 3])
305310
@pytest.mark.parametrize("is_editor", [True, False])
306311
def test_learning_path_items_endpoint_delete_items(client, user, is_editor, num_items):
@@ -334,6 +339,7 @@ def test_learning_path_items_endpoint_delete_items(client, user, is_editor, num_
334339
assert item.position == (old_position - 1 if is_editor else old_position)
335340

336341

342+
@pytest.mark.skip_nplusone_check
337343
@pytest.mark.parametrize("is_editor", [True, False])
338344
def test_learning_path_endpoint_delete(client, user, is_editor):
339345
"""Test learningpath endpoint for deleting a LearningPath"""
@@ -414,6 +420,7 @@ def test_get_resource_learning_paths(user_client, user, is_editor):
414420
assert response_data == expected
415421

416422

423+
@pytest.mark.skip_nplusone_check
417424
def test_set_learning_path_relationships(client, staff_user):
418425
"""Test the learning_paths endpoint for setting multiple userlist relationships"""
419426
course = factories.CourseFactory.create()
@@ -440,6 +447,7 @@ def test_set_learning_path_relationships(client, staff_user):
440447
).exists()
441448

442449

450+
@pytest.mark.skip_nplusone_check
443451
def test_adding_to_learning_path_not_effect_existing_membership(client, staff_user):
444452
"""
445453
Given L1 (existing parent), L2 (new parent), and R (resource),

learning_resources/views_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def test_get_course_detail_endpoint(client, url):
113113
)
114114

115115

116+
@pytest.mark.skip_nplusone_check
116117
@pytest.mark.parametrize(
117118
"url",
118119
[
@@ -139,6 +140,7 @@ def test_get_course_content_files_endpoint(client, url):
139140
assert resp.data.get("results")[idx]["id"] == content_file.id
140141

141142

143+
@pytest.mark.skip_nplusone_check
142144
@pytest.mark.parametrize(
143145
("reverse_url", "expected_url"),
144146
[
@@ -264,6 +266,7 @@ def test_no_excess_offeror_queries(client, django_assert_num_queries, offeror_co
264266
assert result["channel_url"] is not None
265267

266268

269+
@pytest.mark.skip_nplusone_check
267270
@pytest.mark.parametrize(
268271
"user_role",
269272
[
@@ -311,6 +314,7 @@ def test_list_content_files_list_endpoint(client, user_role, django_user_model):
311314
assert result.get("content") is None
312315

313316

317+
@pytest.mark.skip_nplusone_check
314318
def test_list_content_files_list_endpoint_with_no_runs(client):
315319
"""Test ContentFile list endpoint returns results even without associated runs"""
316320
course = CourseFactory.create()
@@ -330,6 +334,7 @@ def test_list_content_files_list_endpoint_with_no_runs(client):
330334
assert result["id"] in content_file_ids
331335

332336

337+
@pytest.mark.skip_nplusone_check
333338
def test_list_content_files_list_filtered(client):
334339
"""Test ContentFile list endpoint"""
335340
course_1 = CourseFactory.create()
@@ -505,6 +510,7 @@ def test_get_podcast_episode_detail_endpoint(client, url):
505510
)
506511

507512

513+
@pytest.mark.skip_nplusone_check
508514
@pytest.mark.parametrize(
509515
"url", ["lr:v1:learning_resource_items_api-list", "lr:v1:podcast_items_api-list"]
510516
)
@@ -836,6 +842,7 @@ def test_offerors_detail_endpoint(client):
836842
assert resp.data == LearningResourceOfferorDetailSerializer(instance=offeror).data
837843

838844

845+
@pytest.mark.skip_nplusone_check
839846
@pytest.mark.parametrize(
840847
("url", "params"),
841848
[
@@ -879,6 +886,7 @@ def test_get_video_playlist_detail_endpoint(client, url):
879886
)
880887

881888

889+
@pytest.mark.skip_nplusone_check
882890
@pytest.mark.parametrize(
883891
"url",
884892
["lr:v1:learning_resource_items_api-list", "lr:v1:video_playlist_items_api-list"],
@@ -923,6 +931,7 @@ def test_get_video_playlist_items_endpoint(client, url):
923931
)
924932

925933

934+
@pytest.mark.skip_nplusone_check
926935
@pytest.mark.parametrize(
927936
("url", "params"),
928937
[
@@ -948,6 +957,7 @@ def test_list_video_endpoint(client, url, params):
948957
)
949958

950959

960+
@pytest.mark.skip_nplusone_check
951961
@pytest.mark.parametrize(
952962
("url", "params"),
953963
[
@@ -1228,6 +1238,7 @@ def test_similar_resources_endpoint_ignores_opensearch_published(mocker, client)
12281238
assert len(response_ids) == 4
12291239

12301240

1241+
@pytest.mark.skip_nplusone_check
12311242
def test_vector_similar_resources_endpoint_does_not_return_self(mocker, client):
12321243
"""Test vector based similar resources endpoint does not return initial id"""
12331244
from learning_resources.models import LearningResource
@@ -1298,6 +1309,7 @@ def test_vector_similar_resources_endpoint_only_returns_published(mocker, client
12981309
assert len(response_ids) == 1
12991310

13001311

1312+
@pytest.mark.skip_nplusone_check
13011313
def test_learning_resources_display_info_list_view(mocker, client):
13021314
"""Test learning_resources_display_info_list_view returns expected results"""
13031315
from learning_resources.models import LearningResource

learning_resources/views_userlist_test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def test_user_list_endpoint_membership_get(client, user, is_authenticated):
136136
assert resp.status_code == 403
137137

138138

139+
@pytest.mark.skip_nplusone_check
139140
@pytest.mark.parametrize("is_author", [True, False])
140141
def test_user_list_items_endpoint_create_item(client, user, is_author):
141142
"""Test userlistitems endpoint for creating a UserListItem"""
@@ -177,6 +178,7 @@ def test_user_list_items_endpoint_create_item_bad_data(client, user):
177178
}
178179

179180

181+
@pytest.mark.skip_nplusone_check
180182
@pytest.mark.parametrize(
181183
("is_author", "position"),
182184
[[True, 0], [True, 2], [False, 1]], # noqa: PT007
@@ -309,6 +311,7 @@ def test_get_resource_user_lists(client, user, is_author, is_unlisted):
309311
assert items_json == []
310312

311313

314+
@pytest.mark.skip_nplusone_check
312315
def test_set_userlist_relationships(client, user):
313316
"""Test the userlists endpoint for setting multiple userlist relationships"""
314317
course = factories.CourseFactory.create()
@@ -376,6 +379,7 @@ def assign_userlists(course, userlists):
376379
)
377380

378381

382+
@pytest.mark.skip_nplusone_check
379383
def test_adding_to_userlist_not_effect_existing_membership(client, user):
380384
"""
381385
Given L1 (existing parent), L2 (new parent), and R (resource),

main/settings.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,17 @@
200200
"django_scim.middleware.SCIMAuthCheckMiddleware",
201201
)
202202

203+
ZEAL_ENABLE = get_bool("ZEAL_ENABLE", False) # noqa: FBT003
204+
205+
# enable the zeal nplusone profiler only in debug mode or under pytest
206+
if ZEAL_ENABLE or ENVIRONMENT == "pytest":
207+
INSTALLED_APPS += ("zeal",)
208+
# this should be the first middleware so we catch any issues in our own middleware
209+
MIDDLEWARE += ("zeal.middleware.zeal_middleware",)
210+
211+
ZEAL_RAISE = False
212+
ZEAL_ALLOWLIST = []
213+
203214
# CORS
204215
CORS_ALLOWED_ORIGINS = get_list_of_str("CORS_ALLOWED_ORIGINS", [])
205216
CORS_ALLOWED_ORIGIN_REGEXES = get_list_of_str("CORS_ALLOWED_ORIGIN_REGEXES", [])
@@ -483,6 +494,7 @@
483494
"opensearch": {"level": OS_LOG_LEVEL},
484495
"nplusone": {"handlers": ["console"], "level": "ERROR"},
485496
"boto3": {"handlers": ["console"], "level": "ERROR"},
497+
"zeal": {"handlers": ["console"], "level": "ERROR"},
486498
},
487499
"root": {"handlers": ["console"], "level": LOG_LEVEL},
488500
}

news_events/filters_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
ITEM_API_URL = "/api/v0/news_events/"
1010

1111

12+
@pytest.mark.skip_nplusone_check
1213
@pytest.mark.parametrize(
1314
"multifilter", ["feed_type={}&feed_type={}", "feed_type={},{}"]
1415
)

news_events/views_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from news_events.factories import FeedEventDetailFactory
1212

1313

14+
@pytest.mark.skip_nplusone_check
1415
def test_feed_source_viewset_list(client):
1516
"""Est that the feed sources list viewset returns data in expected format"""
1617
sources = sorted(factories.FeedSourceFactory.create_batch(5), key=lambda x: x.id)
@@ -25,6 +26,7 @@ def test_feed_source_viewset_list(client):
2526
)
2627

2728

29+
@pytest.mark.skip_nplusone_check
2830
@pytest.mark.parametrize("feed_type", FeedType.names())
2931
def test_feed_source_viewset_list_filtered(client, feed_type):
3032
"""Test that the sources list viewset returns data filtered by feed type"""

poetry.lock

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)