Manyworlds

manyworlds.feature module

Defines the Feature Class

class manyworlds.feature.Feature[source]

Bases: object

A collection of one or more directed trees the vertices of which represent BDD scenarios.

COMMENT_PATTERN: Pattern = re.compile('\n        ^                    # start of line\n        \\#                   # "#" character\n        [ ]                  # space\n        (?P<comment>.*)      # comment\n        $                 , re.VERBOSE)

re.Pattern

Pattern describing a comment line (”# …”)

FEATURE_PATTERN: Pattern = re.compile('\n        ^                    # start of line\n        Feature:             # "Feature:" keyword\n        [ ]                  # space\n        (?P<feature_name>.*) # feature name\n        $        , re.VERBOSE)

re.Pattern

Pattern describing a BDD feature line (“Feature: …”)

TAB_SIZE: int = 4

int

The number of spaces per indentation level

append_data_row(data_row: DataTableRow, at_level: int, line_no: int) None[source]

Appends a data row to the feature.

Adds a data table to the last step if necessary Otherwise adds row to data table.

Parameters:
  • data_row (DataTableRow) – The data row to append

  • at_level (int) – The level at which to add the data row. Used for indentation validation.

  • line_no (int) – The line number of the data row in the input file. Used in InvalidFeatureFile error message.

append_scenario(scenario_name: str, comment: str | None, at_level: int, line_no: int) Scenario[source]

Append a scenario to the feature.

Parameters:
  • scenario (Scenario) – The scenario to append

  • comment (str, optional) – A comment

  • at_level (int) – The indentation level of the scenario in the input file. Used for indentation validation.

  • line_no (int) – The line number of the scenario in the input file. Used in InvalidFeatureFile error message.

append_step(step: Step, at_level: int, line_no: int) None[source]

Appends a step to the feature.

Parameters:
  • step (Prerequisite or Action or Assertion) – The Step subclass instance to append

  • at_level (int) – The level at which to add the step. Used for indentation validation.

  • line_no (int) – The line number of the step in the input file. Used in InvalidFeatureFile error message.

description: List[str]

The description lines for the feature

find(*scenario_names: List[str]) Scenario | None[source]

Finds and returns a scenario by the names of all scenarios along the path from a root scenario to the destination scenario.

Used in tests only

Parameters:

scenario_names (List[str]) – List of scenario names

Returns:

The found scenario, or None if none found

Return type:

Scenario or None

flatten(file_path: str, mode: Literal['strict', 'relaxed'] = 'strict', write_comments: bool = False) None[source]

Writes a flat (no indentation) feature file representing the feature.

Parameters:
  • file_path (str) – Path to flat feature file to be written

  • mode ({"strict", "relaxed"}, default="strict") – Flattening mode. Either “strict” or “relaxed”

  • comments (bool, default = False) – Whether or not to write comments

flatten_relaxed(flat_file: TextIO, write_comments: bool = False) None[source]

Writes a flat (no indentation) feature file representing the feature using the “relaxed” flattening mode.

The “relaxed” flattening mode writes one scenario per leaf vertex in the tree, resulting in a feature file with multiple consecutive sets of “When” and “Then” steps per scenario (generally considered an anti-pattern).

Parameters:
  • flat_file (io.TextIOWrapper) – The flat feature file

  • write_comments (bool, default = False) – Whether or not to write comments if present

flatten_strict(flat_file: TextIO, write_comments: bool = False) None[source]

Write. a flat (no indentation) feature file representing the feature using the “strict” flattening mode.

The “strict” flattening mode writes one scenario per vertex in the tree, resulting in a feature file with one set of “When” steps followed by one set of “Then” steps (generally recommended).

Parameters:
  • flat_file (io.TextIOWrapper) – The flat feature file

  • write_comments (bool, default = False) – Whether or not to write comments

classmethod from_file(file_path) Feature[source]

Parses an indented feature file into a Feature instance.

Parameters:

file_path (str) – The path to the feature file

Returns:

A new Feature instance

Return type:

Feature

graph: Graph

The graph representing the scenario tree(s)

leaf_scenarios() List[Scenario][source]

Returns the leaf scenarios (scenarios with vertices without outgoing edges).

Returns:

All leaf scenarios in index order

Return type:

List[Scenario]

name: str | None

The name of the feature

parse_step_line(line: str) Step | None[source]

Parses a feature file step line into the appropriate Step subclass instance.

If the line begins with “And” then the step type is determined by the type of the last step.

Parameters:

line (str) – The step line (without indentation and newline)

Returns:

An instance of a Step subclass

Return type:

Prerequisite or Action or Assertion

root_scenarios() List[Scenario][source]

Returns the root scenarios (scenarios with vertices without incoming edges).

Returns:

All root scenarios in index order

Return type:

List[Scenario]

scenarios() List[Scenario][source]

Returns all scenarios

Returns:

All scenarios in index order

Return type:

List[Scenario]

classmethod split_line(raw_line: str) Tuple[int, str][source]

Splits a raw feature file line into the indentation part and the line part.

Parameters:

raw_line (str) – The raw feature file line including indentation and newline

Returns:

The indentation part and the line part (without newline) as a tuple

Return type:

tuple[int, str]

classmethod write_data_table(file_handle: TextIO, data_table: DataTable, write_comment: bool = False) None[source]

Writes formatted data table to the end of the flat feature file.

Parameters:
  • file_handle (io.TextIOWrapper) – The file to which to append the data table

  • data_table (DataTable) – A data table

  • write_comment (bool) – Whether or not to write comment if present

classmethod write_feature_declaration(file_handle: TextIO, feature: Feature) None[source]

Writes feature name and (optional) description to the end of a flat feature file.

Parameters:

file_handle (TextIO) – The file to which to append the feature declaration

classmethod write_scenario_name(file_handle: TextIO, scenarios: List[Scenario], write_comment: bool = False) None[source]

Writes formatted scenario name to the end of a “relaxed” flat feature file.

Parameters:
  • file_handle (TextIO) – The file to which to append the scenario name

  • scenarios (List[Scenario]) – Organizational and validated scenarios along the path

  • write_comment (bool, default = False) – Whether or not to write comment if present

classmethod write_scenario_steps(file_handle: TextIO, steps: List[Step], write_comments: bool = False) None[source]

Writes formatted scenario steps to the end of the flat feature file.

Parameters:
  • file_handle (io.TextIOWrapper) – The file to which to append the steps

  • steps (List[Step]) – Steps to append to file_handle

  • write_comments (bool, default = False) – Whether or not to write comments if present

manyworlds.scenario module

Defines the Scenario Class

class manyworlds.scenario.Scenario(name: str, graph: Graph, parent_scenario: Scenario | None = None, comment: str | None = None)[source]

Bases: object

A BDD Scenario

SCENARIO_PATTERN: Pattern = re.compile('\n        ^                        # start of line\n        Scenario:                # "Scenario:" keyword\n        [ ]                      # space\n        (?P<scenario_name>[^#]*) # scenario name\, re.VERBOSE)

re.Pattern

Pattern describing a BDD scenario line (“Scenario: …”) followed by an optional comment

actions() List[Step][source]

Returns all steps of type Action

Returns:

List of steps of type Action

Return type:

List[Action]

ancestors() List[Scenario][source]

Returns the scenario’s ancestors, starting with a root scenario

Returns:

List of scenarios

Return type:

List[Scenario]

assertions() List[Step][source]

Returns all steps of type Assertion

Returns:

List[Assertion]

List of steps of type Assertion

Return type:

list

children() List[Scenario][source]

Returns the scenario’s child scenarios

Returns:

The child scenarios

Return type:

List[Scenario]

comment: str | None
graph: Graph
index() int | None[source]

Returns the “index” of the scenario.

The scenario”s vertical position in the feature file.

Returns:

Index of self

Return type:

int

is_closed() bool[source]

Returns whether or not the scenario is “closed”.

A scenario is “closed” if additional child scenarios cannot be added which is the case when there is a “later” (higher index) scenario with a lower or equal indentation level in the feature file.

Returns:

Whether or not the scenario is “closed”

Return type:

bool

is_organizational() bool[source]

Returns whether the scenario is an “organizational” scenario.

“Organizational” scenarios are used for grouping only. They do not have any assertions.

Returns:

Whether the scenario is an “organizational” scenario

Return type:

bool

level() int[source]

Returns the scenario”s level in the scenario tree.

Root scenario = Level 1

Returns:

The scenario”s level

Return type:

int

name: str
parent() Scenario | None[source]

Returns the scenario’s parent scenario, if one exists

Returns:

The parent scenario

Return type:

Scenario, optional

path_scenarios() List[Scenario][source]

Returns the complete scenario path from the root scenario to (and including) self.

Returns:

List of scenarios. The last scenario is self

Return type:

List[Scenario]

prerequisites() List[Step][source]

Returns all steps of type Prerequisite

Returns:

List of steps of type Prerequisite

Return type:

List[Prerequisite]

siblings() List[Scenario][source]

Returns the scenario’s sibling scenarios

The scenario’s parent’s children (including self)

Returns:

The sibling scenarios

Return type:

List[Scenario]

steps: List[Step]
steps_of_type(step_type: type[Prerequisite] | type[Action] | type[Assertion]) List[Step][source]

Returns all steps of the passed in type

Parameters:

step_class ({Prerequisite, Action, Assertion}) – A step subclass

Returns:

All steps of the passed in type

Return type:

List[Step]

property validated: bool

The “validated” property

Used to keep track of which scenarios had their assertions written to an output scenario already so that assertions are not run multiple times.

Returns:

Whether or not this scenario has been validated

Return type:

bool

vertex: Vertex

manyworlds.step module

Defines the Step Class and subclasses

class manyworlds.step.Action(name: str, data: DataTable | None = None, comment: str | None = None)[source]

Bases: Step

A BDD scenario action (“When”) step

comment: str | None
conjunction: Literal['Given', 'When', 'Then']
data: DataTable | None
name: str
class manyworlds.step.Assertion(name: str, data: DataTable | None = None, comment: str | None = None)[source]

Bases: Step

A BDD scenario assertion (“Then”) step

comment: str | None
conjunction: Literal['Given', 'When', 'Then']
data: DataTable | None
name: str
class manyworlds.step.Prerequisite(name: str, data: DataTable | None = None, comment: str | None = None)[source]

Bases: Step

A BDD scenario prerequisite (“Given”) step

comment: str | None
conjunction: Literal['Given', 'When', 'Then']
data: DataTable | None
name: str
class manyworlds.step.Step(name: str, data: DataTable | None = None, comment: str | None = None)[source]

Bases: object

A BDD scenario step

STEP_PATTERN: Pattern = re.compile('\n        ^                                        # start of line\n        (?P<conjunction>Given|When|Then|And|But) # conjunction\n        [ ]                                      # space\n        (, re.VERBOSE)

re.Pattern

Pattern describing a BDD step line (“Given”, “When”, …) with optional comment

comment: str | None
conjunction: Literal['Given', 'When', 'Then']
data: DataTable | None
format(first_of_type: bool = True) str[source]

Returns a string representation of the Step instance for feature file output.

Uses “And” as a conjunction if the step is not the first of its type.

Parameters:

first_of_type (bool) – Whether or not the step is the first of it”s type

Returns:

String representation of the Step instance

Return type:

str

name: str

manyworlds.data_table module

Defines the DataTable and DataTableRow classes

class manyworlds.data_table.DataTable(header_row: DataTableRow)[source]

Bases: object

A Gherkin data table

TABLE_ROW_PATTERN = re.compile('\n        ^                                  # start of line\n        (?P<table_row>\\| (?:[^|]+[ ]+\\|)+) # pipe-delimited list of values\n        (?:[ ]+\\#[ ](?P<comment>.+))?      # optional comm, re.VERBOSE)

re.Pattern

Pattern describing a Gherkin data table row followed by an optional comment

header_row: DataTableRow
classmethod parse_line(line: str) DataTableRow | None[source]

Parses a pipe delimited data table line into a DataTableRow

Parameters:

line (str) – A pipe delimited data table line

Return type:

DataTableRow

rows: List[DataTableRow]
to_list() List[DataTableRow][source]

Returns a list of DataTableRow representation of itself

Returns:

The list of DataTableRow representation of itself

Return type:

List[DataTableRow]

to_list_of_dict() List[dict][source]

Returns a list of dict representation of itself

Returns:

The list of dict representation of itself

Return type:

List[dict]

to_list_of_list() List[List[str]][source]

Returns a list of list of str representation of itself

First row is header row

Returns:

The list of list of str representation of itself

Return type:

List[List[str]]

class manyworlds.data_table.DataTableRow(values: List[str], comment: str | None = None)[source]

Bases: object

A Gherkin data table row

comment: str | None
values: List[str]