diff --git a/cmd/container-structure-test/app/cmd/test.go b/cmd/container-structure-test/app/cmd/test.go index 14953622..069b1464 100644 --- a/cmd/container-structure-test/app/cmd/test.go +++ b/cmd/container-structure-test/app/cmd/test.go @@ -205,7 +205,7 @@ func run(out io.Writer) error { channel := make(chan interface{}, 1) go runTests(out, channel, args, driverImpl) // TODO(nkubala): put a sync.WaitGroup here - return test.ProcessResults(out, opts.Output, channel) + return test.ProcessResults(out, opts.Output, opts.JunitSuiteName, channel) } func runTests(out io.Writer, channel chan interface{}, args *drivers.DriverConfig, driverImpl func(drivers.DriverConfig) (drivers.Driver, error)) { @@ -246,6 +246,7 @@ func AddTestFlags(cmd *cobra.Command) { cmd.Flags().MarkDeprecated("json", "please use --output instead") cmd.Flags().VarP(&opts.Output, "output", "o", "output format for the test report (available format: text, json, junit)") cmd.Flags().BoolVar(&opts.NoColor, "no-color", false, "no color in the output") + cmd.Flags().StringVar(&opts.JunitSuiteName, "junit-suite-name", "", fmt.Sprintf("name to use for the junit test suite (defaults to '%s')", output.DefaultJunitSuiteName)) cmd.Flags().StringArrayVarP(&opts.ConfigFiles, "config", "c", []string{}, "test config files") cmd.MarkFlagRequired("config") diff --git a/cmd/container-structure-test/app/cmd/test/util.go b/cmd/container-structure-test/app/cmd/test/util.go index 801a64b1..ba912e34 100644 --- a/cmd/container-structure-test/app/cmd/test/util.go +++ b/cmd/container-structure-test/app/cmd/test/util.go @@ -105,7 +105,7 @@ func Parse(fp string, args *drivers.DriverConfig, driverImpl func(drivers.Driver return tests, nil } -func ProcessResults(out io.Writer, format unversioned.OutputValue, c chan interface{}) error { +func ProcessResults(out io.Writer, format unversioned.OutputValue, junitSuiteName string, c chan interface{}) error { totalPass := 0 totalFail := 0 totalDuration := time.Duration(0) @@ -143,7 +143,7 @@ func ProcessResults(out io.Writer, format unversioned.OutputValue, c chan interf // only output results here if we're in json mode summary.Results = results } - output.FinalResults(out, format, summary) + output.FinalResults(out, format, junitSuiteName, summary) return err } diff --git a/pkg/config/options.go b/pkg/config/options.go index ac1dbe9b..ae24c3c3 100644 --- a/pkg/config/options.go +++ b/pkg/config/options.go @@ -28,11 +28,12 @@ type StructureTestOptions struct { TestReport string ConfigFiles []string - JSON bool - Output unversioned.OutputValue - Pull bool - Save bool - Quiet bool - Force bool - NoColor bool + JSON bool + Output unversioned.OutputValue + JunitSuiteName string + Pull bool + Save bool + Quiet bool + Force bool + NoColor bool } diff --git a/pkg/output/output.go b/pkg/output/output.go index 500dd568..4bd69052 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -31,6 +31,15 @@ import ( var bannerLength = 27 // default banner length +const DefaultJunitSuiteName = "container-structure-test.test" + +func getJunitSuiteName(junitSuiteName string) string { + if junitSuiteName != "" { + return junitSuiteName + } + return DefaultJunitSuiteName +} + func OutputResult(out io.Writer, result *types.TestResult) { color.Default.Fprintf(out, "=== RUN: %s\n", result.Name) if result.Pass { @@ -58,7 +67,7 @@ func Banner(out io.Writer, filename string) { color.Purple.Fprintln(out, strings.Repeat("=", bannerLength)) } -func FinalResults(out io.Writer, format types.OutputValue, result types.SummaryObject) error { +func FinalResults(out io.Writer, format types.OutputValue, junitSuiteName string, result types.SummaryObject) error { if format == types.Json { res, err := json.Marshal(result) if err != nil { @@ -95,7 +104,7 @@ func FinalResults(out io.Writer, format types.OutputValue, result types.SummaryO Total: result.Total, Duration: time.Duration.Seconds(result.Duration), // JUnit expects durations as float of seconds TestSuite: types.JUnitTestSuite{ - Name: "container-structure-test.test", + Name: getJunitSuiteName(junitSuiteName), Results: junit_cases, }, } diff --git a/pkg/output/output_test.go b/pkg/output/output_test.go index a2ccae9f..8536d59c 100644 --- a/pkg/output/output_test.go +++ b/pkg/output/output_test.go @@ -36,19 +36,30 @@ func TestFinalResults(t *testing.T) { }, } + var customSuiteName = "custom-suite-name" + var finalResultsTests = []struct { actual *bytes.Buffer format unversioned.OutputValue + name string expected string }{ { actual: bytes.NewBuffer([]byte{}), format: unversioned.Junit, + name: "junit-default-suite-name", expected: `it works!this failed because of thatthis failed`, }, + { + actual: bytes.NewBuffer([]byte{}), + format: unversioned.Junit, + name: "junit-custom-suite-name", + expected: `it works!this failed because of thatthis failed`, + }, { actual: bytes.NewBuffer([]byte{}), format: unversioned.Json, + name: "json", expected: `{"Pass":1,"Fail":1,"Total":2,"Duration":2,"Results":[{"Name":"my first test","Pass":true,"Stdout":"it works!","Duration":1},{"Name":"my fail","Pass":false,"Stderr":"this failed","Errors":["this failed because of that"],"Duration":1}]}`, }, } @@ -56,10 +67,15 @@ func TestFinalResults(t *testing.T) { for _, test := range finalResultsTests { test := test - t.Run(test.format.String(), func(t *testing.T) { + t.Run(test.name, func(t *testing.T) { t.Parallel() - FinalResults(test.actual, test.format, result) + junitSuite := "" + if strings.Contains(test.name, customSuiteName) { + junitSuite = customSuiteName + } + + FinalResults(test.actual, test.format, junitSuite, result) if strings.TrimSpace(test.actual.String()) != test.expected { t.Errorf("expected %s but got %s", test.expected, test.actual)