Based on this issue, it doesn't support it yet.
Solution1: Utilize the markers and register them within the pytest hooks
Until the mentioned issue is resolved, you can choose to utilize the pytest hooks and manually register the markers. The following code iterates through all the registered test items and registers new markers on them based on their respective feature files. It relies on several internal attributes of the pytest-bdd library, but it effectively functions even before the library incorporates the feature internally:
# conftest.py
import re
from pathlib import Path
from typing import List
import pytest
def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]):
for item in items:
if not hasattr(item, "_pyfuncitem") or not hasattr(item, "callspec"):
continue
feature = item._pyfuncitem._obj.__scenario__.feature
feature_content_lines = Path(feature.filename).read_text().splitlines()
parameters = list(item.callspec.params["_pytest_bdd_example"].values())
examples_start_line = None
for i, line in enumerate(feature_content_lines):
if "Examples:" in line:
examples_start_line = i
continue
elif re.match(r"[|\s]+{}[|\s]+".format(r"[|\s]+".join(parameters)), line):
break
if examples_start_line is None:
continue
tag_match = re.search(
r"@(?P<tag>\S+)", feature_content_lines[examples_start_line - 1]
)
if tag_match is None:
continue
tag = tag_match.group("tag")
item.add_marker(tag)
Consider the following feature file:
Feature: Scenario outlines
Scenario Outline: Outlined given, when, then
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
@part1
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 12 | 4 | 8 |
@part2
Examples:
| start | eat | left |
| 11 | 5 | 6 |
And the following test file:
# test_scenario_outlines.py
from pytest_bdd import given, parsers, scenarios, then, when
scenarios("scenario_outlines.feature")
@given(parsers.parse("there are {start:d} cucumbers"), target_fixture="cucumbers")
def given_cucumbers(start):
return {"start": start, "eat": 0}
@when(parsers.parse("I eat {eat:d} cucumbers"))
def eat_cucumbers(cucumbers, eat):
cucumbers["eat"] += eat
@then(parsers.parse("I should have {left:d} cucumbers"))
def should_have_left_cucumbers(cucumbers, left):
assert cucumbers["start"] - cucumbers["eat"] == left
You can simply use the markers to run specific example records:
pytest . -m part1

pytest . -m part2

Note: You should register your markers to prevent pytest warnings.
Solution 2: Utilize the parameters as tags
You can add a new column to your parameters table, specifying the tag:
# scenario_outlines.feature
Feature: Scenario outlines
Scenario Outline: Outlined given, when, then
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left | tag |
| 12 | 5 | 7 | part1 |
| 12 | 4 | 8 | part1 |
Examples:
| start | eat | left | tag |
| 11 | 5 | 6 | part2 |
There's no need to edit the Python test files or pay attention to the tag
parameter in the code. Instead, simply utilize the -k
option to selectively choose records with a specific tag value:
pytest . -k part1

pytest . -k part2
