Skip to content

Commit

Permalink
add feat InEpsilonMapValues into assert
Browse files Browse the repository at this point in the history
  • Loading branch information
hendrywiranto committed Nov 1, 2023
1 parent 331c520 commit 81217a8
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
44 changes: 44 additions & 0 deletions assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,50 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m
return true
}

// InEpsilonMapValues is the same as InEpsilon, but it compares all values between two maps. Both maps must have exactly the same keys.
func InEpsilonMapValues(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if expected == nil || actual == nil ||
reflect.TypeOf(actual).Kind() != reflect.Map ||
reflect.TypeOf(expected).Kind() != reflect.Map {
return Fail(t, "Arguments must be maps", msgAndArgs...)
}

actualMap := reflect.ValueOf(actual)
expectedMap := reflect.ValueOf(expected)

if expectedMap.Len() != actualMap.Len() {
return Fail(t, "Arguments must have the same number of keys", msgAndArgs...)
}

for _, k := range expectedMap.MapKeys() {
ev := expectedMap.MapIndex(k)
av := actualMap.MapIndex(k)

if !ev.IsValid() {
return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...)
}

if !av.IsValid() {
return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...)
}

if !InEpsilon(
t,
ev.Interface(),
av.Interface(),
epsilon,
msgAndArgs...,
) {
return false
}
}

return true
}

/*
Errors
*/
Expand Down
128 changes: 128 additions & 0 deletions assert/assertions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,134 @@ func TestInEpsilonSlice(t *testing.T) {
False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail")
}

func TestInEpsilonMapValues(t *testing.T) {
mockT := new(testing.T)

for _, tc := range []struct {
title string
expected interface{}
actual interface{}
f func(TestingT, bool, ...interface{}) bool
epsilon float64
}{
{
title: "Within epsilon with exactly the same keys",
expected: map[string]float64{
"foo": 2.2,
"bar": math.NaN(),
"baz": 2.0,
},
actual: map[string]float64{
"foo": 2.1,
"bar": math.NaN(),
"baz": 2.1,
},
epsilon: 0.06,
f: True,
},
{
title: "Outside epsilon with exactly the same keys",
expected: map[string]float64{
"foo": 2.2,
"bar": math.NaN(),
"baz": 2.0,
},
actual: map[string]float64{
"foo": 2.1,
"bar": math.NaN(),
"baz": 2.1,
},
epsilon: 0.03,
f: False,
},
{
title: "With different map keys",
expected: map[string]float64{
"foo": 2.2,
"baz": 2.0,
},
actual: map[string]float64{
"baz": 2.1,
"bar": 2.1,
},
epsilon: 0.06,
f: False,
},
{
title: "With different number of keys",
expected: map[string]float64{
"foo": 2.2,
"baz": 2.0,
},
actual: map[string]float64{
"baz": 2.1,
},
epsilon: 0.06,
f: False,
},
{
title: "With zero value on expected",
expected: map[string]float64{
"foo": 0,
},
actual: map[string]float64{
"foo": 0.1,
},
epsilon: 0.06,
f: False,
},
{
title: "Within epsilon with zero value on actual",
expected: map[string]float64{
"foo": 0.1,
},
actual: map[string]float64{
"foo": 0,
},
epsilon: 1,
f: True,
},
{
title: "When expected is not a map",
expected: []float64{2.1},
actual: map[string]float64{
"foo": 2.0,
},
epsilon: 0.1,
f: False,
},
{
title: "When actual is not a map",
expected: map[string]float64{
"foo": 2.1,
},
actual: []float64{2.0},
epsilon: 0.1,
f: False,
},
{
title: "When expected is nil",
expected: nil,
actual: map[string]float64{
"foo": 2.0,
},
epsilon: 0.1,
f: False,
},
{
title: "When actual is nil",
expected: map[string]float64{
"foo": 2.1,
},
actual: nil,
epsilon: 0.1,
f: False,
},
} {
tc.f(t, InEpsilonMapValues(mockT, tc.expected, tc.actual, tc.epsilon), tc.title)
}
}

func TestRegexp(t *testing.T) {
mockT := new(testing.T)

Expand Down

0 comments on commit 81217a8

Please sign in to comment.