Skip to content

Commit b9a7071

Browse files
test: refactor test_client_facades
Explicitly test assumptions about facade name and version numbering, and then build the required data structure more directly in a single pass + sorting.
1 parent 74dbff3 commit b9a7071

1 file changed

Lines changed: 37 additions & 45 deletions

File tree

tests/validate/test_facades.py

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import importlib
55
import re
66
from pathlib import Path
7-
from typing import Dict, List, Set, Tuple, TypedDict, cast
7+
from typing import Dict, List, TypedDict, cast
88

99
import pytest
1010

@@ -23,60 +23,52 @@ def project_root(pytestconfig: pytest.Config) -> Path:
2323
return pytestconfig.rootpath
2424

2525

26-
def test_client_facades(project_root: Path) -> None:
26+
def test_facade_version_matches_filename(project_root: Path) -> None:
27+
ignore_names = dir(_definitions)
28+
for file in (project_root / 'juju' / 'client').glob('_client[0-9]*.py'):
29+
match = re.search('_client([0-9]+).py', file.name)
30+
assert match
31+
version = int(match.group(1))
32+
module = importlib.import_module(f'juju.client.{file.stem}')
33+
for cls_name in dir(module):
34+
if cls_name.startswith('_') or cls_name in ignore_names:
35+
continue
36+
assert getattr(module, cls_name).version == version
37+
38+
39+
def test_class_name_matches_facade_name(project_root: Path) -> None:
40+
ignore_names = dir(_definitions)
41+
for file in (project_root / 'juju' / 'client').glob('_client[0-9]*.py'):
42+
module = importlib.import_module(f'juju.client.{file.stem}')
43+
for cls_name in dir(module):
44+
if cls_name.startswith('_') or cls_name in ignore_names:
45+
continue
46+
assert getattr(module, cls_name).name == cls_name.removesuffix('Facade')
47+
48+
49+
def test_client_facades_matches_generated_code(project_root: Path) -> None:
2750
client_facades = cast(ClientFacades, connection.client_facades)
28-
good_facades = make_client_facades_from_generated_code(project_root)
51+
expected_facades = make_client_facades_from_generated_code(project_root)
2952
assert {
3053
k: v['versions'] for k, v in client_facades.items()
3154
} == {
32-
k: v['versions'] for k, v in good_facades.items()
55+
k: v['versions'] for k, v in expected_facades.items()
3356
}
3457

3558

3659
def make_client_facades_from_generated_code(project_root: Path) -> ClientFacades:
3760
"""Return a client_facades dictionary from generated code under project_root.
3861
"""
39-
files_by_version: List[Tuple[int, Path]] = []
40-
# [(facade_version, Path), ...]
62+
ignore_names = dir(_definitions)
63+
excluded_facades = connection.excluded_facades
64+
facades: Dict[str, List[int]] = {}
4165
for file in (project_root / 'juju' / 'client').glob('_client[0-9]*.py'):
42-
files_by_version.append((_version_from_filename(file), file))
43-
files_by_version.sort()
44-
45-
# _clientN.py files import * from _definitions
46-
# so we will ignore any names from there
47-
ignore = dir(_definitions)
48-
49-
facades_by_version: Dict[int, Set[str]] = {}
50-
# {facade_version: {facade_name, ...}, ...}
51-
for version, file in files_by_version:
5266
module = importlib.import_module(f'juju.client.{file.stem}')
53-
facades = {
54-
name.removesuffix("Facade")
55-
for name in dir(module)
56-
if not (name.startswith('_') or name in ignore)
57-
}
58-
facades_by_version[version] = facades
59-
60-
# client_facades in connection.py is sorted
61-
# so we sort facade names before constructing it
62-
first, *rest = facades_by_version.values()
63-
sorted_facade_names: list[str] = sorted(first.union(*rest))
64-
65-
excluded_facades = connection.excluded_facades
66-
client_facades: ClientFacades = {}
67-
# {facade_name: {'versions': [1, 2, 3, ...]}, ...}
68-
for name in sorted_facade_names:
69-
versions: List[int] = []
70-
for version, facades in facades_by_version.items():
71-
if version in excluded_facades.get(name, []):
67+
for cls_name in dir(module):
68+
if cls_name.startswith('_') or cls_name in ignore_names:
7269
continue
73-
if name in facades:
74-
versions.append(version)
75-
client_facades[name] = {'versions': versions}
76-
return client_facades
77-
78-
79-
def _version_from_filename(path: Path) -> int:
80-
match = re.search('_client([0-9]+).py', path.name)
81-
assert match
82-
return int(match.group(1))
70+
cls = getattr(module, cls_name)
71+
if cls.version in excluded_facades.get(cls.name, []):
72+
continue
73+
facades.setdefault(cls.name, []).append(cls.version)
74+
return {name: {'versions': sorted(facades[name])} for name in sorted(facades)}

0 commit comments

Comments
 (0)