Behave API Reference

This reference is meant for people actually writing step implementations for feature tests. It contains way more information than a typical step implementation will need: most implementations will only need to look at the basic implementation of step functions and maybe environment file functions.

The model stuff is for people getting really serious about their step implementations.

Note

Anywhere this document says “string” it means “unicode string” in Python 2.x

behave works exclusively with unicode strings internally.

Step Functions

Step functions are implemented in the Python modules present in your “steps” directory. All Python files (files ending in ”.py”) in that directory will be imported to find step implementations. They are all loaded before behave starts executing your feature tests.

Step functions are identified using step decorators. All step implementations must start with the import line:

from behave import *

This imports several decorators defined by behave to allow you to identify your step functions. These are available in both PEP-8 (all lowercase) and traditional (title case) versions: “given”, “when”, “then” and the generic “step”. See the full list of variables imported in the above statement.

The decorators all take a single string argument: the string to match against the feature file step text exactly. So the following step implementation code:

@given('some known state')
def step_impl(context):
    set_up(some, state)

will match the “Given” step from the following feature:

Scenario: test something
 Given some known state
  then some observed outcome.

You don’t need to import the decorators: they’re automatically available to your step implmentation modules as global variables.

Steps beginning with “and” or “but” in the feature file are renamed to take the name of their preceding keyword, so given the following feature file:

Given some known state
  and some other known state
 when some action is taken
 then some outcome is observed
  but some other outcome is not observed.

the first “and” step will be renamed internally to “given” and behave will look for a step implementation decorated with either “given” or “step”:

@given('some other known state')
def step_impl(context):
   set_up(some, other, state)

and similarly the “but” would be renamed internally to “then”. Multiple “and” or “but” steps in a row would inherit the non-“and” or “but” keyword.

The function decorated by the step decorator will be passed at least one argument. The first argument is always the Context variable. Additional arguments come from step parameters, if any.

Step Parameters

You may additionally use parameters in your step names. These will be handled by either the default simple parser (parse), its extension “cfparse” or by regular expressions if you invoke use_step_matcher().

behave.use_step_matcher(name)

Change the parameter matcher used in parsing step text.

The change is immediate and may be performed between step definitions in your step implementation modules - allowing adjacent steps to use different matchers if necessary.

There are several parsers available in behave (by default):

parse (the default, based on: parse)

Provides a simple parser that replaces regular expressions for step parameters with a readable syntax like {param:Type}. The syntax is inspired by the Python builtin string.format() function. Step parameters must use the named fields syntax of parse in step definitions. The named fields are extracted, optionally type converted and then used as step function arguments.

Supports type conversions by using type converters (see register_type()).

cfparse (extends: parse, requires: parse_type)

Provides an extended parser with “Cardinality Field” (CF) support. Automatically creates missing type converters for related cardinality as long as a type converter for cardinality=1 is provided. Supports parse expressions like:

  • {values:Type+} (cardinality=1..N, many)
  • {values:Type*} (cardinality=0..N, many0)
  • {value:Type?} (cardinality=0..1, optional)

Supports type conversions (as above).

re

This uses full regular expressions to parse the clause text. You will need to use named groups “(?P<name>...)” to define the variables pulled from the text and passed to your step() function.

Type conversion is not supported. A step function writer may implement type conversion inside the step function (implementation).

You may define your own matcher.

You may add new types to the default parser by invoking register_type().

behave.register_type(**kw)

Registers a custom type that will be available to “parse” for type conversion during step matching.

Converters should be supplied as name=callable arguments (or as dict).

A type converter should follow parse module rules. In general, a type converter is a function that converts text (as string) into a value-type (type converted value).

EXAMPLE:

from behave import register_type, given
import parse

# -- TYPE CONVERTER: For a simple, positive integer number.
@parse.with_pattern(r"\d+")
def parse_number(text):
    return int(text)

# -- REGISTER TYPE-CONVERTER: With behave
register_type(Number=parse_number)

# -- STEP DEFINITIONS: Use type converter.
@given('{amount:Number} vehicles')
def step_impl(context, amount):
    assert isinstance(amount, int)

You may define a new parameter matcher by subclassing behave.matchers.Matcher and registering it with behave.matchers.matcher_mapping which is a dictionary of “matcher name” to Matcher class.

class behave.matchers.Matcher(func, string, step_type=None)

Pull parameters out of step names.

string

The match pattern attached to the step function.

func

The step function the pattern is being attached to.

check_match(step)

Match me against the “step” name supplied.

Return None if I don’t match otherwise return a list of matches as behave.model.Argument instances.

The return value from this function will be converted into a behave.model.Match instance by behave.

describe(schema=None)

Provide a textual description of the step function/matcher object.

Parameters:schema – Text schema to use.
Returns:Textual description of this step definition (matcher).
class behave.model.Argument(start, end, original, value, name=None)

An argument found in a feature file step name and extracted using step decorator parameters.

The attributes are:

original

The actual text matched in the step name.

value

The potentially type-converted value of the argument.

name

The name of the argument. This will be None if the parameter is anonymous.

start

The start index in the step name of the argument. Used for display.

end

The end index in the step name of the argument. Used for display.

class behave.model.Match(func, arguments=None)

An parameter-matched feature file step name extracted using step decorator parameters.

func

The step function that this match will be applied to.

arguments

A list of behave.model.Argument instances containing the matched parameters from the step name.

Calling Steps From Other Steps

If you find you’d like your step implementation to invoke another step you may do so with the Context method execute_steps().

This function allows you to, for example:

@when('I do the same thing as before')
def step_impl(context):
    context.execute_steps('''
        when I press the big red button
         and I duck
    ''')

This will cause the “when I do the same thing as before” step to execute the other two steps as though they had also appeared in the scenario file.

from behave import *

The import statement:

from behave import *

is written to introduce a restricted set of variables into your code:

Name Kind Description
given, when, then, step Decorator Decorators for step implementations.
use_step_matcher(name) Function Selects current step matcher (parser).
register_type(Type=func) Function Registers a type converter.

See also the description in step parameters.

Environment File Functions

The environment.py module may define code to run before and after certain events during your testing:

before_step(context, step), after_step(context, step)
These run before and after every step. The step passed in is an instance of Step.
before_scenario(context, scenario), after_scenario(context, scenario)
These run before and after each scenario is run. The scenario passed in is an instance of Scenario.
before_feature(context, feature), after_feature(context, feature)
These run before and after each feature file is exercised. The feature passed in is an instance of Feature.
before_tag(context, tag), after_tag(context, tag)

These run before and after a section tagged with the given name. They are invoked for each tag encountered in the order they’re found in the feature file. See Controlling Things With Tags. The tag passed in is an instance of Tag and because it’s a subclass of string you can do simple tests like:

# -- ASSUMING: tags @browser.chrome or @browser.any are used.
if tag.startswith("browser."):
    browser_type = tag.replace("browser.", "", 1)
    if browser_type == "chrome":
       context.browser = webdriver.Chrome()
    else:
       context.browser = webdriver.PlainVanilla()
before_all(context), after_all(context)
These run before and after the whole shooting match.

Some Useful Environment Ideas

Here’s some ideas for things you could use the environment for.

Logging Setup

The following recipe works in all cases (log-capture on or off). If you want to use/configure logging, you should use the following snippet:

# -- FILE:features/environment.py
def before_all(context):
    # -- SET LOG LEVEL: behave --logging-level=ERROR ...
    # on behave command-line or in "behave.ini".
    context.config.setup_logging()

    # -- ALTERNATIVE: Setup logging with a configuration file.
    # context.config.setup_logging(configfile="behave_logging.ini")

Capture Logging in Hooks

If you wish to capture any logging generated during an environment hook function’s invocation, you may use the capture() decorator, like:

# -- FILE:features/environment.py
from behave.log_capture import capture

@capture
def after_scenario(context):
    ...

This will capture any logging done during the call to after_scenario and print it out.

Detecting that user code overwrites behave Context attributes

The context variable in all cases is an instance of behave.runner.Context.

class behave.runner.Context(runner)

Hold contextual information during the running of tests.

This object is a place to store information related to the tests you’re running. You may add arbitrary attributes to it of whatever value you need.

During the running of your tests the object will have additional layers of namespace added and removed automatically. There is a “root” namespace and additional namespaces for features and scenarios.

Certain names are used by behave; be wary of using them yourself as behave may overwrite the value you set. These names are:

feature

This is set when we start testing a new feature and holds a Feature. It will not be present outside of a feature (i.e. within the scope of the environment before_all and after_all).

scenario

This is set when we start testing a new scenario (including the individual scenarios of a scenario outline) and holds a Scenario. It will not be present outside of the scope of a scenario.

tags

The current set of active tags (as a Python set containing instances of Tag which are basically just glorified strings) combined from the feature and scenario. This attribute will not be present outside of a feature scope.

aborted

This is set to true in the root namespace when the user aborts a test run (KeyboardInterrupt exception). Initially: False.

failed

This is set to true in the root namespace as soon as a step fails. Initially: False.

table

This is set at the step level and holds any Table associated with the step.

text

This is set at the step level and holds any multiline text associated with the step.

config

The configuration of behave as determined by configuration files and command-line options. The attributes of this object are the same as the configuration file settion names.

active_outline

This is set for each scenario in a scenario outline and references the Row that is active for the current scenario. It is present mostly for debugging, but may be useful otherwise.

log_capture

If logging capture is enabled then this attribute contains the captured logging as an instance of LoggingCapture. It is not present if logging is not being captured.

stdout_capture

If stdout capture is enabled then this attribute contains the captured output as a StringIO instance. It is not present if stdout is not being captured.

stderr_capture

If stderr capture is enabled then this attribute contains the captured output as a StringIO instance. It is not present if stderr is not being captured.

If an attempt made by user code to overwrite one of these variables, or indeed by behave to overwite a user-set variable, then a behave.runner.ContextMaskWarning warning will be raised.

You may use the “in” operator to test whether a certain value has been set on the context, for example:

‘feature’ in context

checks whether there is a “feature” value in the context.

Values may be deleted from the context using “del” but only at the level they are set. You can’t delete a value set by a feature at a scenario level but you can delete a value set for a scenario in that scenario.

execute_steps(steps_text)

The steps identified in the “steps” text string will be parsed and executed in turn just as though they were defined in a feature file.

If the execute_steps call fails (either through error or failure assertion) then the step invoking it will fail.

ValueError will be raised if this is invoked outside a feature context.

Returns boolean False if the steps are not parseable, True otherwise.

class behave.runner.ContextMaskWarning

Raised if a context variable is being overwritten in some situations.

If the variable was originally set by user code then this will be raised if behave overwites the value.

If the variable was originally set by behave then this will be raised if user code overwites the value.

Runner Operation

Given all the code that could be run by behave, this is the order in which that code is invoked (if they exist.)

before_all
for feature in all_features:
    before_feature
    for scenario in feature.scenarios:
        before_scenario
        for step in scenario.steps:
            before_step
                step.run()
            after_step
        after_scenario
    after_feature
after_all

If the feature contains scenario outlines then there is an addtional loop over all the scenarios in the outline making the running look like this:

before_all
for feature in all_features:
    before_feature
    for outline in feature.scenarios:
        for scenario in outline.scenarios:
            before_scenario
            for step in scenario.steps:
                before_step
                    step.run()
                after_step
            after_scenario
    after_feature
after_all

Model Objects

The feature, scenario and step objects represent the information parsed from the feature file. They have a number of common attributes:

keyword
“Feature”, “Scenario”, “Given”, etc.
name
The name of the step (the text after the keyword.)
filename and line
The file name (or “<string>”) and line number of the statement.

The structure of model objects parsed from a feature file will typically be:

Tag (as Feature.tags)
Feature : TaggableModelElement
    Description (as Feature.description)

    Background
        Step
            Table (as Step.table)
            MultiLineText (as Step.text)

    Tag (as Scenario.tags)
    Scenario : TaggableModelElement
        Description (as Scenario.description)
        Step
            Table (as Step.table)
            MultiLineText (as Step.text)

    Tag (as ScenarioOutline.tags)
    ScenarioOutline : TaggableModelElement
        Description (as ScenarioOutline.description)
        Step
            Table (as Step.table)
            MultiLineText (as Step.text)
        Examples
            Table
class behave.model.Feature(filename, line, keyword, name, tags=None, description=None, scenarios=None, background=None)

A feature parsed from a feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will be “Feature”.

name

The name of the feature (the text after “Feature”.)

description

The description of the feature as seen in the feature file. This is stored as a list of text lines.

background

The Background for this feature, if any.

scenarios

A list of Scenario making up this feature.

tags

A list of @tags (as Tag which are basically glorified strings) attached to the feature. See Controlling Things With Tags.

status

Read-Only. A summary status of the feature’s run. If read before the feature is fully tested it will return “untested” otherwise it will return one of:

“untested”
The feature was has not been completely tested yet.
“skipped”
One or more steps of this feature was passed over during testing.
“passed”
The feature was tested successfully.
“failed”
One or more steps of this feature failed.
duration

The time, in seconds, that it took to test this feature. If read before the feature is tested it will return 0.0.

filename

The file name (or “<string>”) of the feature file where the feature was found.

line

The line number of the feature file where the feature was found.

class behave.model.Background(filename, line, keyword, name, steps=None)

A background parsed from a feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will typically be “Background”.

name

The name of the background (the text after “Background:”.)

steps

A list of Step making up this background.

duration

The time, in seconds, that it took to run this background. If read before the background is run it will return 0.0.

filename

The file name (or “<string>”) of the feature file where the scenario was found.

line

The line number of the feature file where the scenario was found.

class behave.model.Scenario(filename, line, keyword, name, tags=None, steps=None, description=None)

A scenario parsed from a feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will typically be “Scenario”.

name

The name of the scenario (the text after “Scenario:”.)

description

The description of the scenario as seen in the feature file. This is stored as a list of text lines.

feature

The Feature this scenario belongs to.

steps

A list of Step making up this scenario.

tags

A list of @tags (as Tag which are basically glorified strings) attached to the scenario. See Controlling Things With Tags.

status

Read-Only. A summary status of the scenario’s run. If read before the scenario is fully tested it will return “untested” otherwise it will return one of:

“untested”
The scenario was has not been completely tested yet.
“skipped”
One or more steps of this scenario was passed over during testing.
“passed”
The scenario was tested successfully.
“failed”
One or more steps of this scenario failed.
duration

The time, in seconds, that it took to test this scenario. If read before the scenario is tested it will return 0.0.

filename

The file name (or “<string>”) of the feature file where the scenario was found.

line

The line number of the feature file where the scenario was found.

class behave.model.ScenarioOutline(filename, line, keyword, name, tags=None, steps=None, examples=None, description=None)

A scenario outline parsed from a feature file.

A scenario outline extends the existing Scenario class with the addition of the Examples tables of data from the feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will typically be “Scenario Outline”.

name

The name of the scenario (the text after “Scenario Outline:”.)

description

The description of the scenario outline as seen in the feature file. This is stored as a list of text lines.

feature

The Feature this scenario outline belongs to.

steps

A list of Step making up this scenario outline.

examples

A list of Examples used by this scenario outline.

tags

A list of @tags (as Tag which are basically glorified strings) attached to the scenario. See Controlling Things With Tags.

status

Read-Only. A summary status of the scenario outlines’s run. If read before the scenario is fully tested it will return “untested” otherwise it will return one of:

“untested”
The scenario was has not been completely tested yet.
“skipped”
One or more scenarios of this outline was passed over during testing.
“passed”
The scenario was tested successfully.
“failed”
One or more scenarios of this outline failed.
duration

The time, in seconds, that it took to test the scenarios of this outline. If read before the scenarios are tested it will return 0.0.

filename

The file name (or “<string>”) of the feature file where the scenario was found.

line

The line number of the feature file where the scenario was found.

class behave.model.Examples(filename, line, keyword, name, table=None)

A table parsed from a scenario outline in a feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will typically be “Example”.

name

The name of the example (the text after “Example:”.)

table

An instance of Table that came with the example in the feature file.

filename

The file name (or “<string>”) of the feature file where the scenario was found.

line

The line number of the feature file where the scenario was found.

class behave.model.Tag

Tags appear may be associated with Features or Scenarios.

They’re a subclass of regular strings (unicode pre-Python 3) with an additional line number attribute (where the tag was seen in the source feature file.

See Controlling Things With Tags.

class behave.model.Step(filename, line, keyword, step_type, name, text=None, table=None)

A single step parsed from a feature file.

The attributes are:

keyword

This is the keyword as seen in the feature file. In English this will typically be “Given”, “When”, “Then” or a number of other words.

name

The name of the step (the text after “Given” etc.)

step_type

The type of step as determined by the keyword. If the keyword is “and” then the previous keyword in the feature file will determine this step’s step_type.

text

An instance of Text that came with the step in the feature file.

table

An instance of Table that came with the step in the feature file.

status

Read-Only. A summary status of the step’s run. If read before the step is tested it will return “untested” otherwise it will return one of:

“skipped”
This step was passed over during testing.
“passed”
The step was tested successfully.
“failed”
The step failed.
duration

The time, in seconds, that it took to test this step. If read before the step is tested it will return 0.0.

error_message

If the step failed then this will hold any error information, as a single string. It will otherwise be None.

filename

The file name (or “<string>”) of the feature file where the step was found.

line

The line number of the feature file where the step was found.

Tables may be associated with either Examples or Steps:

class behave.model.Table(headings, line=None, rows=None)

A table extracted from a feature file.

Table instance data is accessible using a number of methods:

iteration
Iterating over the Table will yield the Row instances from the .rows attribute.
indexed access
Individual rows may be accessed directly by index on the Table instance; table[0] gives the first non-heading row and table[-1] gives the last row.

The attributes are:

headings

The headings of the table as a list of strings.

rows

An list of instances of Row that make up the body of the table in the feature file.

Tables are also comparable, for what that’s worth. Headings and row data are compared.

class behave.model.Row(headings, cells, line=None, comments=None)

One row of a table parsed from a feature file.

Row data is accessible using a number of methods:

iteration
Iterating over the Row will yield the individual cells as strings.
named access
Individual cells may be accessed by heading name; row[‘name’] would give the cell value for the column with heading “name”.
indexed access
Individual cells may be accessed directly by index on the Row instance; row[0] gives the first cell and row[-1] gives the last cell.

The attributes are:

cells

The list of strings that form the cells of this row.

headings

The headings of the table as a list of strings.

Rows are also comparable, for what that’s worth. Only the cells are compared.

And Text may be associated with Steps:

class behave.model.Text

Store multiline text from a Step definition.

The attributes are:

value

The actual text parsed from the feature file.

content_type

Currently only ‘text/plain’.

Logging Capture

The logging capture behave uses by default is implemented by the class LoggingCapture. It has methods

class behave.log_capture.LoggingCapture(config, level=None)

Capture logging events in a memory buffer for later display or query.

Captured logging events are stored on the attribute buffer:

buffer

This is a list of captured logging events as logging.LogRecords.

By default the format of the messages will be:

'%(levelname)s:%(name)s:%(message)s'

This may be overridden using standard logging formatter names in the configuration variable logging_format.

The level of logging captured is set to logging.NOTSET by default. You may override this using the configuration setting logging_level (which is set to a level name.)

Finally there may be filtering of logging events specified by the configuration variable logging_filter.

abandon()

Turn off logging capture.

If other handlers were removed by inveigle() then they are reinstated.

any_errors()

Search through the buffer for any ERROR or CRITICAL events.

Returns boolean indicating whether a match was found.

findEvent(pattern)

Search through the buffer for a message that matches the given regular expression.

Returns boolean indicating whether a match was found.

inveigle()

Turn on logging capture by replacing all existing handlers configured in the logging module.

If the config var logging_clear_handlers is set then we also remove all existing handlers.

We also set the level of the root logger.

The opposite of this is abandon().

The log_capture module also defines a handy logging capture decorator that’s intended to be used on your environment file functions.

behave.log_capture.capture(*args, **kw)

Decorator to wrap an environment file function in log file capture.

It configures the logging capture using the behave context - the first argument to the function being decorated (so don’t use this to decorate something that doesn’t have context as the first argument.)

The basic usage is:

The function prints any captured logging (at the level determined by the log_level configuration setting) directly to stdout, regardless of error conditions.

It is mostly useful for debugging in situations where you are seeing a message like:

No handlers could be found for logger "name"

The decorator takes an optional “level” keyword argument which limits the level of logging captured, overriding the level in the run’s configuration:

This would limit the logging captured to just ERROR and above, and thus only display logged events if they are interesting.

Fork me on GitHub