Skip to content

Commit

Permalink
Add GinkgoWriter
Browse files Browse the repository at this point in the history
  • Loading branch information
Onsi Fakhouri committed Feb 27, 2014
1 parent 884dab8 commit b6566b8
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 16 deletions.
21 changes: 19 additions & 2 deletions example_collection.go
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/onsi/ginkgo/types"

"math/rand"
"os"
"regexp"
"sort"
"time"
Expand All @@ -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),
Expand Down Expand Up @@ -133,17 +136,19 @@ 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() {
collection.runningExample = example
example.run()
if example.failed() {
suiteFailed = true
collection.printWriterToStdout()
}
} else if example.pending() && collection.config.FailOnPending {
suiteFailed = true
Expand All @@ -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 {
Expand Down
61 changes: 56 additions & 5 deletions example_collection_test.go
Expand Up @@ -7,6 +7,7 @@ import (
. "github.com/onsi/gomega"

"math/rand"
"os"
"sort"
"time"
)
Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand All @@ -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()
})

Expand All @@ -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
Expand All @@ -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()
})

Expand Down Expand Up @@ -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()
})
Expand Down
22 changes: 21 additions & 1 deletion ginkgo.go
Expand Up @@ -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"
Expand All @@ -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()
Expand Down
6 changes: 3 additions & 3 deletions ginkgo/convert/testfile_rewriter.go
Expand Up @@ -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]
Expand Down
15 changes: 15 additions & 0 deletions ginkgo_suite_test.go
Expand Up @@ -3,6 +3,7 @@ package ginkgo
import (
. "github.com/onsi/gomega"

"io"
"math/rand"
"testing"
)
Expand Down Expand Up @@ -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
}
4 changes: 2 additions & 2 deletions ginkgo_testing_t_proxy.go
Expand Up @@ -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 {
Expand Down
12 changes: 10 additions & 2 deletions suite.go
Expand Up @@ -4,6 +4,7 @@ import (
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/types"

"io"
"math/rand"
"time"
)
Expand All @@ -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,
}
}

Expand All @@ -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()
}
Expand Down
2 changes: 1 addition & 1 deletion suite_test.go
Expand Up @@ -20,7 +20,7 @@ func init() {
BeforeEach(func() {
fakeT = &fakeTestingT{}
fakeR = reporters.NewFakeReporter()
specSuite = newSuite()
specSuite = newSuite(nil)
})

Describe("running a suite", func() {
Expand Down

0 comments on commit b6566b8

Please sign in to comment.