build(deps): bump github.com/onsi/ginkgo/v2 from 2.25.3 to 2.26.0

Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.25.3 to 2.26.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.25.3...v2.26.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
dependabot[bot]
2025-10-02 17:10:28 +02:00
committed by Ralf Haferkamp
parent 4e06b0c376
commit 4c00db867c
56 changed files with 7287 additions and 3379 deletions
+6
View File
@@ -1,3 +1,9 @@
## 2.26.0
### Features
Ginkgo can now generate json-formatted reports that are compatible with the `go test` json format. Use `ginkgo --gojson-report=report.go.json`. This is not intended to be a replacement for Ginkgo's native json format which is more information rich and better models Ginkgo's test structure semantics.
## 2.25.3
### Fixes
+10
View File
@@ -113,3 +113,13 @@ Ginkgo is MIT-Licensed
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
## Sponsors
Sponsors commit to a [sponsorship](https://github.com/sponsors/onsi) for a year. If you're an organization that makes use of Ginkgo please consider becoming a sponsor!
<p style="font-size:21px; color:black;">Browser testing via
<a href="https://www.lambdatest.com/" target="_blank">
<img src="https://www.lambdatest.com/blue-logo.png" style="vertical-align: middle;" width="250" height="45" />
</a>
</p>
@@ -90,6 +90,9 @@ func FinalizeProfilesAndReportsForSuites(suites TestSuites, cliConfig types.CLIC
if reporterConfig.JSONReport != "" {
reportFormats = append(reportFormats, reportFormat{ReportName: reporterConfig.JSONReport, GenerateFunc: reporters.GenerateJSONReport, MergeFunc: reporters.MergeAndCleanupJSONReports})
}
if reporterConfig.GoJSONReport != "" {
reportFormats = append(reportFormats, reportFormat{ReportName: reporterConfig.GoJSONReport, GenerateFunc: reporters.GenerateGoTestJSONReport, MergeFunc: reporters.MergeAndCleanupGoTestJSONReports})
}
if reporterConfig.JUnitReport != "" {
reportFormats = append(reportFormats, reportFormat{ReportName: reporterConfig.JUnitReport, GenerateFunc: reporters.GenerateJUnitReport, MergeFunc: reporters.MergeAndCleanupJUnitReports})
}
+6
View File
@@ -107,6 +107,9 @@ func runSerial(suite TestSuite, ginkgoConfig types.SuiteConfig, reporterConfig t
if reporterConfig.JSONReport != "" {
reporterConfig.JSONReport = AbsPathForGeneratedAsset(reporterConfig.JSONReport, suite, cliConfig, 0)
}
if reporterConfig.GoJSONReport != "" {
reporterConfig.GoJSONReport = AbsPathForGeneratedAsset(reporterConfig.GoJSONReport, suite, cliConfig, 0)
}
if reporterConfig.JUnitReport != "" {
reporterConfig.JUnitReport = AbsPathForGeneratedAsset(reporterConfig.JUnitReport, suite, cliConfig, 0)
}
@@ -179,6 +182,9 @@ func runParallel(suite TestSuite, ginkgoConfig types.SuiteConfig, reporterConfig
if reporterConfig.JSONReport != "" {
reporterConfig.JSONReport = AbsPathForGeneratedAsset(reporterConfig.JSONReport, suite, cliConfig, 0)
}
if reporterConfig.GoJSONReport != "" {
reporterConfig.GoJSONReport = AbsPathForGeneratedAsset(reporterConfig.GoJSONReport, suite, cliConfig, 0)
}
if reporterConfig.JUnitReport != "" {
reporterConfig.JUnitReport = AbsPathForGeneratedAsset(reporterConfig.JUnitReport, suite, cliConfig, 0)
}
-1
View File
@@ -3,7 +3,6 @@ package main
import (
"fmt"
"os"
_ "go.uber.org/automaxprocs"
"github.com/onsi/ginkgo/v2/ginkgo/build"
"github.com/onsi/ginkgo/v2/ginkgo/command"
"github.com/onsi/ginkgo/v2/ginkgo/generators"
+8
View File
@@ -0,0 +1,8 @@
//go:build !go1.25
// +build !go1.25
package main
import (
_ "go.uber.org/automaxprocs"
)
+158
View File
@@ -0,0 +1,158 @@
package reporters
import (
"errors"
"fmt"
"strings"
"time"
"github.com/onsi/ginkgo/v2/types"
"golang.org/x/tools/go/packages"
)
func ptr[T any](in T) *T {
return &in
}
type encoder interface {
Encode(v any) error
}
// gojsonEvent matches the format from go internals
// https://github.com/golang/go/blob/master/src/cmd/internal/test2json/test2json.go#L31-L41
// https://pkg.go.dev/cmd/test2json
type gojsonEvent struct {
Time *time.Time `json:",omitempty"`
Action GoJSONAction
Package string `json:",omitempty"`
Test string `json:",omitempty"`
Elapsed *float64 `json:",omitempty"`
Output *string `json:",omitempty"`
FailedBuild string `json:",omitempty"`
}
type GoJSONAction string
const (
// start - the test binary is about to be executed
GoJSONStart GoJSONAction = "start"
// run - the test has started running
GoJSONRun GoJSONAction = "run"
// pause - the test has been paused
GoJSONPause GoJSONAction = "pause"
// cont - the test has continued running
GoJSONCont GoJSONAction = "cont"
// pass - the test passed
GoJSONPass GoJSONAction = "pass"
// bench - the benchmark printed log output but did not fail
GoJSONBench GoJSONAction = "bench"
// fail - the test or benchmark failed
GoJSONFail GoJSONAction = "fail"
// output - the test printed output
GoJSONOutput GoJSONAction = "output"
// skip - the test was skipped or the package contained no tests
GoJSONSkip GoJSONAction = "skip"
)
func goJSONActionFromSpecState(state types.SpecState) GoJSONAction {
switch state {
case types.SpecStateInvalid:
return GoJSONFail
case types.SpecStatePending:
return GoJSONSkip
case types.SpecStateSkipped:
return GoJSONSkip
case types.SpecStatePassed:
return GoJSONPass
case types.SpecStateFailed:
return GoJSONFail
case types.SpecStateAborted:
return GoJSONFail
case types.SpecStatePanicked:
return GoJSONFail
case types.SpecStateInterrupted:
return GoJSONFail
case types.SpecStateTimedout:
return GoJSONFail
default:
panic("unexpected state should not happen")
}
}
// gojsonReport wraps types.Report and calcualtes extra fields requires by gojson
type gojsonReport struct {
o types.Report
// Extra calculated fields
goPkg string
elapsed float64
}
func newReport(in types.Report) *gojsonReport {
return &gojsonReport{
o: in,
}
}
func (r *gojsonReport) Fill() error {
// NOTE: could the types.Report include the go package name?
goPkg, err := suitePathToPkg(r.o.SuitePath)
if err != nil {
return err
}
r.goPkg = goPkg
r.elapsed = r.o.RunTime.Seconds()
return nil
}
// gojsonSpecReport wraps types.SpecReport and calculates extra fields required by gojson
type gojsonSpecReport struct {
o types.SpecReport
// extra calculated fields
testName string
elapsed float64
action GoJSONAction
}
func newSpecReport(in types.SpecReport) *gojsonSpecReport {
return &gojsonSpecReport{
o: in,
}
}
func (sr *gojsonSpecReport) Fill() error {
sr.elapsed = sr.o.RunTime.Seconds()
sr.testName = createTestName(sr.o)
sr.action = goJSONActionFromSpecState(sr.o.State)
return nil
}
func suitePathToPkg(dir string) (string, error) {
cfg := &packages.Config{
Mode: packages.NeedFiles | packages.NeedSyntax,
}
pkgs, err := packages.Load(cfg, dir)
if err != nil {
return "", err
}
if len(pkgs) != 1 {
return "", errors.New("error")
}
return pkgs[0].ID, nil
}
func createTestName(spec types.SpecReport) string {
name := fmt.Sprintf("[%s]", spec.LeafNodeType)
if spec.FullText() != "" {
name = name + " " + spec.FullText()
}
labels := spec.Labels()
if len(labels) > 0 {
name = name + " [" + strings.Join(labels, ", ") + "]"
}
semVerConstraints := spec.SemVerConstraints()
if len(semVerConstraints) > 0 {
name = name + " [" + strings.Join(semVerConstraints, ", ") + "]"
}
name = strings.TrimSpace(name)
return name
}
@@ -0,0 +1,111 @@
package reporters
type GoJSONEventWriter struct {
enc encoder
specSystemErrFn specSystemExtractFn
specSystemOutFn specSystemExtractFn
}
func NewGoJSONEventWriter(enc encoder, errFn specSystemExtractFn, outFn specSystemExtractFn) *GoJSONEventWriter {
return &GoJSONEventWriter{
enc: enc,
specSystemErrFn: errFn,
specSystemOutFn: outFn,
}
}
func (r *GoJSONEventWriter) writeEvent(e *gojsonEvent) error {
return r.enc.Encode(e)
}
func (r *GoJSONEventWriter) WriteSuiteStart(report *gojsonReport) error {
e := &gojsonEvent{
Time: &report.o.StartTime,
Action: GoJSONStart,
Package: report.goPkg,
Output: nil,
FailedBuild: "",
}
return r.writeEvent(e)
}
func (r *GoJSONEventWriter) WriteSuiteResult(report *gojsonReport) error {
var action GoJSONAction
switch {
case report.o.PreRunStats.SpecsThatWillRun == 0:
action = GoJSONSkip
case report.o.SuiteSucceeded:
action = GoJSONPass
default:
action = GoJSONFail
}
e := &gojsonEvent{
Time: &report.o.EndTime,
Action: action,
Package: report.goPkg,
Output: nil,
FailedBuild: "",
Elapsed: ptr(report.elapsed),
}
return r.writeEvent(e)
}
func (r *GoJSONEventWriter) WriteSpecStart(report *gojsonReport, specReport *gojsonSpecReport) error {
e := &gojsonEvent{
Time: &specReport.o.StartTime,
Action: GoJSONRun,
Test: specReport.testName,
Package: report.goPkg,
Output: nil,
FailedBuild: "",
}
return r.writeEvent(e)
}
func (r *GoJSONEventWriter) WriteSpecOut(report *gojsonReport, specReport *gojsonSpecReport) error {
events := []*gojsonEvent{}
stdErr := r.specSystemErrFn(specReport.o)
if stdErr != "" {
events = append(events, &gojsonEvent{
Time: &specReport.o.EndTime,
Action: GoJSONOutput,
Test: specReport.testName,
Package: report.goPkg,
Output: ptr(stdErr),
FailedBuild: "",
})
}
stdOut := r.specSystemOutFn(specReport.o)
if stdOut != "" {
events = append(events, &gojsonEvent{
Time: &specReport.o.EndTime,
Action: GoJSONOutput,
Test: specReport.testName,
Package: report.goPkg,
Output: ptr(stdOut),
FailedBuild: "",
})
}
for _, ev := range events {
err := r.writeEvent(ev)
if err != nil {
return err
}
}
return nil
}
func (r *GoJSONEventWriter) WriteSpecResult(report *gojsonReport, specReport *gojsonSpecReport) error {
e := &gojsonEvent{
Time: &specReport.o.EndTime,
Action: specReport.action,
Test: specReport.testName,
Package: report.goPkg,
Elapsed: ptr(specReport.elapsed),
Output: nil,
FailedBuild: "",
}
return r.writeEvent(e)
}
+45
View File
@@ -0,0 +1,45 @@
package reporters
import (
"github.com/onsi/ginkgo/v2/types"
)
type GoJSONReporter struct {
ev *GoJSONEventWriter
}
type specSystemExtractFn func (spec types.SpecReport) string
func NewGoJSONReporter(enc encoder, errFn specSystemExtractFn, outFn specSystemExtractFn) *GoJSONReporter {
return &GoJSONReporter{
ev: NewGoJSONEventWriter(enc, errFn, outFn),
}
}
func (r *GoJSONReporter) Write(originalReport types.Report) error {
// suite start events
report := newReport(originalReport)
err := report.Fill()
if err != nil {
return err
}
r.ev.WriteSuiteStart(report)
for _, originalSpecReport := range originalReport.SpecReports {
specReport := newSpecReport(originalSpecReport)
err := specReport.Fill()
if err != nil {
return err
}
if specReport.o.LeafNodeType == types.NodeTypeIt {
// handle any It leaf node as a spec
r.ev.WriteSpecStart(report, specReport)
r.ev.WriteSpecOut(report, specReport)
r.ev.WriteSpecResult(report, specReport)
} else {
// handle any other leaf node as generic output
r.ev.WriteSpecOut(report, specReport)
}
}
r.ev.WriteSuiteResult(report)
return nil
}
+61
View File
@@ -0,0 +1,61 @@
package reporters
import (
"encoding/json"
"fmt"
"os"
"path"
"github.com/onsi/ginkgo/v2/internal/reporters"
"github.com/onsi/ginkgo/v2/types"
)
// GenerateGoTestJSONReport produces a JSON-formatted in the test2json format used by `go test -json`
func GenerateGoTestJSONReport(report types.Report, destination string) error {
// walk report and generate test2json-compatible objects
// JSON-encode the objects into filename
if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
return err
}
f, err := os.Create(destination)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
r := reporters.NewGoJSONReporter(
enc,
systemErrForUnstructuredReporters,
systemOutForUnstructuredReporters,
)
return r.Write(report)
}
// MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources
// It skips over reports that fail to decode but reports on them via the returned messages []string
func MergeAndCleanupGoTestJSONReports(sources []string, destination string) ([]string, error) {
messages := []string{}
if err := os.MkdirAll(path.Dir(destination), 0770); err != nil {
return messages, err
}
f, err := os.Create(destination)
if err != nil {
return messages, err
}
defer f.Close()
for _, source := range sources {
data, err := os.ReadFile(source)
if err != nil {
messages = append(messages, fmt.Sprintf("Could not open %s:\n%s", source, err.Error()))
continue
}
_, err = f.Write(data)
if err != nil {
messages = append(messages, fmt.Sprintf("Could not write to %s:\n%s", destination, err.Error()))
continue
}
os.Remove(source)
}
return messages, nil
}
+10 -1
View File
@@ -165,7 +165,7 @@ ReportAfterSuite nodes must be created at the top-level (i.e. not nested in a Co
When running in parallel, Ginkgo ensures that only one of the parallel nodes runs the ReportAfterSuite and that it is passed a report that is aggregated across
all parallel nodes
In addition to using ReportAfterSuite to programmatically generate suite reports, you can also generate JSON, JUnit, and Teamcity formatted reports using the --json-report, --junit-report, and --teamcity-report ginkgo CLI flags.
In addition to using ReportAfterSuite to programmatically generate suite reports, you can also generate JSON, GoJSON, JUnit, and Teamcity formatted reports using the --json-report, --gojson-report, --junit-report, and --teamcity-report ginkgo CLI flags.
You cannot nest any other Ginkgo nodes within a ReportAfterSuite node's closure.
You can learn more about ReportAfterSuite here: https://onsi.github.io/ginkgo/#generating-reports-programmatically
@@ -188,6 +188,12 @@ func registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig types.Re
Fail(fmt.Sprintf("Failed to generate JSON report:\n%s", err.Error()))
}
}
if reporterConfig.GoJSONReport != "" {
err := reporters.GenerateGoTestJSONReport(report, reporterConfig.GoJSONReport)
if err != nil {
Fail(fmt.Sprintf("Failed to generate Go JSON report:\n%s", err.Error()))
}
}
if reporterConfig.JUnitReport != "" {
err := reporters.GenerateJUnitReport(report, reporterConfig.JUnitReport)
if err != nil {
@@ -206,6 +212,9 @@ func registerReportAfterSuiteNodeForAutogeneratedReports(reporterConfig types.Re
if reporterConfig.JSONReport != "" {
flags = append(flags, "--json-report")
}
if reporterConfig.GoJSONReport != "" {
flags = append(flags, "--gojson-report")
}
if reporterConfig.JUnitReport != "" {
flags = append(flags, "--junit-report")
}
+4 -1
View File
@@ -96,6 +96,7 @@ type ReporterConfig struct {
ForceNewlines bool
JSONReport string
GoJSONReport string
JUnitReport string
TeamcityReport string
}
@@ -112,7 +113,7 @@ func (rc ReporterConfig) Verbosity() VerbosityLevel {
}
func (rc ReporterConfig) WillGenerateReport() bool {
return rc.JSONReport != "" || rc.JUnitReport != "" || rc.TeamcityReport != ""
return rc.JSONReport != "" || rc.GoJSONReport != "" || rc.JUnitReport != "" || rc.TeamcityReport != ""
}
func NewDefaultReporterConfig() ReporterConfig {
@@ -359,6 +360,8 @@ var ReporterConfigFlags = GinkgoFlags{
{KeyPath: "R.JSONReport", Name: "json-report", UsageArgument: "filename.json", SectionKey: "output",
Usage: "If set, Ginkgo will generate a JSON-formatted test report at the specified location."},
{KeyPath: "R.GoJSONReport", Name: "gojson-report", UsageArgument: "filename.json", SectionKey: "output",
Usage: "If set, Ginkgo will generate a Go JSON-formatted test report at the specified location."},
{KeyPath: "R.JUnitReport", Name: "junit-report", UsageArgument: "filename.xml", SectionKey: "output", DeprecatedName: "reportFile", DeprecatedDocLink: "improved-reporting-infrastructure",
Usage: "If set, Ginkgo will generate a conformant junit test report in the specified file."},
{KeyPath: "R.TeamcityReport", Name: "teamcity-report", UsageArgument: "filename", SectionKey: "output",
+1 -1
View File
@@ -1,3 +1,3 @@
package types
const VERSION = "2.25.3"
const VERSION = "2.26.0"