or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcore-dsl.mddecorators.mdextensions.mdindex.mdreporters.mdreporting.mdtable-driven-testing.mdtypes.md
tile.json

reporters.mddocs/

Built-in Reporters

Ginkgo provides built-in reporters for generating test reports in various formats (JSON, JUnit XML, Teamcity) and supports custom reporters through the Reporter interface.

Report Generation Functions

GenerateJSONReport

Generates a JSON-formatted test report.

func GenerateJSONReport(report types.Report, destination string) error

Parameters:

  • report: Complete test suite report
  • destination: Output file path

Example:

import "github.com/onsi/ginkgo/v2/reporters"

ReportAfterSuite(func(report Report) {
    err := reporters.GenerateJSONReport(report, "results.json")
    if err != nil {
        fmt.Printf("Failed to generate JSON report: %v\n", err)
    }
})

GenerateGoTestJSONReport

Generates a report in Go's test JSON format (compatible with go test -json).

func GenerateGoTestJSONReport(report types.Report, destination string) error

Example:

ReportAfterSuite(func(report Report) {
    err := reporters.GenerateGoTestJSONReport(report, "go-test.json")
    if err != nil {
        fmt.Printf("Failed to generate Go JSON report: %v\n", err)
    }
})

GenerateJUnitReport

Generates a JUnit XML report.

func GenerateJUnitReport(report types.Report, dst string) error

Example:

ReportAfterSuite(func(report Report) {
    err := reporters.GenerateJUnitReport(report, "junit.xml")
    if err != nil {
        fmt.Printf("Failed to generate JUnit report: %v\n", err)
    }
})

GenerateJUnitReportWithConfig

Generates a JUnit XML report with custom configuration.

func GenerateJUnitReportWithConfig(
    report types.Report,
    dst string,
    config JunitReportConfig,
) error

Example:

config := reporters.JunitReportConfig{
    OmitTimelinesForSpecState: types.SpecStatePassed,
    OmitCapturedStdOutErr:     true,
    OmitSpecLabels:            false,
}

ReportAfterSuite(func(report Report) {
    err := reporters.GenerateJUnitReportWithConfig(
        report, "junit.xml", config)
    if err != nil {
        fmt.Printf("Failed to generate JUnit report: %v\n", err)
    }
})

GenerateTeamcityReport

Generates a Teamcity-formatted report.

func GenerateTeamcityReport(report types.Report, dst string) error

Example:

ReportAfterSuite(func(report Report) {
    err := reporters.GenerateTeamcityReport(report, "teamcity.txt")
    if err != nil {
        fmt.Printf("Failed to generate Teamcity report: %v\n", err)
    }
})

Report Merging Functions

When running tests in parallel, Ginkgo generates separate reports for each process. These functions merge and cleanup the individual reports.

MergeAndCleanupJSONReports

Merges multiple JSON reports into one and deletes the originals.

func MergeAndCleanupJSONReports(
    sources []string,
    destination string,
) ([]string, error)

Parameters:

  • sources: Paths to individual JSON report files
  • destination: Path for merged report

Returns:

  • Slice of successfully merged file paths
  • Error if merge fails

Example:

merged, err := reporters.MergeAndCleanupJSONReports(
    []string{"report-1.json", "report-2.json", "report-3.json"},
    "merged-report.json",
)
if err != nil {
    panic(err)
}
fmt.Printf("Merged %d reports\n", len(merged))

MergeAndCleanupGoTestJSONReports

Merges multiple Go test JSON reports.

func MergeAndCleanupGoTestJSONReports(
    sources []string,
    destination string,
) ([]string, error)

MergeAndCleanupJUnitReports

Merges multiple JUnit XML reports.

func MergeAndCleanupJUnitReports(
    sources []string,
    dst string,
) ([]string, error)

MergeAndCleanupTeamcityReports

Merges multiple Teamcity reports.

func MergeAndCleanupTeamcityReports(
    sources []string,
    dst string,
) ([]string, error)

JUnit Report Configuration

JunitReportConfig

Configuration for JUnit report generation.

type JunitReportConfig struct {
    OmitTimelinesForSpecState  types.SpecState
    OmitFailureMessageAttr     bool
    OmitCapturedStdOutErr      bool
    OmitSpecLabels             bool
    OmitSpecSemVerConstraints  bool
    OmitLeafNodeType           bool
    OmitSuiteSetupNodes        bool
}

Fields:

  • OmitTimelinesForSpecState: Don't include timelines for specs in these states
  • OmitFailureMessageAttr: Don't include message attribute in failure elements
  • OmitCapturedStdOutErr: Don't include captured stdout/stderr
  • OmitSpecLabels: Don't include labels in spec names
  • OmitSpecSemVerConstraints: Don't include version constraints in spec names
  • OmitLeafNodeType: Don't include node type in spec names
  • OmitSuiteSetupNodes: Don't create test case entries for suite setup nodes

Example:

// Minimal JUnit report (faster generation for large suites)
config := reporters.JunitReportConfig{
    OmitTimelinesForSpecState: types.SpecStatePassed | types.SpecStateSkipped,
    OmitCapturedStdOutErr:     true,
    OmitSpecLabels:            true,
    OmitSuiteSetupNodes:       true,
}

JUnit XML Types

These types represent the structure of JUnit XML reports.

JUnitTestSuites

Root element of JUnit XML report.

type JUnitTestSuites struct {
    XMLName    xml.Name
    Tests      int
    Disabled   int
    Errors     int
    Failures   int
    Time       float64
    TestSuites []JUnitTestSuite
}

JUnitTestSuite

Individual test suite in JUnit XML.

type JUnitTestSuite struct {
    Name       string
    Package    string
    Tests      int
    Disabled   int
    Skipped    int
    Errors     int
    Failures   int
    Time       float64
    Timestamp  string
    Properties JUnitProperties
    TestCases  []JUnitTestCase
}

JUnitTestCase

Individual test case in JUnit XML.

type JUnitTestCase struct {
    Name      string
    Classname string
    Status    string
    Time      float64
    Owner     string
    Skipped   *JUnitSkipped
    Error     *JUnitError
    Failure   *JUnitFailure
    SystemOut string
    SystemErr string
}

JUnitProperties

Properties collection in JUnit XML.

type JUnitProperties struct {
    Properties []JUnitProperty
}

Methods:

func (props JUnitProperties) WithName(name string) string

JUnitProperty

Individual property.

type JUnitProperty struct {
    Name  string
    Value string
}

JUnitSkipped

Skipped test information.

type JUnitSkipped struct {
    Message string
}

JUnitFailure

Failure information in JUnit XML.

type JUnitFailure struct {
    Message     string
    Type        string
    Description string
}

JUnitError

Error/panic information in JUnit XML.

type JUnitError struct {
    Message     string
    Type        string
    Description string
}

Custom Reporter Interface

Reporter

Interface for implementing custom reporters.

type Reporter interface {
    SuiteWillBegin(report types.Report)
    WillRun(report types.SpecReport)
    DidRun(report types.SpecReport)
    SuiteDidEnd(report types.Report)
    EmitFailure(state types.SpecState, failure types.Failure)
    EmitProgressReport(progressReport types.ProgressReport)
    EmitReportEntry(entry types.ReportEntry)
    EmitSpecEvent(event types.SpecEvent)
}

Example Custom Reporter:

type CustomReporter struct {
    startTime time.Time
    specCount int
}

func (r *CustomReporter) SuiteWillBegin(report types.Report) {
    r.startTime = time.Now()
    fmt.Printf("Starting suite: %s\n", report.SuiteDescription)
    fmt.Printf("Will run %d specs\n", report.PreRunStats.SpecsThatWillRun)
}

func (r *CustomReporter) WillRun(report types.SpecReport) {
    fmt.Printf("Running: %s\n", report.FullText())
}

func (r *CustomReporter) DidRun(report types.SpecReport) {
    r.specCount++
    if report.Failed() {
        fmt.Printf("FAILED: %s\n", report.FullText())
        fmt.Printf("  Error: %s\n", report.Failure.Message)
    } else {
        fmt.Printf("PASSED: %s (%v)\n", report.FullText(), report.RunTime)
    }
}

func (r *CustomReporter) SuiteDidEnd(report types.Report) {
    duration := time.Since(r.startTime)
    fmt.Printf("Suite completed in %v\n", duration)
    fmt.Printf("Ran %d specs\n", r.specCount)
    fmt.Printf("Success: %v\n", report.SuiteSucceeded)
}

func (r *CustomReporter) EmitFailure(
    state types.SpecState,
    failure types.Failure,
) {
    fmt.Printf("Failure emitted: %s\n", failure.Message)
}

func (r *CustomReporter) EmitProgressReport(
    progressReport types.ProgressReport,
) {
    fmt.Printf("Progress: %s\n", progressReport.CurrentNodeText)
}

func (r *CustomReporter) EmitReportEntry(entry types.ReportEntry) {
    fmt.Printf("Report Entry: %s = %v\n", entry.Name, entry.Value)
}

func (r *CustomReporter) EmitSpecEvent(event types.SpecEvent) {
    fmt.Printf("Spec Event: %s\n", event.Message)
}

// Use the custom reporter
func TestMyPackage(t *testing.T) {
    RegisterFailHandler(Fail)
    customReporter := &CustomReporter{}
    RunSpecs(t, "My Suite", Label("custom"), customReporter)
}

NoopReporter

A no-operation reporter that does nothing. Useful as a base for custom reporters.

type NoopReporter struct{}

Methods:

func (r NoopReporter) SuiteWillBegin(report types.Report)
func (r NoopReporter) WillRun(report types.SpecReport)
func (r NoopReporter) DidRun(report types.SpecReport)
func (r NoopReporter) SuiteDidEnd(report types.Report)
func (r NoopReporter) EmitFailure(state types.SpecState, failure types.Failure)
func (r NoopReporter) EmitProgressReport(progressReport types.ProgressReport)
func (r NoopReporter) EmitReportEntry(entry types.ReportEntry)
func (r NoopReporter) EmitSpecEvent(event types.SpecEvent)

Example:

type MyReporter struct {
    reporters.NoopReporter // Embed to inherit no-op methods
}

// Only override methods you care about
func (r *MyReporter) DidRun(report types.SpecReport) {
    if report.Failed() {
        sendAlertToSlack(report)
    }
}

DefaultReporter

Ginkgo's default console reporter.

type DefaultReporter struct{}

Constructors:

func NewDefaultReporter(
    conf types.ReporterConfig,
    writer io.Writer,
) *DefaultReporter

func NewDefaultReporterUnderTest(
    conf types.ReporterConfig,
    writer io.Writer,
) *DefaultReporter

Methods:

func (r *DefaultReporter) SuiteWillBegin(report types.Report)
func (r *DefaultReporter) WillRun(report types.SpecReport)
func (r *DefaultReporter) DidRun(report types.SpecReport)
func (r *DefaultReporter) SuiteDidEnd(report types.Report)
func (r *DefaultReporter) EmitFailure(state types.SpecState, failure types.Failure)
func (r *DefaultReporter) EmitProgressReport(report types.ProgressReport)
func (r *DefaultReporter) EmitReportEntry(entry types.ReportEntry)
func (r *DefaultReporter) EmitSpecEvent(event types.SpecEvent)

Utility Functions

RenderTimeline

Renders a spec timeline as a formatted string.

func RenderTimeline(spec types.SpecReport, noColor bool) string

Example:

ReportAfterEach(func(report SpecReport) {
    if report.Failed() {
        timeline := reporters.RenderTimeline(report, false)
        fmt.Println(timeline)
    }
})

Deprecated Reporter Support

ReportViaDeprecatedReporter

Calls a V1-style custom reporter (for backward compatibility).

func ReportViaDeprecatedReporter(
    reporter DeprecatedReporter,
    report types.Report,
)

DeprecatedReporter

V1 reporter interface (deprecated).

type DeprecatedReporter interface {
    SuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary)
    BeforeSuiteDidRun(setupSummary *types.SetupSummary)
    SpecWillRun(specSummary *types.SpecSummary)
    SpecDidComplete(specSummary *types.SpecSummary)
    AfterSuiteDidRun(setupSummary *types.SetupSummary)
    SuiteDidEnd(summary *types.SuiteSummary)
}

Practical Examples

Multiple Report Formats

func TestMyPackage(t *testing.T) {
    RegisterFailHandler(Fail)
    RunSpecs(t, "My Package Suite")
}

var _ = ReportAfterSuite(func(report Report) {
    // Generate all report formats
    reporters.GenerateJSONReport(report, "results.json")
    reporters.GenerateJUnitReport(report, "junit.xml")
    reporters.GenerateTeamcityReport(report, "teamcity.txt")
})

// Or use CLI flags:
// ginkgo --json-report=results.json --junit-report=junit.xml

Conditional Report Generation

var _ = ReportAfterSuite(func(report Report) {
    // Only generate detailed reports on failure
    if !report.SuiteSucceeded {
        config := reporters.JunitReportConfig{
            OmitTimelinesForSpecState: types.SpecStateNone,
            OmitCapturedStdOutErr:     false,
        }
        reporters.GenerateJUnitReportWithConfig(
            report, "detailed-junit.xml", config)
    } else {
        // Minimal report on success
        config := reporters.JunitReportConfig{
            OmitTimelinesForSpecState: types.SpecStatePassed,
            OmitCapturedStdOutErr:     true,
        }
        reporters.GenerateJUnitReportWithConfig(
            report, "minimal-junit.xml", config)
    }
})

Custom Reporter with Metrics

type MetricsReporter struct {
    reporters.NoopReporter
    metrics map[string]time.Duration
}

func NewMetricsReporter() *MetricsReporter {
    return &MetricsReporter{
        metrics: make(map[string]time.Duration),
    }
}

func (r *MetricsReporter) DidRun(report types.SpecReport) {
    r.metrics[report.FullText()] = report.RunTime
}

func (r *MetricsReporter) SuiteDidEnd(report types.Report) {
    // Send metrics to monitoring system
    for spec, duration := range r.metrics {
        sendMetric("test.duration", duration, map[string]string{
            "spec": spec,
        })
    }
}

func TestWithMetrics(t *testing.T) {
    RegisterFailHandler(Fail)
    metricsReporter := NewMetricsReporter()
    RunSpecs(t, "Suite with Metrics", metricsReporter)
}