BDD reference#
Gherkin syntax, JIRA ticket types, code templates, ska-ser-xray tooling, and CI/CD configuration.
For guidance on writing effective Gherkin, see How BDD testing works.
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-1157
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 |
Background#
Background steps run before every scenario in a feature file:
Feature: Status propagation
Background:
Given a clean database
Scenario: Project status trickles down
Given a Project containing an SBDefinition
When the Project status is updated to "Submitted"
Then the SBDefinition status is "Submitted"
For establishing initial state, SKAO practice prefers pytest fixtures — see How BDD testing works.
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 |
Groups tests for planning and reporting; ska-ser-xray attaches tests and executions to it |
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 |
|
BXT |
Tests |
|
CLT |
Tests |
|
AT |
Tests |
|
MTP |
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:
# XSB-41.feature
# Exported from JIRA Test Set XSB-41
@XSB-41
Feature: Configure subarray for imaging scan
As a telescope operator
I want to configure a subarray
So that I can perform an imaging observation
@XSB-38
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
@XSB-39
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
ska-ser-xray tooling#
The ska-ser-xray
Python package provides the XRay integration commands, including the xray-upload command
that make xray-publish calls. Install it in your development environment (with pip, uv,
or poetry, as your project uses) to manage Test and Test Plan issues from feature files:
pip install ska-ser-xray
Commands#
Command |
Purpose |
|---|---|
|
Find or create Test Plan issues by name ( |
|
Generate |
|
Create a Test issue per scenario in local feature files and link it to Test Plans
( |
|
Upload a test report to XRay ( |
|
Generate a Markdown reference for the test suite from feature files and step modules
( |
|
Add links to the HTML test report, steps docs, and commit to Test Execution issues
( |
generate-steps-docs writes an index.md plus one Markdown file per feature file and
per step module. Publish the output alongside your pipeline’s HTML report and pass both URLs
to xray-enrich-test-execution — typically from the xray-post-publish hook — so every
Test Execution links back to the run that produced it.
Environment variables#
The commands read JIRA access from the environment (each also accepts equivalent flags):
Variable |
Value |
|---|---|
|
|
|
Project holding the Test issues — |
|
Your JIRA username |
|
Personal API token locally; supplied by the shared CI configuration in pipelines |
Execution configuration#
tests/xray-config.json is generated by xray-generate-configuration, not written by
hand. It selects the Test Plan and maps pipeline variables to execution names, test
environments, labels, and versions. Commit the generated file to the repository.
CI/CD configuration#
Result upload is handled by the xray-publish target in the .make submodule
(ska-cicd-makefile). Do not
hand-write an upload job.
Makefile#
base.mk does not pull in the XRay targets, so include xray.mk explicitly:
include .make/base.mk
include .make/python.mk
include .make/xray.mk
PYTHON_VARS_AFTER_PYTEST = --cucumberjson=build/reports/cucumber.json
python-test appends PYTHON_VARS_AFTER_PYTEST to every pytest run, so setting it here
makes local runs and the CI test job both write the report to the path xray-publish
reads (XRAY_TEST_RESULT_FILE).
Pipeline#
Include the XRay template from templates-repository:
include:
- project: 'ska-telescope/templates-repository'
file: 'gitlab-ci/includes/xray-publish.gitlab-ci.yml'
Targets and hooks#
Target |
Purpose |
|---|---|
|
Publish BDD test results from the repository to XRay |
|
Hook that runs before the upload — override in your Makefile |
|
Hook that runs after the upload — override in your Makefile |
The target runs xray-upload -f <result file> -e <execution config>.
Variables#
Variable |
Default |
Purpose |
|---|---|---|
|
|
Cucumber JSON report produced by the test run |
|
|
Test execution configuration for the upload |
|
empty |
Additional switches passed to |
|
set by CI |
JIRA/XRay API token — personal token locally, shared CI configuration in pipelines |
Tip
When an upload misbehaves, run it with the verbose flag to see exactly what XRay received:
make xray-publish XRAY_EXTRA_OPTS="--verbose"
Generate the report#
pytest-bdd writes the Cucumber JSON with --cucumberjson. Set the flag once in your
Makefile, as shown above, rather than per command — a flag passed only on the command line
never runs in CI, so xray-publish would find no report there. With the Makefile set:
make python-test PYTHON_TEST_FILE=tests/bdd
Note
In pipelines, JIRA_AUTH comes from the shared CI configuration — do not add JIRA
credentials to your project’s CI/CD variables. For local runs of the ska-ser-xray
commands, use a personal API token and never commit it. See Secret & Configuration Management.
Warning
Run the upload only on the main/master branch of repositories doing significant integration work. Running it on every branch generates thousands of Test Execution tickets.