test(frontmatter): consolidate set_frontmatter_status tests - #367
Conversation
Part 3 of #357. `set_frontmatter_status`'s original tests stayed in tests/test_resolve.py through parts 1 and 2 so those diffs read as changes rather than as a rename (characterize before restructuring). Flat tests/ mirrors src modules by name, so they belong next to the module that defines them. Two of the four were already covered in test_frontmatter.py and are deleted rather than moved; the plain-flip fixture is folded into the existing byte-exact test; the triple-dash pin moves. `set_frontmatter_field` stays here — that function lives in verify.py. Tests only. No src change.
WalkthroughChangesFrontmatter test coverage
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis is a tests-only consolidation (part 3 of #357):
Confidence Score: 5/5Safe to merge — exclusively test and changelog changes with no src/ modifications. No production code is touched. Every deletion is demonstrably subsumed by a stronger existing assertion in the destination file, the moved test gains a stricter oracle, and the fixture enrichment is consistent with all callers. Files Needing Attention: No files require special attention.
|
| Filename | Overview |
|---|---|
| tests/test_frontmatter.py | Receives one moved test and a richer _PLAIN fixture; moved test is strictly stronger than its origin (byte-exact comparison vs. substring check). |
| tests/test_resolve.py | Drops four set_frontmatter_status tests (2 deleted as subsumed, 1 folded, 1 moved); section header and inline comments updated to reflect coverage now lives in test_frontmatter.py. |
| tests/test_stories.py | Single-line comment fix: stale line-number cross-reference replaced with a stable section-name reference. |
| CHANGELOG.md | Adds an entry describing the test consolidation as a tests-only, no-behavior-change move. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
subgraph before["Before (test_resolve.py)"]
R1[test_set_frontmatter_status_replaces]
R2[test_set_frontmatter_status_idempotent]
R3[test_set_frontmatter_status_no_frontmatter]
R4[test_set_frontmatter_status_preserves_triple_dash_in_value]
end
subgraph after["After (test_frontmatter.py)"]
F1[test_a_plain_flip_changes_the_status_line_and_nothing_else]
F2[test_flipping_to_the_status_already_there_returns_false_and_does_not_write]
F3[test_no_frontmatter_block_returns_false_with_the_bytes_unchanged]
F4[test_set_frontmatter_status_preserves_triple_dash_in_value]
end
R1 -->|folded| F1
R2 -->|deleted - subsumed by mtime check| F2
R3 -->|deleted - subsumed by byte assertion| F3
R4 -->|moved verbatim| F4
Reviews (2): Last reviewed commit: "test(frontmatter): make the triple-dash ..." | Re-trigger Greptile
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_frontmatter.py`:
- Around line 120-129: Update
test_set_frontmatter_status_preserves_triple_dash_in_value to assert the
complete decoded file output equals text.replace("status: in-review", "status:
done") instead of checking only that "body text" is present, while keeping the
existing frontmatter status and title assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b42ed327-2382-43f1-aac0-64dd6de6a3ec
📒 Files selected for processing (4)
CHANGELOG.mdtests/test_frontmatter.pytests/test_resolve.pytests/test_stories.py
CodeRabbit on #367: `assert "body text" in ...` is the one substring assertion in a file whose convention is byte-exact comparison, and it passes a corruption the rest of the file would catch. Evidence: ablating `_verified` to return `yaml.safe_dump(parsed)` — the round-trip the line edit exists to refuse — reorders the keys and strips the title's quotes while leaving "body text" in place. The old form passes that; the byte-exact form fails it.
|
Taken — the substring assert was the weak one, and the ablation makes the case concretely. Ablating Keys reordered, the scalar's quotes stripped — and Fixed in d2ca45f. |
Part 3 of #357 — the last one. Parts 1 (line endings, #364) and 2 (inline comments, #365) are merged; both were confirmed on
mainbefore this branch was cut (frontmatter.pyreadsread_bytes().decode,_replace_valuecarries a trailing comment).Tests only. Zero
src/changes —src/bmad_loop/frontmatter.pyis byte-identical tomain(verified bydiffagainst a pre-edit copy after the ablation below).set_frontmatter_status's original tests stayed intests/test_resolve.pythrough parts 1 and 2 on purpose: moving them then would have hidden those diffs behind a rename. AGENTS.md — flattests/mirrors src modules by name — puts them intests/test_frontmatter.py, next to the module that defines them.set_frontmatter_field's tests stay intest_resolve.py: that function lives inverify.py, so moving it is a different change.What happened to each of the four
Judged against the destination file's actual current content, not against the issue's description of it.
test_resolve.pytest..._idempotenttest_flipping_to_the_status_already_there_returns_false_and_does_not_writealready covers it, and covers it harder: it assertsst_mtime_nsis unchanged, so a no-op write fails it. The resolve copy only checked the return value...._no_frontmattertest_no_frontmatter_block_returns_false_with_the_bytes_unchangedis the same case plus a byte assertion...._replacesowner:,title:,<frozen-after-approval>) are strictly weaker than the destination's byte-exact whole-file comparison — but its fixture carried one thing_PLAINdid not: a<frozen-after-approval>body block. That block moved into_PLAIN, so the byte-exact assertion now covers it (and the CRLF / CR-only / idempotence tests inherit the richer fixture)...._preserves_triple_dash_in_valuetest_the_verified_edit_is_never_a_yaml_round_triphappens to carry a----bearing title today, but that is incidental to what it pins — simplify its fixture and the coverage vanishes silently. Name kept as-is so it still pairs withtest_set_frontmatter_field_preserves_triple_dash_in_value, which stays intest_resolve.py.Adjustments to the moved test, per the destination file's conventions:
tmp_path+write_text→ the_specbyte-writing helper,verify.*→frontmatter.*(the re-export identity is already pinned bytest_verify_re_exports_the_same_exception_object), andread_text→read_bytes().decode()so universal-newline translation can't mask a line-ending change.Its final assertion also stopped being
assert "body text" in ...(d2ca45f, on CodeRabbit's review) — the one substring check in a file whose convention is byte-exact comparison. That is not a style nit: ablating_verifiedtoreturn yaml.safe_dump(parsed), the round-trip the line edit exists to refuse, reorders the keys and strips the scalar's quotes while leavingbody textin place. The substring form passes that corruption — run against the ablated writer to confirm rather than infer it — and the byte-exact form fails it.Cross-references repaired
test_resolve.pymodule docstring: "spec status writer" → "spec field writer".set_frontmatter_statussection header becomes aset_frontmatter_fieldheader that says where the status tests went and why these stayed.set_frontmatter_fielddocstrings/comments that contrast againstset_frontmatter_statusnow nametests/test_frontmatter.pyinstead of pointing at a neighbour that left.test_frontmatter.py's module docstring loses the paragraph that said this consolidation "is filed as frontmatter: set_frontmatter_status does not preserve the bytes its contract promises #357".tests/test_stories.py:58pointed attests/test_resolve.py:346. That reference was correct when written (feat(stories): spec-to-loop engine, adapter, CLI + HITL checkpoints (Phase 2 + 3) #77) and had already rotted to an unrelated assertion through later growth; this PR shifts it again. Replaced with a section name rather than a fresh line number, so it can't rot the same way.Verification
uv run pytest tests/test_frontmatter.py tests/test_resolve.py -q→ 79 passed.test_frontmatter.py36 → 37 (+1 moved in),test_resolve.py46 → 42 (−4), whole suite 3702 → 3699 (−3 = 2 deleted + 1 folded). A silent selector miss would show up here as a mismatch.test_set_frontmatter_status_preserves_triple_dash_in_valueresolves to exactly one definition suite-wide. (A cross-file name-reuse audit turns up 13 pre-existing pairs in other modules; none involve these files.)_split_frontmatter's standalone-delimiter scan with the naivetext.split("---", 2)it exists to refuse makes it FAIL — the property it names is live. (2) Theyaml.safe_dumpround-trip described above, which the pre-d2ca45f assertion form passed.src/was restored and confirmed byte-identical after each.uv run pytest -q -n auto: 3675 passed, 24 skipped — run 4× green here, andmainrun 3× green for comparison. One earlier run failedtest_stories_e2e.py::test_e2e_sprint_mode_regression, which did not reproduce in 4 subsequent full runs or in 3 isolated-n autoruns of that file; it is a real-tmux E2E flake with no path to a docstring-and-deletion diff in three unrelated test modules.trunk fmt+ fulltrunk check --no-fix: no issues.Closes #357