Behaviour test using parametrised Spock framework - groovy

I have a set of behavior tests which should result in the same outcome
def 'behaviour tests for route A'() {
when:
doA();
then:
data == 'Hi'
}
def 'behaviour tests for route B'() {
when:
doB();
then:
data == 'Hi'
}
void doA(){
...
}
void doB(){
...
}
the code looks ugly I would have preferred to use parametrized testing. something alongside this:
#Unroll
def 'behaviour tests for route #name'() {
when:
route
then:
data == 'Hi'
where:
name | route
'A' | doA()
'B' | doB()
}
Is there a way to do it?

You can use closures to extract the code that you want executed in the when block.
class ClosureSpec extends Specification {
#Unroll
def 'behaviour tests for route #name'() {
when:
def data = route()
then:
data == 'Hi'
where:
name | route
'A' | { doA() }
'B' | { doB() }
}
def doA() {
return 'Hi'
}
def doB() {
return 'Hi'
}
}
or you could use groovys dynamic nature to pass in the method name
class DynamicSpec extends Specification {
#Unroll
def 'behaviour tests for route #name'() {
when:
def data = this."do$name"()
then:
data == 'Hi'
where:
name | route
'A' | _
'B' | _
}
def doA() {
return 'Hi'
}
def doB() {
return 'Hi'
}
}
Depending on the use-case I'd go with the closure, but the dynamic method name has its uses, especially if you want to pass in parameters.

Related

How to inject Groovy closure variable into Spock mock predicate argument?

I found an interesting line in Spock interactions documentation:
http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_argument_constraints
last line of constraints, example with closure predicate:
1 * subscriber.receive({ it.size() > 3 && it.contains('a') })
My question is: is there a way in Groovy to pass this predicate as variable?
My testing environment code:
class Something {
Doer doer
Something(Doer doer) {
this.doer = doer
}
boolean doSth(x) {
if (!doer.validate(x)) throw new RuntimeException()
true
}
}
class Doer {
boolean validate(int x) {
x == 2
}
}
and test code:
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
when:
s.doSth(2)
then:
1 * d.validate({ it == 2 }) >> true
}
what I would like to achieve:
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
def myClosureVar = { ??? }
when:
s.doSth(2)
then:
1 * d.validate(myClosureVar) >> true
}
The closure takes an argument, as indicated by it having a defined value. That value is the corresponding method parameter. So whatever closure you define outside of your interaction, you need to make sure that the interaction hands over that parameter to the closure, i.e. you need to create your own (small and simple) closure evaluating the outer (potentially lengthier, more complex) closure with the parameter it:
1 * d.validate({ myClosureVar(it) }) >> true
Sorry for the repetition, but I always prefer a full MCVE in my answers so you can easily copy, paste, compile and run:
Application classes:
package de.scrum_master.stackoverflow.q60341734
class Doer {
boolean validate(int x) {
x == 2
}
}
package de.scrum_master.stackoverflow.q60341734
class Something {
Doer doer
Something(Doer doer) {
this.doer = doer
}
boolean doSth(x) {
if (!doer.validate(x)) throw new RuntimeException()
true
}
}
Spock specification:
package de.scrum_master.stackoverflow.q60341734
import org.junit.Rule
import org.junit.rules.TestName
import spock.lang.Specification
class SomethingTest extends Specification {
#Rule
TestName testName
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
when:
s.doSth(2)
then:
1 * d.validate({ println "$testName.methodName: closure parameter = $it"; it == 2 }) >> true
}
def "another test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
def myClosureVar = { println "$testName.methodName: closure parameter = $it"; it == 2 }
when:
s.doSth(2)
then:
1 * d.validate({ myClosureVar(it) }) >> true
}
}
Console log:
some test: closure parameter = 2
another test: closure parameter = 2

How to count closure calls

How can I count closure method calls.
I have a closure as below:
class SomeTestSpec extends Specification {
def greeting = { "Hello world!" }
#Unroll
def "test description"() {
given: // ….
when:
def v = greeting then: // need something like that: 1 * greeting
}
}
I call it once in the when: clause.
How can I test the call count (one in my case) in the then: clause.

How to use IgnoreIf in Spock, when I check the variable?

I need to skip some functions in the program, but it should depend on a variable defined in the same program. How can I do it?
def skip = true
#IgnoreIf({ skip })
def "some function" () {
..
}
Another way to do this is by using spock's configuration file to include/exclude tests or base classes.
First you create your own annotations and place on your tests.
You then write a Spock configuration file.
When you run your tests you can set the spock.configuration property to the configuration file of your choice.
This way you can include/exclude the tests and base classes you want.
Example of spock configuration file:
runner {
println "Run only tests"
exclude envA
}
Your test:
#envA
def "some function" () {
..
}
You can then run :
./gradlew test -Pspock.configuration=mySpockConfig.groovy
Here is a github example
You can do it by accessing skip field in a static context:
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfSpec extends Specification {
static boolean skip = true
#IgnoreIf({ IgnoreIfSpec.skip })
def "should not execute this test if `IgnoreIfSepc.skip` is set to TRUE"() {
when:
def res = 1 + 1
then:
res == 2
}
def "should execute this test every time"() {
when:
def res = 1 + 1
then:
res == 2
}
}
Otherwise closure passed to #IgnoreIf() tries to find skip field inside the closure and it fails.
If the variable needs to be computed first and then the decision for test ignoring needs to be taken on the basis of computation, we can use static block and static variable
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfSpec extends Specification {
static final boolean skip
static {
//some code for computation
if("some condition")
skip = true
else
skip = false
}
#IgnoreIf({ IgnoreIfSpec.skip })
def "should not execute this test if `IgnoreIfSepc.skip` is set to TRUE"() {
when:
def res = 1 + 1
then:
res == 2
}
def "should execute this test every time"() {
when:
def res = 1 + 1
then:
res == 2
}
}
Another way is:
def skip = true
#IgnoreIf({ instance.skip })
def "some function" () {
..
}
Documentation
instance
The specification instance, if instance fields, shared
fields, or instance methods are needed. If this property is used, the
whole annotated element cannot be skipped up-front without executing
fixtures, data providers and similar. Instead, the whole workflow is
followed up to the feature method invocation, where then the closure
is checked, and it is decided whether to abort the specific iteration
or not.
Then you could do something like:
abstract class BaseTest extends Specification {
boolean skip = false
#IgnoreIf({ instance.skip })
def "some function" () { .. }
}
SubSpecification:
class GoodTest extends BaseTest {
}
class SkipTest extends BaseTest {
boolean skip = true
}
In this case, skip is a property, but it can be a method.

groovy print environments from groovy.config

how do I print available environments from a config file? What is the form of the ojbect ConfigSlurper creates?
I tried
def config2 = new ConfigSlurper().parse(new File('obieeadmincfg.groovy').toURL())
config2.config.environments.each { println ${it} }
and
println prettyPrint(toJson(config2))
and
for ( i in 0 ..config2.config.environments.size()-1)
println config2.config.environments[i]
groovy.config
//Config3.groovy
obieadmin {
//default values
serverurl = "http://default.mycompany.com"
}
environments {
pldev01 {
obieeadmin {
serverurl = 'devgdwobi03.x.com'
}
}
plsbx02 {
obieeadmin {
serverurl = 'devgdwobi03.x.com'
}
}
}
I'm afraid you can't do this out-of box.
But using a bit of Groovy Metaprogramming it's achievable.
Groovy config slurper parses proper Groovy file, and you can do the same with GroovyShell. You can catch call to environment method providing closure in binding. In that closure you have to collect all top-level method calls(with same methodMissing).
Providing base script with property and method missing handlers, you can suppress runtime errors, and execute script without much care to other properties.
Not the nicest path, but it works.
package test
import org.codehaus.groovy.control.CompilerConfiguration
class A extends Script {
def propertyMissing(String name) { null }
def propertyMissing(String name, def arg) {}
def methodMissing(String name, def args) {}
#Override Object run() { null }
}
class NameCollector {
def envs = []
def methodMissing(String name, def args) { envs << name }
}
// configure interceptors.
def configuration = new CompilerConfiguration()
configuration.scriptBaseClass = 'test.A'
def nc = new NameCollector()
def environments = { Closure it ->
it.delegate = nc;
it.resolveStrategy = Closure.DELEGATE_ONLY
it()
}
// execute config script
new GroovyShell([environments: environments] as Binding, configuration).evaluate(new File("config.groovy"))
nc.envs // Return, print them.
Not sure if this is going to work forever but currently you can do it by overriding the setting for the 'environments' conditional block, like this:
def config = """environments {
dev {
foo = "bar"
}
prod {
foo = "baz"
}
}"""
def configSlurper = new ConfigSlurper()
configSlurper.registerConditionalBlock('environments', null)
assert configSlurper.parse(config).environments.keySet() == ['dev', 'prod'].toSet()

In groovy when comparing this and a reference passed in a method: same instance, different metaclass

In groovy 1.8.6, I was trying to do something like this:
class Greeter {
def sayHello() {
this.metaClass.greeting = { System.out.println "Hello!" }
greeting()
}
}
new Greeter().sayHello()
This didn't work:
groovy.lang.MissingPropertyException: No such property: greeting for class: groovy.lang.MetaClassImpl
After a bit of trying, I found that passing a reference to self to the method did work. So, basically what I came up with was this:
class Greeter {
def sayHello(self) {
assert this == self
// assert this.metaClass == self.metaClass
self.metaClass.greeting = { System.out.println "Hello!" }
greeting()
}
}
def greeter = new Greeter()
greeter.sayHello(greeter)
The strangest thing is that the assert this == self actually passes, which means they are the same instance... right? The default toString also seems to confirm this.
On the other hand, the assert this.metaClass == self.metaClass fails:
assert this.metaClass == self.metaClass
| | | |
| | | org.codehaus.groovy.runtime.HandleMetaClass#50c69133[groovy.lang.MetaClassImpl#50c69133[class Greeter]]
| | Greeter#1c66d4b3
| false
groovy.lang.MetaClassImpl#50c69133[class Greeter]
Why is self.metaClass wrapped in a HandleMetaClass, while this.metaClass isn't? Also, how can the first example be made to work without passing in a reference to self?
I figured out the 2 questions:
groovy.lang.MissingPropertyException: No such property: greeting for class: groovy.lang.MetaClassImpl
why this.metaClass == self.metaClass
See this link: https://stackoverflow.com/a/45407488/42769
You can implement methodMissing in the class as below to answer your last question:
class Greeter {
def sayHello() {
//this.metaClass.greeting = { System.out.println "Hello!" }
greeting()
goodNight()
}
def methodMissing(String name, args){
if(name == 'greeting'){
println "Hello!"
} else
println "Good Night"
}
}
new Greeter().sayHello()
Also note that == in groovy actually means equals() (that is value comparison) if you want to compare identity then is() can be used like
a.is(b) //Corresponds to == in Java
a == b //Corresponds to equals() in Java
UPDATE
Can use metaClass as below
Greeter.metaClass.greeting = { println "Hello"}
def greet = new Greeter()
//or
//greet.metaClass.greeting = { println "Hello"}
greet.sayHello()

Resources