Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert: Add new assertion InEpsilonMapValues #1500

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions assert/assertion_format.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions assert/assertion_forward.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions assert/assertions.go
Expand Up @@ -1531,6 +1531,52 @@ 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 {
hendrywiranto marked this conversation as resolved.
Show resolved Hide resolved
if h, ok := t.(tHelper); ok {
h.Helper()
}
if expected == nil || actual == nil ||
reflect.TypeOf(expected).Kind() != reflect.Map {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the check of the kind of actual.

Instead, just check the kind of expected and check that actual has the same type with call IsType(t, expected, actual, msgAndArgs...).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for review, kindly please check again

return Fail(t, "Arguments must be maps", msgAndArgs...)
}
if !IsType(t, expected, actual) {
return Fail(t, "Both values must be of the same type", 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
161 changes: 161 additions & 0 deletions assert/assertions_test.go
Expand Up @@ -1964,6 +1964,167 @@ 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 BoolAssertionFunc
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: "Within epsilon 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: "Within epsilon with different number of map keys",
expected: map[string]float64{
"foo": 2.2,
"baz": 2.0,
},
actual: map[string]float64{
"baz": 2.1,
},
epsilon: 0.06,
f: False,
},
{
title: "Within epsilon 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,
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add tests with map[string]string and map[string]struct{}.

{
title: "When expected and actual are not the same type",
expected: map[string]float64{
"foo": 2.1,
},
actual: map[string]string{
"foo": "2.0",
},
epsilon: 0.1,
f: False,
},
{
title: "When expected and actual map value are string",
expected: map[string]string{
"foo": "2.1",
},
actual: map[string]string{
"foo": "2.0",
},
epsilon: 0.1,
f: False,
},
{
title: "When expected and actual map value are struct",
expected: map[string]struct{}{
"foo": {},
},
actual: map[string]struct{}{
"foo": {},
},
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
22 changes: 22 additions & 0 deletions require/require.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions require/require_forward.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.