# pytest-bdd: Gherkin Scenarios Inside pytest

> pytest-bdd is a Python BDD plugin for teams that want feature files and readable scenarios without introducing a separate test runner. It maps Gherkin steps to pytest functions and fixture-based setup, but it implements a subset of Gherkin and permits only one feature per feature file.

**pytest-dev/pytest-bdd** — BDD library for the pytest runner

- Repository: https://github.com/pytest-dev/pytest-bdd
- Website: https://pytest-bdd.readthedocs.io/en/latest/
- Stars: 1,472 · Forks: 253
- Language: Python
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/pytest-dev-pytest-bdd

## Why pytest-bdd fits a pytest-based Python suite

pytest-bdd addresses teams that want requirements expressed as readable Gherkin scenarios while keeping execution inside pytest. It is aimed at Python developers who already use pytest for unit, integration, and functional tests, especially teams that want to reuse pytest fixtures instead of maintaining behavior in a separate test runner or a custom context object.

The project implements a subset of the Gherkin language. A feature file can describe a feature and its scenarios using Given, When, Then, and related steps, while Python decorators bind those steps to functions. The scenario function then becomes an ordinary pytest test that executes the selected scenario.

This design is useful when functional tests depend on browser fixtures, database sessions, authentication helpers, or application factories already present in a pytest suite. The README specifically describes reuse of unit-test fixtures for setup and actions in feature steps, including dependency injection. The intended result is less setup duplication, not a second independent testing architecture.

The boundary is important. pytest-bdd is not presented as a complete replacement for every BDD framework. It supports a subset of Gherkin and imposes a concrete file constraint: only one feature is allowed per feature file. Teams whose specifications require broader Gherkin behavior or a separate runner should check the documentation and their own feature files before adopting it.

## How pytest-bdd maps scenarios to pytest execution

A typical pytest-bdd flow starts with a feature file containing a feature and a named scenario. The Python test module imports scenario, given, when, and then from pytest_bdd. A function decorated with scenario references the feature filename and scenario name, selecting the scenario that pytest will execute.

Step decorators match textual step names in the feature file to Python functions. Given steps arrange state, When steps perform actions, and Then steps verify outcomes. These functions can accept ordinary Python arguments, including pytest fixtures. In the blog example, the author fixture supplies a user, the browser fixture supplies a browser, and the article step returns a test article through target_fixture.

The dependency flow is shared state through pytest fixtures rather than through a dedicated BDD context. A step that declares target_fixture can expose a value for later steps in the scenario. The README states that the scenario function is executed after all scenario steps and recommends placing as much logic as possible inside Given, When, Then steps.

This is a clear trade-off. Pytest controls discovery, setup, teardown, and fixture resolution, so existing pytest behavior remains available. At the same time, the feature file is not a standalone executable specification. It needs Python step definitions, and meaningful reuse depends on how well the project organizes fixtures and step functions.

## Installing pytest-bdd and connecting the first scenario

The README gives a direct pip installation command. It does not document an alternative package manager installation. The package requires Python 3.10 or later according to pyproject.toml, and its declared pytest dependency is pytest 7.0.0 or later.

After installation, create a feature file with the supported subset of Gherkin. The README example uses one feature, named scenarios, and steps grouped with Given, When, Then, And, and asterisk shorthand. Then create a Python test module that selects the scenario and defines its step functions.

The following command installs the plugin:

```bash
pip install pytest-bdd
```

The README's example feature file is named publish_article.feature and contains the scenario Publishing the article:

```gherkin
Feature: Blog
    A site where you can publish your articles.

    Scenario: Publishing the article
        Given I'm an author user
        And I have an article

        When I go to the article page
        And I press the publish button

        Then I should not see the error message
        And the article should be published
```

The scenario decorator connects that file and scenario to a normal pytest test:

```python
from pytest_bdd import scenario, given, when, then

@scenario('publish_article.feature', 'Publishing the article')
def test_publish():
    pass
```

The test should be collected by pytest after the feature file and Python test module are present. The README also defines the steps used by the example:

```python
@given("I'm an author user")
def author_user(auth, author):
    auth['user'] = author.user

@given("I have an article", target_fixture="article")
def article(author):
    return create_test_article(author=author)
```

The repository README does not give a complete command for running this first example, so no unverified pytest invocation is added here.

## Step arguments, aliases, and pytest fixture reuse

pytest-bdd supports parameterized steps, which lets one Python implementation serve several textual forms. The README names the default string parser and a parse parser based on parse. It also references parse-type as an additional parser option. The default string behavior uses exact step-name matching and does not parse parameters.

Parameterized definitions can match the same step twice within a scenario when the arguments differ. That can reduce repeated implementations, although the exact parser syntax is delegated to the parse library rather than defined by the README excerpt. Developers must therefore check the parser documentation and confirm that their expressions behave as expected for real feature text.

Step aliases are another documented feature. A single function can be decorated more than once to associate different readable names with the same implementation. The README warns that aliases are independent and are executed when mentioned. This is useful when different scenarios need different setup language, but it can also create multiple entry points into related behavior.

Fixture reuse is pytest-bdd's central distinction from many standalone BDD tools. A step can request an author, browser, auth object, database model, or other fixture that pytest already knows how to provide. The repository's example also uses target_fixture to pass the created article into later steps. This keeps data flow visible in Python, but it makes fixture scope and naming part of the BDD design rather than hiding state in a separate context manager.

The trade-off is that feature readability depends on disciplined step definitions. If a feature has many near-duplicate steps, or if fixtures obscure the business action, the abstraction may not improve maintenance.

## Supported Gherkin syntax and file constraints

The documented syntax is narrower than a full Gherkin implementation. The README explicitly describes a subset of Gherkin. It covers features, scenarios, named steps, Given, When, Then, And, But-style usage described through the aliases and wildcard discussion, and the ability to use an asterisk in place of a step keyword.

The asterisk acts as a wildcard that follows the preceding step context. In the README example, an asterisk follows a Given step, so the following statements continue that logical sequence without repeating Given, When, or Then. This can reduce visual repetition, but the accepted grammar should still be tested against the versions of feature files used by the project.

There is also a file-level constraint: the README states that only one feature is allowed per feature file. A project with many product areas may therefore need a clear naming and partitioning convention. The example uses the feature filename as the scenario decorator's first argument, so changing a file name requires updating the Python test module that selects it.

The README does not document the complete set of unsupported Gherkin keywords, tags, examples, backgrounds, hooks, or scenario-outline behavior. Those details should not be assumed. The absence of documentation in the README is a limitation for teams evaluating advanced Gherkin files.

## Maintenance, compatibility, and the alternative approach

The repository is not archived. Its last push was on 2026-10-13, which is recent relative to the article date, but the repository has no GitHub releases. Maintenance status should therefore be based on that dated repository activity rather than an assumption about release frequency.

Version 9.0.0 is declared in pyproject.toml. The package requires Python 3.10 or later and lists pytest 7.0.0 or later. It also depends on Mako, parse, parse-type, typing-extensions, packaging, and gherkin-official, with excluded gherkin-official versions identified in the dependency declaration. These constraints matter when a team adds pytest-bdd to an older Python or pytest environment.

The repository uses an MIT license. That permits use and modification under the license terms, but the license file and project context should be reviewed for the organization's own compliance process. No GitHub releases are available, so upgrade planning may require checking the repository changelog and packaging history rather than relying on release notes.

The README says pytest-bdd differs from many BDD tools because it does not require a separate runner and instead benefits from pytest. For teams already using pytest, that integration can be the main adoption consideration.

## Conclusion

pytest-bdd suits Python teams that already use pytest and want BDD scenarios integrated with existing fixtures. It is less suitable for teams requiring the full Gherkin language or a standalone BDD runner. Before adoption, check that Python 3.10 or later, pytest 7.0.0 or later, and the accepted Gherkin syntax match the project, then verify how step fixtures behave in the first CI run.

## FAQ

### How do I install pytest-bdd?

The README documents `pip install pytest-bdd`. The package metadata requires Python 3.10 or later and declares pytest 7.0.0 or later as a dependency.

### How do I connect a Gherkin scenario to a pytest test?

Use the `scenario` decorator with the feature filename and scenario name. Define the referenced steps with `given`, `when`, and `then` decorators, as shown in the README's blog example.

### Can pytest-bdd reuse pytest fixtures?

Yes. The README says pytest fixtures written for unit tests can be reused in feature steps with dependency injection. A step can also declare `target_fixture` to pass a value to later steps.

### Does pytest-bdd support all of Gherkin?

No. The README describes pytest-bdd as implementing a subset of the Gherkin language. It also states that only one feature is allowed per feature file.

### What is the main difference between pytest-bdd and behave?

The README links to behave but does not document its execution model. It states that pytest-bdd does not require a separate runner and benefits from pytest.

## Sources

- [Issues](https://github.com/pytest-dev/pytest-bdd/issues)
- [License: MIT](https://github.com/pytest-dev/pytest-bdd/blob/master/LICENSE)
- [Project website](https://pytest-bdd.readthedocs.io/en/latest/)
- [pytest-dev/pytest-bdd on GitHub](https://github.com/pytest-dev/pytest-bdd)
- [README](https://github.com/pytest-dev/pytest-bdd/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pytest-dev-pytest-bdd
