Skip to content

Commit db83f33

Browse files
committed
Ginkgo output now includes a timeline-view of the spec
This commit changers Ginkgo default output. Spec details are now presented as a **timeline** that includes events that occur during the spec lifecycle interleaved with any GinkgoWriter content. This makes is much easier to understand the flow of a spec and where a given failure occurs. The --progress, --slow-spec-threshold, --always-emit-ginkgo-writer flags and the SuppressProgressReporting decorator have all been deprecated. Instead the existing -v and -vv flags better capture the level of verbosity to display. However, a new --show-node-events flag is added to include node > Enter and < Exit events in the spec timeline. JUnit reports now include the timeline (rendered with -vv) and custom JUnit reports can be configured and generated using GenerateJUnitReportWithConfig(report types.Report, dst string, config JunitReportConfig)`
1 parent c70867a commit db83f33

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+4916
-2341
lines changed

core_dsl.go

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"os"
2222
"path/filepath"
2323
"strings"
24-
"time"
2524

2625
"github.com/go-logr/logr"
2726
"github.com/onsi/ginkgo/v2/formatter"
@@ -276,7 +275,7 @@ func RunSpecs(t GinkgoTestingT, description string, args ...interface{}) bool {
276275
}
277276

278277
writer := GinkgoWriter.(*internal.Writer)
279-
if reporterConfig.Verbose && suiteConfig.ParallelTotal == 1 {
278+
if reporterConfig.Verbosity().GTE(types.VerbosityLevelVerbose) && suiteConfig.ParallelTotal == 1 {
280279
writer.SetMode(internal.WriterModeStreamAndBuffer)
281280
} else {
282281
writer.SetMode(internal.WriterModeBufferOnly)
@@ -513,31 +512,7 @@ Note that By does not generate a new Ginkgo node - rather it is simply synctacti
513512
You can learn more about By here: https://onsi.github.io/ginkgo/#documenting-complex-specs-by
514513
*/
515514
func By(text string, callback ...func()) {
516-
if !global.Suite.InRunPhase() {
517-
exitIfErr(types.GinkgoErrors.ByNotDuringRunPhase(types.NewCodeLocation(1)))
518-
}
519-
value := struct {
520-
Text string
521-
Duration time.Duration
522-
}{
523-
Text: text,
524-
}
525-
t := time.Now()
526-
global.Suite.SetProgressStepCursor(internal.ProgressStepCursor{
527-
Text: text,
528-
CodeLocation: types.NewCodeLocation(1),
529-
StartTime: t,
530-
})
531-
AddReportEntry("By Step", ReportEntryVisibilityNever, Offset(1), &value, t)
532-
formatter := formatter.NewWithNoColorBool(reporterConfig.NoColor)
533-
GinkgoWriter.Println(formatter.F("{{bold}}STEP:{{/}} %s {{gray}}%s{{/}}", text, t.Format(types.GINKGO_TIME_FORMAT)))
534-
if len(callback) == 1 {
535-
callback[0]()
536-
value.Duration = time.Since(t)
537-
}
538-
if len(callback) > 1 {
539-
panic("just one callback per By, please")
540-
}
515+
exitIfErr(global.Suite.By(text, callback...))
541516
}
542517

543518
/*

docs/index.md

Lines changed: 167 additions & 99 deletions
Large diffs are not rendered by default.

ginkgo/performance/compiling_and_running_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package performance_test
22

33
import (
44
"fmt"
5+
"os"
56

67
. "github.com/onsi/ginkgo/v2"
78
. "github.com/onsi/gomega"
@@ -12,6 +13,10 @@ var _ = Describe("Compiling and Running a single test package", func() {
1213
var cache gmeasure.ExperimentCache
1314

1415
BeforeEach(func() {
16+
if os.Getenv("PERF") == "" {
17+
Skip("PERF environment not set, skipping")
18+
}
19+
1520
var err error
1621
cache, err = gmeasure.NewExperimentCache("./compiling-and-running-single-cache")
1722
Ω(err).ShouldNot(HaveOccurred())
@@ -50,6 +55,10 @@ var _ = Describe("Compiling and Running multiple tests", func() {
5055
var cache gmeasure.ExperimentCache
5156

5257
BeforeEach(func() {
58+
if os.Getenv("PERF") == "" {
59+
Skip("PERF environment not set, skipping")
60+
}
61+
5362
var err error
5463
cache, err = gmeasure.NewExperimentCache("./compiling-and-running-multiple-cache")
5564
Ω(err).ShouldNot(HaveOccurred())

ginkgo/performance/fetching_dependencies_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package performance_test
22

33
import (
44
"fmt"
5+
"os"
56

67
. "github.com/onsi/ginkgo/v2"
78
. "github.com/onsi/gomega"
@@ -12,6 +13,10 @@ var _ = Describe("Fetching Dependencies", func() {
1213
var cache gmeasure.ExperimentCache
1314

1415
BeforeEach(func() {
16+
if os.Getenv("PERF") == "" {
17+
Skip("PERF environment not set, skipping")
18+
}
19+
1520
var err error
1621
cache, err = gmeasure.NewExperimentCache("./fetching-dependencies-cache")
1722
Ω(err).ShouldNot(HaveOccurred())

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/go-logr/logr v1.2.3
77
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
88
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38
9-
github.com/onsi/gomega v1.23.0
9+
github.com/onsi/gomega v1.24.0
1010
golang.org/x/sys v0.1.0
1111
golang.org/x/tools v0.2.0
1212
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
1717
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
1818
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
1919
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
20-
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
21-
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
20+
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
21+
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
2222
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2323
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2424
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

integration/_fixtures/flags_fixture/flags_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
remapped "math"
77
_ "math/cmplx"
8-
"time"
98

109
. "github.com/onsi/ginkgo/v2"
1110
. "github.com/onsi/ginkgo/v2/integration/_fixtures/flags_fixture"
@@ -64,10 +63,6 @@ var _ = Describe("Testing various flags", func() {
6463
println("RANDOM_C")
6564
})
6665

67-
It("should honor -slow-spec-threshold", func() {
68-
time.Sleep(100 * time.Millisecond)
69-
})
70-
7166
It("should pass in additional arguments after '--' directly to the test process", func() {
7267
fmt.Printf("CUSTOM_FLAG: %s", customFlag)
7368
})

integration/_fixtures/progress_fixture/progress_fixture_suite_test.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

integration/_fixtures/progress_fixture/progress_fixture_test.go

Lines changed: 0 additions & 49 deletions
This file was deleted.

integration/_fixtures/report_entries_fixture/report_entries_fixture_suite_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ var _ = Describe("top-level container", func() {
5252
})
5353

5454
It("has By entries", func() {
55-
By("registers a hidden AddReportEntry")
55+
By("registers a By event")
5656
By("includes durations", func() {
5757
time.Sleep(time.Millisecond * 100)
5858
})
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package timeline_fixture_test
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
. "github.com/onsi/ginkgo/v2"
8+
"github.com/onsi/ginkgo/v2/types"
9+
. "github.com/onsi/gomega"
10+
)
11+
12+
func TestTimelineFixture(t *testing.T) {
13+
RegisterFailHandler(Fail)
14+
RunSpecs(t, "TimelineFixture Suite")
15+
}
16+
17+
var _ = Describe("a full timeline", Serial, func() {
18+
Describe("a flaky test", func() {
19+
BeforeEach(func() {
20+
By("logging some events")
21+
GinkgoWriter.Println("hello!")
22+
AddReportEntry("a report!", "Of {{bold}}great{{/}} value")
23+
DeferCleanup(func() {
24+
By("cleaning up a bit", func() {
25+
time.Sleep(time.Millisecond * 50)
26+
GinkgoWriter.Println("all done!")
27+
})
28+
})
29+
})
30+
31+
i := 0
32+
33+
It("retries a few times", func() {
34+
i += 1
35+
GinkgoWriter.Println("let's try...")
36+
if i < 3 {
37+
Fail("bam!")
38+
}
39+
GinkgoWriter.Println("hooray!")
40+
}, FlakeAttempts(3))
41+
42+
AfterEach(func() {
43+
if i == 3 {
44+
GinkgoWriter.Println("feeling sleepy...")
45+
time.Sleep(time.Millisecond * 200)
46+
}
47+
}, PollProgressAfter(time.Millisecond*100))
48+
})
49+
50+
Describe("a test with multiple failures", func() {
51+
It("times out", func(ctx SpecContext) {
52+
By("waiting...")
53+
<-ctx.Done()
54+
GinkgoWriter.Println("then failing!")
55+
Fail("welp")
56+
}, NodeTimeout(time.Millisecond*100))
57+
58+
AfterEach(func() {
59+
panic("aaah!")
60+
})
61+
})
62+
63+
It("passes happily", func() {
64+
AddReportEntry("a verbose-only report", types.ReportEntryVisibilityFailureOrVerbose)
65+
AddReportEntry("a hidden report", types.ReportEntryVisibilityNever)
66+
})
67+
})

integration/decorations_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ some decorated specs
3232
session := startGinkgo(fm.PathTo("decorations", "flaky_repeated"), "-vv", "--no-color")
3333
Eventually(session).Should(gexec.Exit(1))
3434

35-
Ω(session).Should(gbytes.Say("Ginkgo: Attempt #1 Failed. Retrying..."))
36-
Ω(session).Should(gbytes.Say("Ginkgo: Attempt #2 Failed. Retrying..."))
35+
Ω(session).Should(gbytes.Say("Attempt #1 Failed. Retrying"))
36+
Ω(session).Should(gbytes.Say("Attempt #2 Failed. Retrying"))
3737

38-
Ω(session).Should(gbytes.Say("Ginkgo: Attempt #1 Passed. Repeating..."))
39-
Ω(session).Should(gbytes.Say("Ginkgo: Attempt #2 Passed. Repeating..."))
38+
Ω(session).Should(gbytes.Say("Attempt #1 Passed. Repeating"))
39+
Ω(session).Should(gbytes.Say("Attempt #2 Passed. Repeating"))
4040
Ω(session).Should(gbytes.Say("failed on attempt #3"))
4141
})
4242

integration/fail_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ var _ = Describe("Failing Specs", func() {
3535
Ω(output).Should(MatchRegexp(`goroutine \d+ \[chan receive\]`), "from the progress report emitted by the timeout")
3636
Ω(output).Should(MatchRegexp(`>\s*\<\-c\.Done\(\)`), "from the progress report emitted by the timeout")
3737

38-
Ω(output).Should(MatchRegexp(`a top level DescribeTable\n.*fail_fixture_test\.go:41`),
39-
"the output of a failing DescribeTable should include its file path and line number")
40-
Ω(output).Should(MatchRegexp(`\[It\] a TableEntry constructed by Entry\n.*fail_fixture_test\.go:45`),
38+
Ω(output).Should(MatchRegexp(`a top level DescribeTable \[It\] a TableEntry constructed by Entry\n.*fail_fixture_test\.go:45`),
4139
"the output of a failing Entry should include its file path and line number")
4240

4341
Ω(output).Should(ContainSubstring("0 Passed | 7 Failed"))

integration/flags_test.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var _ = Describe("Flags Specs", func() {
2323
Eventually(session).Should(gexec.Exit(types.GINKGO_FOCUS_EXIT_CODE))
2424
output := string(session.Out.Contents())
2525

26-
Ω(output).Should(ContainSubstring("10 Passed"))
26+
Ω(output).Should(ContainSubstring("9 Passed"))
2727
Ω(output).Should(ContainSubstring("0 Failed"))
2828
Ω(output).Should(ContainSubstring("1 Pending"))
2929
Ω(output).Should(ContainSubstring("3 Skipped"))
@@ -60,23 +60,14 @@ var _ = Describe("Flags Specs", func() {
6060
})
6161

6262
It("should randomize tests when told to", func() {
63-
session := startGinkgo(fm.PathTo("flags"), "--no-color", "--randomize-all", "--seed=1")
63+
session := startGinkgo(fm.PathTo("flags"), "--no-color", "--randomize-all", "--seed=40")
6464
Eventually(session).Should(gexec.Exit(types.GINKGO_FOCUS_EXIT_CODE))
6565
output := string(session.Out.Contents())
6666

6767
orders := getRandomOrders(output)
6868
Ω(orders[0]).ShouldNot(BeNumerically("<", orders[1]))
6969
})
7070

71-
It("should watch for slow specs", func() {
72-
session := startGinkgo(fm.PathTo("flags"), "--slow-spec-threshold=50ms")
73-
Eventually(session).Should(gexec.Exit(types.GINKGO_FOCUS_EXIT_CODE))
74-
output := string(session.Out.Contents())
75-
76-
Ω(output).Should(ContainSubstring("SLOW TEST"))
77-
Ω(output).Should(ContainSubstring("should honor -slow-spec-threshold"))
78-
})
79-
8071
It("should pass additional arguments in", func() {
8172
session := startGinkgo(fm.PathTo("flags"), "--", "--customFlag=madagascar")
8273
Eventually(session).Should(gexec.Exit(types.GINKGO_FOCUS_EXIT_CODE))
@@ -154,4 +145,26 @@ var _ = Describe("Flags Specs", func() {
154145
Ω(output).Should(ContainSubstring("1 Skipped"))
155146
Ω(output).Should(ContainSubstring("1 Passed"))
156147
})
148+
149+
It("should emit node start/end events when running with --show-node-events", func() {
150+
session := startGinkgo(fm.PathTo("flags"), "--no-color", "-v", "--show-node-events")
151+
Eventually(session).Should(gexec.Exit(types.GINKGO_FOCUS_EXIT_CODE))
152+
output := string(session.Out.Contents())
153+
154+
Eventually(output).Should(ContainSubstring("> Enter [It] should honor -cover"))
155+
Eventually(output).Should(ContainSubstring("< Exit [It] should honor -cover"))
156+
157+
fm.MountFixture("fail")
158+
session = startGinkgo(fm.PathTo("fail"), "--no-color", "--show-node-events")
159+
Eventually(session).Should(gexec.Exit(1))
160+
output = string(session.Out.Contents())
161+
Ω(output).Should(ContainSubstring("> Enter [It] a top level specify"))
162+
Ω(output).Should(ContainSubstring("< Exit [It] a top level specify"))
163+
164+
session = startGinkgo(fm.PathTo("fail"), "--no-color")
165+
Eventually(session).Should(gexec.Exit(1))
166+
output = string(session.Out.Contents())
167+
Ω(output).ShouldNot(ContainSubstring("> Enter [It] a top level specify"))
168+
Ω(output).ShouldNot(ContainSubstring("< Exit [It] a top level specify"))
169+
})
157170
})

integration/output_interceptor_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ var _ = Describe("OutputInterceptor", func() {
3838
Eventually(sess).Should(gexec.Exit(0))
3939

4040
output := string(sess.Out.Contents())
41-
Ω(output).Should(ContainSubstring(" CAPTURED OUTPUT A\n"))
42-
Ω(output).Should(ContainSubstring(" CAPTURED OUTPUT B\n"))
41+
Ω(output).Should(ContainSubstring("CAPTURED OUTPUT A\n"))
42+
Ω(output).Should(ContainSubstring("CAPTURED OUTPUT B\n"))
4343

4444
Ω(output).ShouldNot(ContainSubstring("OUTPUT TO CONSOLE"))
4545

0 commit comments

Comments
 (0)