Skip to content

[quality] test: unit coverage for scripts/generate_skill_index.py and scripts/update_coverage_snapshot.py - #766

Closed
kubestellar-hive[bot] wants to merge 1 commit into
mainfrom
quality/test-catalog-and-snapshot-scripts
Closed

kubestellar-hive[bot] wants to merge 1 commit into
mainfrom
quality/test-catalog-and-snapshot-scripts

Conversation

@kubestellar-hive

Copy link
Copy Markdown
Contributor

Claimed cluster

This PR claims exactly two files, both new test files only — no production code is touched:

  • tests/unit/test_generate_skill_index.py (new) — covers scripts/generate_skill_index.py: parse_frontmatter, collect, render_json, render_md, main
  • tests/unit/test_update_coverage_snapshot.py (new) — covers scripts/update_coverage_snapshot.py: parse_scenarios, classify, SuiteCounts, count_scenarios, render_snapshot, update_file, main

Disjoint from every open testsuite PR: #751 touches tests/unit/test_screenshot_steps.py, #757 touches tests/smoke/features/steps/system_health_steps.py + tests/unit/test_system_health_steps.py, #765 touches tests/unit/test_suite_environment_contract.py. No overlap in files or functions.

Why

scripts/generate_skill_index.py (165 lines) and scripts/update_coverage_snapshot.py (186 lines) are the only two Python scripts in scripts/ with zero unit tests, and both are merge gates:

  • .github/workflows/docs-validate.yml runs generate_skill_index.py --check
  • .github/workflows/pr-validate.yml runs update_coverage_snapshot.py --check

A regression in either silently breaks a required check or, worse, lets a stale catalog through.

What is covered

test_generate_skill_index.py — 36 tests

  • parse_frontmatter: valid mapping, missing --- front matter, non-mapping front matter
  • collect: entry construction, sort-by-id, description whitespace collapsing, metadata.typedoc_type, each of the 9 required fields missing, unknown category, unknown status, entry_point not matching its own path, id != name, multi-error batching
  • render_json: payload shape, trailing newline, ensure_ascii=False
  • render_md: href relative to docs/skills, generated/schema/count header, empty catalog, front matter block
  • main: generate mode writes both files; --check returns 1 on missing index.json, stale index.json, hand-edited index.md; returns 0 when in sync; --check never writes; --check reuses the committed generated_at instead of today's date (the property that stops the gate failing every day after commit)

test_update_coverage_snapshot.py — 49 tests

  • parse_scenarios: feature-tag inheritance, scenario tags, union of both, tags not leaking to the next scenario, multi-tag lines, accumulation across tag lines, hyphenated tags, Scenario Outline, comment lines ignored, step lines inert, Rule:/Background:/Examples: discarding pending tags
  • classify: precedence quarantine > hardware_blocked/future/pending > active
  • SuiteCounts.total
  • count_scenarios: bucketing, suite name derivation, per-file aggregation, multiple suites
  • render_snapshot: marker wrapping, summary totals + feature-file count, SUITE_NOTES lookup, missing-note empty cell, sorted suite order, empty tree
  • update_file: missing markers → 2, missing end marker → 2, --check pass/stale, --check does not rewrite, write replaces only the marked block, idempotent write, write-then-check clean
  • main: --repo-root honoured, --check exit codes, write path

Verification

python3 -m pytest tests/unit/test_generate_skill_index.py tests/unit/test_update_coverage_snapshot.py -q
85 passed

Full suite: 1321 passed. The remaining failures/errors are pre-existing and unrelated (behave, requests not installed in this environment).

Related

Refs projectbluefin/testsuite skill-catalog and coverage-snapshot gates.


Filed by quality agent (hold-gated mode). Human review required — do not merge without review; the hold label must stay.

— hive: agent=quality backend=copilot model=claude-opus-5

…pdate_coverage_snapshot.py

Both scripts gate CI (docs-validate.yml runs generate_skill_index.py --check,
pr-validate.yml runs update_coverage_snapshot.py --check) but had zero unit
tests. A regression in either silently breaks a merge gate.

tests/unit/test_generate_skill_index.py (36 tests) covers parse_frontmatter,
collect() front-matter validation (required fields, category/status enums,
entry_point self-match, id==name, multi-error reporting), description
whitespace collapsing, metadata.type -> doc_type, render_json, render_md
href/header rendering, and main() in both generate and --check modes,
including that --check reuses the committed generated_at rather than today.

tests/unit/test_update_coverage_snapshot.py (49 tests) covers parse_scenarios
feature-tag inheritance and pending-tag reset semantics, Scenario Outline,
Rule/Background/Examples resets, classify() tag precedence, SuiteCounts.total,
count_scenarios aggregation, render_snapshot markers/totals/notes/ordering,
and update_file marker handling plus write and --check modes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: kubestellar-hive[bot] <kubestellar-hive[bot]@users.noreply.github.com>

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

85 tests, genuinely exercises both scripts including the tricky generated_at date-stability case. CI pytest is red on the same pre-existing/unrelated failure noted on #776, not caused by this diff. Note: overlaps #776 — both add tests/unit/test_update_coverage_snapshot.py at the identical path with different content; this one is broader (also covers generate_skill_index.py), so recommend landing this one and closing #776, flagged on both.


Generated by Claude Code

@hanthor hanthor left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Half of this is already on main, the other half duplicates #788

tests/unit/test_update_coverage_snapshot.py — one of the two files this PR claims as new — already exists on main:

$ ls tests/unit/ | grep -E 'update_coverage|generate_skill'
test_update_coverage_snapshot.py

It landed via #776, and the PR body acknowledges that #776 exists but still adds the file. That is the source of the conflict — mergeable_state: dirty, which I reproduced with a local test merge:

PR766 CONFLICT

The other file, tests/unit/test_generate_skill_index.py, is genuinely missing from main — but #788 adds it, merges cleanly, and I verified it locally:

PR788 | snapshot=STALE(base) | ruff='All checks passed!' | pytest: 1606 passed

vs. main baseline of 1570 — exactly the +36 tests #788 claims.

Recommend closing in favour of #788. If there are assertions in this branch's test_generate_skill_index.py that #788 lacks, worth diffing the two and porting the gap rather than rebasing 634 lines.

One note in this PR's favour that is worth carrying over either way: the guard that --check reuses the committed generated_at instead of date.today() is the right thing to pin. Generated catalogs that stamp today's date go stale the day after they are written, and #788 covers that case too.


Generated by Claude Code

@hanthor

hanthor commented Sep 12, 2026

Copy link
Copy Markdown
Member

Closing — the file this adds is already on main.

$ git ls-files tests/unit/test_update_coverage_snapshot.py
tests/unit/test_update_coverage_snapshot.py

That is also the source of this PR's conflict: it cannot merge because it is trying to create a file that exists. The generate_skill_index.py half is covered by #788, which adds +36 tests (verified locally: 1570 → 1606 passing, ruff clean) and merges cleanly.

So this PR's content has landed by two other routes and keeping it open only costs a rebase that would resolve to an empty diff. #788 is the one to carry forward.

If any test case here is unique — not present in the committed test_update_coverage_snapshot.py and not in #788 — it is worth porting into #788 before that lands rather than reviving this branch. Reopen if you spot one.


Generated by Claude Code

@hanthor hanthor closed this Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold Work is intentionally paused. quality Code quality or test-coverage work. testing Test authoring or test infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant