What Are Cypress Reporters? A Technical Guide to Test Output and Reporting
Cypress reporters transform raw test execution events into human-readable output, statistics, and external file formats like JUnit XML by bridging Cypress internals with Mocha's reporting infrastructure.
Cypress reporters form the output subsystem of the cypress-io/cypress testing framework. They handle the translation of internal test events into structured reports, console output, and machine-readable artifacts essential for CI/CD integration. The reporter architecture lives primarily in packages/server/lib/reporter.ts and interfaces directly with Mocha's reporter ecosystem to normalize test results.
How Cypress Reporters Process Test Events
The reporter system acts as a bridge between Cypress's internal event bus and the final output destination. Understanding this pipeline is crucial for customizing test output or debugging reporter issues.
The Event Translation Pipeline
When Cypress runs tests, the Reporter class orchestrates a four-stage event flow:
-
Instantiation: The Cypress server creates a
Reporterinstance with the configured reporter name (e.g.,spec,junit, or a custom module). -
Mocha Runner Creation: The
Reporterclass constructs a Mocha test runner usingnew Mocha({ reporter })and wires it to the selected reporter implementation. -
Event Translation: As tests execute, Cypress emits internal events such as
test:before:run,pass, andfail. TheReporter.emit()method (defined at lines 22-40 inpackages/server/lib/reporter.ts) translates these into Mocha-compatible event shapes and forwards them viathis.runner.emit. -
Results Finalization: When the run completes,
Reporter.end()(lines 68-86) resolves aReporterResultsobject containing normalized statistics, test records, and hook data.
Core Implementation in packages/server/lib/reporter.ts
The Reporter class serves as the central abstraction. Key methods include:
loadReporter()(lines 55-79): Resolves reporter modules by checking built-in Cypress reporters, Mocha's built-in reporters, or requiring custom modules fromnode_modulesor local paths.emit()andparseArgs(): Convert Cypress proprietary events into the format expected by Mocha reporters while filtering private properties.normalizeTest()andnormalizeHook()(lines 98-134): Transform Mocha's internal objects into the standardized shapes required by Cypress Cloud and the UI, defined inpackages/types/src/reporter.ts.
Built-in, Mocha, and Custom Reporter Types
Cypress supports three distinct categories of reporters, selectable via the reporter configuration field or the --reporter CLI flag.
Built-in Cypress Reporters
Cypress ships with three first-party reporters optimized for different environments:
spec(default): The standard console output showing nested suites, test titles, and duration.teamcity: Formats output for TeamCity CI integration.junit: Generates JUnit XML files for test result aggregation.
Third-Party Mocha Reporters
Because Cypress uses Mocha under the hood, any Mocha reporter (such as dot, nyan, or json) works by name. The loadReporter() method detects these via the code path if (mochaReporters[reporterName]) and instantiates them within the Cypress context.
Custom Reporter Modules
If the specified name matches neither built-in nor Mocha reporters, Cypress attempts to require() a local file or npm module. Custom reporters must extend Mocha.reporters.Base and handle events like pass, fail, and end.
Configuring and Loading Cypress Reporters
Reporter selection and configuration occur through multiple interfaces, all processed by the loadReporter() method in packages/server/lib/reporter.ts.
Configuration File Setup
Specify the reporter and its options in cypress.config.js:
// cypress.config.js
module.exports = {
reporter: 'junit',
reporterOptions: {
mochaFile: 'cypress/results/[hash].xml',
toConsole: true,
},
}
When Cypress initializes, the Reporter constructor receives 'junit' as the reporterName parameter, and loadReporter() resolves it to require('mocha-junit-reporter').
Command Line Interface
Override config settings using CLI flags:
cypress run --reporter ./my-reporter.js --reporter-options '{"output":"my-report.json"}'
The loadReporter() method resolves relative paths against the project root, requiring the module and passing the parsed options to the reporter constructor.
Creating a Custom Cypress Reporter
Custom reporters extend Mocha's base reporter and integrate with Cypress's event system. Here is a minimal implementation that logs passed and failed tests:
// my-reporter.js
const Mocha = require('mocha')
class MyReporter extends Mocha.reporters.Base {
constructor(runner, options) {
super(runner)
runner.on('pass', test => {
console.log(`✅ ${test.fullTitle()}`)
})
runner.on('fail', (test, err) => {
console.log(`❌ ${test.fullTitle()} – ${err.message}`)
})
}
}
module.exports = MyReporter
When invoked via --reporter ./my-reporter.js, Cypress instantiates this class inside Reporter.setRunnables() and pipes all test events through it.
Accessing Reporter Results Programmatically
For programmatic test runners, access the finalized results using the end() method:
const { Reporter } = require('@packages/server/lib/reporter')
const reporter = Reporter.create('spec', {}, process.cwd())
// After emitting all test events...
reporter.end().then(results => {
console.log('Overall stats:', results.stats)
console.log('Test list:', results.tests.map(t => t.title))
})
The end() method returns a promise resolving to a ReporterResults object containing:
- stats: Summary of suites, tests, passes, failures, and duration.
- reporter: The name of the reporter used.
- reporterStats: Raw Mocha statistics object.
- tests: Array of normalized test records with title, state, error, and attempts.
- hooks: Array of normalized hook records.
Summary
- Cypress reporters translate internal test events into consumable output through the
Reporterclass inpackages/server/lib/reporter.ts. - The event pipeline bridges Cypress events with Mocha's reporting system via
emit()andnormalizeTest()methods. - Three reporter types are supported: built-in (
spec,teamcity,junit), Mocha-native (dot,nyan), and custom modules extendingMocha.reporters.Base. - Configuration occurs via
cypress.config.{js,ts}, the--reporterCLI flag, or thereporterOptionsobject. - Programmatic access to results is available through
Reporter.end(), which returns aReporterResultsobject containing stats, tests, and hooks arrays.
Frequently Asked Questions
What is the default Cypress reporter?
The spec reporter is the default output format. It displays nested test suites, test titles, pass/fail status, and duration in the console. According to the source code in packages/server/lib/reporter.ts, when no reporter is specified, the system defaults to this built-in implementation.
How do I configure reporter options in Cypress?
Reporter options are passed via the reporterOptions field in cypress.config.js or as a JSON string to the --reporter-options CLI flag. The Reporter.loadReporter() method parses these options and passes them to the reporter constructor, making them available in the options parameter of custom reporter classes.
Can I use multiple reporters simultaneously in Cypress?
The standard Reporter class in packages/server/lib/reporter.ts instantiates a single reporter per test run. To use multiple reporters, you must either create a custom reporter that composes multiple outputs, or run Cypress multiple times with different --reporter flags, as the internal architecture maintains a one-to-one relationship between the Reporter instance and the Mocha runner.
What data is available in the ReporterResults object?
The ReporterResults object returned by Reporter.end() contains five key properties: stats (aggregate counts), reporter (name string), reporterStats (raw Mocha data), tests (normalized array with titles, states, and errors), and hooks (hook execution records). These types are defined in packages/types/src/reporter.ts and normalized via normalizeTest() and normalizeHook() in the server reporter implementation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →