Story-1734 · functions lane · BDD foundation

pytest-bdd wiring

This Story adds the acceptance-test layer future functions BDD stories will build on: the dependency is locked, feature files have a home, and step modules prove collection through pytest.

The mental model: this is the empty courtroom before the first real case. We are not arguing the cross-firm evidence slice yet; we are proving the courtroom doors open, the clerk can read a written scenario, and testimony moves through fixtures instead of a shared notebook.

What changed

The example scenario

Feature: Pytest BDD wiring
  Scenario: Parse an acceptance value without shared mutable state
    Given an acceptance value named "smoke"
    When the BDD step returns the value
    Then the scenario sees "smoke"

The important part is not the word smoke. The important part is the route the value takes: the Given step returns a fixture, the When step returns another fixture, and the Then step asserts against fixtures. No module-level variable carries state between steps, so the pattern is parallel-safe and order-independent.

What this deliberately does not do

This Story does not add the cross-firm acceptance slice. That belongs to pramaan-spec#1745. It also does not create a separate DB harness; future BDD scenarios should reuse the existing pytest fixtures and test database setup when they need integration coverage.

How to verify

  1. uv run pytest tests/steps/test_pytest_bdd_smoke.py -q proves the new feature and step convention collect.
  2. uv run pytest tests/ proves normal test discovery still runs the scenario.
  3. uv run ruff check proves the new test module follows repo lint rules.