From 0e15685a2a44285fec24485bd580f79eb448809d Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Thu, 26 May 2016 15:30:34 +0200 Subject: [PATCH 1/6] update imports; make unit tests pass; add travis config --- .travis.yml | 11 +++++++++++ README.md | 6 +++--- benchmark_test.go | 3 ++- bootstrap_test.go | 3 ++- check_test.go | 34 +++++++++++++++++----------------- checkers_test.go | 3 ++- fixture_test.go | 6 ++---- foundation_test.go | 5 +++-- gen-coverage.sh | 17 +++++++++++++++++ helpers_test.go | 3 ++- printer_test.go | 2 +- reporter_test.go | 2 +- run_test.go | 7 ++++--- 13 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 .travis.yml create mode 100755 gen-coverage.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..db648e1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: go +sudo: false +go: + - tip +before_install: + - go get github.com/axw/gocov/gocov + - go get github.com/mattn/goveralls + - if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi +script: + - ./gen-coverage.sh coverage.out + - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci diff --git a/README.md b/README.md index 0ca9e57..79a0af5 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ Instructions Install the package with: - go get gopkg.in/check.v1 - + go get github.com/elopio/check + Import it with: - import "gopkg.in/check.v1" + import "github.com/elopio/check" and use _check_ as the package name inside the code. diff --git a/benchmark_test.go b/benchmark_test.go index 4dd827c..7fa8fea 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -4,7 +4,8 @@ package check_test import ( "time" - . "gopkg.in/check.v1" + + . "github.com/elopio/check" ) var benchmarkS = Suite(&BenchmarkS{}) diff --git a/bootstrap_test.go b/bootstrap_test.go index e55f327..4c7bb4e 100644 --- a/bootstrap_test.go +++ b/bootstrap_test.go @@ -14,8 +14,9 @@ package check_test import ( "fmt" - "gopkg.in/check.v1" "strings" + + "github.com/elopio/check" ) type BootstrapS struct{} diff --git a/check_test.go b/check_test.go index 871b325..7b5eac8 100644 --- a/check_test.go +++ b/check_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "gopkg.in/check.v1" + . "github.com/elopio/check" ) // We count the number of suites run at least to get a vague hint that the @@ -23,7 +23,7 @@ const suitesRunExpected = 8 var suitesRun int = 0 func Test(t *testing.T) { - check.TestingT(t) + TestingT(t) if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" { critical(fmt.Sprintf("Expected %d suites to run rather than %d", suitesRunExpected, suitesRun)) @@ -65,8 +65,8 @@ func (s *String) Write(p []byte) (n int, err error) { // Trivial wrapper to test errors happening on a different file // than the test itself. -func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) { - return c.Check(obtained, check.Equals, expected), getMyLine() +func checkEqualWrapper(c *C, obtained, expected interface{}) (result bool, line int) { + return c.Check(obtained, Equals, expected), getMyLine() } // ----------------------------------------------------------------------- @@ -76,7 +76,7 @@ type FailHelper struct { testLine int } -func (s *FailHelper) TestLogAndFail(c *check.C) { +func (s *FailHelper) TestLogAndFail(c *C) { s.testLine = getMyLine() - 1 c.Log("Expected failure!") c.Fail() @@ -87,7 +87,7 @@ func (s *FailHelper) TestLogAndFail(c *check.C) { type SuccessHelper struct{} -func (s *SuccessHelper) TestLogAndSucceed(c *check.C) { +func (s *SuccessHelper) TestLogAndSucceed(c *C) { c.Log("Expected success!") } @@ -104,7 +104,7 @@ type FixtureHelper struct { bytes int64 } -func (s *FixtureHelper) trace(name string, c *check.C) { +func (s *FixtureHelper) trace(name string, c *C) { s.calls = append(s.calls, name) if name == s.panicOn { panic(name) @@ -117,38 +117,38 @@ func (s *FixtureHelper) trace(name string, c *check.C) { } } -func (s *FixtureHelper) SetUpSuite(c *check.C) { +func (s *FixtureHelper) SetUpSuite(c *C) { s.trace("SetUpSuite", c) } -func (s *FixtureHelper) TearDownSuite(c *check.C) { +func (s *FixtureHelper) TearDownSuite(c *C) { s.trace("TearDownSuite", c) } -func (s *FixtureHelper) SetUpTest(c *check.C) { +func (s *FixtureHelper) SetUpTest(c *C) { s.trace("SetUpTest", c) } -func (s *FixtureHelper) TearDownTest(c *check.C) { +func (s *FixtureHelper) TearDownTest(c *C) { s.trace("TearDownTest", c) } -func (s *FixtureHelper) Test1(c *check.C) { +func (s *FixtureHelper) Test1(c *C) { s.trace("Test1", c) } -func (s *FixtureHelper) Test2(c *check.C) { +func (s *FixtureHelper) Test2(c *C) { s.trace("Test2", c) } -func (s *FixtureHelper) Benchmark1(c *check.C) { +func (s *FixtureHelper) Benchmark1(c *C) { s.trace("Benchmark1", c) for i := 0; i < c.N; i++ { time.Sleep(s.sleep) } } -func (s *FixtureHelper) Benchmark2(c *check.C) { +func (s *FixtureHelper) Benchmark2(c *C) { s.trace("Benchmark2", c) c.SetBytes(1024) for i := 0; i < c.N; i++ { @@ -156,7 +156,7 @@ func (s *FixtureHelper) Benchmark2(c *check.C) { } } -func (s *FixtureHelper) Benchmark3(c *check.C) { +func (s *FixtureHelper) Benchmark3(c *C) { var x []int64 s.trace("Benchmark3", c) for i := 0; i < c.N; i++ { @@ -181,7 +181,7 @@ type expectedState struct { // Verify the state of the test. Note that since this also verifies if // the test is supposed to be in a failed state, no other checks should // be done in addition to what is being tested. -func checkState(c *check.C, result interface{}, expected *expectedState) { +func checkState(c *C, result interface{}, expected *expectedState) { failed := c.Failed() c.Succeed() log := c.GetTestLog() diff --git a/checkers_test.go b/checkers_test.go index 5c69747..120b2dd 100644 --- a/checkers_test.go +++ b/checkers_test.go @@ -2,9 +2,10 @@ package check_test import ( "errors" - "gopkg.in/check.v1" "reflect" "runtime" + + "github.com/elopio/check" ) type CheckersS struct{} diff --git a/fixture_test.go b/fixture_test.go index 2bff9e1..134e543 100644 --- a/fixture_test.go +++ b/fixture_test.go @@ -2,9 +2,7 @@ package check_test -import ( - . "gopkg.in/check.v1" -) +import . "github.com/elopio/check" // ----------------------------------------------------------------------- // Fixture test suite. @@ -14,7 +12,7 @@ type FixtureS struct{} var fixtureS = Suite(&FixtureS{}) func (s *FixtureS) TestCountSuite(c *C) { - suitesRun += 1 + suitesRun++ } // ----------------------------------------------------------------------- diff --git a/foundation_test.go b/foundation_test.go index 8ecf791..bc019bc 100644 --- a/foundation_test.go +++ b/foundation_test.go @@ -8,11 +8,12 @@ package check_test import ( "fmt" - "gopkg.in/check.v1" "log" "os" "regexp" "strings" + + "github.com/elopio/check" ) // ----------------------------------------------------------------------- @@ -175,7 +176,7 @@ func (s *FoundationS) TestCallerLoggingInDifferentFile(c *check.C) { "foundation_test.go:%d:\n"+ " result, line := checkEqualWrapper\\(c, 10, 20\\)\n"+ "check_test.go:%d:\n"+ - " return c.Check\\(obtained, check.Equals, expected\\), getMyLine\\(\\)\n"+ + " return c.Check\\(obtained, Equals, expected\\), getMyLine\\(\\)\n"+ "\\.\\.\\. obtained int = 10\n"+ "\\.\\.\\. expected int = 20\n\n", testLine, line) diff --git a/gen-coverage.sh b/gen-coverage.sh new file mode 100755 index 0000000..75147aa --- /dev/null +++ b/gen-coverage.sh @@ -0,0 +1,17 @@ +#!/bin/sh +out_file=$1 + +append_coverage() { + local profile="$1" + if [ -f $profile ]; then + cat $profile | grep -v "mode: count" >> "$out_file" + rm $profile + fi +} + +echo "mode: count" > "$out_file" + +for pkg in $(go list ./...); do + go test -covermode=count -coverprofile=profile.out "$pkg" + append_coverage profile.out +done diff --git a/helpers_test.go b/helpers_test.go index 4baa656..52247ef 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -4,11 +4,12 @@ package check_test import ( - "gopkg.in/check.v1" "os" "reflect" "runtime" "sync" + + "github.com/elopio/check" ) var helpersS = check.Suite(&HelpersS{}) diff --git a/printer_test.go b/printer_test.go index 538b2d5..b02fa51 100644 --- a/printer_test.go +++ b/printer_test.go @@ -1,7 +1,7 @@ package check_test import ( - . "gopkg.in/check.v1" + . "github.com/elopio/check" ) var _ = Suite(&PrinterS{}) diff --git a/reporter_test.go b/reporter_test.go index 0b7ed76..e3eaf74 100644 --- a/reporter_test.go +++ b/reporter_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "runtime" - . "gopkg.in/check.v1" + . "github.com/elopio/check" ) var _ = Suite(&reporterS{}) diff --git a/run_test.go b/run_test.go index f41fffc..2252698 100644 --- a/run_test.go +++ b/run_test.go @@ -4,9 +4,10 @@ package check_test import ( "errors" - . "gopkg.in/check.v1" "os" "sync" + + . "github.com/elopio/check" ) var runnerS = Suite(&RunS{}) @@ -400,7 +401,7 @@ func (s *RunS) TestStreamModeWithMiss(c *C) { // ----------------------------------------------------------------------- // Verify that that the keep work dir request indeed does so. -type WorkDirSuite struct {} +type WorkDirSuite struct{} func (s *WorkDirSuite) Test(c *C) { c.MkDir() @@ -411,7 +412,7 @@ func (s *RunS) TestKeepWorkDir(c *C) { runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true} result := Run(&WorkDirSuite{}, &runConf) - c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir) + c.Assert(result.String(), Matches, ".*\nWORK="+result.WorkDir) stat, err := os.Stat(result.WorkDir) c.Assert(err, IsNil) From 93eb1583df6a5cdeb749d275f3e414d5fcadc77c Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Thu, 26 May 2016 16:29:21 +0200 Subject: [PATCH 2/6] removed unused go packages --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index db648e1..59f0abe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,9 +3,7 @@ sudo: false go: - tip before_install: - - go get github.com/axw/gocov/gocov - go get github.com/mattn/goveralls - - if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi script: - ./gen-coverage.sh coverage.out - $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci From 937a5a0179ab49b94d42daa680276d10bbfc98fa Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Thu, 26 May 2016 09:15:18 -0600 Subject: [PATCH 3/6] Copy the Stream config to the suiteRunner (#2) If the runner needs the Stream value from the config, it should not get it from the reporter. It is better to keep a copy of the value in the runner itself to make the communication between runner and reporter only one-direction. --- check.go | 4 +++- reporter.go | 18 +++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/check.go b/check.go index 82c26fa..0dd5222 100644 --- a/check.go +++ b/check.go @@ -522,6 +522,7 @@ type suiteRunner struct { reportedProblemLast bool benchTime time.Duration benchMem bool + stream bool } type RunConf struct { @@ -561,6 +562,7 @@ func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { tempDir: &tempDir{}, keepDir: conf.KeepWorkDir, tests: make([]*methodType, 0, suiteNumMethods), + stream: conf.Stream, } if runner.benchTime == 0 { runner.benchTime = 1 * time.Second @@ -641,7 +643,7 @@ func (runner *suiteRunner) run() *Result { // goroutine with the provided dispatcher for running it. func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { var logw io.Writer - if runner.output.Stream { + if runner.stream { logw = runner.output } if logb == nil { diff --git a/reporter.go b/reporter.go index fb04f76..cce929b 100644 --- a/reporter.go +++ b/reporter.go @@ -13,12 +13,12 @@ type outputWriter struct { m sync.Mutex writer io.Writer wroteCallProblemLast bool - Stream bool - Verbose bool + stream bool + verbose bool } func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { - return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} + return &outputWriter{writer: writer, stream: stream, verbose: verbose} } func (ow *outputWriter) Write(content []byte) (n int, err error) { @@ -29,7 +29,7 @@ func (ow *outputWriter) Write(content []byte) (n int, err error) { } func (ow *outputWriter) WriteCallStarted(label string, c *C) { - if ow.Stream { + if ow.stream { header := renderCallHeader(label, c, "", "\n") ow.m.Lock() ow.writer.Write([]byte(header)) @@ -39,7 +39,7 @@ func (ow *outputWriter) WriteCallStarted(label string, c *C) { func (ow *outputWriter) WriteCallProblem(label string, c *C) { var prefix string - if !ow.Stream { + if !ow.stream { prefix = "\n-----------------------------------" + "-----------------------------------\n" } @@ -47,14 +47,14 @@ func (ow *outputWriter) WriteCallProblem(label string, c *C) { ow.m.Lock() ow.wroteCallProblemLast = true ow.writer.Write([]byte(header)) - if !ow.Stream { + if !ow.stream { c.logb.WriteTo(ow.writer) } ow.m.Unlock() } func (ow *outputWriter) WriteCallSuccess(label string, c *C) { - if ow.Stream || (ow.Verbose && c.kind == testKd) { + if ow.stream || (ow.verbose && c.kind == testKd) { // TODO Use a buffer here. var suffix string if c.reason != "" { @@ -64,13 +64,13 @@ func (ow *outputWriter) WriteCallSuccess(label string, c *C) { suffix += "\t" + c.timerString() } suffix += "\n" - if ow.Stream { + if ow.stream { suffix += "\n" } header := renderCallHeader(label, c, "", suffix) ow.m.Lock() // Resist temptation of using line as prefix above due to race. - if !ow.Stream && ow.wroteCallProblemLast { + if !ow.stream && ow.wroteCallProblemLast { header = "\n-----------------------------------" + "-----------------------------------\n" + header From 4dee14ea6fc7c8535842bddb69bacd1ab3ea3f76 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Thu, 26 May 2016 18:59:09 -0600 Subject: [PATCH 4/6] Join the Stream and Verbose flags into verbosity (#3) --- check.go | 17 +++++++++++----- export_test.go | 4 ++-- reporter.go | 19 +++++++++--------- reporter_test.go | 50 +++++++++++++++++++----------------------------- 4 files changed, 43 insertions(+), 47 deletions(-) diff --git a/check.go b/check.go index 0dd5222..1d4e04f 100644 --- a/check.go +++ b/check.go @@ -522,7 +522,7 @@ type suiteRunner struct { reportedProblemLast bool benchTime time.Duration benchMem bool - stream bool + verbosity uint8 } type RunConf struct { @@ -552,17 +552,24 @@ func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { suiteType := reflect.TypeOf(suite) suiteNumMethods := suiteType.NumMethod() suiteValue := reflect.ValueOf(suite) - + var verbosity uint8 + if conf.Verbose { + verbosity = 1 + } + if conf.Stream { + verbosity = 2 + } + runner := &suiteRunner{ suite: suite, - output: newOutputWriter(conf.Output, conf.Stream, conf.Verbose), + output: newOutputWriter(conf.Output, verbosity), tracker: newResultTracker(), benchTime: conf.BenchmarkTime, benchMem: conf.BenchmarkMem, tempDir: &tempDir{}, keepDir: conf.KeepWorkDir, tests: make([]*methodType, 0, suiteNumMethods), - stream: conf.Stream, + verbosity: verbosity, } if runner.benchTime == 0 { runner.benchTime = 1 * time.Second @@ -643,7 +650,7 @@ func (runner *suiteRunner) run() *Result { // goroutine with the provided dispatcher for running it. func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { var logw io.Writer - if runner.stream { + if runner.verbosity > 1 { logw = runner.output } if logb == nil { diff --git a/export_test.go b/export_test.go index abb89a2..cf51a99 100644 --- a/export_test.go +++ b/export_test.go @@ -10,8 +10,8 @@ func Indent(s, with string) string { return indent(s, with) } -func NewOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { - return newOutputWriter(writer, stream, verbose) +func NewOutputWriter(writer io.Writer, verbosity uint8) *outputWriter { + return newOutputWriter(writer, verbosity) } func (c *C) FakeSkip(reason string) { diff --git a/reporter.go b/reporter.go index cce929b..68d3c96 100644 --- a/reporter.go +++ b/reporter.go @@ -13,12 +13,11 @@ type outputWriter struct { m sync.Mutex writer io.Writer wroteCallProblemLast bool - stream bool - verbose bool + verbosity uint8 } -func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { - return &outputWriter{writer: writer, stream: stream, verbose: verbose} +func newOutputWriter(writer io.Writer, verbosity uint8) *outputWriter { + return &outputWriter{writer: writer, verbosity: verbosity} } func (ow *outputWriter) Write(content []byte) (n int, err error) { @@ -29,7 +28,7 @@ func (ow *outputWriter) Write(content []byte) (n int, err error) { } func (ow *outputWriter) WriteCallStarted(label string, c *C) { - if ow.stream { + if ow.verbosity > 1 { header := renderCallHeader(label, c, "", "\n") ow.m.Lock() ow.writer.Write([]byte(header)) @@ -39,7 +38,7 @@ func (ow *outputWriter) WriteCallStarted(label string, c *C) { func (ow *outputWriter) WriteCallProblem(label string, c *C) { var prefix string - if !ow.stream { + if ow.verbosity < 2 { prefix = "\n-----------------------------------" + "-----------------------------------\n" } @@ -47,14 +46,14 @@ func (ow *outputWriter) WriteCallProblem(label string, c *C) { ow.m.Lock() ow.wroteCallProblemLast = true ow.writer.Write([]byte(header)) - if !ow.stream { + if ow.verbosity < 2 { c.logb.WriteTo(ow.writer) } ow.m.Unlock() } func (ow *outputWriter) WriteCallSuccess(label string, c *C) { - if ow.stream || (ow.verbose && c.kind == testKd) { + if ow.verbosity > 1 || (ow.verbosity == 1 && c.kind == testKd) { // TODO Use a buffer here. var suffix string if c.reason != "" { @@ -64,13 +63,13 @@ func (ow *outputWriter) WriteCallSuccess(label string, c *C) { suffix += "\t" + c.timerString() } suffix += "\n" - if ow.stream { + if ow.verbosity > 1 { suffix += "\n" } header := renderCallHeader(label, c, "", suffix) ow.m.Lock() // Resist temptation of using line as prefix above due to race. - if !ow.stream && ow.wroteCallProblemLast { + if ow.verbosity < 2 && ow.wroteCallProblemLast { header = "\n-----------------------------------" + "-----------------------------------\n" + header diff --git a/reporter_test.go b/reporter_test.go index e3eaf74..ff4de9f 100644 --- a/reporter_test.go +++ b/reporter_test.go @@ -24,9 +24,8 @@ func (s *reporterS) TestWrite(c *C) { testString := "test string" output := String{} - dummyStream := true - dummyVerbose := true - o := NewOutputWriter(&output, dummyStream, dummyVerbose) + var dummyVerbosity uint8 + o := NewOutputWriter(&output, dummyVerbosity) o.Write([]byte(testString)) c.Assert(output.value, Equals, testString) @@ -34,11 +33,10 @@ func (s *reporterS) TestWrite(c *C) { func (s *reporterS) TestWriteCallStartedWithStreamFlag(c *C) { testLabel := "test started label" - stream := true + var verbosity uint8 = 2 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallStarted(testLabel, c) expected := fmt.Sprintf("%s: %s:\\d+: %s\n", testLabel, s.testFile, c.TestName()) @@ -46,12 +44,11 @@ func (s *reporterS) TestWriteCallStartedWithStreamFlag(c *C) { } func (s *reporterS) TestWriteCallStartedWithoutStreamFlag(c *C) { - stream := false + var verbosity uint8 = 1 output := String{} dummyLabel := "dummy" - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallStarted(dummyLabel, c) c.Assert(output.value, Equals, "") @@ -59,11 +56,10 @@ func (s *reporterS) TestWriteCallStartedWithoutStreamFlag(c *C) { func (s *reporterS) TestWriteCallProblemWithStreamFlag(c *C) { testLabel := "test problem label" - stream := true + var verbosity uint8 = 2 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallProblem(testLabel, c) expected := fmt.Sprintf("%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) @@ -72,11 +68,10 @@ func (s *reporterS) TestWriteCallProblemWithStreamFlag(c *C) { func (s *reporterS) TestWriteCallProblemWithoutStreamFlag(c *C) { testLabel := "test problem label" - stream := false + var verbosity uint8 = 1 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallProblem(testLabel, c) expected := fmt.Sprintf(""+ @@ -89,11 +84,10 @@ func (s *reporterS) TestWriteCallProblemWithoutStreamFlag(c *C) { func (s *reporterS) TestWriteCallProblemWithoutStreamFlagWithLog(c *C) { testLabel := "test problem label" testLog := "test log" - stream := false + var verbosity uint8 = 1 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) c.Log(testLog) o.WriteCallProblem(testLabel, c) @@ -106,11 +100,10 @@ func (s *reporterS) TestWriteCallProblemWithoutStreamFlagWithLog(c *C) { func (s *reporterS) TestWriteCallSuccessWithStreamFlag(c *C) { testLabel := "test success label" - stream := true + var verbosity uint8 = 2 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallSuccess(testLabel, c) expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n\n", testLabel, s.testFile, c.TestName()) @@ -120,11 +113,10 @@ func (s *reporterS) TestWriteCallSuccessWithStreamFlag(c *C) { func (s *reporterS) TestWriteCallSuccessWithStreamFlagAndReason(c *C) { testLabel := "test success label" testReason := "test skip reason" - stream := true + var verbosity uint8 = 2 output := String{} - dummyVerbose := true - o := NewOutputWriter(&output, stream, dummyVerbose) + o := NewOutputWriter(&output, verbosity) c.FakeSkip(testReason) o.WriteCallSuccess(testLabel, c) @@ -135,11 +127,10 @@ func (s *reporterS) TestWriteCallSuccessWithStreamFlagAndReason(c *C) { func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithVerboseFlag(c *C) { testLabel := "test success label" - stream := false - verbose := true + var verbosity uint8 = 1 output := String{} - o := NewOutputWriter(&output, stream, verbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallSuccess(testLabel, c) expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n", testLabel, s.testFile, c.TestName()) @@ -148,11 +139,10 @@ func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithVerboseFlag(c *C) { func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithoutVerboseFlag(c *C) { testLabel := "test success label" - stream := false - verbose := false + var verbosity uint8 = 0 output := String{} - o := NewOutputWriter(&output, stream, verbose) + o := NewOutputWriter(&output, verbosity) o.WriteCallSuccess(testLabel, c) c.Assert(output.value, Equals, "") From 55f12babaf0cea7c15396f6c0380af89a236feef Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 27 May 2016 09:21:49 -0600 Subject: [PATCH 5/6] Split the logger and the reporter (#4) The logger and the reporter should be configured independently. We can do many improvements in the logger, but for now this change preserves the public interfaces, keeps all the tests passing and lets us focus on improving the reporter first. --- check.go | 29 +++++++++++++++-------------- reporter.go | 7 ------- reporter_test.go | 11 ----------- 3 files changed, 15 insertions(+), 32 deletions(-) diff --git a/check.go b/check.go index 1d4e04f..a8c8d4d 100644 --- a/check.go +++ b/check.go @@ -84,7 +84,6 @@ type C struct { testName string _status funcStatus logb *logger - logw io.Writer done chan *C reason string mustFail bool @@ -109,25 +108,30 @@ func (c *C) stopNow() { // logger is a concurrency safe byte.Buffer type logger struct { sync.Mutex - writer bytes.Buffer + buffer bytes.Buffer + output io.Writer + verbosity uint8 } func (l *logger) Write(buf []byte) (int, error) { l.Lock() defer l.Unlock() - return l.writer.Write(buf) + if l.verbosity > 1 { + l.output.Write(buf) + } + return l.buffer.Write(buf) } func (l *logger) WriteTo(w io.Writer) (int64, error) { l.Lock() defer l.Unlock() - return l.writer.WriteTo(w) + return l.buffer.WriteTo(w) } func (l *logger) String() string { l.Lock() defer l.Unlock() - return l.writer.String() + return l.buffer.String() } // ----------------------------------------------------------------------- @@ -198,9 +202,6 @@ func (c *C) logNewLine() { func (c *C) writeLog(buf []byte) { c.logb.Write(buf) - if c.logw != nil { - c.logw.Write(buf) - } } func hasStringOrError(x interface{}) (ok bool) { @@ -518,6 +519,7 @@ type suiteRunner struct { tracker *resultTracker tempDir *tempDir keepDir bool + logOutput io.Writer output *outputWriter reportedProblemLast bool benchTime time.Duration @@ -562,6 +564,7 @@ func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { runner := &suiteRunner{ suite: suite, + logOutput: conf.Output, output: newOutputWriter(conf.Output, verbosity), tracker: newResultTracker(), benchTime: conf.BenchmarkTime, @@ -649,19 +652,17 @@ func (runner *suiteRunner) run() *Result { // Create a call object with the given suite method, and fork a // goroutine with the provided dispatcher for running it. func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { - var logw io.Writer - if runner.verbosity > 1 { - logw = runner.output - } if logb == nil { - logb = new(logger) + logb = &logger{ + output: runner.logOutput, + verbosity: runner.verbosity, + } } c := &C{ method: method, kind: kind, testName: testName, logb: logb, - logw: logw, tempDir: runner.tempDir, done: make(chan *C, 1), timer: timer{benchTime: runner.benchTime}, diff --git a/reporter.go b/reporter.go index 68d3c96..f963659 100644 --- a/reporter.go +++ b/reporter.go @@ -20,13 +20,6 @@ func newOutputWriter(writer io.Writer, verbosity uint8) *outputWriter { return &outputWriter{writer: writer, verbosity: verbosity} } -func (ow *outputWriter) Write(content []byte) (n int, err error) { - ow.m.Lock() - n, err = ow.writer.Write(content) - ow.m.Unlock() - return -} - func (ow *outputWriter) WriteCallStarted(label string, c *C) { if ow.verbosity > 1 { header := renderCallHeader(label, c, "", "\n") diff --git a/reporter_test.go b/reporter_test.go index ff4de9f..11892aa 100644 --- a/reporter_test.go +++ b/reporter_test.go @@ -20,17 +20,6 @@ func (s *reporterS) SetUpSuite(c *C) { s.testFile = filepath.Base(fileName) } -func (s *reporterS) TestWrite(c *C) { - testString := "test string" - output := String{} - - var dummyVerbosity uint8 - o := NewOutputWriter(&output, dummyVerbosity) - - o.Write([]byte(testString)) - c.Assert(output.value, Equals, testString) -} - func (s *reporterS) TestWriteCallStartedWithStreamFlag(c *C) { testLabel := "test started label" var verbosity uint8 = 2 From 8b4d3d9114eec3a189b45e60aa0bf58eeb952308 Mon Sep 17 00:00:00 2001 From: Leo Arias Date: Fri, 29 Jan 2016 15:29:42 +0000 Subject: [PATCH 6/6] Added an interface for the reporter --- check.go | 20 +++--- export_test.go | 4 ++ reporter.go | 50 +++++++++++-- reporter_test.go | 183 ++++++++++++++++++++++++++++------------------- 4 files changed, 169 insertions(+), 88 deletions(-) diff --git a/check.go b/check.go index a8c8d4d..cbef564 100644 --- a/check.go +++ b/check.go @@ -520,7 +520,7 @@ type suiteRunner struct { tempDir *tempDir keepDir bool logOutput io.Writer - output *outputWriter + reporter testReporter reportedProblemLast bool benchTime time.Duration benchMem bool @@ -565,7 +565,7 @@ func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { runner := &suiteRunner{ suite: suite, logOutput: conf.Output, - output: newOutputWriter(conf.Output, verbosity), + reporter: newOutputWriter(conf.Output, verbosity), tracker: newResultTracker(), benchTime: conf.BenchmarkTime, benchMem: conf.BenchmarkMem, @@ -853,7 +853,7 @@ func (runner *suiteRunner) checkFixtureArgs() bool { } func (runner *suiteRunner) reportCallStarted(c *C) { - runner.output.WriteCallStarted("START", c) + runner.reporter.StartTest(c) } func (runner *suiteRunner) reportCallDone(c *C) { @@ -861,23 +861,23 @@ func (runner *suiteRunner) reportCallDone(c *C) { switch c.status() { case succeededSt: if c.mustFail { - runner.output.WriteCallSuccess("FAIL EXPECTED", c) + runner.reporter.AddExpectedFailure(c) } else { - runner.output.WriteCallSuccess("PASS", c) + runner.reporter.AddSuccess(c) } case skippedSt: - runner.output.WriteCallSuccess("SKIP", c) + runner.reporter.AddSkip(c) case failedSt: - runner.output.WriteCallProblem("FAIL", c) + runner.reporter.AddFailure(c) case panickedSt: - runner.output.WriteCallProblem("PANIC", c) + runner.reporter.AddError(c) case fixturePanickedSt: // That's a testKd call reporting that its fixture // has panicked. The fixture call which caused the // panic itself was tracked above. We'll report to // aid debugging. - runner.output.WriteCallProblem("PANIC", c) + runner.reporter.AddError(c) case missedSt: - runner.output.WriteCallSuccess("MISS", c) + runner.reporter.AddMissed(c) } } diff --git a/export_test.go b/export_test.go index cf51a99..96127b0 100644 --- a/export_test.go +++ b/export_test.go @@ -2,6 +2,10 @@ package check import "io" +type TestReporter interface { + testReporter +} + func PrintLine(filename string, line int) (string, error) { return printLine(filename, line) } diff --git a/reporter.go b/reporter.go index f963659..3a42ba3 100644 --- a/reporter.go +++ b/reporter.go @@ -6,6 +6,18 @@ import ( "sync" ) +type testReporter interface { + StartTest(*C) + StopTest(*C) + AddFailure(*C) + AddError(*C) + AddUnexpectedSuccess(*C) + AddSuccess(*C) + AddExpectedFailure(*C) + AddSkip(*C) + AddMissed(*C) +} + // ----------------------------------------------------------------------- // Output writer manages atomic output writing according to settings. @@ -20,16 +32,27 @@ func newOutputWriter(writer io.Writer, verbosity uint8) *outputWriter { return &outputWriter{writer: writer, verbosity: verbosity} } -func (ow *outputWriter) WriteCallStarted(label string, c *C) { +func (ow *outputWriter) StartTest(c *C) { if ow.verbosity > 1 { - header := renderCallHeader(label, c, "", "\n") + header := renderCallHeader("START", c, "", "\n") ow.m.Lock() ow.writer.Write([]byte(header)) ow.m.Unlock() } } -func (ow *outputWriter) WriteCallProblem(label string, c *C) { +func (ow *outputWriter) StopTest(c *C) { +} + +func (ow *outputWriter) AddFailure(c *C) { + ow.writeProblem("FAIL", c) +} + +func (ow *outputWriter) AddError(c *C) { + ow.writeProblem("PANIC", c) +} + +func (ow *outputWriter) writeProblem(label string, c *C) { var prefix string if ow.verbosity < 2 { prefix = "\n-----------------------------------" + @@ -45,7 +68,26 @@ func (ow *outputWriter) WriteCallProblem(label string, c *C) { ow.m.Unlock() } -func (ow *outputWriter) WriteCallSuccess(label string, c *C) { +func (ow *outputWriter) AddUnexpectedSuccess(c *C) { +} + +func (ow *outputWriter) AddSuccess(c *C) { + ow.writeSuccess("PASS", c) +} + +func (ow *outputWriter) AddExpectedFailure(c *C) { + ow.writeSuccess("FAIL EXPECTED", c) +} + +func (ow *outputWriter) AddSkip(c *C) { + ow.writeSuccess("SKIP", c) +} + +func (ow *outputWriter) AddMissed(c *C) { + ow.writeSuccess("MISS", c) +} + +func (ow *outputWriter) writeSuccess(label string, c *C) { if ow.verbosity > 1 || (ow.verbosity == 1 && c.kind == testKd) { // TODO Use a buffer here. var suffix string diff --git a/reporter_test.go b/reporter_test.go index 11892aa..5a8c9a2 100644 --- a/reporter_test.go +++ b/reporter_test.go @@ -20,119 +20,154 @@ func (s *reporterS) SetUpSuite(c *C) { s.testFile = filepath.Base(fileName) } -func (s *reporterS) TestWriteCallStartedWithStreamFlag(c *C) { - testLabel := "test started label" +func (s *reporterS) TestStartTestWithHighVerbosity(c *C) { var verbosity uint8 = 2 output := String{} o := NewOutputWriter(&output, verbosity) - o.WriteCallStarted(testLabel, c) - expected := fmt.Sprintf("%s: %s:\\d+: %s\n", testLabel, s.testFile, c.TestName()) + o.StartTest(c) + expected := fmt.Sprintf("START: %s:\\d+: %s\n", s.testFile, c.TestName()) c.Assert(output.value, Matches, expected) } -func (s *reporterS) TestWriteCallStartedWithoutStreamFlag(c *C) { +func (s *reporterS) TestStartTestLowVerbosity(c *C) { var verbosity uint8 = 1 output := String{} - dummyLabel := "dummy" o := NewOutputWriter(&output, verbosity) - o.WriteCallStarted(dummyLabel, c) + o.StartTest(c) c.Assert(output.value, Equals, "") } -func (s *reporterS) TestWriteCallProblemWithStreamFlag(c *C) { - testLabel := "test problem label" - var verbosity uint8 = 2 - output := String{} +var problemTests = []string{"FAIL", "PANIC"} - o := NewOutputWriter(&output, verbosity) +func addProblem(label string, r TestReporter, c *C) { + if label == "FAIL" { + r.AddFailure(c) + } else if label == "PANIC" { + r.AddError(c) + } else { + panic("Unknown problem: " + label) + } +} - o.WriteCallProblem(testLabel, c) - expected := fmt.Sprintf("%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) - c.Assert(output.value, Matches, expected) +func (s *reporterS) TestAddProblemWitHighVerbosity(c *C) { + for _, testLabel := range problemTests { + var verbosity uint8 = 2 + output := String{} + + o := NewOutputWriter(&output, verbosity) + + addProblem(testLabel, o, c) + expected := fmt.Sprintf("%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) + c.Check(output.value, Matches, expected) + } } -func (s *reporterS) TestWriteCallProblemWithoutStreamFlag(c *C) { - testLabel := "test problem label" - var verbosity uint8 = 1 - output := String{} +func (s *reporterS) TestAddProblemWithLowVerbosity(c *C) { + for _, testLabel := range problemTests { + var verbosity uint8 = 1 + output := String{} + + o := NewOutputWriter(&output, verbosity) + + addProblem(testLabel, o, c) + expected := fmt.Sprintf(""+ + "\n"+ + "----------------------------------------------------------------------\n"+ + "%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) + c.Check(output.value, Matches, expected) + } +} - o := NewOutputWriter(&output, verbosity) +func (s *reporterS) TestAddProblemWithLowVerbosityWithLog(c *C) { + for _, testLabel := range problemTests { + testLog := "test log" + var verbosity uint8 = 1 + output := String{} - o.WriteCallProblem(testLabel, c) - expected := fmt.Sprintf(""+ - "\n"+ - "----------------------------------------------------------------------\n"+ - "%s: %s:\\d+: %s\n\n", testLabel, s.testFile, c.TestName()) - c.Assert(output.value, Matches, expected) -} + o := NewOutputWriter(&output, verbosity) -func (s *reporterS) TestWriteCallProblemWithoutStreamFlagWithLog(c *C) { - testLabel := "test problem label" - testLog := "test log" - var verbosity uint8 = 1 - output := String{} + c.Log(testLog) + addProblem(testLabel, o, c) - o := NewOutputWriter(&output, verbosity) + expected := fmt.Sprintf(""+ + "\n"+ + "----------------------------------------------------------------------\n"+ + "%s: %s:\\d+: %s\n\n%s\n", testLabel, s.testFile, c.TestName(), testLog) + c.Check(output.value, Matches, expected) + } +} - c.Log(testLog) - o.WriteCallProblem(testLabel, c) - expected := fmt.Sprintf(""+ - "\n"+ - "----------------------------------------------------------------------\n"+ - "%s: %s:\\d+: %s\n\n%s\n", testLabel, s.testFile, c.TestName(), testLog) - c.Assert(output.value, Matches, expected) +var successTests = []string{"PASS", "SKIP", "FAIL EXPECTED", "MISS"} + +func addSuccess(label string, r TestReporter, c *C) { + if label == "PASS" { + r.AddSuccess(c) + } else if label == "SKIP" { + r.AddSkip(c) + } else if label == "FAIL EXPECTED" { + r.AddExpectedFailure(c) + } else if label == "MISS" { + r.AddMissed(c) + } else { + panic("Unknown success: " + label) + } } -func (s *reporterS) TestWriteCallSuccessWithStreamFlag(c *C) { - testLabel := "test success label" - var verbosity uint8 = 2 - output := String{} +func (s *reporterS) TestAddSuccessWithHighVerbosity(c *C) { + for _, testLabel := range successTests { + var verbosity uint8 = 2 + output := String{} - o := NewOutputWriter(&output, verbosity) + o := NewOutputWriter(&output, verbosity) - o.WriteCallSuccess(testLabel, c) - expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n\n", testLabel, s.testFile, c.TestName()) - c.Assert(output.value, Matches, expected) + addSuccess(testLabel, o, c) + expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n\n", testLabel, s.testFile, c.TestName()) + c.Check(output.value, Matches, expected) + } } -func (s *reporterS) TestWriteCallSuccessWithStreamFlagAndReason(c *C) { - testLabel := "test success label" - testReason := "test skip reason" - var verbosity uint8 = 2 - output := String{} +func (s *reporterS) TestAddSuccessWithHighVerbosityAndReason(c *C) { + for _, testLabel := range successTests { + testReason := "test skip reason" + var verbosity uint8 = 2 + output := String{} - o := NewOutputWriter(&output, verbosity) - c.FakeSkip(testReason) + o := NewOutputWriter(&output, verbosity) + c.FakeSkip(testReason) - o.WriteCallSuccess(testLabel, c) - expected := fmt.Sprintf("%s: %s:\\d+: %s \\(%s\\)\t\\d\\.\\d+s\n\n", - testLabel, s.testFile, c.TestName(), testReason) - c.Assert(output.value, Matches, expected) + addSuccess(testLabel, o, c) + expected := fmt.Sprintf("%s: %s:\\d+: %s \\(%s\\)\t\\d\\.\\d+s\n\n", + testLabel, s.testFile, c.TestName(), testReason) + c.Check(output.value, Matches, expected) + } } -func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithVerboseFlag(c *C) { - testLabel := "test success label" - var verbosity uint8 = 1 - output := String{} +func (s *reporterS) TestAddSuccessWithLowVerbosity(c *C) { + for _, testLabel := range successTests { + var verbosity uint8 = 1 + output := String{} - o := NewOutputWriter(&output, verbosity) + o := NewOutputWriter(&output, verbosity) - o.WriteCallSuccess(testLabel, c) - expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n", testLabel, s.testFile, c.TestName()) - c.Assert(output.value, Matches, expected) + addSuccess(testLabel, o, c) + + expected := fmt.Sprintf("%s: %s:\\d+: %s\t\\d\\.\\d+s\n", testLabel, s.testFile, c.TestName()) + c.Check(output.value, Matches, expected) + } } -func (s *reporterS) TestWriteCallSuccessWithoutStreamFlagWithoutVerboseFlag(c *C) { - testLabel := "test success label" - var verbosity uint8 = 0 - output := String{} +func (s *reporterS) TestAddSuccessWithoutVerbosity(c *C) { + for _, testLabel := range successTests { + var verbosity uint8 = 0 + output := String{} - o := NewOutputWriter(&output, verbosity) + o := NewOutputWriter(&output, verbosity) - o.WriteCallSuccess(testLabel, c) - c.Assert(output.value, Equals, "") + addSuccess(testLabel, o, c) + c.Check(output.value, Equals, "") + } }