From df200ccd2ee45ff96a3c03123b850b3460d3b3ce Mon Sep 17 00:00:00 2001 From: Adam Colton Date: Wed, 19 Oct 2016 13:03:41 -0400 Subject: [PATCH 1/3] Supressing output during testing Tests output misleading warnings when tests were passing. Added printer to hold a reference to fmt.Print, then changed it out with voidPrinter during testing. --- is.go | 32 ++++++++++++++++++++++++++++++-- is_test.go | 5 +++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/is.go b/is.go index 0c4f7a5..a2c1c55 100644 --- a/is.go +++ b/is.go @@ -3,6 +3,7 @@ package is import ( "fmt" "reflect" + "strings" "sync" ) @@ -45,6 +46,9 @@ type I interface { // Failf indicates that the test has failed with the // formatted arguments. Failf(format string, args ...interface{}) + // Contains asserts that the container contains the + // containee + Contains(container, containee interface{}) } // New creates a new I capable of making @@ -67,6 +71,9 @@ type T interface { FailNow() } +// printer allows output to be supressed during testing +var printer = (func(...interface{}) (int, error))(fmt.Print) + // i represents an implementation of interface I. type i struct { t T @@ -79,7 +86,7 @@ func (i *i) Log(args ...interface{}) { i.l.Lock() fail := fmt.Sprint(args...) i.fails = append(i.fails, fail) - fmt.Print(decorate(fail)) + printer(decorate(fail)) i.l.Unlock() if !i.relaxed { i.t.FailNow() @@ -89,7 +96,7 @@ func (i *i) Logf(format string, args ...interface{}) { i.l.Lock() fail := fmt.Sprintf(format, args...) i.fails = append(i.fails, fail) - fmt.Print(decorate(fail)) + printer(decorate(fail)) i.l.Unlock() if !i.relaxed { i.t.FailNow() @@ -320,3 +327,24 @@ func areEqual(a, b interface{}) bool { return false } + +func (i *i) Contains(container, containee interface{}) { + switch cs := container.(type) { + case string: + i.containsString(cs, containee) + } +} + +func (i *i) containsString(container string, containee interface{}) { + var cs string + if s, ok := containee.(string); ok { + cs = s + } else if s, ok := containee.(fmt.Stringer); ok { + cs = s.String() + } else { + i.Log("expected string or String") + } + if !strings.Contains(container, cs) { + i.Logf("expected: %s", cs) + } +} diff --git a/is_test.go b/is_test.go index c1a9f85..17cbbd5 100644 --- a/is_test.go +++ b/is_test.go @@ -23,7 +23,12 @@ func (m *mockT) Failed() bool { return m.failed } +func voidPrinter(...interface{}) (int, error) { + return 0, nil +} + func TestIs(t *testing.T) { + printer = voidPrinter for _, test := range []struct { N string From 141d297c50bec0246d7a8396a51a463c14441eed Mon Sep 17 00:00:00 2001 From: Adam Colton Date: Wed, 19 Oct 2016 14:07:30 -0400 Subject: [PATCH 2/3] More accurate testing Made testing more accurate, there was a bug that prevented err string comparisons. Now looks for the error as a substring, to ignore the file and line. --- is.go | 17 ++++++++--------- is_test.go | 36 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/is.go b/is.go index a2c1c55..e6300cf 100644 --- a/is.go +++ b/is.go @@ -72,21 +72,21 @@ type T interface { } // printer allows output to be supressed during testing -var printer = (func(...interface{}) (int, error))(fmt.Print) +var printer = (func(string))( + func(s string) { + fmt.Print(decorate(s)) + }) // i represents an implementation of interface I. type i struct { t T - fails []string l sync.Mutex relaxed bool } func (i *i) Log(args ...interface{}) { i.l.Lock() - fail := fmt.Sprint(args...) - i.fails = append(i.fails, fail) - printer(decorate(fail)) + printer(decorate(fmt.Sprint(args...))) i.l.Unlock() if !i.relaxed { i.t.FailNow() @@ -94,9 +94,7 @@ func (i *i) Log(args ...interface{}) { } func (i *i) Logf(format string, args ...interface{}) { i.l.Lock() - fail := fmt.Sprintf(format, args...) - i.fails = append(i.fails, fail) - printer(decorate(fail)) + printer(decorate(fmt.Sprintf(format, args...))) i.l.Unlock() if !i.relaxed { i.t.FailNow() @@ -246,11 +244,12 @@ func (i *i) NotEqual(a, b interface{}) { } func (i *i) Fail(args ...interface{}) { + args = append([]interface{}{"failed: "}, args...) i.Log(args...) } func (i *i) Failf(format string, args ...interface{}) { - i.Logf(format, args...) + i.Logf("failed: "+format, args...) } // Panic asserts that the specified function diff --git a/is_test.go b/is_test.go index 17cbbd5..1ee5980 100644 --- a/is_test.go +++ b/is_test.go @@ -23,8 +23,10 @@ func (m *mockT) Failed() bool { return m.failed } -func voidPrinter(...interface{}) (int, error) { - return 0, nil +var printerOutput []string + +func voidPrinter(s string) { + printerOutput = append(printerOutput, strings.TrimSpace(s)) } func TestIs(t *testing.T) { @@ -143,7 +145,7 @@ func TestIs(t *testing.T) { F: func(is I) { is.NoErr(&customErr{}, &customErr{}, &customErr{}) }, - Fails: []string{"unexpected error: Oops"}, + Fails: []string{"unexpected error (0): Oops", "unexpected error (1): Oops", "unexpected error (2): Oops"}, }, { N: "NoErr(err1, err2, err3)", @@ -187,7 +189,7 @@ func TestIs(t *testing.T) { var err3 error is.Err(err1, err2, err3) }, - Fails: []string{"error expected"}, + Fails: []string{"error expected (0)", "error expected (1)", "error expected (2)"}, }, // OK { @@ -308,7 +310,7 @@ func TestIs(t *testing.T) { F: func(is I) { is.True(false, false) }, - Fails: []string{"true!=false"}, + Fails: []string{"expected true (0): false", "expected true (1): false"}, }, // is.False { @@ -321,7 +323,7 @@ func TestIs(t *testing.T) { F: func(is I) { is.False(true, true) }, - Fails: []string{"false!=true"}, + Fails: []string{"expected false (0): true", "expected false (1): true"}, }, // is.NotEqual @@ -364,6 +366,7 @@ func TestIs(t *testing.T) { tt := new(mockT) is := New(tt) + printerOutput = make([]string, 0) func() { defer func() { @@ -372,21 +375,18 @@ func TestIs(t *testing.T) { test.F(is) }() - if len(test.Fails) > 0 { - for n, fail := range test.Fails { - if !tt.Failed() { - t.Errorf("%s should fail", test.N) - } - if test.Fails[n] != fail { - t.Errorf("expected fail \"%s\" but was \"%s\".", test.Fails[n], fail) - } + for n, fail := range test.Fails { + if n >= len(printerOutput) { + t.Errorf("(%d) expected fail \"%s\"", n, fail) + } else if !strings.Contains(printerOutput[n], fail) { + t.Errorf("(%d) expected fail \"%s\" but was \"%s\"", n, fail, printerOutput[n]) } - } else { - if tt.Failed() { - t.Errorf("%s shouldn't fail but: %s", test.N, strings.Join(test.Fails, ", ")) + } + if n, l := len(test.Fails), len(printerOutput); n < l { + for ; n < l; n++ { + t.Errorf("(%d) unexpected fail \"%s\"", n, printerOutput[n]) } } - } } From 3728216cbf4bfede1dbb0c9587b3ee76730f0641 Mon Sep 17 00:00:00 2001 From: Adam Colton Date: Wed, 19 Oct 2016 14:26:55 -0400 Subject: [PATCH 3/3] Removed contains work Had been working on Contains, removed it to isolate the improvements to testing. --- is.go | 25 ------------------------- is_test.go | 6 ++++++ 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/is.go b/is.go index e6300cf..dd13b15 100644 --- a/is.go +++ b/is.go @@ -3,7 +3,6 @@ package is import ( "fmt" "reflect" - "strings" "sync" ) @@ -46,9 +45,6 @@ type I interface { // Failf indicates that the test has failed with the // formatted arguments. Failf(format string, args ...interface{}) - // Contains asserts that the container contains the - // containee - Contains(container, containee interface{}) } // New creates a new I capable of making @@ -326,24 +322,3 @@ func areEqual(a, b interface{}) bool { return false } - -func (i *i) Contains(container, containee interface{}) { - switch cs := container.(type) { - case string: - i.containsString(cs, containee) - } -} - -func (i *i) containsString(container string, containee interface{}) { - var cs string - if s, ok := containee.(string); ok { - cs = s - } else if s, ok := containee.(fmt.Stringer); ok { - cs = s.String() - } else { - i.Log("expected string or String") - } - if !strings.Contains(container, cs) { - i.Logf("expected: %s", cs) - } -} diff --git a/is_test.go b/is_test.go index 1ee5980..f8a9fcf 100644 --- a/is_test.go +++ b/is_test.go @@ -23,6 +23,12 @@ func (m *mockT) Failed() bool { return m.failed } +type fooStringer struct{} + +func (fooStringer) String() string { + return "foo" +} + var printerOutput []string func voidPrinter(s string) {