Drone CI’s test reporting feature is surprisingly manual, often requiring explicit configuration to surface results outside of the build logs.
Let’s see what this looks like in practice. Imagine a simple Go project. We’ll use go test -v -json to generate machine-readable test output, and then we’ll pipe that into a tool that Drone can understand.
Here’s a .drone.yml snippet demonstrating this:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: golang:1.20
commands:
- go test -v -json ./... > report.json
- echo "Test report generated."
- drone-report --file report.json --type go
The drone-report command is a key piece here. It’s a utility that takes the raw test output (in this case, JSON from go test) and transforms it into a format Drone understands for its UI. The --type go flag tells drone-report how to parse the input. Other common types include junit for Java/Maven/Gradle, pytest for Python, and mocha for Node.js.
The fundamental problem this solves is making test results visible and actionable. Without it, you’d have to comb through potentially massive build logs to find out if a test failed, which one, and why. Drone’s reporting feature aggregates this, showing clear pass/fail indicators and linking directly to the failing tests.
Internally, drone-report works by parsing the specified input format. For Go’s JSON output, it reads each JSON event, identifies test start, pass, fail, and skip events, and then constructs a summary. This summary is then sent to the Drone API, which associates it with the current build. The Drone UI then queries this data to display the test results in a structured way.
The image used in the pipeline (golang:1.20) is crucial. It needs to contain the necessary tools to run your tests and generate the output. If your tests require specific dependencies, you’ll need to ensure they are installed within this image or a custom image you build.
The commands section is where the magic happens. The go test -v -json ./... > report.json command executes the tests verbosely, outputs them in JSON format, and redirects that output to a file named report.json. The subsequent drone-report command then processes this file. You’d typically install drone-report within your build image or use an image that already includes it. A common approach is to have a multi-stage build or a dedicated image for reporting.
The --file report.json argument tells drone-report which file to read. If your test runner outputs to standard out, you might omit this and pipe directly: go test -v -json ./... | drone-report --type go. However, saving to a file often makes debugging easier.
The --type go argument is essential. Drone needs to know how to interpret the report.json file. If you were using Maven, for example, you’d configure your Maven build to output JUnit XML reports and then use --type junit with drone-report. The structure of the output file dictates the type you need to specify.
The Drone UI will then display a "Tests" tab for the build, showing the number of tests run, passed, failed, and skipped. Clicking on a failed test will usually show the associated error message and stack trace directly within the UI.
To get the drone-report tool, you can often find it as a pre-built binary or install it via a package manager if you’re building a custom Docker image. For instance, if you’re using a Debian-based image, you might apt-get update && apt-get install -y drone-report if it’s available in the repositories, or download the binary and place it in your PATH.
The most subtle point is that Drone itself doesn’t run the tests; it ingests the reports. This means your pipeline needs to execute the tests and generate an output file in a format that drone-report (or a similar ingestion tool) can parse. The drone-report tool is essentially a translator, bridging the gap between your test runner’s output and Drone’s internal representation of test results.
The next step in managing CI output is often integrating security scanning tools to report vulnerabilities alongside test results.