BDD Reference#
Gherkin syntax, JIRA ticket types, code templates, and CI/CD configuration.
Gherkin syntax#
Gherkin defines test scenarios using natural language keywords.
Keywords#
Keyword |
Purpose |
Example |
|---|---|---|
|
Set up initial state/context |
|
|
Perform an action |
|
|
Verify expected outcome |
|
|
Continue previous step type |
|
|
Negative continuation |
|
Scenario structure#
@XTP-1156
Scenario: Descriptive name of the test
Given some initial context
And additional context
When an action occurs
And another action
Then expected outcome
And additional verification
Scenario Outline (parameterised)#
Use Scenario Outline with an Examples table for multiple test cases:
@XTP-1156
Scenario Outline: Handle invalid inputs
Given the system is ready
When I provide <input>
Then I receive <output>
Examples:
| input | output |
| valid | success |
| invalid | error message |
| empty | validation fail |
JIRA ticket types#
Ticket Type |
Project |
Purpose |
|---|---|---|
Requirement |
L1, L2, IFID, VTS |
Source requirements JAMA imports |
Feature |
Various |
User-defined features for PI planning |
Test Set |
XTP |
Groups related tests for a requirement |
Test |
XTP |
Individual BDD test with Gherkin steps |
Test Plan |
XTP |
Describes test conditions (mainly for manual tests) |
Test Execution |
XTP |
Records test run results (CI/CD auto-generates these) |
JIRA projects#
Project |
Name |
URL |
|---|---|---|
L1 |
Level 1 Requirements |
|
L2 |
Level 2 Requirements |
|
IFID |
Interface Requirements |
|
VTS |
Verification Requirements |
|
XTP |
Tests |
pytest-bdd code templates#
Basic test structure#
"""BDD tests for [feature name]."""
from pytest_bdd import given, when, then, scenarios, parsers
import pytest
# Load all scenarios from the feature file
scenarios('path/to/feature_file.feature')
@pytest.fixture
def context():
"""Fixture to share data between steps."""
return {}
@given('initial state description')
def setup_initial_state(context):
"""Set up the test context."""
context['key'] = 'value'
@when('action description')
def perform_action(context):
"""Execute the action under test."""
context['result'] = do_something(context['key'])
@then('expected outcome description')
def verify_outcome(context):
"""Assert the expected result."""
assert context['result'] == expected_value
Parameterised steps#
from pytest_bdd import when, then, parsers
@when(parsers.parse('I provide {input_value}'))
def provide_input(input_value, context):
"""Handle variable input from Examples table."""
context['input'] = input_value
@when(parsers.re(r'I wait (?P<seconds>\d+) seconds'))
def wait_seconds(seconds, context):
"""Use regex for more complex patterns."""
import time
time.sleep(int(seconds))
Feature file format#
Structure feature files as follows:
# XTP-494.feature
# Exported from JIRA Test Set XTP-494
@XTP-494
Feature: Configure subarray for imaging scan
As a telescope operator
I want to configure a subarray
So that I can perform an imaging observation
@XTP-417
Scenario: Configure subarray with valid parameters
Given the telescope is in STANDBY state
And I have a valid configuration file
When I send the Configure command
Then the subarray enters READY state
And the configuration is applied
@XTP-427
Scenario: Handle invalid configuration
Given the telescope is in STANDBY state
When I send an invalid configuration
Then the subarray returns an error
And the subarray remains in STANDBY state
CI/CD configuration#
GitLab CI/CD job for BDD tests with JIRA integration:
bdd-tests:
stage: test
script:
- pip install pytest pytest-bdd
- pytest tests/bdd/ --cucumber-json=bdd-results.json
artifacts:
paths:
- bdd-results.json
reports:
cucumber: bdd-results.json
only:
- main
- master
upload-to-jira:
stage: deploy
needs: [bdd-tests]
script:
- curl -X POST -H "Authorization: Bearer $XRAY_TOKEN" \
-H "Content-Type: application/json" \
-d @bdd-results.json \
"https://xray.cloud.getxray.app/api/v2/import/execution/cucumber"
only:
- main
- master
Note
Configure the XRAY_TOKEN environment variable in your GitLab project’s CI/CD settings.
Writing effective Gherkin#
Follow these practices for clear, reusable test definitions:
- Use consistent phrasing
Check existing tests in JIRA before writing new steps. Consistent wording enables step reuse.
- Keep steps atomic
Each step performs one action or checks one thing. Avoid compound steps.
- Use domain language
Write steps that stakeholders understand. Avoid technical jargon.
- Make steps reusable
Generic steps like
Given the telescope is in STANDBY statecan be reused across many tests.- Include context
The scenario title and steps together tell the complete story of what the test verifies. Ensure readers understand the test purpose without external documentation.
Example of good vs poor Gherkin:
# Good - clear, reusable steps
Given the telescope is in STANDBY state
When I send the Configure command with valid parameters
Then the subarray enters READY state
# Poor - vague, compound, not reusable
Given everything is set up
When I do the thing and check the result
Then it works