11package e2e
22
33import (
4+ "bytes"
45 "fmt"
6+ "io"
57 "log"
68 "os"
9+ "strings"
710 "testing"
811
912 "github.com/cucumber/godog"
@@ -14,52 +17,121 @@ import (
1417 "github.com/operator-framework/operator-controller/test/e2e/steps"
1518)
1619
17- var opts = godog.Options {
18- Format : "pretty" ,
19- Paths : []string {"features" },
20- Output : colors .Colored (os .Stdout ),
21- Concurrency : 1 ,
22- NoColors : true ,
20+ var defaultOpts = godog.Options {
21+ Format : "pretty" ,
22+ Paths : []string {"features" },
23+ Output : colors .Colored (os .Stdout ),
24+ NoColors : true ,
2325}
2426
2527func init () {
26- godog .BindCommandLineFlags ("godog." , & opts )
28+ godog .BindCommandLineFlags ("godog." , & defaultOpts )
2729}
2830
2931func TestMain (m * testing.M ) {
3032 // parse CLI arguments
3133 pflag .Parse ()
32- opts .Paths = pflag .Args ()
34+ defaultOpts .Paths = pflag .Args ()
3335
34- // run tests
35- sc := godog.TestSuite {
36+ // Create buffers to capture output for final summary
37+ var parallelBuf , serialBuf bytes.Buffer
38+
39+ parallelOpts := defaultOpts
40+ parallelOpts .Concurrency = 100
41+ parallelOpts .Tags = "~@Serial"
42+ parallelOpts .Randomize = - 1
43+ // Write to both stdout (live) and buffer (for summary)
44+ parallelOpts .Output = io .MultiWriter (os .Stdout , & parallelBuf )
45+ // run tests concurrently
46+ scParallel := godog.TestSuite {
47+ TestSuiteInitializer : InitializeSuite ,
48+ ScenarioInitializer : InitializeScenario ,
49+ Options : & parallelOpts ,
50+ }.Run ()
51+
52+ fmt .Println ("End of parallel run - beginning serial tests" )
53+
54+ serialOpts := defaultOpts
55+ serialOpts .Concurrency = 1
56+ serialOpts .Tags = "@Serial"
57+ // Write to both stdout (live) and buffer (for summary)
58+ serialOpts .Output = io .MultiWriter (os .Stdout , & serialBuf )
59+ // run tests serially
60+ scSerial := godog.TestSuite {
3661 TestSuiteInitializer : InitializeSuite ,
3762 ScenarioInitializer : InitializeScenario ,
38- Options : & opts ,
63+ Options : & serialOpts ,
3964 }.Run ()
4065
41- switch sc {
42- // 0 - success
43- case 0 :
44-
45- path := os .Getenv ("E2E_SUMMARY_OUTPUT" )
46- if path == "" {
47- fmt .Println ("Note: E2E_SUMMARY_OUTPUT is unset; skipping summary generation" )
48- } else {
49- if err := testutil .PrintSummary (path ); err != nil {
50- // Fail the run if alerts are found
51- fmt .Printf ("%v" , err )
52- os .Exit (1 )
53- }
66+ // TODO We re-print the output of any failed steps here for easier debugging. However, it would be
67+ // better to combine this with the E2E_SUMMARY_OUTPUT and show pass/fail + performance in one
68+ // markdown output then preserve the console output for local testing.
69+
70+ // Print aggregated summary
71+ fmt .Println ("\n " + strings .Repeat ("=" , 80 ))
72+ fmt .Println ("TEST EXECUTION SUMMARY" )
73+ fmt .Println (strings .Repeat ("=" , 80 ))
74+
75+ fmt .Printf ("\n Parallel Tests Exit Code: %d\n " , scParallel )
76+ if scParallel != 0 {
77+ failedSteps := extractFailedSteps (parallelBuf .String ())
78+ if failedSteps != "" {
79+ fmt .Println ("\n Parallel Test Failures:" )
80+ fmt .Println (strings .Repeat ("-" , 80 ))
81+ fmt .Println (failedSteps )
82+ }
83+ }
84+
85+ fmt .Printf ("\n Serial Tests Exit Code: %d\n " , scSerial )
86+ if scSerial != 0 {
87+ failedSteps := extractFailedSteps (serialBuf .String ())
88+ if failedSteps != "" {
89+ fmt .Println ("\n Serial Test Failures:" )
90+ fmt .Println (strings .Repeat ("-" , 80 ))
91+ fmt .Println (failedSteps )
92+ }
93+ }
94+
95+ fmt .Println (strings .Repeat ("=" , 80 ))
96+
97+ if scParallel != 0 || scSerial != 0 {
98+ // 1 - failed
99+ // 2 - command line usage error
100+ // 128 - or higher, os signal related error exit codes
101+ log .Fatalf ("non-zero status returned; parallel: (%d), serial: (%d), failed to run feature tests" , scParallel , scSerial )
102+ }
103+
104+ path := os .Getenv ("E2E_SUMMARY_OUTPUT" )
105+ if path == "" {
106+ fmt .Println ("Note: E2E_SUMMARY_OUTPUT is unset; skipping summary generation" )
107+ } else {
108+ if err := testutil .PrintSummary (path ); err != nil {
109+ // Fail the run if alerts are found
110+ fmt .Printf ("%v" , err )
111+ os .Exit (1 )
112+ }
113+ }
114+ }
115+
116+ // extractFailedSteps extracts the "--- Failed steps:" section from godog output
117+ func extractFailedSteps (output string ) string {
118+ lines := strings .Split (output , "\n " )
119+ var failedSection []string
120+ capturing := false
121+
122+ for _ , line := range lines {
123+ if strings .Contains (line , "--- Failed steps:" ) {
124+ capturing = true
125+ }
126+ if capturing {
127+ failedSection = append (failedSection , line )
54128 }
55- return
129+ }
56130
57- // 1 - failed
58- // 2 - command line usage error
59- // 128 - or higher, os signal related error exit codes
60- default :
61- log .Fatalf ("non-zero status returned (%d), failed to run feature tests" , sc )
131+ if len (failedSection ) == 0 {
132+ return ""
62133 }
134+ return strings .Join (failedSection , "\n " )
63135}
64136
65137func InitializeSuite (tc * godog.TestSuiteContext ) {
0 commit comments