Assert two lists are equal in Spock structure

I am testing my application using the Spock framework, tests are written in Groovy.

As a result of some evaluation of the method, I have a list of objects. I want to check if this list matches the list I expect. I encoded the following:

def expectedResults = [ ... ] //the list I expect to see def isEqual = true; when: def realResults = getRealResultsMethod() //get real results in a list here expectedResults.each {isEqual &= realResults.contains(it)} then: isEqual 0 * errorHandler.handleError(_) //by the way assert that my errorHandler is never called 

This is one of my first experiences with Groovy, maybe I missed something?

PS

I am confused by the 'equals' operator in Groovy and Spock. Given an array of Java ArrayList or Java, the equals operator is simply the identifier: equals is ==. In Groovy, as I understand it, equality by default is equal to action equals (form here: http://groovy.codehaus.org/Differences+from+Java ). But what are the 'equals' for a Groovy List or Set?

UPDATE

More precisely. I want to find out if two lists have the same objects, no additional objects for both lists, the order does not matter. For instance:

 list=[1,5,8] list1=[5,1,8] list2=[1,5,8,9] println(list == list1) //should be equal, if we use == not equal println(list == list2) //should not be equal, if we use == not equal 
+5
source share
4 answers

Just do:

 when: def expectedResults = [ ... ] def realResults = getRealResultsMethod() then: realResults == expectedResults 

Or, if you don't need order (which violates the List contract, but there you go), you can do:

 then: realResults.sort() == expectedResults.sort() 

Or convert them to settings or something like that

+10
source

If you just need to check if both lists have the same elements, you can try:

 when: def expectedResults = [ ... ] def realResults = getRealResultsMethod() then: realResults.size() == expectedResults.size() realResults.containsAll(expectedResults) expectedResults.containsAll(realResults) 

But if you need to check if both lists are equal, then you just need (as in @tim_yates answer):

 when: def expectedResults = [ ... ] def realResults = getRealResultsMethod() then: realResults == expectedResults 

Remember that two lists are equal only if they have the same elements in the same order .

+4
source

The semantic data structure you are looking for is often referred to as a bag. In the bag, as in the set, the order of the elements does not matter. However, in the bag, as in the list, duplicate items are allowed. Thus, the equality of the amounts consists of the fact that each of them has the same elements in the same quantities, although not necessarily in the same order. Thus, it seems that what you are looking for is a way to apply bag semantics to your list. The easiest way to do this is to duplicate one of the bags and remove the other bag elements from the duplicate until:

  • all other elements of the bag are exhausted, and the duplicate is empty (they are equal!)
  • all other elements of the bag are exhausted, and the duplicate is NOT empty (they are different!)
  • during iteration, one of the other elements of the bag cannot be removed from the duplicate (they are different!)

Something like the equals() implementation shown below:

 class Bag { List list Bag(List list) { this.list = list } @Override boolean equals(that) { def thisList = list?.clone() ?: [] that instanceof Bag && (that?.list ?: []).every { thisList.remove((Object)it) } && !thisList } @Override int hashCode() { this?.list?.sum { it?.hashCode() ?: 0 } ?: 0 } @Override String toString() { this?.list?.toString() } } def a = [1, 5, 1, -1, 8] as Bag def b = [5, 1, -1, 8, 1] as Bag // same elements different order def c = [1, 5, -1, 8] as Bag // same elements different size def d = [5, 5, 1, -1, 8] as Bag // same elements same size different amounts of each assert a == b assert a != c assert a != d println a // [1, 5, 1, -1, 8] println b // [5, 1, -1, 8, 1] 

Alternatively, if you do not care about the initial order for the list at all, you can present the bag in the form of a card. The values โ€‹โ€‹of the summing element are the keys of the map, and the number of occurrences of each element of the bag are the values โ€‹โ€‹of the map. At this point, equality is simply equality of the map.

Like this:

 class BagAsMap { Map map = [:] BagAsMap(List list) { (list ?: []).each { map[it] = (map[it] ?: 0) + 1 } } @Override boolean equals(that) { that instanceof BagAsMap && this?.map == that?.map } @Override int hashCode() { this?.map?.hashCode() ?: 0 } @Override String toString() { '[' + map.keySet().sum { k -> (0..<(map[k])).sum { "${k}, " } }[0..-3] + ']' } } def a1 = [1, 5, 1, -1, 8] as BagAsMap def b1 = [5, 1, -1, 8, 1] as BagAsMap // same elements different order def c1 = [1, 5, -1, 8] as BagAsMap // same elements different size def d1 = [5, 5, 1, -1, 8] as BagAsMap // same elements same size different amounts assert a1 == b1 assert a1 != c1 assert a1 != d1 println a1 println b1 

In any case, this is a serious search, if you just need to check the equivalence of the list one or two times, but if the semantics of the package are a frequent need, then defining the Bag class in one of these two ways is probably a good idea.

As noted elsewhere, in this particular case, a.sort() == b.sort() is a sufficient stop second instead of the full semantics of the package. However, not all objects that can be put together in the list are mutually sorted, even with the most difficult closing of the comparator. However, they all have hashCode() and equals() , which is all that is needed for the package implementation shown.

In addition, List.sort() has the algorithmic complexity O (n log n), while all List.sort() operations are shown as O (n). Do not worry about these small lists, but much more for large ones.

0
source
 list1.containsAll(list2) && list2.containsAll(list1) 
-4
source

Source: https://habr.com/ru/post/1204346/


All Articles