"Test a little, code a little" in Grails project, using Easyb or Spock, in IntelliJ - grails

My original issue is described perfectly by this post: I want to follow TDD:
write a small test
watch it fail
write just enough code to make it succeed
watch it succeed
repeat
I am working on a Grails project in IntelliJ. If all I want is to write normal JUnit tests, the above post solves everything:
Head to /test/unit
Put some test code in a "class Xyz extends GroovyTestCase" class
Hit Shift F10
JUnit report pops up within a second or two
The problem is that I would like to use one of the very cool "describe-in-english" testing setups, like Easyb or Spock.
What do I do? It would be magic to just start with the auto-generated Test class Grails makes for me, then cram Spock stuff into it. Obviously I can't use "extends" twice. Does this give the gist of what I'm trying to do though?
class Xyz extends GroovyTestCase extends spock.lang.Specification {
//void testSomething() {
// fail "Implement me"
//}
def "length of Spock's and his friends' names"() {
expect:
name.size() == length
where:
name | length
"Spock" | 5
"Kirk" | 4
"Scotty" | 6
}
}

Extend spock classes, not groovy's. You can choose from UnitSpec, ControllerSpec, IntegrationSpec and others as listed in source code. Spock will take care of the rest.

-Use "grails install-templates"
-Change the Tests templates to something along the lines of:
#artifact.package#
import grails.test.mixin.*
import org.junit.*
import spock.lang.Specification
#TestFor(#artifact.testclass#)
class #artifact.name# extends Specification {
}
-Write the test code in Spock (or normal JUnit code)
-IntelliJ->Run->Edit Configurations. Add New Configuration of the JUnit type. Test kind: <All in package/All in UnitTest directory/All in one UnitTest class/etc.>
-(Shortcut: Cursor over method name, or class name->ctrl-shift-F10)
On my original question:
In retrospect, I was getting hung-up on the "run all in directory" part of that blog post. Current IntelliJ DOES let you run all JUnit tests in a directory, or the entire project.
Once I understood that, the next step was to realize that Spock tests ARE JUnit tests. Make a "class Xyz extends Specification {}" class in the test/unit directory, fill it with Spock code, and Run as... JUnit. Magic!

Related

Grails 3.3.1 and passing system properties to test-app

I am bumping into an issue in my integration test. My code uses a system property (System.getProperty(...) ) and I am not being able to set the system property when running the integration test. Any idea on how to define system properties that are visible inside code running in integration test?
I am using Grails 3.3.1.
Slimmed down example of integration test not seeing the system property:
package injecttest
import grails.testing.mixin.integration.Integration
import grails.transaction.*
import org.springframework.beans.factory.annotation.Autowired
import spock.lang.Specification
#Integration
#Rollback
class C1ITSpec extends Specification {
void "test system property readable inside test"() {
String val = System.getProperty("var1", "ERROR")
expect:"system variable to match value passed as '-Dvar1=OK' in command line"
"OK" == val
}
}
A new JVM is forked to run the test, so you have to pass the command-line system properties to the test's JVM.
In Grails 4, which uses gradle, you can pass the system properties in your gradle file:
integrationTest.doFirst {
systemProperties System.getProperties().subMap(["var1"])
}
I adapted this from the answers to this question for Grails 3: How to give System property to my test via Gradle and -D.

How to take screenshots in a module in geb

Hi we run Geb tests on the Spock framework. I am trying to take a screenshot in a module using report "Screenshot". It does not recognize the report function as it does on a Spec. How should I go about taking screenshots in a module.
Here is a example code which is in a module.
try{
$(By.xpath("//button[#ng-click=\"ok()\"]")).click()
}
catch (Throwable t){
failures.add("\n Could not click on the Ok button after the Ticket created successfully message appeared")
report "Failure"
}
The report() method is available on Browser class and an instance of that class is available as browser property inside of modules, so you can call it from within a module using:
browser.report("Failure")
Use the parent class GebReportingSpec (instead of GebSpec) to create a report of all your tests.
When you only want a screenshot of failing tests, use the config value reportOnTestFailureOnly=true in your GebConfig.groovy

How to execute a function at the end of all specification files have been executed using spock framework

Problem statement:
How to execute a function at the end of all specification files have been executed using spock framework.
Explantion: I am using geb-spock framework for automation.
I have few specification files. I want to run a function after all specification files have been executed.
I want something like AfterSuite in TestNG. How can i get the feature of AfterSuite in spock. cleanupSpec will be called after every specification file is executed.
Thanks,
Debasish
The simple answer is: no. There's nothing like before or after suite methods in spock since spock is JUnit based and JUnit does not handle such methods. If you siÄ™ tool like maven or gradle maybe you can use task's lifecycle methods.
You can use the JUnit 4 SuiteRunner Look at this answer
#RunWith(Suite.class)
#SuiteClasses({ TestSpec.class, TestSpec.class })
public class CompleteTestSuite {
#BeforeClass
public static void setUpClass() {
System.out.println("Master setup");
}
#AfterClass public static void tearDownClass() {
System.out.println("Master tearDown");
}
}
If you are using build tool as for example Gradle you may wire it on a build configuration level after tests are finished.

Spock Integration Test fails when run with other integration tests-succeeds in isolation using integration:spock

I am adding a first spock integration test to an existing set of tests for a grails 2.1.1 application. The test runs and tests pass when run using:
grails test-app integration:spock CreditServiceSpec
(Yes, everything is in the default package - fixing this is a ton of work that will not be approved...file under technical debt.)
However, when I run all the tests (grails test-app), unit test pass, spock unit tests pass, integration tests pass, but I get the following failure for spock integration:
| Completed 818 integration tests, 0 failed in 104001ms
| Running 1 spock test...
| Failure: CreditServiceSpec
| groovy.lang.GroovyRuntimeException: failed to invoke constructor: public org.codehaus.groovy.grails.test.support.GrailsTestAutowirer(org.springframework.context.ApplicationContext) with arguments: [] reason: java.lang.IllegalArgumentException
at grails.plugin.spock.IntegrationSpec.$spock_initializeSharedFields(IntegrationSpec.groovy:33)
| Completed 0 spock test, 0 failed in 33ms
| Tests PASSED - view reports in /Users/*/projects/GrailsPlugins/DomainServices/target/test-reports
I get the exact same exception whether I run the full test I built or the following, very strip down example:
import grails.plugin.spock.IntegrationSpec
class CreditServiceSpec extends IntegrationSpec {
def setup() {}
def cleanup() {}
public void "sample"() {
setup:"Nothing to do here."
expect:"This is the truest of truths..."
true == true
}
}
I did crack open IntegrationSpec and looked at line 33:
#Shared private autowirer = new GrailsTestAutowirer(applicationContext)
But determining how/why the applicationContext is not being passed in properly is beyond me and, perhaps, is the thrust of my question.
Has anyone encountered this kind of behavior and found a way to get spock integration to play nice with other tests? Thanks.
It looks like Grails 2.1.1 had several issues with Spock tests in the Integration scope. Jeff's comment and Peter's in particular sound like the issue you were having; basically the ApplicationHolder was null or an empty list.
The parent task lists Grails 2.2.5 as the fix version. Any chance you can upgrade to that (or some even later version) and see if the problem persists?
There have also been cases where a simple grails clean has fixed issues like this.
I had a problem with the exact same symptom.
I was using the BuildTestData plugin and used the #Build annotation in a IntegrationSpec, but using the #Build with use a transformation wich extended the #TestFor transformation which is incompatible with the Intengration runtime.
So just remove the #Build annotations and it will run.

Why is SpringSecurityUtils null in this Grails unit test?

In Grails 2.0.4, I'm trying to write a controller unit test which invokes the static SpringSecurityUtils.reauthenticate. The test returns a NullPointerException on that invocation. In a debugger, I can see that none of the Groovy dynamic properties (declaredMethods,etc.) of SpringSecurityUtils are populated.
I do note that when running the tests, the "Configuring Spring Security Core" log message is emitted after the unit-test failure. Here is a sample test:
class ReproTest {
void testSpringSecurityUtils() {
String.valueOf(true) // OK: a public final class from the JDK
URLUtils.isRelativeURL("foo") // OK: a class from another plugin
SpringSecurityUtils.reauthenticate "user", "pw" // fails, NPE
}
}
My initial reaction is that maybe plugins aren't accessible during unit tests, but if so, why is the URLUtils call working? And why does the test get "far enough" to initialize the plugin, but after the tests have completed?
For a unit test the container isn't starting up. No Spring injection or "grails goodness" is happening. You see in the logs that the plugin is initializing after the unit tests run, because it [container] does start for the integration tests. If you want to test the SpringSecurityUtils, although guessing it is already tested properly in the plugin, you would want to write an integration test.

Resources