go-test / deep

Golang deep variable equality test that returns human-readable differences
MIT License
743 stars 54 forks source link

Ignore order when comparing equality of slices/maps #28

Closed alenkacz closed 1 year ago

alenkacz commented 5 years ago

It would be great to have option to ignore order of items in slices/maps and just assert that it contains the same element.

daniel-nichter commented 4 years ago

Can you give an example of what you'd like to see for both? Order shouldn't matter for maps, but it's inherent to slices.

bdandy commented 4 years ago

I think there should be an option for slices; sometimes order is matter; sometimes doesn't. But maps are unordered by default

tatemz commented 3 years ago

+1 for this

I have a use case where I am testing a slice that results from go routines and the order varies.

Maybe the method signature can use flags?

Equal(a, b interface{}, ...flags interface{})
deep.Equal([]string{"hello", "world"}, []string{"world", "hello"}, deep.FLAG_IGNORE_SLICE_ORDER) 
benjamin-rood commented 2 years ago

Order shouldn't matter for maps, but it's inherent to slices.

It's inherent to the data structure, but not inherent from the perspective of the user. Sometimes people use slices as an unordered list, sometimes they use them as ordered lists.

If you are dealing with a lot of data mangling and manipulation because of the restrictiveness of Go's type system (and it will be years before most libraries switch to using implementation with generics now that 1.18 has come out), then it's a massive pain point. Currently, I have to copy the deeply-nested slices inside two structs I am comparing, sort both, then overwrite the sorted slices with what was originally there, before I can call deep.Equal. That alone is a good enough use case.

A case in point is the generated go code from Protobuf definitions, which can be an absolute nightmare to deal with if you need to do any kind of validation between definitions in separate files, especially when the underlying values of the objects being compared are absolutely identical.

If you look at the stretchr/testify library, the decision was made over time to switch to an unordered comparison. Sadly, that library is not valid for comparing deeply-nested objects. I would like to do the work on a PR implementing @tatemz suggestion, that it be an optional argument to Equal.

daniel-nichter commented 1 year ago

It's been a few years, but better late than never: implemented in https://github.com/go-test/deep/pull/56 and will be released as v1.1.0 since it's a relatively major addition even though it's backwards compatible.

benjamin-rood commented 1 year ago

It's been a few years, but better late than never: implemented in #56 and will be released as v1.1.0 since it's a relatively major addition even though it's backwards compatible.

Thank you, Daniel!

daniel-nichter commented 1 year ago

Released: https://github.com/go-test/deep/releases/tag/v1.1.0