sobota, 27 kwietnia 2013

Migration project to grails 2.2

Leave a Comment
Once upon a time in my team appeared a thoughts : ”Lets migrate from grails 2.1 to 2.2”. Hmm, why not. This operation is not simple change of framework version. It is more like a chain reaction, because new grails requires groovy 2.0 and groovy 2.0 require Spock 0.7. Thus in our case the migration resulted in upgrading three basic cores of the application.
So lets see what new features we gain thanks to the migration.

Grails 2.2.0

The Grails team, on official website described all changes. The most important are:
  • tuning of the developer server,
  • improved support for namespace conflicts between various plugins occurring in url mapping,
  • access to Hibernate's SQL projection API in criteria queries.
For details go Grails Website Grails 2.2 news

Groovy 2.0

By googling, you can find a lot of articles about 2.0 version, whereas this post is about how to migrate your grails project. Thus I think in this case, it is sufficient to quote the Groovy website::
“In a nutshell, Groovy 2.0 add static type checking to let the compiler tell you about the correctness of your code, static compilation for the performance of the critical parts of your application, modularity by splitting the Groovy JAR into smaller feature-oriented modules as well as allowing you to create your own extension modules, JDK 7 Project Coinsyntax enhancements so that Groovy marries itself well with Java, and JDK 7 Invoke Dynamic integration to benefit from the dynamic language support of the JVM.”

Spock 0.7

Spock 0.7 is the first version compatible with groovy 2.0, thus if you still used earlier version, now you will have to upgrade yours test framework. At the first glimpse it could be actually a good idea because Spock0.7 has a lot of quite useful features. Firstly there are some usability improvements e.g.:
  • improved mocking failure message for to ToManyInvocationsError and ToFewInvoactionError
  • grouping condition with same target object,
  • grouping interactions with same target object,
  • improved Failure Messages for notThrown and noExceptionThrown.
There are also some new smoking hot features at your fingertips ready to be used:
  • new mocking objects: Stubs, Spies, Groovy Mock, Global Mocks,
  • pooling conditions for testing asynchronous code,
  • @Beta annotation.

Let's get migrate

First steps are rather standard and shouldn't be supprising. You have to prepare the environment
set system variables
  • GRAILS_HOME=path_to_grails_2.2
  • PATH=PATH:GRAILS_HOME/bin

Then, in project settings update versions of required libraries
  • grails 2.2
  • groovy 2.0
  • spock 0.7

Now you ready to check how far from the end of the journey you are. So go to the project dir and fire:
grails clean
grails upgrade
grails test-app
If there is no erros - congratulations You have just migrate to Grails 2.2. But if any errors occured, further steps and problem, strongly depends on the code of yours project and state of the grails cache. So at the first I suggest to clear grails cache. Just run
rm -rf ~/.grails
and then you can fire
grails test-app
and now you can go for a lunch or a long coffee break because grails will recreate .grails – that means in most of cases, download a lot of stuff from the Internet.

Works only when separately and CannotCreateMockException()

In my case, first test-app failed. There were a lot of errors connected with CannotCreateMockException() After some investigation, occurred that
  • grails test-app unit: - works fine
  • grails test-app integration: - works fine
  • grails test-app - FAIL
After more investigation it occured that the problem is connected with creating mock of the same Class in unit and integration test. Assume we have two test Classes
class FooSpec {

 Foo foo = Mock(Foo)

 …....
}

class FooIntegrationSpec {
 
 Foo foo = Mock(Foo)

 …...
}
then
  • grails test-app FooSpec => Pass
  • grails test-app FooIntegrationSpec => Pass
  • grails test-app FooSpec FooIntegrationSpec => Fail

At the first glance situation looks awful. Source of tests and tested Classes did not change and just do not work with spock 0.7. Unfortunately there is no way to migration to Grails 2.2 and still use spock 0.6. Fortunately there is no need to rebuild the whole structure of your app in order to remove mocks of the same Class. Maybe the resolution is not nice and good looking but at least works. In spock 0.7 there are few new mock objects, and one of them is GroovyMock. It make mock object to be more groovylike – with whole automagic stuff underneath. In most of cases there is no reasonable reasons to use GroovyMock instead of Mock but it will fix your tests. Thus, all you have to do is in one test use Mock and in the other GroovyMock. Thus in every place where is a problem use Mock in unit tests and GroovyMock in integration tests.
class FooSpec {

    Foo foo = Mock(Foo)
    …....
}

class FooIntegrationSpec { 
    Foo foo = GroovyMock(Foo)
    …...
}
and now
grails test-app FooSpec FooIntegrationSpec => Pass

Spock 0.7 is so slow?

Thus, when all tests are passed there is last problem to defeat. After migration tests work amazingly slow. Before migration grails test-app took~7min, and after it takes even ~30min. I’ve noticed that the difference grows up exponentially with tests quantity. At the first I thought about some memory issue, so I decided to monitored parameters of the tests process. Comparison of charts of Heap Memory usage and CPU usage did not bring any explanation.
Charts for 'grails test-app" process - all tests and Grails 2.1
Charts for 'grails test-app" process - almost half tests and Grails 2.2.0
I have been still waiting for blink a stun and it appeared when I’ve was seeing checked VM arguments of grails 2.2 tests process. At the first sight those values seemed to be to poor. I have compared it with arguments for grails 2.1 values of almost each important parameter was significant higher for grails 2.1. I have never given those parameters explicitly, so it seemed like in case of grails 2.2 there are changed 'default' values of JVM argument. Fortunately user can provide custom JVM arguments. Thus, in order to bring back fast test process, for example type:
export GRAILS_OPTS="-Xmx2048M -Xms768M -XX:PermSize=256m -XX:MaxPermSize=256m"
grails test-app
This way I can manage time of my tests, so if only I have some free hardware resources, I provide specific JVM arguments and my tests may shorten and make take even under 2 minutes.

0 komentarze:

Prześlij komentarz