Fragments
Fragments are reusable scenario steps that can be included in multiple scenarios. They help reduce duplication and improve maintainability of your test suites.
Creating Fragments
Fragment files use the .fragment extension and are placed in the
src/test/resources/berrycrush/fragments/ directory by default.
berrycrush/fragments/auth.fragment:
# Authentication Fragment
# Reusable authentication steps for protected endpoints
fragment: authenticate
given I have valid credentials
call using auth ^login
body: {"username": "test", "password": "test"}
extract $.token => authToken
then authentication is successful
assert status 200
fragment: logout
when I log out
call using auth ^logout
then the session is terminated
assert status 200
Fragment Structure
Each fragment starts with fragment: <name> followed by indented steps:
fragment: <fragment-name>
<step-type> <description>
<actions>
<step-type> <description>
<actions>
Using Fragments
Include fragments in your scenarios using the include directive:
scenarios/list-pets.scenario:
scenario: Authenticated list pets
given I authenticate first
include authenticate
when I request the list of pets
call ^listPets
then I get a successful response
assert status 200
The steps from the authenticate fragment are expanded inline during execution.
Fragment Discovery
BerryCrush discovers fragment files using patterns specified in the
@BerryCrushScenarios annotation.
Default Discovery
By default, BerryCrush searches for fragment files matching the pattern
berrycrush/fragments/*.fragment:
@BerryCrushScenarios(locations = ["berrycrush/scenarios/*.scenario"])
// fragments = ["berrycrush/fragments/*.fragment"] is the default
class MyApiTest
Custom Fragment Locations
You can specify custom fragment locations using the fragments property:
@BerryCrushScenarios(
locations = ["scenarios/*.scenario"],
fragments = ["shared/fragments/*.fragment", "auth/*.fragment"]
)
class MyApiTest
The fragments property accepts an array of glob patterns, allowing you to:
Search multiple directories
Use wildcard patterns (
*,**)Specify exact file paths
Examples:
// Single directory
fragments = ["my-fragments/*.fragment"]
// Multiple directories
fragments = ["auth/*.fragment", "common/*.fragment", "api/*.fragment"]
// Recursive search
fragments = ["**/*.fragment"]
// Specific files
fragments = ["fragments/auth.fragment", "fragments/setup.fragment"]
Directory Structure
Typical project structure with custom fragment locations:
src/test/resources/
├── petstore.yaml
├── auth/
│ └── auth.fragment
├── common/
│ └── setup.fragment
└── scenarios/
├── pet-crud.scenario
└── user-api.scenario
With annotation:
@BerryCrushScenarios(
locations = ["scenarios/*.scenario"],
fragments = ["auth/*.fragment", "common/*.fragment"]
)
class MyApiTest
Variables in Fragments
Fragments can extract values that become available in the calling scenario:
fragment: authenticate
given I have valid credentials
call using auth ^login
body: {"username": "test", "password": "test"}
extract $.token => authToken
The authToken variable is now available in the scenario that included this fragment:
scenario: Access protected resource
given I am authenticated
include authenticate
when I access the protected endpoint
call ^getSecretData
header_Authorization: Bearer {{authToken}}
then I get the data
assert status 200
Parameterized Fragments
Fragments can accept parameters to make them more flexible and reusable. Parameters are passed when including the fragment and become available as variables within the fragment’s scope.
Defining Parameterized Fragments
A fragment can use variables that will be provided by the calling scenario:
fragment: create_user
when creating the user
call ^createUser
body: {"name": "{{name}}", "email": "{{email}}", "age": {{age}}}
extract $.id => userId
then user is created
assert status 201
Passing Parameters
Use indented key-value pairs after the include directive to pass parameters:
scenario: Create a specific user
given I create a user
include create_user
name: "John Doe"
email: "john@example.com"
age: 30
then the user exists
assert $.name equals "John Doe"
Parameter Types
Parameters support various value types:
include configure_pet
name: "Fluffy" # String (must be quoted if spaces/special chars)
petId: 123 # Number
active: true # Boolean
tags: ["cute", "small"] # JSON array
metadata: {"key": "val"} # JSON object
Using Variable References
Parameters can reference existing variables using {{variableName}} syntax:
scenario: Create user from context
given I have user data
set userName => "Alice"
set userEmail => "alice@example.com"
when I create the user
include create_user
name: {{userName}}
email: {{userEmail}}
age: 25
then the user exists in the system
Complete Example
fragments/crud.fragment:
fragment: create_entity
when creating the entity
call ^createEntity
body: {"type": "{{entityType}}", "name": "{{name}}", "owner": "{{owner}}"}
extract $.id => entityId
then entity is created
assert status 201
fragment: delete_entity
when deleting the entity
call ^deleteEntity
id: {{entityId}}
then entity is removed
assert status 204
scenarios/entity-test.scenario:
scenario: Full entity lifecycle
given I create a pet entity
include create_entity
entityType: "pet"
name: "Buddy"
owner: "john@example.com"
then I clean up
include delete_entity
entityId: {{entityId}}
Multi-Spec in Fragments
Fragments can use the using keyword to call operations from named specs:
fragment: admin-login
given I have admin credentials
call using auth ^login
body: {"username": "admin", "password": "admin123"}
extract $.token => adminToken
then admin authentication is successful
assert status 200
Example: Complete Test Suite
Directory structure:
src/test/resources/
├── petstore.yaml
├── auth.yaml
├── fragments/
│ └── auth.fragment
└── scenarios/
├── 01-setup.scenario
├── pet-crud.scenario
└── 99-cleanup.scenario
fragments/auth.fragment:
fragment: authenticate
given I have valid credentials
call using auth ^login
body: {"username": "test", "password": "test"}
extract $.token => authToken
then authentication is successful
assert status 200
fragment: authenticate-admin
given I have admin credentials
call using auth ^login
body: {"username": "admin", "password": "admin123"}
extract $.token => adminToken
then admin authentication is successful
assert status 200
scenarios/pet-crud.scenario:
scenario: Create pet as authenticated user
given I am authenticated
include authenticate
when I create a new pet
call ^createPet
header_Authorization: Bearer {{authToken}}
body: {"name": "Fluffy", "status": "available"}
then the pet is created
assert status 201
extract $.id => petId
scenario: Delete pet as admin
given I am an admin
include authenticate-admin
when I delete the pet
call ^deletePet
header_Authorization: Bearer {{adminToken}}
petId: {{petId}}
then the pet is deleted
assert status 204
Best Practices
Keep fragments focused: Each fragment should do one thing well
Use descriptive names: Fragment names should clearly indicate their purpose
Document variables: Comment which variables are extracted by the fragment
Organize by domain: Group related fragments together
Avoid deep nesting: Don’t include fragments within fragments