Skip to content

Commit

Permalink
Merge 477443d into 369f37c
Browse files Browse the repository at this point in the history
  • Loading branch information
maxatome committed Jun 13, 2018
2 parents 369f37c + 477443d commit 0bd6254
Show file tree
Hide file tree
Showing 9 changed files with 758 additions and 140 deletions.
71 changes: 71 additions & 0 deletions cmp_deeply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2018, Maxime Soulé
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.

package testdeep

import (
"bytes"
"fmt"
"reflect"
"strings"
)

func formatError(t TestingT, err *Error, args ...interface{}) {
t.Helper()

const failedTest = "Failed test"

var buf *bytes.Buffer
switch len(args) {
case 0:
buf = bytes.NewBufferString(failedTest + "\n")
case 1:
buf = bytes.NewBufferString(failedTest + " '")
fmt.Fprint(buf, args[0])
buf.WriteString("'\n")
default:
buf = bytes.NewBufferString(failedTest + " '")
if str, ok := args[0].(string); ok && strings.ContainsRune(str, '%') {
fmt.Fprintf(buf, str, args[1:]...)
} else {
fmt.Fprint(buf, args...)
}
buf.WriteString("'\n")
}

err.Append(buf, "")

t.Error(buf.String())
}

func cmpDeeply(ctx Context, t TestingT, got, expected interface{},
args ...interface{}) bool {
t.Helper()

err := deepValueEqualFinal(ctx,
reflect.ValueOf(got), reflect.ValueOf(expected))
if err == nil {
return true
}
formatError(t, err, args...)
return false
}

// CmpDeeply returns true if "got" matches "expected". "expected" can
// be the same type as "got" is, or contains some TestDeep
// operators. If "got" does not match "expected", it returns false and
// the reason of failure is logged with the help of "t" Error()
// method.
//
// "args..." are optional and allow to name the test. This name is
// logged as is in case of failure. If len(args) > 1 and the first
// item of args is a string and contains a '%' rune then fmt.Fprintf
// is used to compose the name, else args are passed to fmt.Fprint.
func CmpDeeply(t TestingT, got, expected interface{},
args ...interface{}) bool {
t.Helper()
return cmpDeeply(NewContext(), t, got, expected, args...)
}
316 changes: 270 additions & 46 deletions cmp_funcs.go

Large diffs are not rendered by default.

36 changes: 26 additions & 10 deletions cmp_funcs_misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@

package testdeep

import (
"testing"
)

// CmpTrue is a shortcut for:
//
// CmpDeeply(t, got, true, args...)
//
// Returns true if the test is OK, false if it fails.
func CmpTrue(t *testing.T, got interface{}, args ...interface{}) bool {
//
// "args..." are optional and allow to name the test. This name is
// logged as is in case of failure. If len(args) > 1 and the first
// item of args is a string and contains a '%' rune then fmt.Fprintf
// is used to compose the name, else args are passed to fmt.Fprint.
func CmpTrue(t TestingT, got interface{}, args ...interface{}) bool {
t.Helper()
return CmpDeeply(t, got, true, args...)
}
Expand All @@ -25,12 +26,17 @@ func CmpTrue(t *testing.T, got interface{}, args ...interface{}) bool {
// CmpDeeply(t, got, false, args...)
//
// Returns true if the test is OK, false if it fails.
func CmpFalse(t *testing.T, got interface{}, args ...interface{}) bool {
//
// "args..." are optional and allow to name the test. This name is
// logged as is in case of failure. If len(args) > 1 and the first
// item of args is a string and contains a '%' rune then fmt.Fprintf
// is used to compose the name, else args are passed to fmt.Fprint.
func CmpFalse(t TestingT, got interface{}, args ...interface{}) bool {
t.Helper()
return CmpDeeply(t, got, false, args...)
}

func cmpError(ctx Context, t *testing.T, got error, args ...interface{}) bool {
func cmpError(ctx Context, t TestingT, got error, args ...interface{}) bool {
t.Helper()

if got != nil {
Expand All @@ -49,7 +55,7 @@ func cmpError(ctx Context, t *testing.T, got error, args ...interface{}) bool {
return false
}

func cmpNoError(ctx Context, t *testing.T, got error, args ...interface{}) bool {
func cmpNoError(ctx Context, t TestingT, got error, args ...interface{}) bool {
t.Helper()

if got == nil {
Expand All @@ -72,7 +78,12 @@ func cmpNoError(ctx Context, t *testing.T, got error, args ...interface{}) bool
//
// _, err := MyFunction(1, 2, 3)
// CmpError(t, err, "MyFunction(1, 2, 3) should return an error")
func CmpError(t *testing.T, got error, args ...interface{}) bool {
//
// "args..." are optional and allow to name the test. This name is
// logged as is in case of failure. If len(args) > 1 and the first
// item of args is a string and contains a '%' rune then fmt.Fprintf
// is used to compose the name, else args are passed to fmt.Fprint.
func CmpError(t TestingT, got error, args ...interface{}) bool {
t.Helper()
return cmpError(NewContext(), t, got, args...)
}
Expand All @@ -83,7 +94,12 @@ func CmpError(t *testing.T, got error, args ...interface{}) bool {
// if CmpNoError(t, err) {
// // one can now check value...
// }
func CmpNoError(t *testing.T, got error, args ...interface{}) bool {
//
// "args..." are optional and allow to name the test. This name is
// logged as is in case of failure. If len(args) > 1 and the first
// item of args is a string and contains a '%' rune then fmt.Fprintf
// is used to compose the name, else args are passed to fmt.Fprint.
func CmpNoError(t TestingT, got error, args ...interface{}) bool {
t.Helper()
return cmpNoError(NewContext(), t, got, args...)
}
54 changes: 0 additions & 54 deletions equal.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@
package testdeep

import (
"bytes"
"fmt"
"reflect"
"testing"
"unsafe"
)

Expand Down Expand Up @@ -414,55 +412,3 @@ func EqDeeplyError(got, expected interface{}) (err *Error) {
return deepValueEqualFinal(NewContext(),
reflect.ValueOf(got), reflect.ValueOf(expected))
}

func cmpDeeply(ctx Context, t *testing.T, got, expected interface{},
args ...interface{}) bool {
t.Helper()

err := deepValueEqualFinal(ctx,
reflect.ValueOf(got), reflect.ValueOf(expected))
if err == nil {
return true
}
formatError(t, err, args...)
return false
}

func formatError(t *testing.T, err *Error, args ...interface{}) {
t.Helper()

const failedTest = "Failed test"

var buf *bytes.Buffer
switch len(args) {
case 0:
buf = bytes.NewBufferString(failedTest + "\n")
case 1:
buf = bytes.NewBufferString(failedTest + " '" + args[0].(string) + "'\n")
default:
buf = bytes.NewBufferString(failedTest + " '")
fmt.Fprintf(buf, args[0].(string), args[1:]...)
buf.WriteString("'\n")
}

err.Append(buf, "")

t.Error(buf.String())
}

// CmpDeeply returns true if "got" matches "expected". "expected" can
// be the same type as "got" is, or contains some TestDeep
// operators. If "got" does not match "expected", it returns false and
// the reason of failure is logged with the help of "t" Error()
// method.
//
// "args..." are optional and allow to name the test. This name is
// logged as well in case of failure. The first arg must be a
// string. If more than one arg is passed, the first one is supposed
// to be a fmt.Sprintf format with remaining args the format
// parameters. See fmt.Sprintf for details.
func CmpDeeply(t *testing.T, got, expected interface{},
args ...interface{}) bool {
t.Helper()
return cmpDeeply(NewContext(), t, got, expected, args...)
}
64 changes: 64 additions & 0 deletions equal_private_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
package testdeep

import (
"bytes"
"fmt"
"reflect"
"testing"
)
Expand Down Expand Up @@ -62,3 +64,65 @@ func TestGetInterface(t *testing.T) {
// t.Error("panic() did not occur")
//}
}

type TestTestingT struct {
LastMessage string
}

func (t *TestTestingT) Error(args ...interface{}) {
t.LastMessage = fmt.Sprint(args...)
}

func (t *TestTestingT) Helper() {
// Do nothing
}

func TestFormatError(t *testing.T) {
ttt := &TestTestingT{}

err := &Error{
Context: NewContext(),
Message: "test error message",
Summary: rawString("test error summary"),
}

nonStringName := bytes.NewBufferString("zip!")

//
// Without args
formatError(ttt, err)
equalStr(t, ttt.LastMessage, `Failed test
DATA: test error message
test error summary`)

//
// With one arg
formatError(ttt, err, "foo bar!")
equalStr(t, ttt.LastMessage, `Failed test 'foo bar!'
DATA: test error message
test error summary`)

formatError(ttt, err, nonStringName)
equalStr(t, ttt.LastMessage, `Failed test 'zip!'
DATA: test error message
test error summary`)

//
// With several args & Printf format
formatError(ttt, err, "hello %d!", 123)
equalStr(t, ttt.LastMessage, `Failed test 'hello 123!'
DATA: test error message
test error summary`)

//
// With several args without Printf format
formatError(ttt, err, "hello ", "world! ", 123)
equalStr(t, ttt.LastMessage, `Failed test 'hello world! 123'
DATA: test error message
test error summary`)

formatError(ttt, err, nonStringName, "hello ", "world! ", 123)
equalStr(t, ttt.LastMessage, `Failed test 'zip!hello world! 123'
DATA: test error message
test error summary`)
}
Loading

0 comments on commit 0bd6254

Please sign in to comment.