Skip to content

Guard: pin BDD tag-set keys against the generated feature files #1708

Description

@numarasSigmaSoftware

The BDD conftest routes scenarios by scenario-tag string — which wired set a tag belongs to, and which xfail reason it gets. Nothing asserts those tag strings still exist in the feature files they refer to.

Problem

tests/bdd/conftest.py carries several tag-keyed collections:

  • _UC003_WIRED
  • _UC019_WIRED
  • _UC002_CREATE_WIRED
  • _UC003_UNWIRED_REASONS

The feature files these tags come from are generated (# DO NOT EDIT -- re-run: python scripts/compile_bdd.py --merge). If a regeneration renames a tag, or a key is simply mistyped, the failure is silent in both directions:

  • A stale key in a _WIRED set means the scenario quietly stops being wired — coverage is lost with nothing red.
  • A stale key in _UC003_UNWIRED_REASONS means the scenario quietly falls back to the generic "harness not yet wired" reason.

Neither shows up in counts, because an unwired scenario xfails either way. The aggregate is identical, so no test reddens and no reviewer sees a diff.

Why now

The _UC003_UNWIRED_REASONS case is concrete: the whole point of that map is to stop reporting a deliberate, tracked divergence as a wiring TODO. A key drift silently restores exactly the misreporting it exists to prevent, and the only signal is a human reading an xfail reason in a test report.

All four symbols are recent additions, so this is a good moment to pin them before more accumulate.

Fix

A unit-level guard (no DB needed) that parses tests/bdd/conftest.py and asserts every tag key in those collections appears as a tag in tests/bdd/features/**/*.feature. Precedent exists for reading the feature tree at unit-test time — test_architecture_bdd_feature_parse.py and test_architecture_bdd_obligation_sync.py already do it.

Worth considering as a second assertion: keys in _UC003_UNWIRED_REASONS should be disjoint from the wired sets, i.e. they actually reach the unwired branch. A tag in both places is a contradiction that currently resolves silently by branch order.

Context

Raised by two independent reviewers of #1544 while reviewing the xfail-reason routing. The scope is deliberately wider than that one map, since the _WIRED sets carry the higher consequence (silent coverage loss).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions