Warning: If you are new to BDD, then I strongly recommend reading the BDD 101 series before trying to use the behave framework.
Overview
behave is a behavior-driven (BDD) test framework that is very similar to Cucumber, Cucumber-JVM, and SpecFlow. BDD frameworks are unique in that test cases are not written in raw programming code but rather in plain specification language that is then “glued” to code. The “behavior specs” help to define what the behavior is, and steps can be reused by multiple test cases (or “scenarios”). This is very different from more traditional frameworks like unittest and pytest. Although behave is not an official Cucumber variant, it still uses the Gherkin language (“Given-When-Then”) for behavior specification.
Test scenarios are written in Gherkin “.feature” files. Each Given, When, and Then step is “glued” to a step definition – a Python function decorated by a matching string in a step definition module. The behave framework essentially runs feature files like test scripts. Hooks (in “environment.py”) and fixtures can also insert helper logic for test execution.
behave is officially supported for Python 2, but it seems to run just fine using Python 3.
Installation
Use pip to install the behave module.
pip install behave
Project Structure
Since behave is an opinionated framework, it has a very opinionated project structure. All code must be located under a directory named “features”. Gherkin feature files and the “environment.py” file for hooks must appear under “features”, and step definition modules must appear under “features/steps”. Configuration files can store common execution settings and even override the path to the “features” directory.
Note: Step definition module names do not need to be the same as feature file names. Any step definition can be used by any feature file within the same project.
[project root directory] |‐‐ [product code packages] |-- features | |-- environment.py | |-- *.feature | `-- steps | `-- *_steps.py `-- [behave.ini|.behaverc|tox.ini|setup.cfg]
Example Code
An example project named behavior-driven-python located in GitHub shows how to write tests using behave. This section will explain how the Web tests are designed.
The top layer in a behave project is the set of Gherkin feature files. Notice how the scenario below is concise, focused, meaningful, and declarative:
@web @duckduckgo Feature: DuckDuckGo Web Browsing As a web surfer, I want to find information online, So I can learn new things and get tasks done. # The "@" annotations are tags # One feature can have multiple scenarios # The lines immediately after the feature title are just comments Scenario: Basic DuckDuckGo Search Given the DuckDuckGo home page is displayed When the user searches for "panda" Then results are shown for "panda"
Each scenario step is “glued” to a decorated Python function called a step definition. Step defs can use different types of step matchers and can also take parametrized inputs:
from behave import * from selenium.webdriver.common.keys import Keys DUCKDUCKGO_HOME = 'https://duckduckgo.com/' @given('the DuckDuckGo home page is displayed') def step_impl(context): context.browser.get(DUCKDUCKGO_HOME) @when('the user searches for "{phrase}"') def step_impl(context, phrase): search_input = context.browser.find_element_by_name('q') search_input.send_keys(phrase + Keys.RETURN) @then('results are shown for "{phrase}"') def step_impl(context, phrase): links_div = context.browser.find_element_by_id('links') assert len(links_div.find_elements_by_xpath('//div')) > 0 search_input = context.browser.find_element_by_name('q') assert search_input.get_attribute('value') == phrase
The “environment.py” file can specify hooks to execute additional logic before and after steps, scenarios, features, and even the whole test suite. Hooks should handle automation concerns that should not be exposed through Gherkin. For example, Selenium WebDriver setup and cleanup should be handled by hooks instead of step definitions because after hooks always get run despite failures, while steps after an abortive failure will not get run.
from selenium import webdriver def before_scenario(context, scenario): if 'web' in context.tags: context.browser = webdriver.Firefox() context.browser.implicitly_wait(10) def after_scenario(context, scenario): if 'web' in context.tags: context.browser.quit()
Test Launch
behave boasts a powerful command line with many options. Below are common use case examples when running tests from the project root directory:
# Run all scenarios in the project behave # Run all scenarios in a specific feature file behave features/web.feature # Filter tests by tag behave --tags-help behave --tags @duckduckgo behave --tags ~@unit behave --tags @basket --tags @add,@remove # Write a JUnit report (useful for Jenkins and other CI tools) behave --junit # Don't print skipped scenarios behave -k
Pros and Cons
Like all BDD test frameworks, behave is opinionated. It works best for black box testing due to its behavior focus. Web testing would be a great use case because user interactions can easily be described using plain language. Reusable steps also foster a snowball effect for automation development. However, behave would not be good for unit testing or low-level integration testing – the verbosity would become more of a hindrance than a helper.
My recommendation is to use behave for black box testing if the team has bought into BDD. I would also strongly consider pytest-bdd as an alternative BDD framework because it leverages all the goodness of pytest.
Thank you for this great article, I have shared it on Twitter.
LikeLike
Hi, this is really good to understand how python behave works also can you please help me how can I run the features folder in multiple browsers like chrome, edge using behave?
LikeLike
How can we run parallel tests in behave?
LikeLike
Unfortunately, behave does not natively support parallel execution. There are a few projects you can find by searching online that extend behave with parallel testing support.
LikeLike
We have been trying for a long time to implement parallel test executions over behave. Finally, we implemented our own wrapper, that not only allow us to execute tests in parallel, but also comes with great reports and some additional features:
https://github.com/hrcorval/behavex
I hope it helps!
LikeLike