Scenario Sorter

The sorter module reorders behave’s feature and scenario lists by priority.

class behave_priority.sorter.ScenarioLike(*args, **kwargs)[source]

Bases: Protocol

Protocol for scenario-like objects.

Variables:
  • name (str) – Display name of the scenario.

  • tags (list[str]) – List of tag strings (without ‘@’ prefix).

  • status (str) – Execution status ("passed", "failed", etc.).

  • duration (float) – Execution time in seconds.

class behave_priority.sorter.FeatureLike(*args, **kwargs)[source]

Bases: Protocol

Protocol for feature-like objects.

Variables:
  • name (str | None) – Display name of the feature, or None.

  • filename (str) – Path to the feature file.

  • tags (list[str]) – List of tag strings (without ‘@’ prefix).

  • scenarios (list[behave_priority.sorter.ScenarioLike]) – List of scenarios belonging to this feature.

class behave_priority.sorter.ScenarioSorter(config: PriorityConfig)[source]

Bases: object

Reorders behave’s feature and scenario lists by priority.

sort(features: list[FeatureLike]) list[FeatureLike][source]

Sort features and their scenarios by priority.

Each feature’s scenarios list and run_items list (if present) are reordered in-place. The features list itself is also sorted when ordering is enabled.

The sort is stable: scenarios with the same priority preserve their original relative order. This ensures that Scenario Outlines expanded by behave (which share the same tags and therefore the same priority) remain grouped together after sorting.

When a feature’s run_items contains Rule objects (Gherkin v6), each rule’s inner run_items and scenarios are also sorted.

Parameters:

features – List of features to sort.

Returns:

A new list of features sorted by priority.

Sorting Algorithm

The ScenarioSorter performs a multi-level sort:

  1. Feature-level sorting: Features are sorted by their “best” (lowest) scenario priority. This ensures features with high-priority scenarios run first.

  2. Scenario-level sorting: Within each feature, scenarios are sorted by their resolved priority (scenario > rule > feature > default).

  3. Rule-level sorting: When a feature contains Rule objects (Gherkin v6), each rule’s inner scenarios are sorted independently, and the rules themselves are sorted among other run items.

Sort Key Computation

The sort key is a tuple (primary, secondary):

  • primary: 0 if the scenario has the priority_tag (e.g. @smoke), 1 otherwise. This ensures tagged scenarios run first regardless of priority number.

  • secondary: The resolved priority value. When reverse=True, the priority is negated so that higher numbers sort first.

The sort is stable: scenarios with the same priority preserve their original relative order. This is important for Scenario Outlines, which behave expands into multiple scenarios sharing the same tags (and therefore the same priority).

Gherkin v6 Rule Handling

When a feature’s run_items contains Rule objects:

  1. Each rule’s inner run_items and scenarios are sorted using the rule’s tags as an intermediate priority level.

  2. Rules are sorted among other run items (scenarios, scenario outlines) based on their best inner scenario’s sort key.

  3. A rule with no inner scenarios gets a sort key of (1, default_priority).

The _is_rule method detects Rule objects by checking for the presence of a run_items attribute. Within feature.run_items, only Rule objects have this attribute; Scenario and ScenarioOutline do not.

Protocols

The module defines two structural protocols:

  • ScenarioLike: Objects with name, tags, status, and duration attributes.

  • FeatureLike: Objects with name, filename, tags, and scenarios attributes.

These protocols allow the sorter to work with behave’s model objects without hard dependencies on behave at runtime.

Examples

Basic sorting:

from behave_priority import PriorityConfig, ScenarioSorter

config = PriorityConfig(order=True)
sorter = ScenarioSorter(config)
sorter.sort(features)  # Sorts in-place

With smoke tag priority:

config = PriorityConfig(order=True, priority_tag="smoke")
sorter = ScenarioSorter(config)
sorter.sort(features)  # @smoke scenarios run first

Reversed order:

config = PriorityConfig(order=True, reverse=True)
sorter = ScenarioSorter(config)
sorter.sort(features)  # Higher priority numbers first

Feature sorting is controlled by the same config flags. When order=True, features are sorted by their best scenario’s priority. When order=False and reverse=False and priority_tag is None, features preserve their original order.