diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index 848d7f0e641..6d8e1c7e12e 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -30,6 +30,7 @@ import ( "time" "github.com/onsi/ginkgo/v2" + "github.com/onsi/ginkgo/v2/reporters" "github.com/onsi/ginkgo/v2/types" restclient "k8s.io/client-go/rest" @@ -356,14 +357,6 @@ func CreateGinkgoConfig() (types.SuiteConfig, types.ReporterConfig) { suiteConfig.RandomizeAllSpecs = true // Turn on verbose by default to get spec names reporterConfig.Verbose = true - // Enable JUnit output to the result directory, but only if not already specified - // via -junit-report. - if reporterConfig.JUnitReport == "" && TestContext.ReportDir != "" { - // With Ginkgo v1, we used to write one file per parallel node. Now Ginkgo v2 automatically - // merges all results into a single file for us. The 01 suffix is kept in case that users - // expect files to be called "junit_.xml". - reporterConfig.JUnitReport = path.Join(TestContext.ReportDir, "junit_"+TestContext.ReportPrefix+"01.xml") - } // Disable skipped tests unless they are explicitly requested. if len(suiteConfig.FocusStrings) == 0 && len(suiteConfig.SkipStrings) == 0 { suiteConfig.SkipStrings = []string{`\[Flaky\]|\[Feature:.+\]`} @@ -561,4 +554,54 @@ func AfterReadingAllFlags(t *TestContextType) { } os.Exit(1) } + + if TestContext.ReportDir != "" { + ginkgo.ReportAfterSuite("Kubernetes e2e JUnit report", writeJUnitReport) + } +} + +// writeJUnitReport generates a JUnit file in the e2e report directory that is +// shorter than the one normally written by `ginkgo --junit-report`. This is +// needed because the full report can become too large for tools like Spyglass +// (https://github.com/kubernetes/kubernetes/issues/111510). +// +// Users who want the full report can use `--junit-report`. +func writeJUnitReport(report ginkgo.Report) { + trimmedReport := report + trimmedReport.SpecReports = nil + for _, specReport := range report.SpecReports { + // Remove details for any spec that hasn't failed. In Prow, + // the test output captured in build-log.txt has all of this + // information, so we don't need it in the XML. + if specReport.State != types.SpecStateFailed { + specReport.CapturedGinkgoWriterOutput = "" + specReport.CapturedStdOutErr = "" + } + + // Remove report entries generated by ginkgo.By("doing + // something") because those are not useful (just have the + // start time) and cause Spyglass to show an additional "open + // stdout" button with a summary of the steps, which usually + // doesn't help. We don't remove all entries because other + // measurements also get reported this way. + // + // Removing the report entries is okay because message text was + // already added to the test output when ginkgo.By was called. + reportEntries := specReport.ReportEntries + specReport.ReportEntries = nil + for _, reportEntry := range reportEntries { + if reportEntry.Name != "By Step" { + specReport.ReportEntries = append(specReport.ReportEntries, reportEntry) + } + } + + trimmedReport.SpecReports = append(trimmedReport.SpecReports, specReport) + } + + // With Ginkgo v1, we used to write one file per parallel node. Now + // Ginkgo v2 automatically merges all results into a report for us. The + // 01 suffix is kept in case that users expect files to be called + // "junit_.xml". + junitReport := path.Join(TestContext.ReportDir, "junit_"+TestContext.ReportPrefix+"01.xml") + reporters.GenerateJUnitReport(trimmedReport, junitReport) }