Array assertion in Spock
Asked Answered
C

4

10

I have a list of some objects - let's assume companies. Now I want to check if this list contains companies with some names but not taking order into consideration. Currently I'm using such construction:

companyList.name.sort() == ["First", "Second"]

Is there any operator in Spock or Groovy that allows me to compare arrays without order?

Cobweb answered 11/2, 2015 at 10:2 Comment(1)
I've never really thought of using .sort() as much of a trouble. It's fairly terse.Collotype
F
15

There's no such operator as far as I know. If the list doesn't contain any duplicates the following assertion may be used:

companyList.name as Set == ["First", "Second"] as Set

Or something like that:

companyList.name.size() == ["First", "Second"].size() && companyList.name.containsAll(["First", "Second"])
Fire answered 11/2, 2015 at 10:6 Comment(5)
I wanted something shorter than .sort() :) Answer like use ~== would be great :)Cobweb
Unfortunately there' no such operator. Will have a look in a minute.Fire
IMHO as Set is the most logical, as it states, that order is not importantCassaundra
Yes, I think exactly the same.Fire
Yep - it's not as cool as operator but code readability is goodCobweb
H
17

You can make use of Hamcrest support in Spock and use the Matcher designed explicitly for this case - containsInAnyOrder. You need the following imports:

import static org.hamcrest.Matchers.containsInAnyOrder
import static spock.util.matcher.HamcrestSupport.that

Then you can write your test code as follows:

given:
    def companyList = [ "Second", "First"]
expect:
    that companyList, containsInAnyOrder("First", "Second")

This has the benefit over using .sort() in that duplicate elements in the List will be considered correctly. The following test will fail using Hamcrest but passes using .sort()

given:
    def companyList = [ "Second", "First", "Second"]
expect:
    that companyList, containsInAnyOrder("First", "Second")

Condition not satisfied:

that companyList, containsInAnyOrder("First", "Second")
|    |
|    [Second, First, Second]
false

Expected: iterable over ["First", "Second"] in any order
     but: Not matched: "Second"

If you're using then: instead of expect: you can use the expect instead of that import for readability.

then:
    expect companyList, containsInAnyOrder("First", "Second")
Hounding answered 3/10, 2015 at 18:47 Comment(0)
F
15

There's no such operator as far as I know. If the list doesn't contain any duplicates the following assertion may be used:

companyList.name as Set == ["First", "Second"] as Set

Or something like that:

companyList.name.size() == ["First", "Second"].size() && companyList.name.containsAll(["First", "Second"])
Fire answered 11/2, 2015 at 10:6 Comment(5)
I wanted something shorter than .sort() :) Answer like use ~== would be great :)Cobweb
Unfortunately there' no such operator. Will have a look in a minute.Fire
IMHO as Set is the most logical, as it states, that order is not importantCassaundra
Yes, I think exactly the same.Fire
Yep - it's not as cool as operator but code readability is goodCobweb
T
2

Upvoted for @Opal answer, it's probably the best in all terms. As a curiosity I would only add an example of usage of minus operator to compare two unsorted lists:

import spock.lang.Specification

class ComparingListsSpec extends Specification {

    def "should contain all companies in two unsorted lists"() {
        when:
        def companies = ["Lorem", "ipsum", "dolor", "sit", "amet"]
        def unsorted = ["ipsum", "sit", "Lorem", "dolor", "amet"]

        then:
        companies - unsorted == []

        and:
        unsorted - companies == []

        and:
        companies - unsorted in [[]]
    }
}

It also works if one of the lists contains redundant data.

Threw answered 11/2, 2015 at 20:3 Comment(1)
i'd stay away from - for anything, that is not a trivial type. assert [[x:0,y:0]]-[[x:1,y:1]] == []Cassaundra
F
0

Now there are dedicated matchers available in Spock:

You can compare list elements ignoring their ordering using the following operators:

  1. ==~ - Strict match (accounting for duplicated elements, etc.)
  2. =~ - Lenient match (ignoring duplicates)

So [1,2,3] ==~ [2,3,1] is truthy.

Frottage answered 30/5, 2023 at 13:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.