diff --git a/assert/assertion_format.go b/assert/assertion_format.go index e97c3d0..e0364e9 100644 --- a/assert/assertion_format.go +++ b/assert/assertion_format.go @@ -325,6 +325,14 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // diff --git a/assert/assertion_forward.go b/assert/assertion_forward.go index e11c070..2683040 100644 --- a/assert/assertion_forward.go +++ b/assert/assertion_forward.go @@ -639,6 +639,22 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. return JSONEqf(a.t, expected, actual, msg, args...) } +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEqf(a.t, expected, actual, msg, args...) +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // diff --git a/assert/assertions.go b/assert/assertions.go index 880e950..87e6422 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -18,6 +18,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" + yaml "gopkg.in/yaml.v2" ) //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl @@ -1369,6 +1370,24 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{ return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) } +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedYAMLAsInterface, actualYAMLAsInterface interface{} + + if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) +} + func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { t := reflect.TypeOf(v) k := t.Kind() diff --git a/assert/assertions_test.go b/assert/assertions_test.go index b3981e2..a4a9585 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -1443,6 +1443,81 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) } +func TestYAMLEq_EqualYAMLString(t *testing.T) { + mockT := new(testing.T) + True(t, YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)) +} + +func TestYAMLEq_EquivalentButNotEqual(t *testing.T) { + mockT := new(testing.T) + True(t, YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) +} + +func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) { + mockT := new(testing.T) + expected := ` +numeric: 1.5 +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +` + + actual := ` +numeric: 1.5 +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +` + True(t, YAMLEq(mockT, expected, actual)) +} + +func TestYAMLEq_Array(t *testing.T) { + mockT := new(testing.T) + True(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)) +} + +func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) { + mockT := new(testing.T) + False(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)) +} + +func TestYAMLEq_HashesNotEquivalent(t *testing.T) { + mockT := new(testing.T) + False(t, YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) +} + +func TestYAMLEq_ActualIsSimpleString(t *testing.T) { + mockT := new(testing.T) + False(t, YAMLEq(mockT, `{"foo": "bar"}`, "Simple String")) +} + +func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) { + mockT := new(testing.T) + False(t, YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`)) +} + +func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) { + mockT := new(testing.T) + True(t, YAMLEq(mockT, "Simple String", "Simple String")) +} + +func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) { + mockT := new(testing.T) + False(t, YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) +} + func TestDiff(t *testing.T) { expected := ` diff --git a/assert/forward_assertions_test.go b/assert/forward_assertions_test.go index 22e1df1..4d83d6a 100644 --- a/assert/forward_assertions_test.go +++ b/assert/forward_assertions_test.go @@ -609,3 +609,101 @@ func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { t.Error("JSONEq should return false") } } + +func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) { + assert := New(new(testing.T)) + if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) { + t.Error("YAMLEq should return true") + } + +} + +func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) { + assert := New(new(testing.T)) + if !assert.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { + t.Error("YAMLEq should return true") + } + +} + +func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) { + assert := New(new(testing.T)) + expected := ` +numeric: 1.5 +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +` + + actual := ` +numeric: 1.5 +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +` + if !assert.YAMLEq(expected, actual) { + t.Error("YAMLEq should return true") + } +} + +func TestYAMLEqWrapper_Array(t *testing.T) { + assert := New(new(testing.T)) + if !assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) { + t.Error("YAMLEq should return true") + } + +} + +func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { + assert := New(new(testing.T)) + if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) { + t.Error("YAMLEq should return false") + } +} + +func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) { + assert := New(new(testing.T)) + if assert.YAMLEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { + t.Error("YAMLEq should return false") + } +} + +func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) { + assert := New(new(testing.T)) + if assert.YAMLEq(`{"foo": "bar"}`, "Simple String") { + t.Error("YAMLEq should return false") + } +} + +func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) { + assert := New(new(testing.T)) + if assert.YAMLEq("Simple String", `{"foo": "bar", "hello": "world"}`) { + t.Error("YAMLEq should return false") + } +} + +func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) { + assert := New(new(testing.T)) + if !assert.YAMLEq("Simple String", "Simple String") { + t.Error("YAMLEq should return true") + } +} + +func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) { + assert := New(new(testing.T)) + if assert.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) { + t.Error("YAMLEq should return false") + } +} diff --git a/go.mod b/go.mod index 90e5dbe..5053648 100644 --- a/go.mod +++ b/go.mod @@ -4,4 +4,5 @@ require ( github.com/davecgh/go-spew v1.1.0 github.com/pmezard/go-difflib v1.0.0 github.com/stretchr/objx v0.1.0 + gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 5b98bf3..cccb647 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/require/forward_requirements_test.go b/require/forward_requirements_test.go index b120ae3..1ec65fa 100644 --- a/require/forward_requirements_test.go +++ b/require/forward_requirements_test.go @@ -383,3 +383,129 @@ func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { t.Error("Check should fail") } } + +func TestYAMLEqWrapper_EqualYAMLString(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEqWrapper_EquivalentButNotEqual(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEqWrapper_HashOfArraysAndHashes(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + expected := ` +numeric: 1.5 +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +` + + actual := ` +numeric: 1.5 +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +` + + mockRequire.YAMLEq(expected, actual) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEqWrapper_Array(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEqWrapper_HashesNotEquivalent(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEqWrapper_ActualIsSimpleString(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`{"foo": "bar"}`, "Simple String") + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEqWrapper_ExpectedIsSimpleString(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq("Simple String", `{"foo": "bar", "hello": "world"}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEqWrapper_ExpectedAndActualSimpleString(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq("Simple String", "Simple String") + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEqWrapper_ArraysOfDifferentOrder(t *testing.T) { + mockT := new(MockT) + mockRequire := New(mockT) + + mockRequire.YAMLEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) + if !mockT.Failed { + t.Error("Check should fail") + } +} diff --git a/require/require.go b/require/require.go index 2c19547..c5903f5 100644 --- a/require/require.go +++ b/require/require.go @@ -820,6 +820,28 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int t.FailNow() } +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.YAMLEq(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.YAMLEqf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // diff --git a/require/require_forward.go b/require/require_forward.go index 19cedd1..804fae0 100644 --- a/require/require_forward.go +++ b/require/require_forward.go @@ -640,6 +640,22 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. JSONEqf(a.t, expected, actual, msg, args...) } +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + YAMLEqf(a.t, expected, actual, msg, args...) +} + // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // diff --git a/require/requirements_test.go b/require/requirements_test.go index 39467d9..c4d0afa 100644 --- a/require/requirements_test.go +++ b/require/requirements_test.go @@ -369,6 +369,111 @@ func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { } } +func TestYAMLEq_EqualYAMLString(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEq_EquivalentButNotEqual(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEq_HashOfArraysAndHashes(t *testing.T) { + mockT := new(MockT) + expected := ` +numeric: 1.5 +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +` + + actual := ` +numeric: 1.5 +hash: + nested: hash + nested_slice: [this, is, nested] +string: "foo" +array: + - foo: bar + - 1 + - "string" + - ["nested", "array", 5.5] +` + YAMLEq(mockT, expected, actual) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEq_Array(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEq_HashAndArrayNotEquivalent(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEq_HashesNotEquivalent(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEq_ActualIsSimpleString(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `{"foo": "bar"}`, "Simple String") + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEq_ExpectedIsSimpleString(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, "Simple String", `{"foo": "bar", "hello": "world"}`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + +func TestYAMLEq_ExpectedAndActualSimpleString(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, "Simple String", "Simple String") + if mockT.Failed { + t.Error("Check should pass") + } +} + +func TestYAMLEq_ArraysOfDifferentOrder(t *testing.T) { + mockT := new(MockT) + YAMLEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) + if !mockT.Failed { + t.Error("Check should fail") + } +} + func ExampleComparisonAssertionFunc() { t := &testing.T{} // provided by test