How to use NewDefaultReporterUnderTest method of reporters Package

Best Ginkgo code snippet using reporters.NewDefaultReporterUnderTest

Run Ginkgo automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

default_reporter_test.go

Source: default_reporter_test.go Github

copy
1package reporters_test
2
3import (
4	"reflect"
5	"runtime"
6	"strings"
7	"time"
8
9	. "github.com/onsi/ginkgo/v2"
10	"github.com/onsi/ginkgo/v2/internal"
11	"github.com/onsi/ginkgo/v2/internal/test_helpers"
12	"github.com/onsi/ginkgo/v2/reporters"
13	"github.com/onsi/ginkgo/v2/types"
14	. "github.com/onsi/gomega"
15	"github.com/onsi/gomega/format"
16	"github.com/onsi/gomega/gbytes"
17)
18
19type StackTrace string
20
21const DELIMITER = `{{gray}}------------------------------{{/}}`
22
23var cl0 = types.CodeLocation{FileName: "cl0.go", LineNumber: 12, FullStackTrace: "full-trace\ncl-0"}
24var cl1 = types.CodeLocation{FileName: "cl1.go", LineNumber: 37, FullStackTrace: "full-trace\ncl-1"}
25var cl2 = types.CodeLocation{FileName: "cl2.go", LineNumber: 80, FullStackTrace: "full-trace\ncl-2"}
26var cl3 = types.CodeLocation{FileName: "cl3.go", LineNumber: 103, FullStackTrace: "full-trace\ncl-3"}
27var cl4 = types.CodeLocation{FileName: "cl4.go", LineNumber: 144, FullStackTrace: "full-trace\ncl-4"}
28
29func CLS(cls ...types.CodeLocation) []types.CodeLocation { return cls }
30func CTS(componentTexts ...string) []string              { return componentTexts }
31func CLabels(labels ...Labels) []Labels                  { return labels }
32
33type FailureNodeLocation types.CodeLocation
34type ForwardedPanic string
35
36var PLACEHOLDER_TIME = time.Now()
37var FORMATTED_TIME = PLACEHOLDER_TIME.Format(types.GINKGO_TIME_FORMAT)
38
39// convenience helper to quickly make Failures
40func F(options ...interface{}) types.Failure {
41	failure := types.Failure{}
42	for _, option := range options {
43		switch reflect.TypeOf(option) {
44		case reflect.TypeOf(""):
45			failure.Message = option.(string)
46		case reflect.TypeOf(types.CodeLocation{}):
47			failure.Location = option.(types.CodeLocation)
48		case reflect.TypeOf(ForwardedPanic("")):
49			failure.ForwardedPanic = string(option.(ForwardedPanic))
50		case reflect.TypeOf(types.FailureNodeInContainer):
51			failure.FailureNodeContext = option.(types.FailureNodeContext)
52		case reflect.TypeOf(0):
53			failure.FailureNodeContainerIndex = option.(int)
54		case reflect.TypeOf(FailureNodeLocation{}):
55			failure.FailureNodeLocation = types.CodeLocation(option.(FailureNodeLocation))
56		case reflect.TypeOf(types.NodeTypeIt):
57			failure.FailureNodeType = option.(types.NodeType)
58		}
59	}
60	return failure
61}
62
63type STD string
64type GW string
65
66// convenience helper to quickly make summaries
67func S(options ...interface{}) types.SpecReport {
68	report := types.SpecReport{
69		LeafNodeType: types.NodeTypeIt,
70		State:        types.SpecStatePassed,
71		NumAttempts:  1,
72		RunTime:      time.Second,
73	}
74	for _, option := range options {
75		switch reflect.TypeOf(option) {
76		case reflect.TypeOf([]string{}):
77			report.ContainerHierarchyTexts = option.([]string)
78		case reflect.TypeOf([]types.CodeLocation{}):
79			report.ContainerHierarchyLocations = option.([]types.CodeLocation)
80		case reflect.TypeOf([]Labels{}):
81			report.ContainerHierarchyLabels = [][]string{}
82			for _, labels := range option.([]Labels) {
83				report.ContainerHierarchyLabels = append(report.ContainerHierarchyLabels, []string(labels))
84			}
85		case reflect.TypeOf(""):
86			report.LeafNodeText = option.(string)
87		case reflect.TypeOf(types.NodeTypeIt):
88			report.LeafNodeType = option.(types.NodeType)
89		case reflect.TypeOf(types.CodeLocation{}):
90			report.LeafNodeLocation = option.(types.CodeLocation)
91		case reflect.TypeOf(Labels{}):
92			report.LeafNodeLabels = []string(option.(Labels))
93		case reflect.TypeOf(types.SpecStatePassed):
94			report.State = option.(types.SpecState)
95		case reflect.TypeOf(time.Second):
96			report.RunTime = option.(time.Duration)
97		case reflect.TypeOf(types.Failure{}):
98			report.Failure = option.(types.Failure)
99		case reflect.TypeOf(0):
100			report.NumAttempts = option.(int)
101		case reflect.TypeOf(STD("")):
102			report.CapturedStdOutErr = string(option.(STD))
103		case reflect.TypeOf(GW("")):
104			report.CapturedGinkgoWriterOutput = string(option.(GW))
105		case reflect.TypeOf(types.ReportEntry{}):
106			report.ReportEntries = append(report.ReportEntries, option.(types.ReportEntry))
107		}
108	}
109	if len(report.ContainerHierarchyLabels) == 0 {
110		for range report.ContainerHierarchyTexts {
111			report.ContainerHierarchyLabels = append(report.ContainerHierarchyLabels, []string{})
112		}
113	}
114	return report
115}
116
117func RE(name string, cl types.CodeLocation, args ...interface{}) types.ReportEntry {
118	entry, _ := internal.NewReportEntry(name, cl, args...)
119	entry.Time = PLACEHOLDER_TIME
120	return entry
121}
122
123type ConfigFlags uint8
124
125const (
126	Succinct ConfigFlags = 1 << iota
127	Verbose
128	VeryVerbose
129	ReportPassed
130	FullTrace
131)
132
133func (cf ConfigFlags) Has(flag ConfigFlags) bool { return cf&flag != 0 }
134
135func C(flags ...ConfigFlags) types.ReporterConfig {
136	f := ConfigFlags(0)
137	if len(flags) > 0 {
138		f = flags[0]
139	}
140	Ω(f.Has(Verbose) && f.Has(Succinct)).Should(BeFalse(), "Setting more than one of Succinct, Verbose, or VeryVerbose is a configuration error")
141	Ω(f.Has(VeryVerbose) && f.Has(Succinct)).Should(BeFalse(), "Setting more than one of Succinct, Verbose, or VeryVerbose is a configuration error")
142	Ω(f.Has(VeryVerbose) && f.Has(Verbose)).Should(BeFalse(), "Setting more than one of Succinct, Verbose, or VeryVerbose is a configuration error")
143	return types.ReporterConfig{
144		NoColor:                true,
145		SlowSpecThreshold:      SlowSpecThreshold,
146		Succinct:               f.Has(Succinct),
147		Verbose:                f.Has(Verbose),
148		VeryVerbose:            f.Has(VeryVerbose),
149		AlwaysEmitGinkgoWriter: f.Has(ReportPassed),
150		FullTrace:              f.Has(FullTrace),
151	}
152}
153
154const SlowSpecThreshold = 3 * time.Second
155
156var _ = Describe("DefaultReporter", func() {
157	var DENOTER = "•"
158	var RETRY_DENOTER = "↺"
159	if runtime.GOOS == "windows" {
160		DENOTER = "+"
161		RETRY_DENOTER = "R"
162	}
163
164	var buf *gbytes.Buffer
165	verifyExpectedOutput := func(expected []string) {
166		if len(expected) == 0 {
167			ExpectWithOffset(1, buf.Contents()).Should(BeEmpty())
168		} else {
169			ExpectWithOffset(1, string(buf.Contents())).Should(Equal(strings.Join(expected, "\n")), test_helpers.MultilneTextHelper(string(buf.Contents())))
170		}
171	}
172
173	BeforeEach(func() {
174		buf = gbytes.NewBuffer()
175		format.CharactersAroundMismatchToInclude = 100
176	})
177
178	DescribeTable("Rendering SuiteWillBegin",
179		func(conf types.ReporterConfig, report types.Report, expected ...string) {
180			reporter := reporters.NewDefaultReporterUnderTest(conf, buf)
181			reporter.SuiteWillBegin(report)
182			verifyExpectedOutput(expected)
183		},
184		Entry("Default Behavior",
185			C(),
186			types.Report{
187				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
188				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
189			},
190			"Running Suite: My Suite - /path/to/suite",
191			"========================================",
192			"Random Seed: {{bold}}17{{/}}",
193			"",
194			"Will run {{bold}}15{{/}} of {{bold}}20{{/}} specs",
195			"",
196		),
197		Entry("With Labels",
198			C(),
199			types.Report{
200				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", SuiteLabels: []string{"dog", "fish"}, PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
201				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
202			},
203			"Running Suite: My Suite - /path/to/suite",
204			"{{coral}}[dog, fish]{{/}} ",
205			"========================================",
206			"Random Seed: {{bold}}17{{/}}",
207			"",
208			"Will run {{bold}}15{{/}} of {{bold}}20{{/}} specs",
209			"",
210		),
211		Entry("With long Labels",
212			C(),
213			types.Report{
214				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", SuiteLabels: []string{"dog", "fish", "kalamazoo", "kangaroo", "chicken", "asparagus"}, PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
215				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
216			},
217			"Running Suite: My Suite - /path/to/suite",
218			"{{coral}}[dog, fish, kalamazoo, kangaroo, chicken, asparagus]{{/}} ",
219			"====================================================",
220			"Random Seed: {{bold}}17{{/}}",
221			"",
222			"Will run {{bold}}15{{/}} of {{bold}}20{{/}} specs",
223			"",
224		),
225		Entry("When configured to randomize all specs",
226			C(),
227			types.Report{
228				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
229				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1, RandomizeAllSpecs: true},
230			},
231			"Running Suite: My Suite - /path/to/suite",
232			"========================================",
233			"Random Seed: {{bold}}17{{/}} - will randomize all specs",
234			"",
235			"Will run {{bold}}15{{/}} of {{bold}}20{{/}} specs",
236			"",
237		),
238		Entry("when configured to run in parallel",
239			C(),
240			types.Report{
241				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
242				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 3},
243			},
244			"Running Suite: My Suite - /path/to/suite",
245			"========================================",
246			"Random Seed: {{bold}}17{{/}}",
247			"",
248			"Will run {{bold}}15{{/}} of {{bold}}20{{/}} specs",
249			"Running in parallel across {{bold}}3{{/}} processes",
250			"",
251		),
252		Entry("when succinct and in series",
253			C(Succinct),
254			types.Report{
255				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
256				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 1},
257			},
258			"[17] {{bold}}My Suite{{/}} - 15/20 specs ",
259		),
260		Entry("when succinct and in parallel",
261			C(Succinct),
262			types.Report{
263				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
264				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 3},
265			},
266			"[17] {{bold}}My Suite{{/}} - 15/20 specs - 3 procs ",
267		),
268
269		Entry("when succinct and with labels",
270			C(Succinct),
271			types.Report{
272				SuiteDescription: "My Suite", SuitePath: "/path/to/suite", SuiteLabels: Label("dog, fish"), PreRunStats: types.PreRunStats{SpecsThatWillRun: 15, TotalSpecs: 20},
273				SuiteConfig: types.SuiteConfig{RandomSeed: 17, ParallelTotal: 3},
274			},
275			"[17] {{bold}}My Suite{{/}} {{coral}}[dog, fish]{{/}} - 15/20 specs - 3 procs ",
276		),
277	)
278
279	DescribeTable("WillRun",
280		func(conf types.ReporterConfig, report types.SpecReport, output ...string) {
281			reporter := reporters.NewDefaultReporterUnderTest(conf, buf)
282			reporter.WillRun(report)
283			verifyExpectedOutput(output)
284		},
285		Entry("when not verbose, it emits nothing", C(), S(CTS("A"), CLS(cl0))),
286		Entry("pending specs are not emitted", C(Verbose), S(types.SpecStatePending)),
287		Entry("skipped specs are not emitted", C(Verbose), S(types.SpecStateSkipped)),
288		Entry("setup nodes", C(Verbose),
289			S(types.NodeTypeBeforeSuite, cl0),
290			DELIMITER,
291			"{{bold}}[BeforeSuite] {{/}}",
292			"{{gray}}"+cl0.String()+"{{/}}",
293			"",
294		),
295		Entry("ReportAfterSuite nodes", C(Verbose),
296			S("my report", cl0, types.NodeTypeReportAfterSuite),
297			DELIMITER,
298			"{{bold}}[ReportAfterSuite] my report{{/}}",
299			"{{gray}}"+cl0.String()+"{{/}}",
300			"",
301		),
302		Entry("top-level it nodes", C(Verbose),
303			S("My Test", cl0),
304			DELIMITER,
305			"{{bold}}My Test{{/}}",
306			"{{gray}}"+cl0.String()+"{{/}}",
307			"",
308		),
309		Entry("nested it nodes", C(Verbose),
310			S(CTS("Container", "Nested Container"), "My Test", CLS(cl0, cl1), cl2),
311			DELIMITER,
312			"{{/}}Container {{gray}}Nested Container{{/}}",
313			"  {{bold}}My Test{{/}}",
314			"  {{gray}}"+cl2.String()+"{{/}}",
315			"",
316		),
317		Entry("specs with labels", C(Verbose),
318			S(CTS("Container", "Nested Container"), "My Test", CLS(cl0, cl1), cl2, CLabels(Label("dog", "cat"), Label("cat", "fruit")), Label("giraffe", "gorilla", "cat")),
319			DELIMITER,
320			"{{/}}Container {{gray}}Nested Container{{/}}",
321			"  {{bold}}My Test{{/}} {{coral}}[dog, cat, fruit, giraffe, gorilla]{{/}}",
322			"  {{gray}}"+cl2.String()+"{{/}}",
323			"",
324		),
325	)
326
327	DescribeTable("DidRun",
328		func(conf types.ReporterConfig, report types.SpecReport, output ...string) {
329			reporter := reporters.NewDefaultReporterUnderTest(conf, buf)
330			reporter.DidRun(report)
331			verifyExpectedOutput(output)
332		},
333		// Passing Tests
334		Entry("a passing test",
335			C(),
336			S("A", cl0),
337			"{{green}}"+DENOTER+"{{/}}",
338		),
339		Entry("a passing test that was retried",
340			C(),
341			S(CTS("A"), "B", CLS(cl0), cl1, 2),
342			DELIMITER,
343			"{{green}}"+RETRY_DENOTER+" [FLAKEY TEST - TOOK 2 ATTEMPTS TO PASS] [1.000 seconds]{{/}}",
344			"{{/}}A {{gray}}B{{/}}",
345			"{{gray}}"+cl1.String()+"{{/}}",
346			DELIMITER,
347			"",
348		),
349		Entry("a passing test that has ginkgo writer output and/or non-visible report entries",
350			C(),
351			S("A", cl0, GW("GINKGO-WRITER-OUTPUT"), RE("fail-report-name", cl1, types.ReportEntryVisibilityFailureOrVerbose), RE("hidden-report-name", cl2, types.ReportEntryVisibilityNever)),
352			"{{green}}"+DENOTER+"{{/}}",
353		),
354		Entry("a passing test that has ginkgo writer output, with ReportPassed configured",
355			C(ReportPassed),
356			S(CTS("A"), "B", CLS(cl0), cl1, GW("GINKGO-WRITER-OUTPUT\nSHOULD EMIT")),
357			DELIMITER,
358			"{{green}}"+DENOTER+" [1.000 seconds]{{/}}",
359			"{{/}}A {{gray}}B{{/}}",
360			"{{gray}}"+cl1.String()+"{{/}}",
361			"",
362			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
363			"    GINKGO-WRITER-OUTPUT",
364			"    SHOULD EMIT",
365			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
366			DELIMITER,
367			"",
368		),
369		Entry("a passing test that has ginkgo writer output and a FailurOrVerbose entry, with Verbose configured",
370			C(Verbose),
371			S("A", cl0, GW("GINKGO-WRITER-OUTPUT\nSHOULD EMIT"), RE("failure-or-verbose-report-name", cl1, types.ReportEntryVisibilityFailureOrVerbose), RE("hidden-report-name", cl2, types.ReportEntryVisibilityNever)),
372			DELIMITER,
373			"{{green}}"+DENOTER+" [1.000 seconds]{{/}}",
374			"A",
375			"{{gray}}"+cl0.String()+"{{/}}",
376			"",
377			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
378			"    GINKGO-WRITER-OUTPUT",
379			"    SHOULD EMIT",
380			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
381			"",
382			"  {{gray}}Begin Report Entries >>{{/}}",
383			"    {{bold}}failure-or-verbose-report-name{{gray}} - "+cl1.String()+" @ "+FORMATTED_TIME+"{{/}}",
384			"  {{gray}}<< End Report Entries{{/}}",
385			DELIMITER,
386			"",
387		),
388		Entry("a slow passing test",
389			C(),
390			S(CTS("A"), "B", CLS(cl0), cl1, time.Minute, GW("GINKGO-WRITER-OUTPUT")),
391			DELIMITER,
392			"{{green}}"+DENOTER+" [SLOW TEST] [60.000 seconds]{{/}}",
393			"{{/}}A {{gray}}B{{/}}",
394			"{{gray}}"+cl1.String()+"{{/}}",
395			DELIMITER,
396			"",
397		),
398		Entry("a passing test with captured stdout",
399			C(),
400			S(CTS("A"), "B", CLS(cl0), cl1, GW("GINKGO-WRITER-OUTPUT"), STD("STD-OUTPUT\nSHOULD EMIT")),
401			DELIMITER,
402			"{{green}}"+DENOTER+" [1.000 seconds]{{/}}",
403			"{{/}}A {{gray}}B{{/}}",
404			"{{gray}}"+cl1.String()+"{{/}}",
405			"",
406			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
407			"    STD-OUTPUT",
408			"    SHOULD EMIT",
409			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
410			DELIMITER,
411			"",
412		),
413		Entry("a passing test with a ReportEntry that is always visible",
414			C(),
415			S(CTS("A"), "B", CLS(cl0), cl1, GW("GINKGO-WRITER-OUTPUT"), RE("report-name", cl2, "report-content"), RE("other-report-name", cl3), RE("fail-report-name", cl4, types.ReportEntryVisibilityFailureOrVerbose)),
416			DELIMITER,
417			"{{green}}"+DENOTER+" [1.000 seconds]{{/}}",
418			"{{/}}A {{gray}}B{{/}}",
419			"{{gray}}"+cl1.String()+"{{/}}",
420			"",
421			"  {{gray}}Begin Report Entries >>{{/}}",
422			"    {{bold}}report-name{{gray}} - "+cl2.String()+" @ "+FORMATTED_TIME+"{{/}}",
423			"      report-content",
424			"    {{bold}}other-report-name{{gray}} - "+cl3.String()+" @ "+FORMATTED_TIME+"{{/}}",
425			"  {{gray}}<< End Report Entries{{/}}",
426			DELIMITER,
427			"",
428		),
429		Entry("a passing suite setup emits nothing",
430			C(),
431			S(types.NodeTypeBeforeSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
432		),
433		Entry("a passing suite setup with verbose always emits",
434			C(Verbose),
435			S(types.NodeTypeBeforeSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
436			DELIMITER,
437			"{{green}}[BeforeSuite] PASSED [1.000 seconds]{{/}}",
438			"[BeforeSuite] ",
439			"{{gray}}"+cl0.String()+"{{/}}",
440			"",
441			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
442			"    GINKGO-WRITER-OUTPUT",
443			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
444			DELIMITER,
445			"",
446		),
447		Entry("a passing suite setup with captured stdout always emits",
448			C(),
449			S(types.NodeTypeBeforeSuite, cl0, STD("STD-OUTPUT")),
450			DELIMITER,
451			"{{green}}[BeforeSuite] PASSED [1.000 seconds]{{/}}",
452			"{{/}}[BeforeSuite] {{/}}",
453			"{{gray}}"+cl0.String()+"{{/}}",
454			"",
455			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
456			"    STD-OUTPUT",
457			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
458			DELIMITER,
459			"",
460		),
461		Entry("a passing ReportAfterSuite emits nothing",
462			C(),
463			S("my report", types.NodeTypeReportAfterSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
464		),
465		Entry("a passing ReportAfterSuite with verbose always emits",
466			C(Verbose),
467			S("my report", types.NodeTypeReportAfterSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
468			DELIMITER,
469			"{{green}}[ReportAfterSuite] PASSED [1.000 seconds]{{/}}",
470			"[ReportAfterSuite] my report",
471			"{{gray}}"+cl0.String()+"{{/}}",
472			"",
473			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
474			"    GINKGO-WRITER-OUTPUT",
475			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
476			DELIMITER,
477			"",
478		),
479		Entry("a passing ReportAfterSuite with captured stdout always emits",
480			C(),
481			S("my report", types.NodeTypeReportAfterSuite, cl0, STD("STD-OUTPUT")),
482			DELIMITER,
483			"{{green}}[ReportAfterSuite] PASSED [1.000 seconds]{{/}}",
484			"{{/}}[ReportAfterSuite] my report{{/}}",
485			"{{gray}}"+cl0.String()+"{{/}}",
486			"",
487			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
488			"    STD-OUTPUT",
489			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
490			DELIMITER,
491			"",
492		),
493		Entry("a passing ReportAfterSuite with verbose always emits",
494			C(Verbose),
495			S("my report", types.NodeTypeReportAfterSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
496			DELIMITER,
497			"{{green}}[ReportAfterSuite] PASSED [1.000 seconds]{{/}}",
498			"[ReportAfterSuite] my report",
499			"{{gray}}"+cl0.String()+"{{/}}",
500			"",
501			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
502			"    GINKGO-WRITER-OUTPUT",
503			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
504			DELIMITER,
505			"",
506		),
507		Entry("a passing Suite-level DeferCleanup emits nothing",
508			C(),
509			S(types.NodeTypeCleanupAfterSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
510		),
511		Entry("a passing Suite-level DeferCleanup with verbose always emits",
512			C(Verbose),
513			S(types.NodeTypeCleanupAfterSuite, cl0, GW("GINKGO-WRITER-OUTPUT")),
514			DELIMITER,
515			"{{green}}[DeferCleanup (Suite)] PASSED [1.000 seconds]{{/}}",
516			"[DeferCleanup (Suite)] ",
517			"{{gray}}cl0.go:12{{/}}",
518			"",
519			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
520			"    GINKGO-WRITER-OUTPUT",
521			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
522			DELIMITER,
523			"",
524		),
525
526		// Pending Tests
527		Entry("a pending test when succinct",
528			C(Succinct),
529			S("A", cl0, types.SpecStatePending, GW("GW-OUTPUT"), STD("STD-OUTPUT")),
530			"{{yellow}}P{{/}}",
531		),
532		Entry("a pending test normally",
533			C(),
534			S("A", cl0, types.SpecStatePending, GW("GW-OUTPUT")),
535			DELIMITER,
536			"{{yellow}}P [PENDING]{{/}}",
537			"{{/}}A{{/}}",
538			"{{gray}}cl0.go:12{{/}}",
539			DELIMITER,
540			"",
541		),
542
543		Entry("a pending test when verbose",
544			C(Verbose),
545			S("A", cl0, types.SpecStatePending, GW("GW-OUTPUT")),
546			DELIMITER,
547			"{{yellow}}P [PENDING]{{/}}",
548			"{{/}}A{{/}}",
549			"{{gray}}cl0.go:12{{/}}",
550			DELIMITER,
551			"",
552		),
553		Entry("a pending test when very verbose",
554			C(VeryVerbose),
555			S(CTS("A"), "B", CLS(cl0), cl1, types.SpecStatePending, GW("GW-OUTPUT"), STD("STD-OUTPUT")),
556			DELIMITER,
557			"{{yellow}}P [PENDING]{{/}}",
558			"A",
559			"{{gray}}"+cl0.String()+"{{/}}",
560			"  B",
561			"  {{gray}}"+cl1.String()+"{{/}}",
562			"",
563			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
564			"    STD-OUTPUT",
565			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
566			DELIMITER,
567			"",
568		),
569		// Skipped Tests
570		Entry("a skipped test without a failure message when succinct",
571			C(Succinct),
572			S("A", cl0, types.SpecStateSkipped, GW("GW-OUTPUT")),
573			"{{cyan}}S{{/}}",
574		),
575		Entry("a skipped test without a failure message",
576			C(),
577			S("A", cl0, types.SpecStateSkipped, GW("GW-OUTPUT")),
578			"{{cyan}}S{{/}}",
579		),
580		Entry("a skipped test without a failure message when verbose",
581			C(Verbose),
582			S("A", cl0, types.SpecStateSkipped, GW("GW-OUTPUT")),
583			"{{cyan}}S{{/}}",
584		),
585		Entry("a skipped test without a failure message when very verbose",
586			C(VeryVerbose),
587			S("A", cl0, types.SpecStateSkipped, GW("GW-OUTPUT")),
588			"{{gray}}------------------------------{{/}}",
589			"{{cyan}}S [SKIPPED] [1.000 seconds]{{/}}",
590			"A",
591			"{{gray}}cl0.go:12{{/}}",
592			"",
593			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
594			"    GW-OUTPUT",
595			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
596			"{{gray}}------------------------------{{/}}",
597			"",
598		),
599		Entry("a skipped test with a failure message when succinct",
600			C(Succinct),
601			S(CTS("A"), "B", CLS(cl0), cl1, types.SpecStateSkipped, GW("GW-OUTPUT"), STD("STD-OUTPUT"),
602				F("user skipped", types.FailureNodeIsLeafNode, types.NodeTypeIt, FailureNodeLocation(cl1), cl2),
603			),
604			DELIMITER,
605			"{{cyan}}S [SKIPPED] [1.000 seconds]{{/}}",
606			"{{/}}A {{gray}}{{cyan}}{{bold}}[It] B{{/}}{{/}}",
607			"{{gray}}"+cl1.String()+"{{/}}",
608			"",
609			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
610			"    STD-OUTPUT",
611			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
612			"",
613			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
614			"    GW-OUTPUT",
615			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
616			"",
617			"  {{cyan}}user skipped{{/}}",
618			"  {{cyan}}In {{bold}}[It]{{/}}{{cyan}} at: {{bold}}"+cl2.String()+"{{/}}",
619			DELIMITER,
620			"",
621		),
622		Entry("a skipped test with a failure message and normal verbosity",
623			C(),
624			S(CTS("A"), "B", CLS(cl0), cl1, types.SpecStateSkipped, GW("GW-OUTPUT"), STD("STD-OUTPUT"),
625				F("user skipped", types.FailureNodeIsLeafNode, types.NodeTypeIt, FailureNodeLocation(cl1), cl2),
626			),
627			DELIMITER,
628			"{{cyan}}S [SKIPPED] [1.000 seconds]{{/}}",
629			"A",
630			"{{gray}}"+cl0.String()+"{{/}}",
631			"  {{cyan}}{{bold}}[It] B{{/}}",
632			"  {{gray}}"+cl1.String()+"{{/}}",
633			"",
634			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
635			"    STD-OUTPUT",
636			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
637			"",
638			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
639			"    GW-OUTPUT",
640			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
641			"",
642			"  {{cyan}}user skipped{{/}}",
643			"  {{cyan}}In {{bold}}[It]{{/}}{{cyan}} at: {{bold}}"+cl2.String()+"{{/}}",
644			DELIMITER,
645			"",
646		),
647		Entry("a skipped test with a failure message and verbose",
648			C(Verbose),
649			S(CTS("A"), "B", CLS(cl0), cl1, types.SpecStateSkipped, GW("GW-OUTPUT"), STD("STD-OUTPUT"),
650				F("user skipped", types.FailureNodeIsLeafNode, types.NodeTypeIt, FailureNodeLocation(cl1), cl2),
651			),
652			DELIMITER,
653			"{{cyan}}S [SKIPPED] [1.000 seconds]{{/}}",
654			"A",
655			"{{gray}}"+cl0.String()+"{{/}}",
656			"  {{cyan}}{{bold}}[It] B{{/}}",
657			"  {{gray}}"+cl1.String()+"{{/}}",
658			"",
659			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
660			"    STD-OUTPUT",
661			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
662			"",
663			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
664			"    GW-OUTPUT",
665			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
666			"",
667			"  {{cyan}}user skipped{{/}}",
668			"  {{cyan}}In {{bold}}[It]{{/}}{{cyan}} at: {{bold}}"+cl2.String()+"{{/}}",
669			DELIMITER,
670			"",
671		),
672		Entry("a skipped test with a failure message and very verbose",
673			C(VeryVerbose),
674			S(CTS("A"), "B", CLS(cl0), cl1, types.SpecStateSkipped, GW("GW-OUTPUT"), STD("STD-OUTPUT"),
675				F("user skipped", types.FailureNodeIsLeafNode, types.NodeTypeIt, FailureNodeLocation(cl1), cl2),
676			),
677			DELIMITER,
678			"{{cyan}}S [SKIPPED] [1.000 seconds]{{/}}",
679			"A",
680			"{{gray}}"+cl0.String()+"{{/}}",
681			"  {{cyan}}{{bold}}[It] B{{/}}",
682			"  {{gray}}"+cl1.String()+"{{/}}",
683			"",
684			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
685			"    STD-OUTPUT",
686			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
687			"",
688			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
689			"    GW-OUTPUT",
690			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
691			"",
692			"  {{cyan}}user skipped{{/}}",
693			"  {{cyan}}In {{bold}}[It]{{/}}{{cyan}} at: {{bold}}"+cl2.String()+"{{/}}",
694			DELIMITER,
695			"",
696		),
697		//Failed tests
698		Entry("when a test has failed in an It",
699			C(),
700			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2, CLabels(Label("dog", "cat"), Label("cat", "cow")),
701				types.SpecStateFailed, 2,
702				Label("cow", "fish"),
703				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
704				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, types.NodeTypeIt, FailureNodeLocation(cl2), cl3),
705				RE("report-name", cl4, "report-content"),
706				RE("fail-report-name", cl4, "fail-report-content", types.ReportEntryVisibilityFailureOrVerbose),
707				RE("hidden-report-name", cl4, "hidden-report-content", types.ReportEntryVisibilityNever),
708			),
709			DELIMITER,
710			"{{red}}"+DENOTER+" [FAILED] [1.000 seconds]{{/}}",
711			"Describe A {{coral}}[dog, cat]{{/}}",
712			"{{gray}}"+cl0.String()+"{{/}}",
713			"  Context B {{coral}}[cat, cow]{{/}}",
714			"  {{gray}}"+cl1.String()+"{{/}}",
715			"    {{red}}{{bold}}[It] The Test{{/}} {{coral}}[cow, fish]{{/}}",
716			"    {{gray}}"+cl2.String()+"{{/}}",
717			"",
718			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
719			"    STD-OUTPUT",
720			"    IS EMITTED",
721			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
722			"",
723			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
724			"    GW-OUTPUT",
725			"    IS EMITTED",
726			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
727			"",
728			"  {{gray}}Begin Report Entries >>{{/}}",
729			"    {{bold}}report-name{{gray}} - "+cl4.String()+" @ "+FORMATTED_TIME+"{{/}}",
730			"      report-content",
731			"    {{bold}}fail-report-name{{gray}} - "+cl4.String()+" @ "+FORMATTED_TIME+"{{/}}",
732			"      fail-report-content",
733			"  {{gray}}<< End Report Entries{{/}}",
734			"",
735			"  {{red}}FAILURE MESSAGE",
736			"  WITH DETAILS{{/}}",
737			"  {{red}}In {{bold}}[It]{{/}}{{red}} at: {{bold}}"+cl3.String()+"{{/}}",
738			DELIMITER,
739			"",
740		),
741		Entry("when a test has failed in a setup/teardown node",
742			C(),
743			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
744				types.SpecStateFailed, 2,
745				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
746				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
747			),
748			DELIMITER,
749			"{{red}}"+DENOTER+" [FAILED] [1.000 seconds]{{/}}",
750			"Describe A",
751			"{{gray}}"+cl0.String()+"{{/}}",
752			"  {{red}}{{bold}}Context B [JustBeforeEach]{{/}}",
753			"  {{gray}}"+cl3.String()+"{{/}}",
754			"    The Test",
755			"    {{gray}}"+cl2.String()+"{{/}}",
756			"",
757			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
758			"    STD-OUTPUT",
759			"    IS EMITTED",
760			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
761			"",
762			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
763			"    GW-OUTPUT",
764			"    IS EMITTED",
765			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
766			"",
767			"  {{red}}FAILURE MESSAGE",
768			"  WITH DETAILS{{/}}",
769			"  {{red}}In {{bold}}[JustBeforeEach]{{/}}{{red}} at: {{bold}}"+cl4.String()+"{{/}}",
770			DELIMITER,
771			"",
772		),
773		Entry("when a test has failed in a setup/teardown node defined at the top level",
774			C(),
775			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
776				types.SpecStateFailed, 2,
777				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
778				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeAtTopLevel, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
779			),
780			DELIMITER,
781			"{{red}}"+DENOTER+" [FAILED] [1.000 seconds]{{/}}",
782			"{{red}}{{bold}}TOP-LEVEL [JustBeforeEach]{{/}}",
783			"{{gray}}"+cl3.String()+"{{/}}",
784			"  Describe A",
785			"  {{gray}}"+cl0.String()+"{{/}}",
786			"    Context B",
787			"    {{gray}}"+cl1.String()+"{{/}}",
788			"      The Test",
789			"      {{gray}}"+cl2.String()+"{{/}}",
790			"",
791			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
792			"    STD-OUTPUT",
793			"    IS EMITTED",
794			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
795			"",
796			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
797			"    GW-OUTPUT",
798			"    IS EMITTED",
799			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
800			"",
801			"  {{red}}FAILURE MESSAGE",
802			"  WITH DETAILS{{/}}",
803			"  {{red}}In {{bold}}[JustBeforeEach]{{/}}{{red}} at: {{bold}}"+cl4.String()+"{{/}}",
804			DELIMITER,
805			""),
806		Entry("when a test has failed in a setup/teardown node and Succinct is configured",
807			C(Succinct),
808			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
809				types.SpecStateFailed, 2,
810				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
811				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
812			),
813			DELIMITER,
814			"{{red}}"+DENOTER+" [FAILED] [1.000 seconds]{{/}}",
815			"{{/}}Describe A {{gray}}{{red}}{{bold}}Context B [JustBeforeEach]{{/}} {{/}}The Test{{/}}",
816			"{{gray}}"+cl2.String()+"{{/}}",
817			"",
818			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
819			"    STD-OUTPUT",
820			"    IS EMITTED",
821			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
822			"",
823			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
824			"    GW-OUTPUT",
825			"    IS EMITTED",
826			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
827			"",
828			"  {{red}}FAILURE MESSAGE",
829			"  WITH DETAILS{{/}}",
830			"  {{red}}In {{bold}}[JustBeforeEach]{{/}}{{red}} at: {{bold}}"+cl4.String()+"{{/}}",
831			DELIMITER,
832			"",
833		),
834		Entry("when a test has failed and FullTrace is configured",
835			C(FullTrace),
836			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
837				types.SpecStateFailed, 2,
838				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
839				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
840			),
841			DELIMITER,
842			"{{red}}"+DENOTER+" [FAILED] [1.000 seconds]{{/}}",
843			"Describe A",
844			"{{gray}}"+cl0.String()+"{{/}}",
845			"  {{red}}{{bold}}Context B [JustBeforeEach]{{/}}",
846			"  {{gray}}"+cl3.String()+"{{/}}",
847			"    The Test",
848			"    {{gray}}"+cl2.String()+"{{/}}",
849			"",
850			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
851			"    STD-OUTPUT",
852			"    IS EMITTED",
853			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
854			"",
855			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
856			"    GW-OUTPUT",
857			"    IS EMITTED",
858			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
859			"",
860			"  {{red}}FAILURE MESSAGE",
861			"  WITH DETAILS{{/}}",
862			"  {{red}}In {{bold}}[JustBeforeEach]{{/}}{{red}} at: {{bold}}"+cl4.String()+"{{/}}",
863			"",
864			"  {{red}}Full Stack Trace{{/}}",
865			"    full-trace",
866			"    cl-4",
867			DELIMITER,
868			"",
869		),
870		Entry("when a suite setup node has failed",
871			C(),
872			S(types.NodeTypeSynchronizedBeforeSuite, cl0, types.SpecStateFailed, 1,
873				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
874				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeSynchronizedBeforeSuite, 1, cl1),
875			),
876			DELIMITER,
877			"{{red}}[SynchronizedBeforeSuite] [FAILED] [1.000 seconds]{{/}}",
878			"{{red}}{{bold}}[SynchronizedBeforeSuite] {{/}}",
879			"{{gray}}"+cl0.String()+"{{/}}",
880			"",
881			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
882			"    STD-OUTPUT",
883			"    IS EMITTED",
884			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
885			"",
886			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
887			"    GW-OUTPUT",
888			"    IS EMITTED",
889			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
890			"",
891			"  {{red}}FAILURE MESSAGE",
892			"  WITH DETAILS{{/}}",
893			"  {{red}}In {{bold}}[SynchronizedBeforeSuite]{{/}}{{red}} at: {{bold}}"+cl1.String()+"{{/}}",
894			DELIMITER,
895			"",
896		),
897		Entry("when a ReportAfterSuite node has failed",
898			C(),
899			S("my report", cl0, types.NodeTypeReportAfterSuite, types.SpecStateFailed, 1,
900				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
901				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeReportAfterSuite, 1, cl1),
902			),
903			DELIMITER,
904			"{{red}}[ReportAfterSuite] [FAILED] [1.000 seconds]{{/}}",
905			"{{red}}{{bold}}[ReportAfterSuite] my report{{/}}",
906			"{{gray}}"+cl0.String()+"{{/}}",
907			"",
908			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
909			"    STD-OUTPUT",
910			"    IS EMITTED",
911			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
912			"",
913			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
914			"    GW-OUTPUT",
915			"    IS EMITTED",
916			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
917			"",
918			"  {{red}}FAILURE MESSAGE",
919			"  WITH DETAILS{{/}}",
920			"  {{red}}In {{bold}}[ReportAfterSuite]{{/}}{{red}} at: {{bold}}"+cl1.String()+"{{/}}",
921			DELIMITER,
922			"",
923		),
924
925		Entry("when a test has panicked and there is no forwarded panic",
926			C(),
927			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
928				types.SpecStatePanicked, 2,
929				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
930				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
931			),
932			DELIMITER,
933			"{{magenta}}"+DENOTER+"! [PANICKED] [1.000 seconds]{{/}}",
934			"Describe A",
935			"{{gray}}"+cl0.String()+"{{/}}",
936			"  {{magenta}}{{bold}}Context B [JustBeforeEach]{{/}}",
937			"  {{gray}}"+cl3.String()+"{{/}}",
938			"    The Test",
939			"    {{gray}}"+cl2.String()+"{{/}}",
940			"",
941			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
942			"    STD-OUTPUT",
943			"    IS EMITTED",
944			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
945			"",
946			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
947			"    GW-OUTPUT",
948			"    IS EMITTED",
949			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
950			"",
951			"  {{magenta}}FAILURE MESSAGE",
952			"  WITH DETAILS{{/}}",
953			"  {{magenta}}In {{bold}}[JustBeforeEach]{{/}}{{magenta}} at: {{bold}}"+cl4.String()+"{{/}}",
954			DELIMITER,
955			"",
956		),
957		Entry("when a test has panicked and there is a forwarded panic",
958			C(),
959			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
960				types.SpecStatePanicked, 2,
961				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
962				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4, ForwardedPanic("the panic\nthusly forwarded")),
963			),
964			DELIMITER,
965			"{{magenta}}"+DENOTER+"! [PANICKED] [1.000 seconds]{{/}}",
966			"Describe A",
967			"{{gray}}"+cl0.String()+"{{/}}",
968			"  {{magenta}}{{bold}}Context B [JustBeforeEach]{{/}}",
969			"  {{gray}}"+cl3.String()+"{{/}}",
970			"    The Test",
971			"    {{gray}}"+cl2.String()+"{{/}}",
972			"",
973			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
974			"    STD-OUTPUT",
975			"    IS EMITTED",
976			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
977			"",
978			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
979			"    GW-OUTPUT",
980			"    IS EMITTED",
981			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
982			"",
983			"  {{magenta}}FAILURE MESSAGE",
984			"  WITH DETAILS{{/}}",
985			"  {{magenta}}In {{bold}}[JustBeforeEach]{{/}}{{magenta}} at: {{bold}}"+cl4.String()+"{{/}}",
986			"",
987			"  {{magenta}}the panic",
988			"  thusly forwarded{{/}}",
989			"",
990			"  {{magenta}}Full Stack Trace{{/}}",
991			"    full-trace",
992			"    cl-4",
993			DELIMITER,
994			"",
995		),
996
997		Entry("when a test is interrupted",
998			C(),
999			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
1000				types.SpecStateInterrupted, 2,
1001				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
1002				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
1003			),
1004			DELIMITER,
1005			"{{orange}}"+DENOTER+"! [INTERRUPTED] [1.000 seconds]{{/}}",
1006			"Describe A",
1007			"{{gray}}"+cl0.String()+"{{/}}",
1008			"  {{orange}}{{bold}}Context B [JustBeforeEach]{{/}}",
1009			"  {{gray}}"+cl3.String()+"{{/}}",
1010			"    The Test",
1011			"    {{gray}}"+cl2.String()+"{{/}}",
1012			"",
1013			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
1014			"    STD-OUTPUT",
1015			"    IS EMITTED",
1016			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
1017			"",
1018			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
1019			"    GW-OUTPUT",
1020			"    IS EMITTED",
1021			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
1022			"",
1023			"  {{orange}}FAILURE MESSAGE",
1024			"  WITH DETAILS{{/}}",
1025			"  {{orange}}In {{bold}}[JustBeforeEach]{{/}}{{orange}} at: {{bold}}"+cl4.String()+"{{/}}",
1026			DELIMITER,
1027			"",
1028		),
1029
1030		Entry("when a test is aborted",
1031			C(),
1032			S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
1033				types.SpecStateAborted, 2,
1034				GW("GW-OUTPUT\nIS EMITTED"), STD("STD-OUTPUT\nIS EMITTED"),
1035				F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
1036			),
1037			DELIMITER,
1038			"{{coral}}"+DENOTER+"! [ABORTED] [1.000 seconds]{{/}}",
1039			"Describe A",
1040			"{{gray}}"+cl0.String()+"{{/}}",
1041			"  {{coral}}{{bold}}Context B [JustBeforeEach]{{/}}",
1042			"  {{gray}}"+cl3.String()+"{{/}}",
1043			"    The Test",
1044			"    {{gray}}"+cl2.String()+"{{/}}",
1045			"",
1046			"  {{gray}}Begin Captured StdOut/StdErr Output >>{{/}}",
1047			"    STD-OUTPUT",
1048			"    IS EMITTED",
1049			"  {{gray}}<< End Captured StdOut/StdErr Output{{/}}",
1050			"",
1051			"  {{gray}}Begin Captured GinkgoWriter Output >>{{/}}",
1052			"    GW-OUTPUT",
1053			"    IS EMITTED",
1054			"  {{gray}}<< End Captured GinkgoWriter Output{{/}}",
1055			"",
1056			"  {{coral}}FAILURE MESSAGE",
1057			"  WITH DETAILS{{/}}",
1058			"  {{coral}}In {{bold}}[JustBeforeEach]{{/}}{{coral}} at: {{bold}}"+cl4.String()+"{{/}}",
1059			DELIMITER,
1060			"",
1061		))
1062
1063	DescribeTable("Rendering SuiteDidEnd",
1064		func(conf types.ReporterConfig, report types.Report, expected ...string) {
1065			reporter := reporters.NewDefaultReporterUnderTest(conf, buf)
1066			reporter.SuiteDidEnd(report)
1067			verifyExpectedOutput(expected)
1068		},
1069
1070		Entry("when configured to be succinct",
1071			C(Succinct),
1072			types.Report{
1073				SuiteSucceeded: true,
1074				RunTime:        time.Minute,
1075				SpecReports:    types.SpecReports{S()},
1076			},
1077			" {{green}}SUCCESS!{{/}} 1m0s ",
1078		),
1079		Entry("the suite passes",
1080			C(),
1081			types.Report{
1082				SuiteSucceeded: true,
1083				PreRunStats:    types.PreRunStats{TotalSpecs: 8, SpecsThatWillRun: 8},
1084				RunTime:        time.Minute,
1085				SpecReports: types.SpecReports{
1086					S(types.NodeTypeBeforeSuite),
1087					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1088					S(types.SpecStatePending), S(types.SpecStatePending),
1089					S(types.SpecStateSkipped), S(types.SpecStateSkipped), S(types.SpecStateSkipped),
1090					S(types.NodeTypeAfterSuite),
1091				},
1092			},
1093			"",
1094			"{{green}}{{bold}}Ran 3 of 8 Specs in 60.000 seconds{{/}}",
1095			"{{green}}{{bold}}SUCCESS!{{/}} -- {{green}}{{bold}}3 Passed{{/}} | {{red}}{{bold}}0 Failed{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}3 Skipped{{/}}",
1096			"",
1097		),
1098		Entry("the suite passes and has flaky specs",
1099			C(),
1100			types.Report{
1101				SuiteSucceeded: true,
1102				PreRunStats:    types.PreRunStats{TotalSpecs: 10, SpecsThatWillRun: 8},
1103				RunTime:        time.Minute,
1104				SpecReports: types.SpecReports{
1105					S(types.NodeTypeBeforeSuite),
1106					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1107					S(types.SpecStatePassed, 3), S(types.SpecStatePassed, 4), //flakey
1108					S(types.SpecStatePending), S(types.SpecStatePending),
1109					S(types.SpecStateSkipped), S(types.SpecStateSkipped), S(types.SpecStateSkipped),
1110					S(types.NodeTypeAfterSuite),
1111				},
1112			},
1113			"",
1114			"{{green}}{{bold}}Ran 5 of 10 Specs in 60.000 seconds{{/}}",
1115			"{{green}}{{bold}}SUCCESS!{{/}} -- {{green}}{{bold}}5 Passed{{/}} | {{red}}{{bold}}0 Failed{{/}} | {{light-yellow}}{{bold}}2 Flaked{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}3 Skipped{{/}}",
1116			"",
1117		),
1118		Entry("the suite fails with one failed test",
1119			C(),
1120			types.Report{
1121				SuiteSucceeded: false,
1122				PreRunStats:    types.PreRunStats{TotalSpecs: 11, SpecsThatWillRun: 9},
1123				RunTime:        time.Minute,
1124				SpecReports: types.SpecReports{
1125					S(types.NodeTypeBeforeSuite),
1126					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1127					S(types.SpecStatePassed, 3), S(types.SpecStatePassed, 4), //flakey
1128					S(types.SpecStatePending), S(types.SpecStatePending),
1129					S(types.SpecStateSkipped), S(types.SpecStateSkipped), S(types.SpecStateSkipped),
1130					S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2,
1131						types.SpecStateFailed, 2,
1132						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
1133					),
1134					S(types.NodeTypeAfterSuite),
1135				},
1136			},
1137			"",
1138			"{{red}}{{bold}}Ran 6 of 11 Specs in 60.000 seconds{{/}}",
1139			"{{red}}{{bold}}FAIL!{{/}} -- {{green}}{{bold}}5 Passed{{/}} | {{red}}{{bold}}1 Failed{{/}} | {{light-yellow}}{{bold}}2 Flaked{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}3 Skipped{{/}}",
1140			"",
1141		),
1142		Entry("the suite fails with multiple failed tests",
1143			C(),
1144			types.Report{
1145				SuiteSucceeded: false,
1146				PreRunStats:    types.PreRunStats{TotalSpecs: 13, SpecsThatWillRun: 9},
1147				RunTime:        time.Minute,
1148				SpecReports: types.SpecReports{
1149					S(types.NodeTypeBeforeSuite),
1150					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1151					S(types.SpecStatePassed, 3), S(types.SpecStatePassed, 4), //flakey
1152					S(types.SpecStatePending), S(types.SpecStatePending),
1153					S(types.SpecStateSkipped), S(types.SpecStateSkipped), S(types.SpecStateSkipped),
1154					S(CTS("Describe A", "Context B"), "The Test", CLS(cl0, cl1), cl2, CLabels(Label("cat", "dog"), Label("dog", "fish")), Label("fish", "giraffe"),
1155						types.SpecStateFailed, 2,
1156						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeInContainer, FailureNodeLocation(cl3), types.NodeTypeJustBeforeEach, 1, cl4),
1157					),
1158					S(CTS("Describe A"), "The Test", CLS(cl0), cl1,
1159						types.SpecStatePanicked, 2,
1160						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl1), types.NodeTypeIt, cl2),
1161					),
1162					S("The Test", cl0,
1163						types.SpecStateInterrupted, 2,
1164						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, cl1),
1165					),
1166					S("The Test", cl0,
1167						types.SpecStateAborted, 2,
1168						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeIt, cl1),
1169					),
1170					S(types.NodeTypeAfterSuite),
1171				},
1172			},
1173			"",
1174			"",
1175			"{{red}}{{bold}}Summarizing 4 Failures:{{/}}",
1176			"  {{red}}[FAIL]{{/}} {{/}}Describe A {{gray}}{{red}}{{bold}}Context B [JustBeforeEach]{{/}} {{/}}The Test{{/}} {{coral}}[cat, dog, fish, giraffe]{{/}}",
1177			"  {{gray}}"+cl4.String()+"{{/}}",
1178			"  {{magenta}}[PANICKED!]{{/}} {{/}}Describe A {{gray}}{{magenta}}{{bold}}[It] The Test{{/}}{{/}}",
1179			"  {{gray}}"+cl2.String()+"{{/}}",
1180			"  {{orange}}[INTERRUPTED]{{/}} {{/}}{{orange}}{{bold}}[It] The Test{{/}}{{/}}",
1181			"  {{gray}}"+cl1.String()+"{{/}}",
1182			"  {{coral}}[ABORTED]{{/}} {{/}}{{coral}}{{bold}}[It] The Test{{/}}{{/}}",
1183			"  {{gray}}"+cl1.String()+"{{/}}",
1184			"",
1185			"{{red}}{{bold}}Ran 9 of 13 Specs in 60.000 seconds{{/}}",
1186			"{{red}}{{bold}}FAIL!{{/}} -- {{green}}{{bold}}5 Passed{{/}} | {{red}}{{bold}}4 Failed{{/}} | {{light-yellow}}{{bold}}2 Flaked{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}3 Skipped{{/}}",
1187			"",
1188		),
1189		Entry("the suite fails with failed suite setups",
1190			C(),
1191			types.Report{
1192				SuiteSucceeded: false,
1193				PreRunStats:    types.PreRunStats{TotalSpecs: 10, SpecsThatWillRun: 5},
1194				RunTime:        time.Minute,
1195				SpecReports: types.SpecReports{
1196					S(types.NodeTypeBeforeSuite, cl0, types.SpecStateFailed, 2,
1197						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl0), types.NodeTypeBeforeSuite, 1, cl1),
1198					),
1199					S(types.NodeTypeAfterSuite, cl2, types.SpecStateFailed, 2,
1200						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl2), types.NodeTypeAfterSuite, 1, cl3),
1201					),
1202					S(types.NodeTypeReportAfterSuite, "my report", cl1, types.SpecStateFailed, 2,
1203						F("FAILURE MESSAGE\nWITH DETAILS", types.FailureNodeIsLeafNode, FailureNodeLocation(cl3), types.NodeTypeReportAfterSuite, 1, cl4),
1204					),
1205				},
1206			},
1207			"",
1208			"",
1209			"{{red}}{{bold}}Summarizing 3 Failures:{{/}}",
1210			"  {{red}}[FAIL]{{/}} {{/}}{{red}}{{bold}}[BeforeSuite] {{/}}{{/}}",
1211			"  {{gray}}"+cl1.String()+"{{/}}",
1212			"  {{red}}[FAIL]{{/}} {{/}}{{red}}{{bold}}[AfterSuite] {{/}}{{/}}",
1213			"  {{gray}}"+cl3.String()+"{{/}}",
1214			"  {{red}}[FAIL]{{/}} {{/}}{{red}}{{bold}}[ReportAfterSuite] my report{{/}}{{/}}",
1215			"  {{gray}}"+cl4.String()+"{{/}}",
1216			"",
1217			"{{red}}{{bold}}Ran 0 of 10 Specs in 60.000 seconds{{/}}",
1218			"{{red}}{{bold}}FAIL!{{/}} -- {{cyan}}{{bold}}A BeforeSuite node failed so all tests were skipped.{{/}}",
1219			"",
1220		),
1221
1222		Entry("when the suite includes a special failure reason",
1223			C(),
1224			types.Report{
1225				SuiteSucceeded:             false,
1226				SpecialSuiteFailureReasons: []string{"Detected pending specs and --fail-on-pending is set"},
1227				SuiteConfig:                types.SuiteConfig{FailOnPending: true},
1228				PreRunStats:                types.PreRunStats{TotalSpecs: 5, SpecsThatWillRun: 3},
1229				RunTime:                    time.Minute,
1230				SpecReports: types.SpecReports{
1231					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1232					S(types.SpecStatePending), S(types.SpecStatePending),
1233				},
1234			},
1235			"",
1236			"{{red}}{{bold}}Ran 3 of 5 Specs in 60.000 seconds{{/}}",
1237			"{{red}}{{bold}}FAIL! - Detected pending specs and --fail-on-pending is set{{/}} -- {{green}}{{bold}}3 Passed{{/}} | {{red}}{{bold}}0 Failed{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}0 Skipped{{/}}",
1238			"",
1239		),
1240		Entry("when the suite includes multiple special failure reasons",
1241			C(),
1242			types.Report{
1243				SuiteSucceeded:             false,
1244				SpecialSuiteFailureReasons: []string{"Detected pending specs and --fail-on-pending is set", "Interrupted by Timeout"},
1245				SuiteConfig:                types.SuiteConfig{FailOnPending: true},
1246				PreRunStats:                types.PreRunStats{TotalSpecs: 5, SpecsThatWillRun: 3},
1247				RunTime:                    time.Minute,
1248				SpecReports: types.SpecReports{
1249					S(types.SpecStatePassed), S(types.SpecStatePassed), S(types.SpecStatePassed),
1250					S(types.SpecStatePending), S(types.SpecStatePending),
1251				},
1252			},
1253			"",
1254			"{{red}}{{bold}}Ran 3 of 5 Specs in 60.000 seconds{{/}}",
1255			"{{red}}{{bold}}FAIL! - Detected pending specs and --fail-on-pending is set, Interrupted by Timeout{{/}}",
1256			"{{green}}{{bold}}3 Passed{{/}} | {{red}}{{bold}}0 Failed{{/}} | {{yellow}}{{bold}}2 Pending{{/}} | {{cyan}}{{bold}}0 Skipped{{/}}",
1257			"",
1258		),
1259	)
1260})
1261
Full Screen

default_reporter.go

Source: default_reporter.go Github

copy
1/*
2Ginkgo's Default Reporter
3
4A number of command line flags are available to tweak Ginkgo's default output.
5
6These are documented [here](http://onsi.github.io/ginkgo/#running_tests)
7*/
8package reporters
9
10import (
11	"fmt"
12	"io"
13	"runtime"
14	"strings"
15
16	"github.com/onsi/ginkgo/v2/formatter"
17	"github.com/onsi/ginkgo/v2/types"
18)
19
20type DefaultReporter struct {
21	conf   types.ReporterConfig
22	writer io.Writer
23
24	// managing the emission stream
25	lastChar                 string
26	lastEmissionWasDelimiter bool
27
28	// rendering
29	specDenoter  string
30	retryDenoter string
31	formatter    formatter.Formatter
32}
33
34func NewDefaultReporterUnderTest(conf types.ReporterConfig, writer io.Writer) *DefaultReporter {
35	reporter := NewDefaultReporter(conf, writer)
36	reporter.formatter = formatter.New(formatter.ColorModePassthrough)
37
38	return reporter
39}
40
41func NewDefaultReporter(conf types.ReporterConfig, writer io.Writer) *DefaultReporter {
42	reporter := &DefaultReporter{
43		conf:   conf,
44		writer: writer,
45
46		lastChar:                 "\n",
47		lastEmissionWasDelimiter: false,
48
49		specDenoter:  "•",
50		retryDenoter: "↺",
51		formatter:    formatter.NewWithNoColorBool(conf.NoColor),
52	}
53	if runtime.GOOS == "windows" {
54		reporter.specDenoter = "+"
55		reporter.retryDenoter = "R"
56	}
57
58	return reporter
59}
60
61/* The Reporter Interface */
62
63func (r *DefaultReporter) SuiteWillBegin(report types.Report) {
64	if r.conf.Verbosity().Is(types.VerbosityLevelSuccinct) {
65		r.emit(r.f("[%d] {{bold}}%s{{/}} ", report.SuiteConfig.RandomSeed, report.SuiteDescription))
66		if len(report.SuiteLabels) > 0 {
67			r.emit(r.f("{{coral}}[%s]{{/}} ", strings.Join(report.SuiteLabels, ", ")))
68		}
69		r.emit(r.f("- %d/%d specs ", report.PreRunStats.SpecsThatWillRun, report.PreRunStats.TotalSpecs))
70		if report.SuiteConfig.ParallelTotal > 1 {
71			r.emit(r.f("- %d procs ", report.SuiteConfig.ParallelTotal))
72		}
73	} else {
74		banner := r.f("Running Suite: %s - %s", report.SuiteDescription, report.SuitePath)
75		r.emitBlock(banner)
76		bannerWidth := len(banner)
77		if len(report.SuiteLabels) > 0 {
78			labels := strings.Join(report.SuiteLabels, ", ")
79			r.emitBlock(r.f("{{coral}}[%s]{{/}} ", labels))
80			if len(labels)+2 > bannerWidth {
81				bannerWidth = len(labels) + 2
82			}
83		}
84		r.emitBlock(strings.Repeat("=", bannerWidth))
85
86		out := r.f("Random Seed: {{bold}}%d{{/}}", report.SuiteConfig.RandomSeed)
87		if report.SuiteConfig.RandomizeAllSpecs {
88			out += r.f(" - will randomize all specs")
89		}
90		r.emitBlock(out)
91		r.emit("\n")
92		r.emitBlock(r.f("Will run {{bold}}%d{{/}} of {{bold}}%d{{/}} specs", report.PreRunStats.SpecsThatWillRun, report.PreRunStats.TotalSpecs))
93		if report.SuiteConfig.ParallelTotal > 1 {
94			r.emitBlock(r.f("Running in parallel across {{bold}}%d{{/}} processes", report.SuiteConfig.ParallelTotal))
95		}
96	}
97}
98
99func (r *DefaultReporter) WillRun(report types.SpecReport) {
100	if r.conf.Verbosity().LT(types.VerbosityLevelVerbose) || report.State.Is(types.SpecStatePending|types.SpecStateSkipped) {
101		return
102	}
103
104	r.emitDelimiter()
105	indentation := uint(0)
106	if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
107		r.emitBlock(r.f("{{bold}}[%s] %s{{/}}", report.LeafNodeType.String(), report.LeafNodeText))
108	} else {
109		if len(report.ContainerHierarchyTexts) > 0 {
110			r.emitBlock(r.cycleJoin(report.ContainerHierarchyTexts, " "))
111			indentation = 1
112		}
113		line := r.fi(indentation, "{{bold}}%s{{/}}", report.LeafNodeText)
114		labels := report.Labels()
115		if len(labels) > 0 {
116			line += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels, ", "))
117		}
118		r.emitBlock(line)
119	}
120	r.emitBlock(r.fi(indentation, "{{gray}}%s{{/}}", report.LeafNodeLocation))
121}
122
123func (r *DefaultReporter) DidRun(report types.SpecReport) {
124	v := r.conf.Verbosity()
125	var header, highlightColor string
126	includeRuntime, emitGinkgoWriterOutput, stream, denoter := true, true, false, r.specDenoter
127	succinctLocationBlock := v.Is(types.VerbosityLevelSuccinct)
128
129	hasGW := report.CapturedGinkgoWriterOutput != ""
130	hasStd := report.CapturedStdOutErr != ""
131	hasEmittableReports := report.ReportEntries.HasVisibility(types.ReportEntryVisibilityAlways) || (report.ReportEntries.HasVisibility(types.ReportEntryVisibilityFailureOrVerbose) && (!report.Failure.IsZero() || v.GTE(types.VerbosityLevelVerbose)))
132
133	if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
134		denoter = fmt.Sprintf("[%s]", report.LeafNodeType)
135	}
136
137	switch report.State {
138	case types.SpecStatePassed:
139		highlightColor, succinctLocationBlock = "{{green}}", v.LT(types.VerbosityLevelVerbose)
140		emitGinkgoWriterOutput = (r.conf.AlwaysEmitGinkgoWriter || v.GTE(types.VerbosityLevelVerbose)) && hasGW
141		if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
142			if v.GTE(types.VerbosityLevelVerbose) || hasStd || hasEmittableReports {
143				header = fmt.Sprintf("%s PASSED", denoter)
144			} else {
145				return
146			}
147		} else {
148			header, stream = denoter, true
149			if report.NumAttempts > 1 {
150				header, stream = fmt.Sprintf("%s [FLAKEY TEST - TOOK %d ATTEMPTS TO PASS]", r.retryDenoter, report.NumAttempts), false
151			}
152			if report.RunTime > r.conf.SlowSpecThreshold {
153				header, stream = fmt.Sprintf("%s [SLOW TEST]", header), false
154			}
155		}
156		if hasStd || emitGinkgoWriterOutput || hasEmittableReports {
157			stream = false
158		}
159	case types.SpecStatePending:
160		highlightColor = "{{yellow}}"
161		includeRuntime, emitGinkgoWriterOutput = false, false
162		if v.Is(types.VerbosityLevelSuccinct) {
163			header, stream = "P", true
164		} else {
165			header, succinctLocationBlock = "P [PENDING]", v.LT(types.VerbosityLevelVeryVerbose)
166		}
167	case types.SpecStateSkipped:
168		highlightColor = "{{cyan}}"
169		if report.Failure.Message != "" || v.Is(types.VerbosityLevelVeryVerbose) {
170			header = "S [SKIPPED]"
171		} else {
172			header, stream = "S", true
173		}
174	case types.SpecStateFailed:
175		highlightColor, header = "{{red}}", fmt.Sprintf("%s [FAILED]", denoter)
176	case types.SpecStatePanicked:
177		highlightColor, header = "{{magenta}}", fmt.Sprintf("%s! [PANICKED]", denoter)
178	case types.SpecStateInterrupted:
179		highlightColor, header = "{{orange}}", fmt.Sprintf("%s! [INTERRUPTED]", denoter)
180	case types.SpecStateAborted:
181		highlightColor, header = "{{coral}}", fmt.Sprintf("%s! [ABORTED]", denoter)
182	}
183
184	// Emit stream and return
185	if stream {
186		r.emit(r.f(highlightColor + header + "{{/}}"))
187		return
188	}
189
190	// Emit header
191	r.emitDelimiter()
192	if includeRuntime {
193		header = r.f("%s [%.3f seconds]", header, report.RunTime.Seconds())
194	}
195	r.emitBlock(r.f(highlightColor + header + "{{/}}"))
196
197	// Emit Code Location Block
198	r.emitBlock(r.codeLocationBlock(report, highlightColor, succinctLocationBlock, false))
199
200	//Emit Stdout/Stderr Output
201	if hasStd {
202		r.emitBlock("\n")
203		r.emitBlock(r.fi(1, "{{gray}}Begin Captured StdOut/StdErr Output >>{{/}}"))
204		r.emitBlock(r.fi(2, "%s", report.CapturedStdOutErr))
205		r.emitBlock(r.fi(1, "{{gray}}<< End Captured StdOut/StdErr Output{{/}}"))
206	}
207
208	//Emit Captured GinkgoWriter Output
209	if emitGinkgoWriterOutput && hasGW {
210		r.emitBlock("\n")
211		r.emitBlock(r.fi(1, "{{gray}}Begin Captured GinkgoWriter Output >>{{/}}"))
212		r.emitBlock(r.fi(2, "%s", report.CapturedGinkgoWriterOutput))
213		r.emitBlock(r.fi(1, "{{gray}}<< End Captured GinkgoWriter Output{{/}}"))
214	}
215
216	if hasEmittableReports {
217		r.emitBlock("\n")
218		r.emitBlock(r.fi(1, "{{gray}}Begin Report Entries >>{{/}}"))
219		reportEntries := report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways)
220		if !report.Failure.IsZero() || v.GTE(types.VerbosityLevelVerbose) {
221			reportEntries = report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways, types.ReportEntryVisibilityFailureOrVerbose)
222		}
223		for _, entry := range reportEntries {
224			r.emitBlock(r.fi(2, "{{bold}}"+entry.Name+"{{gray}} - %s @ %s{{/}}", entry.Location, entry.Time.Format(types.GINKGO_TIME_FORMAT)))
225			if representation := entry.StringRepresentation(); representation != "" {
226				r.emitBlock(r.fi(3, representation))
227			}
228		}
229		r.emitBlock(r.fi(1, "{{gray}}<< End Report Entries{{/}}"))
230	}
231
232	// Emit Failure Message
233	if !report.Failure.IsZero() {
234		r.emitBlock("\n")
235		r.emitBlock(r.fi(1, highlightColor+"%s{{/}}", report.Failure.Message))
236		r.emitBlock(r.fi(1, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}}\n", report.Failure.FailureNodeType, report.Failure.Location))
237		if report.Failure.ForwardedPanic != "" {
238			r.emitBlock("\n")
239			r.emitBlock(r.fi(1, highlightColor+"%s{{/}}", report.Failure.ForwardedPanic))
240		}
241
242		if r.conf.FullTrace || report.Failure.ForwardedPanic != "" {
243			r.emitBlock("\n")
244			r.emitBlock(r.fi(1, highlightColor+"Full Stack Trace{{/}}"))
245			r.emitBlock(r.fi(2, "%s", report.Failure.Location.FullStackTrace))
246		}
247	}
248
249	r.emitDelimiter()
250}
251
252func (r *DefaultReporter) SuiteDidEnd(report types.Report) {
253	failures := report.SpecReports.WithState(types.SpecStateFailureStates)
254	if len(failures) > 1 {
255		r.emitBlock("\n\n")
256		r.emitBlock(r.f("{{red}}{{bold}}Summarizing %d Failures:{{/}}", len(failures)))
257		for _, specReport := range failures {
258			highlightColor, heading := "{{red}}", "[FAIL]"
259			switch specReport.State {
260			case types.SpecStatePanicked:
261				highlightColor, heading = "{{magenta}}", "[PANICKED!]"
262			case types.SpecStateAborted:
263				highlightColor, heading = "{{coral}}", "[ABORTED]"
264			case types.SpecStateInterrupted:
265				highlightColor, heading = "{{orange}}", "[INTERRUPTED]"
266			}
267			locationBlock := r.codeLocationBlock(specReport, highlightColor, true, true)
268			r.emitBlock(r.fi(1, highlightColor+"%s{{/}} %s", heading, locationBlock))
269		}
270	}
271
272	//summarize the suite
273	if r.conf.Verbosity().Is(types.VerbosityLevelSuccinct) && report.SuiteSucceeded {
274		r.emit(r.f(" {{green}}SUCCESS!{{/}} %s ", report.RunTime))
275		return
276	}
277
278	r.emitBlock("\n")
279	color, status := "{{green}}{{bold}}", "SUCCESS!"
280	if !report.SuiteSucceeded {
281		color, status = "{{red}}{{bold}}", "FAIL!"
282	}
283
284	specs := report.SpecReports.WithLeafNodeType(types.NodeTypeIt) //exclude any suite setup nodes
285	r.emitBlock(r.f(color+"Ran %d of %d Specs in %.3f seconds{{/}}",
286		specs.CountWithState(types.SpecStatePassed)+specs.CountWithState(types.SpecStateFailureStates),
287		report.PreRunStats.TotalSpecs,
288		report.RunTime.Seconds()),
289	)
290
291	switch len(report.SpecialSuiteFailureReasons) {
292	case 0:
293		r.emit(r.f(color+"%s{{/}} -- ", status))
294	case 1:
295		r.emit(r.f(color+"%s - %s{{/}} -- ", status, report.SpecialSuiteFailureReasons[0]))
296	default:
297		r.emitBlock(r.f(color+"%s - %s{{/}}\n", status, strings.Join(report.SpecialSuiteFailureReasons, ", ")))
298	}
299
300	if len(specs) == 0 && report.SpecReports.WithLeafNodeType(types.NodeTypeBeforeSuite|types.NodeTypeSynchronizedBeforeSuite).CountWithState(types.SpecStateFailureStates) > 0 {
301		r.emit(r.f("{{cyan}}{{bold}}A BeforeSuite node failed so all tests were skipped.{{/}}\n"))
302	} else {
303		r.emit(r.f("{{green}}{{bold}}%d Passed{{/}} | ", specs.CountWithState(types.SpecStatePassed)))
304		r.emit(r.f("{{red}}{{bold}}%d Failed{{/}} | ", specs.CountWithState(types.SpecStateFailureStates)))
305		if specs.CountOfFlakedSpecs() > 0 {
306			r.emit(r.f("{{light-yellow}}{{bold}}%d Flaked{{/}} | ", specs.CountOfFlakedSpecs()))
307		}
308		r.emit(r.f("{{yellow}}{{bold}}%d Pending{{/}} | ", specs.CountWithState(types.SpecStatePending)))
309		r.emit(r.f("{{cyan}}{{bold}}%d Skipped{{/}}\n", specs.CountWithState(types.SpecStateSkipped)))
310	}
311}
312
313/* Emitting to the writer */
314func (r *DefaultReporter) emit(s string) {
315	if len(s) > 0 {
316		r.lastChar = s[len(s)-1:]
317		r.lastEmissionWasDelimiter = false
318		r.writer.Write([]byte(s))
319	}
320}
321
322func (r *DefaultReporter) emitBlock(s string) {
323	if len(s) > 0 {
324		if r.lastChar != "\n" {
325			r.emit("\n")
326		}
327		r.emit(s)
328		if r.lastChar != "\n" {
329			r.emit("\n")
330		}
331	}
332}
333
334func (r *DefaultReporter) emitDelimiter() {
335	if r.lastEmissionWasDelimiter {
336		return
337	}
338	r.emitBlock(r.f("{{gray}}%s{{/}}", strings.Repeat("-", 30)))
339	r.lastEmissionWasDelimiter = true
340}
341
342/* Rendering text */
343func (r *DefaultReporter) f(format string, args ...interface{}) string {
344	return r.formatter.F(format, args...)
345}
346
347func (r *DefaultReporter) fi(indentation uint, format string, args ...interface{}) string {
348	return r.formatter.Fi(indentation, format, args...)
349}
350
351func (r *DefaultReporter) cycleJoin(elements []string, joiner string) string {
352	return r.formatter.CycleJoin(elements, joiner, []string{"{{/}}", "{{gray}}"})
353}
354
355func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightColor string, succinct bool, usePreciseFailureLocation bool) string {
356	texts, locations, labels := []string{}, []types.CodeLocation{}, [][]string{}
357	texts, locations, labels = append(texts, report.ContainerHierarchyTexts...), append(locations, report.ContainerHierarchyLocations...), append(labels, report.ContainerHierarchyLabels...)
358	if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) {
359		texts = append(texts, r.f("[%s] %s", report.LeafNodeType, report.LeafNodeText))
360	} else {
361		texts = append(texts, report.LeafNodeText)
362	}
363	labels = append(labels, report.LeafNodeLabels)
364	locations = append(locations, report.LeafNodeLocation)
365
366	failureLocation := report.Failure.FailureNodeLocation
367	if usePreciseFailureLocation {
368		failureLocation = report.Failure.Location
369	}
370
371	switch report.Failure.FailureNodeContext {
372	case types.FailureNodeAtTopLevel:
373		texts = append([]string{r.f(highlightColor+"{{bold}}TOP-LEVEL [%s]{{/}}", report.Failure.FailureNodeType)}, texts...)
374		locations = append([]types.CodeLocation{failureLocation}, locations...)
375		labels = append([][]string{{}}, labels...)
376	case types.FailureNodeInContainer:
377		i := report.Failure.FailureNodeContainerIndex
378		texts[i] = r.f(highlightColor+"{{bold}}%s [%s]{{/}}", texts[i], report.Failure.FailureNodeType)
379		locations[i] = failureLocation
380	case types.FailureNodeIsLeafNode:
381		i := len(texts) - 1
382		texts[i] = r.f(highlightColor+"{{bold}}[%s] %s{{/}}", report.LeafNodeType, report.LeafNodeText)
383		locations[i] = failureLocation
384	}
385
386	out := ""
387	if succinct {
388		out += r.f("%s", r.cycleJoin(texts, " "))
389		flattenedLabels := report.Labels()
390		if len(flattenedLabels) > 0 {
391			out += r.f(" {{coral}}[%s]{{/}}", strings.Join(flattenedLabels, ", "))
392		}
393		out += "\n"
394		if usePreciseFailureLocation {
395			out += r.f("{{gray}}%s{{/}}", failureLocation)
396		} else {
397			out += r.f("{{gray}}%s{{/}}", locations[len(locations)-1])
398		}
399	} else {
400		for i := range texts {
401			out += r.fi(uint(i), "%s", texts[i])
402			if len(labels[i]) > 0 {
403				out += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels[i], ", "))
404			}
405			out += "\n"
406			out += r.fi(uint(i), "{{gray}}%s{{/}}\n", locations[i])
407		}
408	}
409	return out
410}
411
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)