Skip to content

Commit

Permalink
small QoL improvements assert package test failure messages
Browse files Browse the repository at this point in the history
ContainExactly will warn you about incorrect Type use more clearly,
along with showing you the kind as well.
  • Loading branch information
adamluzsi committed Jun 16, 2023
1 parent a0437ef commit d308538
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 44 deletions.
76 changes: 42 additions & 34 deletions assert/Asserter.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,57 +593,64 @@ func (a Asserter) NotContain(haystack, v any, msg ...any) {
})
}

func (a Asserter) ContainExactly(expected, actual any, msg ...any) {
func (a Asserter) ContainExactly(v, oth any /* slice | map */, msg ...any) {
a.TB.Helper()

exp := reflect.ValueOf(expected)
act := reflect.ValueOf(actual)
rv := reflect.ValueOf(v)
roth := reflect.ValueOf(oth)

if !exp.IsValid() {
if !rv.IsValid() {
panic(fmterror.Message{
Method: "ContainExactly",
Cause: "invalid expected value",
Values: []fmterror.Value{
{
Label: "value",
Value: expected,
Value: v,
},
},
}.String())
}
if !act.IsValid() {
if !roth.IsValid() {
panic(fmterror.Message{
Method: "ContainExactly",
Cause: `invalid actual value`,
Values: []fmterror.Value{
{
Label: "value",
Value: actual,
Value: oth,
},
},
}.String())
}

switch {
case exp.Kind() == reflect.Slice && exp.Type() == act.Type():
a.containExactlySlice(exp, act, msg)
case rv.Kind() == reflect.Slice && rv.Type() == roth.Type():
a.containExactlySlice(rv, roth, msg)

case exp.Kind() == reflect.Map && exp.Type() == act.Type():
a.containExactlyMap(exp, act, msg)
case rv.Kind() == reflect.Map && rv.Type() == roth.Type():
a.containExactlyMap(rv, roth, msg)

default:
// TODO: maybe use Equal as default approach?
panic(fmterror.Message{
Method: "ContainExactly",
Cause: "Unimplemented scenario or type mismatch.",
Cause: "invalid type, slice or map was expected",
Values: []fmterror.Value{
{
Label: "expected-type",
Value: fmt.Sprintf("%T", expected),
Label: "type of the value",
Value: fmterror.Raw(fmt.Sprintf("%T", v)),
},
{
Label: "kind of the value",
Value: fmterror.Raw(rv.Kind().String()),
},
{
Label: "actual-type",
Value: fmt.Sprintf("%T", actual),
Label: "type of the other value",
Value: fmterror.Raw(fmt.Sprintf("%T", oth)),
},
{
Label: "kind of the other value",
Value: fmterror.Raw(roth.Kind().String()),
},
},
}.String())
Expand Down Expand Up @@ -788,13 +795,14 @@ func (a Asserter) NotEmpty(v any, msg ...any) {
// ErrorIs allow you to assert an error value by an expectation.
// ErrorIs allow asserting an error regardless if it's wrapped or not.
// Suppose the implementation of the test subject later changes by wrap errors to add more context to the return error.
func (a Asserter) ErrorIs(expected, actual error, msg ...any) {
// TODO: think about it if this could be swapped safely. Maybe check it back and forth as well.
func (a Asserter) ErrorIs(exp, got error, msg ...any) {
a.TB.Helper()

if errors.Is(actual, expected) {
if errors.Is(got, exp) {
return
}
if a.eq(expected, actual) {
if a.eq(exp, got) {
return
}
if ErrorEqAs := func(expected, actual error) bool {
Expand All @@ -804,7 +812,7 @@ func (a Asserter) ErrorIs(expected, actual error, msg ...any) {
nErr := reflect.New(reflect.TypeOf(expected))
return errors.As(actual, nErr.Interface()) &&
a.eq(expected, nErr.Elem().Interface())
}; ErrorEqAs(expected, actual) {
}; ErrorEqAs(exp, got) {
return
}

Expand All @@ -813,8 +821,8 @@ func (a Asserter) ErrorIs(expected, actual error, msg ...any) {
Cause: "The actual error is not what was expected.",
Message: msg,
Values: []fmterror.Value{
{Label: "expected", Value: expected},
{Label: "actual", Value: actual},
{Label: "expected", Value: exp},
{Label: "actual", Value: got},
},
})
}
Expand Down Expand Up @@ -850,7 +858,7 @@ func (a Asserter) NoError(err error, msg ...any) {
})
}

func (a Asserter) Read(expected any, r io.Reader, msg ...any) {
func (a Asserter) Read(v any /* string | []byte */, r io.Reader, msg ...any) {
const FnMethod = "Read"
a.TB.Helper()
if r == nil {
Expand All @@ -861,7 +869,7 @@ func (a Asserter) Read(expected any, r io.Reader, msg ...any) {
})
return
}
actual, err := io.ReadAll(r)
content, err := io.ReadAll(r)
if err != nil {
a.fn(fmterror.Message{
Method: FnMethod,
Expand All @@ -874,28 +882,28 @@ func (a Asserter) Read(expected any, r io.Reader, msg ...any) {
})
return
}
var exp, act any
switch v := expected.(type) {
var val, got any
switch v := v.(type) {
case string:
exp = v
act = string(actual)
val = v
got = string(content)
case []byte:
exp = v
act = actual
val = v
got = content
default:
a.TB.Fatalf("only string and []byte is supported, not %T", v)
return
}
if a.eq(exp, act) {
if a.eq(val, got) {
return
}
a.fn(fmterror.Message{
Method: FnMethod,
Cause: "Read output is not as expected.",
Message: msg,
Values: []fmterror.Value{
{Label: "expected", Value: exp},
{Label: "actual", Value: act},
{Label: "expected value", Value: val},
{Label: "io.Reader content", Value: got},
},
})
}
Expand Down
20 changes: 10 additions & 10 deletions assert/pkgfunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ func NotPanic(tb testing.TB, blk func(), msg ...any) {
Must(tb).NotPanic(blk, msg...)
}

func Equal[T any](tb testing.TB, expected, actually T, msg ...any) {
func Equal[T any](tb testing.TB, v, oth T, msg ...any) {
tb.Helper()
Must(tb).Equal(expected, actually, msg...)
Must(tb).Equal(v, oth, msg...)
}

func NotEqual[T any](tb testing.TB, expected, actually T, msg ...any) {
func NotEqual[T any](tb testing.TB, v, oth T, msg ...any) {
tb.Helper()
Must(tb).NotEqual(expected, actually, msg...)
Must(tb).NotEqual(v, oth, msg...)
}

func Contain(tb testing.TB, haystack, needle any, msg ...any) {
Expand All @@ -67,19 +67,19 @@ func NotContain(tb testing.TB, haystack, v any, msg ...any) {
Must(tb).NotContain(haystack, v, msg...)
}

func ContainExactly[T any](tb testing.TB, expected, actual T, msg ...any) {
func ContainExactly[T any /* Map or Slice */](tb testing.TB, v, oth T, msg ...any) {
tb.Helper()
Must(tb).ContainExactly(expected, actual, msg...)
Must(tb).ContainExactly(v, oth, msg...)
}

func Sub[T any](tb testing.TB, haystack, needle []T, msg ...any) {
tb.Helper()
Must(tb).Sub(haystack, needle, msg...)
}

func ErrorIs(tb testing.TB, expected, actual error, msg ...any) {
func ErrorIs(tb testing.TB, exp, got error, msg ...any) {
tb.Helper()
Must(tb).ErrorIs(expected, actual, msg...)
Must(tb).ErrorIs(exp, got, msg...)
}

func Error(tb testing.TB, err error, msg ...any) {
Expand All @@ -92,9 +92,9 @@ func NoError(tb testing.TB, err error, msg ...any) {
Must(tb).NoError(err, msg...)
}

func Read[T string | []byte](tb testing.TB, expected T, r io.Reader, msg ...any) {
func Read[T string | []byte](tb testing.TB, v T, r io.Reader, msg ...any) {
tb.Helper()
Must(tb).Read(expected, r, msg...)
Must(tb).Read(v, r, msg...)
}

func ReadAll(tb testing.TB, r io.Reader, msg ...any) []byte {
Expand Down

0 comments on commit d308538

Please sign in to comment.