From b6566b8bcac24aac1528093a832ee2c7ef668ad2 Mon Sep 17 00:00:00 2001 From: Onsi Fakhouri Date: Thu, 27 Feb 2014 09:05:51 -0800 Subject: [PATCH] Add GinkgoWriter --- example_collection.go | 21 +++++++++- example_collection_test.go | 61 ++++++++++++++++++++++++++--- ginkgo.go | 22 ++++++++++- ginkgo/convert/testfile_rewriter.go | 6 +-- ginkgo_suite_test.go | 15 +++++++ ginkgo_testing_t_proxy.go | 4 +- suite.go | 12 +++++- suite_test.go | 2 +- 8 files changed, 127 insertions(+), 16 deletions(-) diff --git a/example_collection.go b/example_collection.go index 0580f4fce..f82969064 100644 --- a/example_collection.go +++ b/example_collection.go @@ -5,6 +5,7 @@ import ( "github.com/onsi/ginkgo/types" "math/rand" + "os" "regexp" "sort" "time" @@ -19,15 +20,17 @@ type exampleCollection struct { startTime time.Time suiteID string runningExample *example + writer ginkgoWriter config config.GinkgoConfigType } -func newExampleCollection(t GinkgoTestingT, description string, examples []*example, reporters []Reporter, config config.GinkgoConfigType) *exampleCollection { +func newExampleCollection(t GinkgoTestingT, description string, examples []*example, reporters []Reporter, writer ginkgoWriter, config config.GinkgoConfigType) *exampleCollection { collection := &exampleCollection{ t: t, description: description, examples: examples, reporters: reporters, + writer: writer, config: config, suiteID: types.GenerateRandomID(), exampleCountBeforeParallelization: len(examples), @@ -133,10 +136,11 @@ func (collection *exampleCollection) shuffle(r *rand.Rand) { func (collection *exampleCollection) run() bool { collection.reportSuiteWillBegin() - suiteFailed := false for _, example := range collection.examples { + collection.clearWriterBuffer() + collection.reportExampleWillRun(example) if !example.skippedOrPending() { @@ -144,6 +148,7 @@ func (collection *exampleCollection) run() bool { example.run() if example.failed() { suiteFailed = true + collection.printWriterToStdout() } } else if example.pending() && collection.config.FailOnPending { suiteFailed = true @@ -167,6 +172,18 @@ func (collection *exampleCollection) fail(failure failureData) { } } +func (collection *exampleCollection) clearWriterBuffer() { + if collection.writer != nil { + collection.writer.Truncate(0) + } +} + +func (collection *exampleCollection) printWriterToStdout() { + if collection.writer != nil { + collection.writer.WriteTo(os.Stdout) + } +} + func (collection *exampleCollection) currentGinkgoTestDescription() GinkgoTestDescription { currentExample := collection.runningExample if currentExample == nil { diff --git a/example_collection_test.go b/example_collection_test.go index cd823ae27..d1293e30d 100644 --- a/example_collection_test.go +++ b/example_collection_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/gomega" "math/rand" + "os" "sort" "time" ) @@ -48,7 +49,7 @@ func init() { exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), } - collection = newExampleCollection(fakeT, "collection description", examples, []Reporter{fakeR}, config.GinkgoConfigType{}) + collection = newExampleCollection(fakeT, "collection description", examples, []Reporter{fakeR}, nil, config.GinkgoConfigType{}) }) It("should enumerate and assign example indices", func() { @@ -64,7 +65,7 @@ func init() { exampleWithItFunc("C", flagTypeNone, false), exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), - }, []Reporter{fakeR}, config.GinkgoConfigType{}) + }, []Reporter{fakeR}, nil, config.GinkgoConfigType{}) }) It("should be sortable", func() { @@ -89,7 +90,7 @@ func init() { exampleWithItFunc("C", flagTypeNone, false), exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), - }, []Reporter{fakeR, otherFakeR}, config.GinkgoConfigType{}) + }, []Reporter{fakeR, otherFakeR}, nil, config.GinkgoConfigType{}) collection.run() }) @@ -100,6 +101,56 @@ func init() { }) }) + Describe("logging GinkgoWriter output", func() { + Context("when instantiated with no GinkgoWriter", func() { + It("should not panic when a test fails", func() { + collection = newExampleCollection(fakeT, "collection description", []*example{ + exampleWithItFunc("C", flagTypeNone, true), + }, []Reporter{fakeR}, nil, config.GinkgoConfigType{}) + + Ω(func() { + collection.run() + }).ShouldNot(Panic()) + }) + }) + + Context("when instantiated with a GinkgoWriter", func() { + var writer *fakeGinkgoWriter + + BeforeEach(func() { + writer = &fakeGinkgoWriter{} + }) + + Context("when a test fails", func() { + BeforeEach(func() { + collection = newExampleCollection(fakeT, "collection description", []*example{ + exampleWithItFunc("C", flagTypeNone, true), + }, []Reporter{fakeR}, writer, config.GinkgoConfigType{}) + collection.run() + }) + + It("should truncate and write to stdout", func() { + Ω(writer.didTruncate).Should(BeTrue()) + Ω(writer.wroteTo).Should(Equal(os.Stdout)) + }) + }) + + Context("when a test passes", func() { + BeforeEach(func() { + collection = newExampleCollection(fakeT, "collection description", []*example{ + exampleWithItFunc("C", flagTypeNone, false), + }, []Reporter{fakeR}, writer, config.GinkgoConfigType{}) + collection.run() + }) + + It("should truncate but not write to stdout", func() { + Ω(writer.didTruncate).Should(BeTrue()) + Ω(writer.wroteTo).Should(BeNil()) + }) + }) + }) + }) + Describe("running an example collection", func() { var ( example1 *example @@ -118,7 +169,7 @@ func init() { }) JustBeforeEach(func() { - collection = newExampleCollection(fakeT, "collection description", []*example{example1, example2, example3}, []Reporter{fakeR}, conf) + collection = newExampleCollection(fakeT, "collection description", []*example{example1, example2, example3}, []Reporter{fakeR}, nil, conf) runResult = collection.run() }) @@ -556,7 +607,7 @@ func init() { exampleWithItFunc("A", flagTypeNone, false), exampleWithItFunc("B", flagTypeNone, false), exampleWithMeasure("measure"), - }, []Reporter{fakeR}, conf) + }, []Reporter{fakeR}, nil, conf) collection.run() }) diff --git a/ginkgo.go b/ginkgo.go index f3db30905..34a55f2f7 100644 --- a/ginkgo.go +++ b/ginkgo.go @@ -12,11 +12,14 @@ Ginkgo is MIT-Licensed package ginkgo import ( + "bytes" + "flag" "github.com/onsi/ginkgo/config" "github.com/onsi/ginkgo/remote" "github.com/onsi/ginkgo/reporters" "github.com/onsi/ginkgo/stenographer" "github.com/onsi/ginkgo/types" + "io" "net/http" "os" "time" @@ -30,9 +33,26 @@ var globalSuite *suite func init() { config.Flags("ginkgo", true) - globalSuite = newSuite() + flag.Parse() + + if config.DefaultReporterConfig.Verbose { + GinkgoWriter = os.Stdout + globalSuite = newSuite(nil) + } else { + buffer := &bytes.Buffer{} + GinkgoWriter = buffer + globalSuite = newSuite(buffer) + } } +//GinkgoWriter implements an io.Writer +//When running in verbose mode any writes to GinkgoWriter will be immediately printed +//to stdout +// +//When not in verbose mode, GinkgoWriter will buffer any writes and flush them to screen +//only if the current test fails. In this mode, GinkgoWriter is truncated between tests. +var GinkgoWriter io.Writer + //The interface by which Ginkgo receives *testing.T type GinkgoTestingT interface { Fail() diff --git a/ginkgo/convert/testfile_rewriter.go b/ginkgo/convert/testfile_rewriter.go index 654daedfe..4b001a7db 100644 --- a/ginkgo/convert/testfile_rewriter.go +++ b/ginkgo/convert/testfile_rewriter.go @@ -39,9 +39,9 @@ func rewriteTestsInFile(pathToFile string) { } underscoreDecl := &ast.GenDecl{ - Tok: 85, // gah, magick numbers are needed to make this work - TokPos: 14, // this tricks Go into writing "var _ = Describe" - Specs: []ast.Spec{varUnderscoreBlock}, + Tok: 85, // gah, magick numbers are needed to make this work + TokPos: 14, // this tricks Go into writing "var _ = Describe" + Specs: []ast.Spec{varUnderscoreBlock}, } imports := rootNode.Decls[0] diff --git a/ginkgo_suite_test.go b/ginkgo_suite_test.go index e637762b5..f528b6aab 100644 --- a/ginkgo_suite_test.go +++ b/ginkgo_suite_test.go @@ -3,6 +3,7 @@ package ginkgo import ( . "github.com/onsi/gomega" + "io" "math/rand" "testing" ) @@ -33,3 +34,17 @@ type fakeTestingT struct { func (fakeT *fakeTestingT) Fail() { fakeT.didFail = true } + +type fakeGinkgoWriter struct { + didTruncate bool + wroteTo io.Writer +} + +func (writer *fakeGinkgoWriter) Truncate(n int) { + writer.didTruncate = true +} + +func (writer *fakeGinkgoWriter) WriteTo(w io.Writer) (n int64, err error) { + writer.wroteTo = w + return 0, nil +} diff --git a/ginkgo_testing_t_proxy.go b/ginkgo_testing_t_proxy.go index c4119bd60..96235326f 100644 --- a/ginkgo_testing_t_proxy.go +++ b/ginkgo_testing_t_proxy.go @@ -43,11 +43,11 @@ func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) { } func (t *ginkgoTestingTProxy) Log(args ...interface{}) { - fmt.Println(args...) + fmt.Fprintln(GinkgoWriter, args...) } func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) { - fmt.Printf(format, args...) + fmt.Fprintf(GinkgoWriter, format, args...) } func (t *ginkgoTestingTProxy) Failed() bool { diff --git a/suite.go b/suite.go index ce148bed7..9e653f799 100644 --- a/suite.go +++ b/suite.go @@ -4,6 +4,7 @@ import ( "github.com/onsi/ginkgo/config" "github.com/onsi/ginkgo/types" + "io" "math/rand" "time" ) @@ -18,14 +19,21 @@ type suite struct { topLevelContainer *containerNode currentContainer *containerNode exampleCollection *exampleCollection + writer ginkgoWriter } -func newSuite() *suite { +type ginkgoWriter interface { + Truncate(n int) + WriteTo(w io.Writer) (n int64, err error) +} + +func newSuite(writer ginkgoWriter) *suite { topLevelContainer := newContainerNode("[Top Level]", flagTypeNone, types.CodeLocation{}) return &suite{ topLevelContainer: topLevelContainer, currentContainer: topLevelContainer, + writer: writer, } } @@ -41,7 +49,7 @@ func (suite *suite) run(t GinkgoTestingT, description string, reporters []Report panic("ginkgo.parallel.node is one-indexed and must be <= ginkgo.parallel.total") } - suite.exampleCollection = newExampleCollection(t, description, suite.topLevelContainer.generateExamples(), reporters, config) + suite.exampleCollection = newExampleCollection(t, description, suite.topLevelContainer.generateExamples(), reporters, suite.writer, config) return suite.exampleCollection.run() } diff --git a/suite_test.go b/suite_test.go index a5248163e..d9cd19c38 100644 --- a/suite_test.go +++ b/suite_test.go @@ -20,7 +20,7 @@ func init() { BeforeEach(func() { fakeT = &fakeTestingT{} fakeR = reporters.NewFakeReporter() - specSuite = newSuite() + specSuite = newSuite(nil) }) Describe("running a suite", func() {