Skip to content

Commit 28b2a0d

Browse files
committed
style(spp_registry): apply ruff fixes and formatting to test suite
Replace blind `assertRaises(Exception)` with the actual `UserError` raised by `phone_validation.phone_format`, drop unused imports, and apply ruff format to the new test files so pre-commit passes on CI.
1 parent 061b10f commit 28b2a0d

12 files changed

Lines changed: 78 additions & 234 deletions

spp_registry/tests/common.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,11 @@ def setUpClass(cls):
2020
cls.Membership = cls.env["spp.group.membership"]
2121
cls.VocabCode = cls.env["spp.vocabulary.code"]
2222

23-
cls.head_code = cls.VocabCode.sudo().get_code(
24-
"urn:openspp:vocab:group-membership-type", "head"
25-
)
23+
cls.head_code = cls.VocabCode.sudo().get_code("urn:openspp:vocab:group-membership-type", "head")
2624

27-
cls.group = cls.Partner.create(
28-
{"name": "Test Household", "is_registrant": True, "is_group": True}
29-
)
30-
cls.individual_a = cls.Partner.create(
31-
{"name": "Alice", "is_registrant": True, "is_group": False}
32-
)
33-
cls.individual_b = cls.Partner.create(
34-
{"name": "Bob", "is_registrant": True, "is_group": False}
35-
)
25+
cls.group = cls.Partner.create({"name": "Test Household", "is_registrant": True, "is_group": True})
26+
cls.individual_a = cls.Partner.create({"name": "Alice", "is_registrant": True, "is_group": False})
27+
cls.individual_b = cls.Partner.create({"name": "Bob", "is_registrant": True, "is_group": False})
3628

3729
@classmethod
3830
def _make_user(cls, login, group_xmlids):

spp_registry/tests/test_constraints.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -158,32 +158,24 @@ def setUpClass(cls):
158158
cls.IDType = cls.env["spp.id.type"]
159159

160160
def test_valid_uri_accepted(self):
161-
rec = self.IDType.create(
162-
{"name": "PSA National ID", "namespace_uri": "urn:gov:ph:psa:national-id"}
163-
)
161+
rec = self.IDType.create({"name": "PSA National ID", "namespace_uri": "urn:gov:ph:psa:national-id"})
164162
self.assertEqual(rec.namespace_uri, "urn:gov:ph:psa:national-id")
165163

166164
def test_create_lowercases_namespace(self):
167165
"""create() override should normalise to lowercase + trim whitespace."""
168-
rec = self.IDType.create(
169-
{"name": "Mixed Case Type", "namespace_uri": " URN:GOV:PH:Mixed "}
170-
)
166+
rec = self.IDType.create({"name": "Mixed Case Type", "namespace_uri": " URN:GOV:PH:Mixed "})
171167
self.assertEqual(rec.namespace_uri, "urn:gov:ph:mixed")
172168

173169
def test_write_lowercases_namespace(self):
174170
"""write() override should normalise to lowercase + trim whitespace."""
175-
rec = self.IDType.create(
176-
{"name": "Writable Type", "namespace_uri": "urn:gov:ph:initial"}
177-
)
171+
rec = self.IDType.create({"name": "Writable Type", "namespace_uri": "urn:gov:ph:initial"})
178172
rec.write({"namespace_uri": " URN:GOV:PH:UPDATED "})
179173
self.assertEqual(rec.namespace_uri, "urn:gov:ph:updated")
180174

181175
def test_invalid_scheme_rejected(self):
182176
"""Non-``urn:`` URIs violate the ADR-007 pattern."""
183177
with self.assertRaises(ValidationError):
184-
self.IDType.create(
185-
{"name": "Bad Scheme", "namespace_uri": "http://example.org/id"}
186-
)
178+
self.IDType.create({"name": "Bad Scheme", "namespace_uri": "http://example.org/id"})
187179

188180
def test_missing_type_component_rejected(self):
189181
"""``urn:<namespace>`` without the trailing ``:<type>`` is rejected."""
@@ -193,9 +185,7 @@ def test_missing_type_component_rejected(self):
193185
def test_disallowed_characters_rejected(self):
194186
"""The pattern only permits [a-z0-9._-] in each segment."""
195187
with self.assertRaises(ValidationError):
196-
self.IDType.create(
197-
{"name": "Spaces", "namespace_uri": "urn:gov:ph:national id"}
198-
)
188+
self.IDType.create({"name": "Spaces", "namespace_uri": "urn:gov:ph:national id"})
199189

200190
def test_empty_namespace_is_allowed(self):
201191
"""Empty / falsy namespace_uri short-circuits validation (see code)."""
@@ -204,9 +194,7 @@ def test_empty_namespace_is_allowed(self):
204194

205195
def test_duplicate_namespace_uri_rejected(self):
206196
"""The ``_unique_namespace_uri`` SQL constraint must fire."""
207-
self.IDType.create(
208-
{"name": "First", "namespace_uri": "urn:gov:ph:psa:national-id"}
209-
)
197+
self.IDType.create({"name": "First", "namespace_uri": "urn:gov:ph:psa:national-id"})
210198
# TODO: assert IntegrityError via with self.assertRaises + flush().
211199
# SQL constraints raise on flush, not on the ORM call, so the
212200
# idiomatic Odoo pattern is ``with mute_logger(...): self.env.flush_all()``.

spp_registry/tests/test_group_aggregation.py

Lines changed: 16 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@
3636
way to ``spp.vocabulary.code``. So callers must pass display strings.
3737
"""
3838

39-
from datetime import datetime, timedelta
40-
41-
from odoo import fields
4239
from odoo.tests import tagged
4340

4441
from .common import RegistryCommon
@@ -49,17 +46,11 @@ class AggregationCommon(RegistryCommon):
4946
@classmethod
5047
def setUpClass(cls):
5148
super().setUpClass()
52-
cls.individual_c = cls.Partner.create(
53-
{"name": "Carol", "is_registrant": True, "is_group": False}
54-
)
55-
cls.individual_d = cls.Partner.create(
56-
{"name": "Dave", "is_registrant": True, "is_group": False}
57-
)
49+
cls.individual_c = cls.Partner.create({"name": "Carol", "is_registrant": True, "is_group": False})
50+
cls.individual_d = cls.Partner.create({"name": "Dave", "is_registrant": True, "is_group": False})
5851

5952
# Second group so multi-group queries can be tested.
60-
cls.group_b = cls.Partner.create(
61-
{"name": "Second Household", "is_registrant": True, "is_group": True}
62-
)
53+
cls.group_b = cls.Partner.create({"name": "Second Household", "is_registrant": True, "is_group": True})
6354

6455
# Synthesize a non-head membership-type code so we can filter
6556
# by relationship_kinds without head-uniqueness collisions.
@@ -81,9 +72,7 @@ def _add_member(self, group, individual, type_codes=()):
8172
{
8273
"group": group.id,
8374
"individual": individual.id,
84-
"membership_type_ids": [(6, 0, [c.id for c in type_codes])]
85-
if type_codes
86-
else False,
75+
"membership_type_ids": [(6, 0, [c.id for c in type_codes])] if type_codes else False,
8776
}
8877
)
8978

@@ -146,10 +135,7 @@ def test_disabled_individual_excluded(self):
146135
``_query_members_aggregate`` from ``expression.expression()`` to
147136
the ``Domain`` API (the deprecation warning's own suggestion).
148137
Then drop these skips."""
149-
self.skipTest(
150-
"BROKEN: deprecated expression.expression() yields empty "
151-
"filter SQL on Odoo 19 — see docstring"
152-
)
138+
self.skipTest("BROKEN: deprecated expression.expression() yields empty filter SQL on Odoo 19 — see docstring")
153139

154140
def test_ended_membership_excluded(self):
155141
"""Same Odoo-19 ``expression.expression()`` deprecation bug as
@@ -186,26 +172,20 @@ class TestCountIndividualsKindFilter(AggregationCommon):
186172
def test_filter_by_head_display_matches_only_head_members(self):
187173
self._add_member(self.group, self.individual_a, type_codes=[self.head_code])
188174
self._add_member(self.group, self.individual_b, type_codes=[self.member_code])
189-
result = self._to_dict(
190-
self.group.count_individuals(relationship_kinds=["Head"])
191-
)
175+
result = self._to_dict(self.group.count_individuals(relationship_kinds=["Head"]))
192176
self.assertEqual(result.get(self.group.id), 1)
193177

194178
def test_filter_by_multiple_displays(self):
195179
self._add_member(self.group, self.individual_a, type_codes=[self.head_code])
196180
self._add_member(self.group, self.individual_b, type_codes=[self.member_code])
197-
result = self._to_dict(
198-
self.group.count_individuals(relationship_kinds=["Head", "Member"])
199-
)
181+
result = self._to_dict(self.group.count_individuals(relationship_kinds=["Head", "Member"]))
200182
self.assertEqual(result.get(self.group.id), 2)
201183

202184
def test_filter_with_no_matches_returns_no_row(self):
203185
"""No memberships with the requested kind → group falls out of
204186
the GROUP BY entirely."""
205187
self._add_member(self.group, self.individual_a, type_codes=[self.head_code])
206-
result = self._to_dict(
207-
self.group.count_individuals(relationship_kinds=["Member"])
208-
)
188+
result = self._to_dict(self.group.count_individuals(relationship_kinds=["Member"]))
209189
self.assertNotIn(self.group.id, result)
210190

211191
def test_lowercase_code_does_not_match(self):
@@ -215,9 +195,7 @@ def test_lowercase_code_does_not_match(self):
215195
216196
Pin the surprise; document until the impl is harmonized."""
217197
self._add_member(self.group, self.individual_a, type_codes=[self.head_code])
218-
result = self._to_dict(
219-
self.group.count_individuals(relationship_kinds=["head"])
220-
)
198+
result = self._to_dict(self.group.count_individuals(relationship_kinds=["head"]))
221199
self.assertNotIn(self.group.id, result)
222200

223201

@@ -229,16 +207,12 @@ class TestCountIndividualsDomainFilter(AggregationCommon):
229207
def test_filter_by_individual_name(self):
230208
self._add_member(self.group, self.individual_a) # "Alice"
231209
self._add_member(self.group, self.individual_b) # "Bob"
232-
result = self._to_dict(
233-
self.group.count_individuals(domain=[("name", "=", "Alice")])
234-
)
210+
result = self._to_dict(self.group.count_individuals(domain=[("name", "=", "Alice")]))
235211
self.assertEqual(result.get(self.group.id), 1)
236212

237213
def test_filter_with_no_matching_individuals(self):
238214
self._add_member(self.group, self.individual_a)
239-
result = self._to_dict(
240-
self.group.count_individuals(domain=[("name", "=", "Nobody")])
241-
)
215+
result = self._to_dict(self.group.count_individuals(domain=[("name", "=", "Nobody")]))
242216
self.assertNotIn(self.group.id, result)
243217

244218
def test_compound_domain(self):
@@ -247,9 +221,7 @@ def test_compound_domain(self):
247221
self._add_member(self.group, self.individual_b) # Bob, individual
248222
# All individuals match is_registrant=True; restrict to "Alice".
249223
result = self._to_dict(
250-
self.group.count_individuals(
251-
domain=[("is_registrant", "=", True), ("name", "=", "Alice")]
252-
)
224+
self.group.count_individuals(domain=[("is_registrant", "=", True), ("name", "=", "Alice")])
253225
)
254226
self.assertEqual(result.get(self.group.id), 1)
255227

@@ -259,9 +231,7 @@ def test_kind_and_domain_combined(self):
259231
self._add_member(self.group, self.individual_b, type_codes=[self.member_code])
260232
# Only Bob is a "Member" AND named "Bob" → expect 1.
261233
result = self._to_dict(
262-
self.group.count_individuals(
263-
relationship_kinds=["Member"], domain=[("name", "=", "Bob")]
264-
)
234+
self.group.count_individuals(relationship_kinds=["Member"], domain=[("name", "=", "Bob")])
265235
)
266236
self.assertEqual(result.get(self.group.id), 1)
267237

@@ -297,11 +267,7 @@ def test_kind_domain_with_translated_name_leaf(self):
297267
op, val)`` for the vocab query. Pin that the translation is the
298268
contract — pass a ``name`` leaf and observe display filtering."""
299269
self._add_member(self.group, self.individual_a, type_codes=[self.head_code])
300-
result = dict(
301-
self.group._query_members_aggregate(
302-
membership_kind_domain=[("name", "in", ["Head"])]
303-
)
304-
)
270+
result = dict(self.group._query_members_aggregate(membership_kind_domain=[("name", "in", ["Head"])]))
305271
self.assertEqual(result.get(self.group.id), 1)
306272

307273

@@ -339,9 +305,7 @@ def test_no_records_is_noop(self):
339305
# Pass only individuals; ``.filtered(lambda a: a.is_group)`` yields
340306
# empty. Method should silently return.
341307
individuals = self.individual_a | self.individual_b
342-
individuals.compute_count_and_set_indicator(
343-
field_name="never_set", kinds=None, domain=None
344-
)
308+
individuals.compute_count_and_set_indicator(field_name="never_set", kinds=None, domain=None)
345309

346310

347311
@tagged("post_install", "-at_install")
@@ -353,9 +317,7 @@ class TestUpdateComputeFields(AggregationCommon):
353317
def test_filters_to_groups_only_no_raise(self):
354318
"""Non-group records are filtered out by the first line."""
355319
individuals = self.individual_a | self.individual_b
356-
self.env["res.partner"]._update_compute_fields(
357-
individuals, field_name="never_set", kinds=None, domain=None
358-
)
320+
self.env["res.partner"]._update_compute_fields(individuals, field_name="never_set", kinds=None, domain=None)
359321

360322
def test_happy_path_requires_host_module_field(self):
361323
# TODO: same as TestComputeCountAndSetIndicator — needs an integer

spp_registry/tests/test_individual_name.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,7 @@ def test_create_sets_name_from_parts(self):
132132

133133
def test_create_respects_explicit_name_when_no_parts(self):
134134
"""No name parts in vals → ``name`` is NOT overwritten."""
135-
rec = self.Partner.create(
136-
{"is_registrant": True, "name": "Explicit Name"}
137-
)
135+
rec = self.Partner.create({"is_registrant": True, "name": "Explicit Name"})
138136
self.assertEqual(rec.name, "Explicit Name")
139137

140138
def test_create_does_not_format_for_groups(self):
@@ -151,9 +149,7 @@ def test_create_does_not_format_for_groups(self):
151149
self.assertEqual(rec.name, "Test Household")
152150

153151
def test_create_with_only_addl(self):
154-
rec = self.Partner.create(
155-
{"is_registrant": True, "addl_name": "Marie"}
156-
)
152+
rec = self.Partner.create({"is_registrant": True, "addl_name": "Marie"})
157153
self.assertEqual(rec.name, "MARIE")
158154

159155

@@ -199,9 +195,7 @@ def test_skip_name_format_context_bypasses_reformat(self):
199195
super() without recursion. Anyone passing the context explicitly
200196
gets the same opt-out.
201197
"""
202-
self.rec.with_context(skip_name_format=True).write(
203-
{"family_name": "Smith"}
204-
)
198+
self.rec.with_context(skip_name_format=True).write({"family_name": "Smith"})
205199
# family_name updated but name unchanged.
206200
self.assertEqual(self.rec.family_name, "Smith")
207201
self.assertEqual(self.rec.name, "DOE, JANE")

spp_registry/tests/test_membership_constraints.py

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
from odoo import fields
2323
from odoo.exceptions import ValidationError
24-
from odoo.tests import Form, tagged
24+
from odoo.tests import tagged
2525

2626
from .common import RegistryCommon
2727

@@ -57,45 +57,27 @@ class TestCheckGroupMembers(MembershipCommon):
5757
"""``_check_group_members`` — no duplicate individuals in a group."""
5858

5959
def test_same_individual_twice_in_same_group_rejected(self):
60-
self.Membership.create(
61-
{"group": self.group.id, "individual": self.individual_a.id}
62-
)
60+
self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
6361
with self.assertRaises(ValidationError):
64-
self.Membership.create(
65-
{"group": self.group.id, "individual": self.individual_a.id}
66-
)
62+
self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
6763

6864
def test_different_individuals_in_same_group_allowed(self):
69-
self.Membership.create(
70-
{"group": self.group.id, "individual": self.individual_a.id}
71-
)
72-
rec = self.Membership.create(
73-
{"group": self.group.id, "individual": self.individual_b.id}
74-
)
65+
self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
66+
rec = self.Membership.create({"group": self.group.id, "individual": self.individual_b.id})
7567
self.assertTrue(rec.id)
7668

7769
def test_same_individual_in_different_groups_allowed(self):
7870
"""Cross-group memberships for the same person are fine."""
79-
other_group = self.Partner.create(
80-
{"name": "Second Household", "is_registrant": True, "is_group": True}
81-
)
82-
self.Membership.create(
83-
{"group": self.group.id, "individual": self.individual_a.id}
84-
)
85-
rec = self.Membership.create(
86-
{"group": other_group.id, "individual": self.individual_a.id}
87-
)
71+
other_group = self.Partner.create({"name": "Second Household", "is_registrant": True, "is_group": True})
72+
self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
73+
rec = self.Membership.create({"group": other_group.id, "individual": self.individual_a.id})
8874
self.assertTrue(rec.id)
8975

9076
def test_write_into_duplicate_individual_rejected(self):
9177
"""Reassigning a membership to an already-present individual trips
9278
the constraint via the write path."""
93-
self.Membership.create(
94-
{"group": self.group.id, "individual": self.individual_a.id}
95-
)
96-
existing = self.Membership.create(
97-
{"group": self.group.id, "individual": self.individual_b.id}
98-
)
79+
self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
80+
existing = self.Membership.create({"group": self.group.id, "individual": self.individual_b.id})
9981
with self.assertRaises(ValidationError):
10082
existing.write({"individual": self.individual_a.id})
10183

@@ -239,9 +221,7 @@ class TestComputeStatus(MembershipCommon):
239221
``ended_date``."""
240222

241223
def test_active_when_no_end_date(self):
242-
rec = self.Membership.create(
243-
{"group": self.group.id, "individual": self.individual_a.id}
244-
)
224+
rec = self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
245225
self.assertEqual(rec.status, "active")
246226

247227
def test_active_when_end_date_in_future(self):
@@ -292,9 +272,7 @@ class TestComputeIsEnded(MembershipCommon):
292272
"""``_compute_is_ended`` — boolean shadow of ``status``."""
293273

294274
def test_false_when_no_end_date(self):
295-
rec = self.Membership.create(
296-
{"group": self.group.id, "individual": self.individual_a.id}
297-
)
275+
rec = self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
298276
self.assertFalse(rec.is_ended)
299277

300278
def test_false_when_end_date_in_future(self):
@@ -363,9 +341,7 @@ class TestMembershipDisplayName(MembershipCommon):
363341
"""``_compute_display_name`` — uses the group's name."""
364342

365343
def test_display_name_is_group_name(self):
366-
rec = self.Membership.create(
367-
{"group": self.group.id, "individual": self.individual_a.id}
368-
)
344+
rec = self.Membership.create({"group": self.group.id, "individual": self.individual_a.id})
369345
self.assertEqual(rec.display_name, self.group.name)
370346

371347
def test_display_name_falls_back_when_no_group(self):

0 commit comments

Comments
 (0)