Skip to content

Fix empty docstring delivery to step functions (#809)#810

Open
golikovichev wants to merge 2 commits into
pytest-dev:masterfrom
golikovichev:fix/809-empty-docstring
Open

Fix empty docstring delivery to step functions (#809)#810
golikovichev wants to merge 2 commits into
pytest-dev:masterfrom
golikovichev:fix/809-empty-docstring

Conversation

@golikovichev

@golikovichev golikovichev commented May 9, 2026

Copy link
Copy Markdown

Closes #809.

Problem

When a step has an empty docstring, pytest-bdd raises fixture 'docstring' not found:

When extra labels are injected
  """
  """

The reproducer from the issue triggers this on pytest-bdd 8.1.0.

Cause

In ScenarioTemplate.steps_from_template_steps (src/pytest_bdd/parser.py), the docstring of each rendered step was assigned with a truthy check:

docstring=render_string(step.docstring, context) if step.docstring else None,

step.docstring here is a str (set earlier in parse_steps from step.docstring.content). For an empty docstring, that string is "", which is falsy, so the whole expression collapses to None. The downstream check in scenario.py only forwards the docstring to the step function when step.docstring is not None, so the argument is never injected and pytest treats docstring as a missing fixture.

The earlier line in parse_steps is fine because it tests the DocString object itself (always truthy when present) before reading .content.

Fix

Switch the truthy check to is not None so empty docstrings are forwarded as "":

docstring=render_string(step.docstring, context) if step.docstring is not None else None,

Tests

  • New regression test test_steps_with_empty_docstring in tests/steps/test_docstring.py, following the style of the existing tests in that file.
  • Verified the new test fails on master and passes with the fix.
  • Existing docstring tests still pass (pytest tests/steps/test_docstring.py: 5 passed).
  • Targeted run of tests/steps, tests/parser/test_parser.py, tests/feature/test_scenario.py, tests/feature/test_outline.py: 42 passed.

CHANGES.rst entry added under the Unreleased Fixed section.

ScenarioTemplate.steps_from_template_steps used a truthy check
(`if step.docstring`) when building the step list. An empty docstring
is a valid value, but `""` is falsy, so the docstring was replaced
with None. The step then looked like it had no docstring at all,
and pytest fell back to fixture lookup, raising
"fixture 'docstring' not found".

Switched the check to `is not None` so empty docstrings are passed
through as `""`. Added a regression test in tests/steps/test_docstring.py.
@golikovichev golikovichev force-pushed the fix/809-empty-docstring branch from 9084928 to 28ac968 Compare May 9, 2026 14:19
@golikovichev

Copy link
Copy Markdown
Author

Hi, just checking if there's anything I can clarify on this.

@golikovichev

Copy link
Copy Markdown
Author

Friendly nudge - this is still ready whenever someone has a moment. It fixes #809 (empty docstrings were not delivered to step functions), the change is small with a regression test, and CI is green. Happy to rebase onto main if that helps.

@youtux youtux enabled auto-merge (squash) June 15, 2026 07:04
@golikovichev

Copy link
Copy Markdown
Author

Thanks for the review. Quick note on the red CI: those 4 failing tests already fail on master, so they are not from this change. The same set is red on the latest master run (the 2026-06-09 push, run 27186482739):

  • tests/feature/test_outline.py::test_outline_with_escaped_pipes
  • tests/feature/test_scenario.py::test_scenario_comments
  • tests/parser/test_errors.py::test_step_outside_scenario_or_background_error
  • tests/parser/test_parser.py::test_parser

This branch does not add any new failures. I can open a separate PR to fix the master breakage if that would help.

@golikovichev

Copy link
Copy Markdown
Author

I dug into the one that reproduces everywhere, test_step_outside_scenario_or_background_error. It is a behavior change in gherkin-official, not a regression in pytest-bdd.

On gherkin-official 39.1.0, parsing a feature with a step outside a scenario no longer raises CompositeParserException - the orphan step is silently dropped from the AST. I confirmed it directly:

Parser().parse(feature_with_orphan_step)  # no exception, feature has only the scenario child

Because no exception is raised, the ERROR_PATTERNS match in gherkin_parser.py never fires, so the expected FeatureError is never raised and the test fails.

Two ways to fix, depending on what you prefer:

  1. Keep the strict behavior: detect the orphan step in pytest-bdd and raise FeatureError ourselves (more work, since gherkin discards it before we see it).
  2. Accept the upstream leniency: update the test (and possibly the now-unused ERROR_PATTERNS entry).

Happy to send a PR for whichever direction you want. The other CI failures look pin/env-specific - they pass locally on gherkin 39, so they are likely a separate locked-deps issue rather than the same cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Empty docstring results in "fixture not found"

2 participants