-
Notifications
You must be signed in to change notification settings - Fork 8
Behavior Driven Development (BDD)
BDD is a set of practices of Software Engineering that aims to improve the quality of the code and the delivery of correct software. BDD is based on agile and lean development techniques that aim at collaboration between developers and different stakeholders in the verification and validation process.
BDD proposes the use of a language that is understandable by all stakeholders. In this way, everyone involved will use this language to describe the software's functionalities, which will be described in several files ending with the suffix .feature
. One of BDD's ideas is to use these files as a form of documentation and also to test the various behaviors of the software.
The scenarios are composed of several rules and each rule can be mapped to a method that will check if it is executed correctly.
For the creation of the scenarios, languages are used that can be understood by all stakeholders, an example is the Gherkin language.
A feature, using Gherkin, can be specified as follows (gherkin reference):
Feature: brief description of the functionality
Scenario: description of a specific feature scenario.
Given a precondition
And other precondition
When an action occurs
And another action takes place
Then a testable result is obtained
The purpose of the keyword feature is to give a high-level description of a system's functionality and to group the scenarios related to this feature.
The Scenario keyword describes a business rule for functionality and consists of several Given/When/Then rules.
Define an initial state before starting to test. In this step, object instances, database configurations, search for a web page can be made, among other configurations necessary to leave the system in an initial state. In the case of the simulation, in the Given step, all settings of the scenarios necessary to correctly execute the simulation are made.
Defines an event or an action to be performed on the system being tested. This action can be done by a person or by another system.
Describes the expected result of performing the previous steps. In this step, the assert will be carried out to verify that the received output is equal to the output that was expected.
It serves as a synonym for the step before it and is used to avoid multiple writing of Given/When/Then.
It is possible to create specifications for a robotic mission (scenarios) using a BDD specification language, in which case Gherkin will be used. For this we will use the pytest-bdd library.
The description of the scenarios will be made in a .feature
file. Each .feature
file is responsible for a certain functionality, and in that file it can describe various scenarios related to that particular functionality. The scenarios can be described as several Given, When and Then steps.
The Given steps will be used for setting up the scenarios, for example, instantiating a simulation, defining the necessary systems, adding components. The When step is responsible for running the simulation. Finally, the Then step is used to verify that the result of the execution came as expected.
In this project, the features are present in the tests/features folder. For each .feature
file in that folder, there is a test file present in the tests/step_defs folder that checks each Given, When, Then step for each feature scenario.
There are also auxiliary methods to help create the scenarios and to help make the asserts.
The methods for creating scenarios are present in the file ScenarioCreationHelper.py
in the folder tests/helpers and the class has methods to add components, to add POIs (Point of Interest), to add events, to add systems to the simulation, among others.
The methods to help with assertions are present in the file AssertionHelper.py
also in the folder tests/helpers. The AssertionHelper class has several methods, among them, a method to verify that the camera has detected the person, a method to verify that the robot approximated a person, a method to verify if a collision has occurred, a method to verify if an entity is in a specific POI.
The simulations maps are made using the drawio. Examples of maps are present in the tests/data folder and in the simulator/resources/map folder.
To create a test using the BDD, you will first create a scenario, for example, the following scenario describes a robot in position 1.1 that remains stationary throughout the simulation, when the simulation is finished and a check is made, the robot needs be in position 1.1, otherwise an error has occurred. Example file: tests/feature/single_static_robot.feature
Feature: Single Static Robot
Scenario: Single static robot
Given a map with one room
And a robot with id 'robot' in position '1,1' inside the room
When the robot stay still
Then the robot with id 'robot' is in '1,1'
Soon after, a test file will be created to execute and verify each step present in the scenario above. Example file: tests/step_defs/test_single_static_robot.py.
scenarios('../features/single_static_robot.feature')
@pytest.fixture
def scenario_helper(simulation):
return ScenarioCreationHelper(simulation)
@pytest.fixture
def assertion_helper(simulation):
return AssertionHelper(simulation)
@given("a map with one room", target_fixture="simulation")
def map_with_one_room():
config = {
"context": "tests/data",
"map": "one_room_map.drawio",
"FPS": 60,
"DLW": 10,
"duration": 10
}
simulation = Simulator(config)
return simulation
@given(parsers.parse("a robot with id '{robot}' in position '{position}' inside the room"))
def a_robot_in_given_position(scenario_helper: ScenarioCreationHelper, robot, position):
pos = position.replace(' ', '').split(',')
scenario_helper.set_position(robot, int(pos[0]), int(pos[1]))
@when("the robot stay still")
def stay_still(simulation):
simulation.run()
@then(parsers.parse("the robot with id '{robot}' is in '{position}'"))
def check_the_robot_is_in_position(assertion_helper: AssertionHelper, robot, position):
pos = position.replace(' ', '').split(',')
assert assertion_helper.is_in_position(robot, (int(pos[0]),int(pos[1])))
The first step Given instantiates a simulation that uses a one_room_map.drawio
map present in the tests/data folder. The second step Given configures the robot to be in position 1,1. The When step will run the simulation. The Then step will check if the robot is located at position 1,1.
Remembering that it is also necessary to create the drawio map with the robot and everything that is necessary.
After creating the scenario and the tests, just run pytest to check if everything is going through. .