Skip to content

Commit 5380a64

Browse files
jesperhodgeclaude
andcommitted
test: cover every #641 acceptance criterion and the deletion edge cases
Add a test per acceptance criterion, plus the cases the previous per-foreign-key shape could not reach: a taxonomy or course run deleted with a scoped rule profile, two taxonomies deleted together, an archived profile's scope being reused, and an ObjectTag delete leaving a childless group behind. Add test_criteria_trees.py for whole-tree deletion, so a test proves the bad outcome is avoided rather than only that a cascade fired: it builds a root/branch/grandchild tree with criteria at two levels and a mix of profile-assigned and override criteria, deletes in the middle, and asserts exactly which rows survive. Run the deletion paths under MySQL's collector semantics while still on SQLite, by setting can_defer_constraint_checks to False. That is what makes this class of bug visible in the fast local suite instead of only in the MySQL CI job. Rename every test so the name states the expected behavior rather than the mechanism, and move the fixtures duplicated across both files into conftest.py. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 091724e commit 5380a64

4 files changed

Lines changed: 1002 additions & 260 deletions

File tree

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Shared fixtures for the CBE criteria test modules (schema, deletion, and tree-integration tests).
3+
4+
Every fixture here used to be duplicated verbatim across test_criteria_models.py and
5+
test_criteria_deletion.py. Consolidated here so both files, plus test_criteria_trees.py, share one
6+
definition.
7+
"""
8+
import pytest
9+
from organizations.api import ensure_organization
10+
from organizations.models import Organization
11+
12+
from openedx_catalog.models import CatalogCourse, CourseRun
13+
from openedx_learning.models import CompetencyCriteriaGroup, CompetencyRuleProfile, CompetencyTaxonomy
14+
from openedx_tagging.models import ObjectTag, Tag
15+
16+
17+
@pytest.fixture(name="organization")
18+
def _organization() -> Organization:
19+
"""An Organization for use as a scope in these tests."""
20+
ensure_organization("Org1")
21+
return Organization.objects.get(short_name="Org1")
22+
23+
24+
@pytest.fixture(name="organization2")
25+
def _organization2() -> Organization:
26+
"""A second Organization, distinct from `organization`, for use as a scope in these tests."""
27+
ensure_organization("Org2")
28+
return Organization.objects.get(short_name="Org2")
29+
30+
31+
@pytest.fixture(name="course_run")
32+
def _course_run(organization: Organization) -> CourseRun:
33+
"""A CourseRun for use as a scope in these tests."""
34+
catalog_course = CatalogCourse.objects.create(org=organization, course_code="Python100")
35+
return CourseRun.objects.create(catalog_course=catalog_course, run_code="Fall2026")
36+
37+
38+
@pytest.fixture(name="competency_taxonomy")
39+
def _competency_taxonomy() -> CompetencyTaxonomy:
40+
"""A CompetencyTaxonomy for use as a scope, and as the home taxonomy for `tag`."""
41+
return CompetencyTaxonomy.objects.create(name="Nursing", export_id="nursing-v1")
42+
43+
44+
@pytest.fixture(name="tag")
45+
def _tag(competency_taxonomy: CompetencyTaxonomy) -> Tag:
46+
"""A Tag, from `competency_taxonomy`, for use as the competency a criteria tree evaluates."""
47+
return Tag.objects.create(taxonomy=competency_taxonomy, value="Writing Poetry")
48+
49+
50+
@pytest.fixture(name="object_tag")
51+
def _object_tag(competency_taxonomy: CompetencyTaxonomy, tag: Tag) -> ObjectTag:
52+
"""An ObjectTag associating `tag` with a made-up content object, for use as a criterion's target."""
53+
return ObjectTag.objects.create(
54+
object_id="block-v1:Org1+Python100+Fall2026+problem+p1",
55+
taxonomy=competency_taxonomy,
56+
tag=tag,
57+
)
58+
59+
60+
@pytest.fixture(name="group")
61+
def _group(tag: Tag) -> CompetencyCriteriaGroup:
62+
"""A root CompetencyCriteriaGroup for `tag`, for use as a criterion's parent group."""
63+
return CompetencyCriteriaGroup.objects.create(tag=tag)
64+
65+
66+
@pytest.fixture(name="default_rule_profile")
67+
def _default_rule_profile() -> CompetencyRuleProfile:
68+
"""The system-default CompetencyRuleProfile seeded by migration 0003."""
69+
return CompetencyRuleProfile.objects.get(
70+
organization__isnull=True,
71+
course__isnull=True,
72+
competency_taxonomy__isnull=True,
73+
)

0 commit comments

Comments
 (0)