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
pytest-bddis added to the dev dependency input and locked intorequirements-dev.lock.tests/features/now holds Gherkin feature files.tests/steps/now holds collected pytest modules that bind scenarios to Python step functions.- The smoke scenario uses
@scenario,parsers.parse, andtarget_fixture.
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
uv run pytest tests/steps/test_pytest_bdd_smoke.py -qproves the new feature and step convention collect.uv run pytest tests/proves normal test discovery still runs the scenario.uv run ruff checkproves the new test module follows repo lint rules.