I am actually an author of one of the tutorials you have mentioned. I think the best to answer your question would be to really understand what particular labels are for. Maybe then it would be more obvious why certain combinations make sense and other do not. Please refer to original documentation http://spockframework.github.io/spock/docs/1.0/spock_primer.html. It explains really well all labels and their purpose. Also it comes with this diagram:
Which I hope should already tell you a lot. So for instance having both when and expect labels makes not much sense. The expect label was designed to substitute both when and then. The reasoning behind it is well explained in the documentation:
An expect block [...] is useful in situations where it is more natural to describe stimulus and expected response in a single expression.
Spock itself will not allow you to use this combination. If you try to execute following code.
def "test"() {
when:
println("test")
expect:
1==1
}
You will receive an error message like this.
startup failed:
/Users/wooki/IdeaProjects/mylibrary/src/test/groovy/ExampleTest.groovy:
13: 'expect' is not allowed here; instead, use one of: [and, then] @
line 13, column 9.
To my surprise the second of your examples works. However I believe there is really not much gain of using expect here instead of and as I would normally do.
def "do something else"() {
when:
// stimulus
then:
// 1st verification
and:
// 2nd verification
where:
// parametrization
}
The only reason to have expect or and after then is to separate code responsible for verifying the result of executing the code inside when label. For instance to group verifications that are somehow related to each other, or even to separate single verifications but to have a possibility of giving them a description using strings that can be attached to labels in Spock.
def "do something else"() {
when:
// stimulus
then: "1 is always 1"
1 == 1
and: "2 is always 2"
2 == 2
}
Hence, since you are already stating that verification part of the test began (using then block) I would stick to and label for separating further code.
Regarding where label. It works sort of as a loop indicator. So whatever combinations of labels you use before you could always put at the end the where label. This one is not really a part of a single test run, it just enforces the test to be run a number of times.
As well it is possible to have something like this:
def "test"() {
given:
def value
when:
value = 1
then:
value == 1
when:
value = 2
then:
value == 2
}
Using the above, just make sure that your test is not "testing too much". Meaning that maybe a reason why you use two groups of when-then makes a perfect excuse for this test to be actually split into two separate tests.
I hope this answered at least some of your questions.
where
label a little bit more I think I should be all set! – Manes