Spock Reporting: Spock Reports Plugin, HTML Reports, and CI Integration
Spock's built-in test output is minimal — pass/fail counts with method names. The Spock Reports plugin generates rich HTML reports that show your BDD specification blocks (given/when/then) in readable prose, making test results accessible to non-engineers. This guide covers setup, template customization, and publishing reports in Jenkins, GitHub Actions, and GitLab CI.
Why Spock Reports
JUnit XML reports — the standard output from most test frameworks — show test names and stack traces. That's enough for developers, but product managers, QA leads, and stakeholders need more context.
Spock Reports converts your test specifications into readable HTML documents where:
- Feature method names become section headers
given:,when:,then:blocks become labeled paragraphs- Data tables render as formatted tables
- Failures include the exact assertion that failed
A failing test reads: "Given a logged-out user, When they access /dashboard, Then they are redirected to /login" — not LoginRedirectSpec > testDashboardRedirect FAILED.
Installation
Gradle
repositories {
mavenCentral()
}
dependencies {
testImplementation 'com.athaydes:spock-reports:2.5.1-groovy-4.0'
// Optionally for Groovy ASTTransformation support:
testImplementation 'org.codehaus.groovy:groovy-templates:4.0.21'
}The plugin auto-registers via Spock's global extension SPI — no additional configuration required for basic use.
Maven
<dependency>
<groupId>com.athaydes</groupId>
<artifactId>spock-reports</artifactId>
<version>2.5.1-groovy-4.0</version>
<scope>test</scope>
</dependency>Basic Configuration
Create src/test/resources/META-INF/services/com.athaydes.spockframework.report.IReportCreator (this file exists automatically when using the plugin). The plugin reads src/test/resources/spock-reports/config.properties:
# Output directory (relative to build dir)
com.athaydes.spockframework.report.outputDir=build/spock-reports
# Report format: html (default) or json
com.athaydes.spockframework.report.IReportCreator=com.athaydes.spockframework.report.internal.HtmlReportCreator
# Show summary in individual reports
com.athaydes.spockframework.report.showSummary=true
# Hide @Unroll iterations in the summary
com.athaydes.spockframework.report.aggregateStats=false
# Project name shown in report header
com.athaydes.spockframework.report.projectName=My Project
# Project version
com.athaydes.spockframework.report.projectVersion=1.0.0After running tests with ./gradlew test, reports appear in build/spock-reports/.
Report Structure
The plugin generates:
index.html— summary of all spec classes: total features, passed, failed, skippedcom.example.MySpec.html— individual spec report with full feature details
The index lists all specs with pass/fail status at a glance. Individual spec reports show the full specification tree.
Sample HTML Report Content
For a spec like:
class CartSpec extends Specification {
def "adding item increases cart total"() {
given: "an empty cart"
def cart = new Cart()
when: "an item is added"
cart.add(new Item("Widget", 9.99))
then: "total reflects the item price"
cart.total == 9.99
}
}The HTML report renders:
CartSpec
✓ adding item increases cart total
GIVEN: an empty cart
WHEN: an item is added
THEN: total reflects the item priceThe prose labels come directly from your given:, when:, then: strings — writing descriptive block labels pays off in report readability.
Customizing Templates
The plugin uses Groovy's SimpleTemplateEngine. Override the default templates by placing your versions in src/test/resources/spock-reports/:
spec-template.html— individual spec reportsummary-template.html— index/summary report
Get the default templates from the plugin's JAR:
jar xf ~/.gradle/caches/modules-2/files-2.1/com.athaydes/spock-reports/*/spock-reports-*.jar \
templates/spec-template.html templates/summary-template.html
mv templates/spec-template.html src/test/resources/spock-reports/Templates receive these variables:
| Variable | Type | Description |
|---|---|---|
reportTitle |
String | Spec class name |
features |
List | All feature results |
stats |
Map | passed, failed, skipped, total |
projectName |
String | From config |
dateCreated |
String | Report generation time |
Example: add a custom footer to spec-template.html:
<!-- Near the bottom of the template -->
<footer class="report-footer">
Generated by CI build ${buildNumber ?: "local"} on ${dateCreated}
</footer>Pass buildNumber via system property:
./gradlew test -Dbuild.number=$CI_BUILD_NUMBERRead it in config:
com.athaydes.spockframework.report.customProperties.buildNumber=\${System.getProperty('build.number', 'local')}Adding Multiple Report Formats
Generate both HTML and JSON reports:
com.athaydes.spockframework.report.IReportCreator=\
com.athaydes.spockframework.report.internal.HtmlReportCreator,\
com.athaydes.spockframework.report.internal.JsonReportCreatorJSON output is useful for processing results programmatically — feeding into dashboards, ticket systems, or custom notification webhooks.
CI Integration
Jenkins
In your Jenkinsfile:
pipeline {
agent any
stages {
stage('Test') {
steps {
sh './gradlew test'
}
post {
always {
// Publish JUnit XML (Gradle generates this alongside Spock Reports)
junit 'build/test-results/test/*.xml'
// Publish HTML report
publishHTML(target: [
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'build/spock-reports',
reportFiles: 'index.html',
reportName: 'Spock Test Report'
])
}
}
}
}
}The publishHTML plugin must be installed in Jenkins. The report appears as a sidebar link in each build.
GitHub Actions
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Run tests
run: ./gradlew test
- name: Publish test results
uses: dorny/test-reporter@v1
if: always()
with:
name: Spock Tests
path: build/test-results/test/*.xml
reporter: java-junit
- name: Upload Spock HTML report
uses: actions/upload-artifact@v4
if: always()
with:
name: spock-reports
path: build/spock-reports/
retention-days: 30The dorny/test-reporter action renders JUnit XML results directly in the GitHub PR check. The HTML report is available as a downloadable artifact.
To make the HTML report accessible without downloading the artifact, publish to GitHub Pages from your CI workflow, or use a hosted artifact service.
GitLab CI
test:
stage: test
script:
- ./gradlew test
after_script:
- echo "Tests complete"
artifacts:
when: always
reports:
junit: build/test-results/test/*.xml
paths:
- build/spock-reports/
expire_in: 1 week
pages:
stage: deploy
dependencies:
- test
script:
- mkdir -p public
- cp -r build/spock-reports/* public/
artifacts:
paths:
- public
only:
- mainThe pages job deploys the HTML report to GitLab Pages, making it browsable at https://<group>.gitlab.io/<project>/.
Linking Reports to Issue Trackers
Configure issue link patterns in spock-reports/config.properties:
# Prefix for issue numbers in test names (e.g., JIRA-1234)
com.athaydes.spockframework.report.issueNamePrefix=JIRA-
# URL template (%s is replaced with the issue number)
com.athaydes.spockframework.report.issueUrlPrefix=https://jira.company.com/browse/JIRA-Then annotate features with @Issue:
@Issue("1234")
def "checkout flow processes payment correctly"() { ... }The HTML report renders JIRA-1234 as a clickable link to your Jira ticket.
Similarly for @See (external documentation links):
@See("https://docs.company.com/checkout-flow")
def "checkout follows the documented flow"() { ... }Excluding Specs from Reports
Use @IgnoreFor to exclude specific specs from report generation (useful for infrastructure helpers that aren't real tests):
Or configure report filtering via:
# Exclude specs matching these patterns
com.athaydes.spockframework.report.excludedSpecs=.*Helper,.*BaseAggregating Reports Across Subprojects
For multi-module Gradle projects, each subproject generates its own reports. Aggregate them in the root project:
// root build.gradle
task aggregateSpockReports(type: Copy) {
from subprojects.collect { it.fileTree("${it.buildDir}/spock-reports") }
into "${buildDir}/spock-reports"
}
aggregateSpockReports.dependsOn subprojects.collect { it.tasks.named('test') }Or use the spock-reports Gradle plugin's built-in aggregation support if your version provides it.
Report Quality: Writing for Readability
The HTML output is only as good as your specification text. Compare:
Poor specification (misleading report):
def "test1"() {
given: "setup"
// ...
when: "action"
// ...
then: "result"
// ...
}Readable specification (useful report):
def "expired session redirects to login with return URL"() {
given: "a session that expired 2 hours ago"
// ...
when: "the user requests a protected page"
// ...
then: "they are redirected to /login?returnTo=/dashboard"
// ...
}The second form produces a report that product managers can read without engineering context. Block labels like "a session that expired 2 hours ago" communicate intent, not implementation.
Summary
Spock Reports transforms your test results from raw pass/fail data into readable specifications. Setup takes minutes — add the dependency, run tests, open the HTML. CI integration ensures reports are published with every build. The real value comes from writing descriptive feature names and block labels that make the reports genuinely informative to everyone on your team, not just the engineers who wrote the tests.