ceylon-sdk icon indicating copy to clipboard operation
ceylon-sdk copied to clipboard

ceylon.test should have collections assertions

Open renatoathaydes opened this issue 11 years ago • 9 comments

Feature Request The following returns false:

{1,2,3} == {1,2,3}.map((Integer i) => i);

But for tests, we need something that compares just the elements are the same, not caring about the collection itself:

assertElementsEqual({1,2,3}, {1,2,3}.map((Integer i) => i) ); // should pass

The above is very common as results of functions usually go through some transformations with map or for comprehensions etc..

Maybe something similar for Sets (so, independent of the implementation of equals for the actual sets):

assertContainsAll({1,2,3}, {3,2,1}.map((Integer i) => i) ); // should pass

renatoathaydes avatar Feb 05 '14 19:02 renatoathaydes

The following returns false

are you sure that’s correct and intended behaviour? Seems weird to me. The following returns true:

{1, 2, 3} == [*{1, 2, 3}.map((Integer i) => i)]

lucaswerkmeister avatar Feb 05 '14 21:02 lucaswerkmeister

@lucaswerkmeister yes, it's correct. There's no definition of equality that works in general for all iterables.

gavinking avatar Feb 05 '14 21:02 gavinking

Yeah, I noticed that afterwards – I was just about to send another comment :D Here it is, mildly obsolete now.

equals isn’t overridden for Iterables, only for sequences – which makes sense because equals is an eager operation. The code in my previous comment returns true because the compiler optimizes {1, 2, 3} to an ArraySequence (which is consequently printed [1, 2, 3]).

lucaswerkmeister avatar Feb 05 '14 22:02 lucaswerkmeister

So the method could look like this:

shared void assertElementsEqual({Object*} actual, {Object*} expected) {
    assert(expected.sequence == actual.sequence);
}

only with more documentation, of course.

lucaswerkmeister avatar Feb 05 '14 22:02 lucaswerkmeister

Didn't realize sequence equals would work... will do this for now, thanks.

renatoathaydes avatar Feb 05 '14 22:02 renatoathaydes

Be careful though, Iterables are not "stable", it's not guaranteed that repeated iterations over their content return the same result. Turning them into a sequence might give you access to it's equals() but that doesn't mean the result will be what you expect, it would still depend on the underlying implementation. In my opinion if you're going to turn them into sequences anyway just make the method take Sequence instead of Iterable and make it explicit. Then for Iterable you could make special versions that first make sure that the contents can somehow be compared in a strict way. For example assertSortedElementsEqual() or assertElementsSetEqual() that first sorts the items or treats them as a set or whatever.

quintesse avatar Feb 05 '14 22:02 quintesse

Be careful though, Iterables are not "stable", it's not guaranteed that repeated iterations over their content return the same result.

In my case I just needed to ensure a function was returning the correct values, in the correct order, in a unit test. I don't think lazy evaluation would help in my case, because all items are fixed (and immutable)... I think what this means is that I should have used Sequences rather than Iterables. Will keep that in mind...

After reading the Tour of Ceylon, it was not clear to me why I should use one or the other.... maybe a note about the difference would have helped.

But in any case, I believe that, to help in unit tests, the proposed assertion would be useful (in many cases, you might not need to care, at least in the test, what type of collection you get!).

renatoathaydes avatar Feb 06 '14 08:02 renatoathaydes

I'll assign this for 1.2 for now

quintesse avatar Oct 03 '14 18:10 quintesse

Some additional suggestions:

  • assertEmpty
  • assertContains
  • assertContainsExactly
  • assertDoesNotContain
  • assertIsSorted
  • assertElementsSatisfyCondition

AssertJ has a lot of convenient methods for common types such as collections, but also strings, numbers and more.

gustavkarlsson avatar Nov 12 '16 18:11 gustavkarlsson