Skip to content

Commit 8d9d6ca

Browse files
committed
implement: Test against real Lambda Feedback exports (t19)
1 parent 4c3d206 commit 8d9d6ca

2 files changed

Lines changed: 23 additions & 19 deletions

File tree

in2lambda/json_convert/json_convert.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,13 @@ def converter(
9797
)
9898

9999
# Lambda Feedback names the file after the title with only spaces made
100-
# underscores; path separators go too, so a title cannot leave the set folder.
100+
# underscores. Path separators go too, so a title cannot leave the set folder,
101+
# and so do the characters Windows forbids in file names.
101102
filename = (
102103
"question_"
103104
+ str(i).zfill(3)
104105
+ "_"
105-
+ re.sub(r"[\s/\\]", "_", output["title"].strip())
106+
+ re.sub(r'[\s/\\<>:"|?*]', "_", output["title"].strip())
106107
)
107108

108109
# write questions into directory

tests/test_exports.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,21 @@ def _key_paths(value, path: str = "") -> set[str]:
5757
paths |= {f"{path}.{key}"} | _key_paths(item, f"{path}.{key}")
5858
return paths
5959
if isinstance(value, list):
60-
return set().union(*(_key_paths(item, f"{path}[]") for item in value))
60+
return set().union(
61+
*(_key_paths(item, f"{path}[{i}]") for i, item in enumerate(value))
62+
)
6163
return set()
6264

6365

64-
def _keys_by_kind(directory: Path) -> dict[str, set[str]]:
65-
# Pooled over every set_ or question_ file rather than matched file to file:
66-
# exports leave out components with no content, such as a part's worked solution.
67-
keys: dict[str, set[str]] = {}
68-
for file in directory.glob("*.json"):
69-
kind = file.name.split("_")[0]
70-
keys.setdefault(kind, set()).update(_key_paths(json.loads(file.read_text())))
71-
return keys
66+
def _unexported_keys(written: dict, exported: dict) -> list[str]:
67+
missing = _key_paths(written) - _key_paths(exported)
68+
# Lambda Feedback leaves a part's workedSolution out of its export when the part
69+
# has none, but the writer always emits one, so only then may it be absent.
70+
for i, part in enumerate(written.get("parts", [])):
71+
if not part["workedSolution"]["content"]:
72+
prefix = f".parts[{i}].workedSolution"
73+
missing = {key for key in missing if not key.startswith(prefix)}
74+
return sorted(missing)
7275

7376

7477
def test_export_round_trips(export_dir: Path, tmp_path: Path) -> None:
@@ -85,12 +88,12 @@ def test_export_round_trips(export_dir: Path, tmp_path: Path) -> None:
8588

8689
def test_written_keys_exist_in_export(export_dir: Path, tmp_path: Path) -> None:
8790
"""The writer emits no key, at any depth, that Lambda Feedback never exports there."""
88-
written = _keys_by_kind(_write_back(load_export(export_dir), tmp_path))
89-
exported = _keys_by_kind(export_dir)
90-
91-
missing = {
92-
kind: sorted(keys - exported[kind])
93-
for kind, keys in written.items()
94-
if keys - exported[kind]
95-
}
91+
written = _write_back(load_export(export_dir), tmp_path)
92+
93+
missing = {}
94+
for file in written.glob("*.json"):
95+
exported = json.loads((export_dir / file.name).read_text())
96+
keys = _unexported_keys(json.loads(file.read_text()), exported)
97+
if keys:
98+
missing[file.name] = keys
9699
assert not missing, missing

0 commit comments

Comments
 (0)