Getting Started with Grails & IntelliJ Part 3

Posted by jt - 13/10/09 at 05:10 pm

One of the things that is baked right into Grails is the support for testing.  Most importantly, it is not cooked in as an after thought.  No, it is very much in the core philosophy behind Grails.  Which is important.  In this series, you’ve seen some of the cool stuff that you can do with the dynamic nature of Groovy.  You gain a lot of flexibility, but it is a knife that can cut both ways.  Because Groovy is a dynamically typed language, the compiler cannot do all the checks that it can on a statically typed language, like Java, C#, or C++.   This leaves you more prone to run time errors.

Out of the box, Grails supports 3 different environments – development, test, and production.  All are configured to use HSQLDB.  Development and test use an in-memory database, while production will persist the data to disk.  No worries if you want to use a different database, its just a matter of editing the JDBC configuration in a properties file.

What is interesting behind the approach is development and test are setup as in memory databases.  Meaning when you bounce the application server, they’re gone.  You start fresh each time.  Which is a blessing to me.  I’ve seen too many shops depending on database refreshes from production so they could ‘test’.  I’ve never bought into this argument.  Its down right dangerous and irresponsible to develop software like this.  The ‘need’ for to copy data from production typically is rooted in poor work habits.

Just to recap, Grails will automatically build your data model from your domain classes.  Tables, indexes, constraints, etc – will all be built automatically for you.  For simplicity, I am going to keep focus on the HSQL in memory database for this series.  If you’re working in an enterprise, no worries.  There are tools available to assist with migrations. And that is a topic for another day.

Typically, an empty data structure is not going to do you much good.  Just about any application will need some seed data in the database.  In Grails, this is a very easy problem to solve.  Grails offers a ‘BootStrap’ class that will run at start-up.  You can easily add code which will run to populate your baseline data.  One important note about the BootStrap class, it will be called on startup, and when running integration tests.  It will *not* be called for running unit tests.

I’ve modified my BootStrap class as follows:

class BootStrap {
 
   def init = {servletContext ->
 
    //check default values, setup if not initalized
    if (Module.count() == 0) {
      setDefaultModule()
 
      if (LogLevel.count() == 0) {
        setDefaultLogLevels()
      }
 
      if (LogMethod.count() == 0) {
        setDefaultLogMethods()
        setupDebugLogger()
      }
 
    }
 
  }
 
  def destroy = {
  }
 
  def setDefaultModule = {
    new Module(owner: 'DEFAULT', object: 'DEFAULT').save()
  }
 
  def setDefaultLogLevels = {
    new LogLevel(levelCode: 'TRACE').save()
    new LogLevel(levelCode: 'DEBUG').save()
    new LogLevel(levelCode: 'INFO').save()
    new LogLevel(levelCode: 'ERROR').save()
    new LogLevel(levelCode: 'FATAL').save()
    new LogLevel(levelCode: 'WARN').save()
  }
 
  def setDefaultLogMethods = {
    new LogMethod(methodCode: 'LOG_TABLE', methodDescription: 'Log to database table via AQ').save()
    new LogMethod(methodCode: 'DBMS_OUTPUT', methodDescription: 'Write messages to DBMS_OUTPUT buffer').save()
    new LogMethod(methodCode: 'JMS_SUBSCRIBER', methodDescription: 'Send Log Message to JMS Subscriber').save()
 
  }
 
  def setupDebugLogger = {
    def module = Module.findByOwnerAndObject('DEFAULT', 'DEFAULT')
 
    def level = LogLevel.findByLevelCode('DEBUG')
 
    def method = LogMethod.findByMethodCode('LOG_TABLE')
 
    def moduleLevel = new ModuleLevel(module: module, level: level, loggingEnabled: 'Y')
 
    moduleLevel.addToModuleLevelMethod(new ModuleLevelMethod(moduleLevel: moduleLevel, logMethod: method))
 
    module.addToModuleLevels(moduleLevel)
 
    module.save()
 
  }

The code above is rather self explanatory. You can see that I simply check to see if there are any records in the associated entity, and if not, add my defaults.

The Grails framework offers two levels of testing, unit and integration. I’m going to run through an example of creating some integration tests to verify that my BootStrap methods are in fact persisting data to the database.

There is no option in IntelliJ for creating integration test classes. But there are Grails goals which support this. From the tools menu, select the option for “Run Grails Target”.

picture-11

In the pop-up, enter the command create-integration-test ModuleIntergrationTest.

picture-12a

This is the same as entering on the command line:

grails create-integration-test ModuleIntergrationTest

You’ll see IntelliJ execute the command, and the script output will be available in a window at the bottom of the IDE.

picture-13

The class created for you will look like this:

import grails.test.*
 
class ModuleIntegrationTests extends GrailsUnitTestCase {
    protected void setUp() {
        super.setUp()
    }
 
    protected void tearDown() {
        super.tearDown()
    }
 
    void testSomething() {
 
    }
}

I’m going to add these modules into the generated class.

    void testDefaultModule() {
      def module = Module.findByOwnerAndObject('DEFAULT', 'DEFAULT')
 
      assertEquals 'failed to find default record', 'DEFAULT', module.owner
 
    }
 
    void testDefaultLogLevels() {
      assertEquals 'Expected 6 records in log level.', 6, LogLevel.count()
    }
 
    void testLogMethod() {
      assertEquals 'Expected 3 records in Log Method', 3, LogMethod.count()
    }

Nothing all that fancy here. Just a couple quick tests to demo the fact the data from the BootStrap methods exists in the database.

Executing the tests is just a couple clicks away. Right click on the test class and select the run option. You’ll get a prompt for Grails or JUnit, select Grails.

picture-15

The results of the tests are stored under /test/reports. In test/reports/html you will find a jUnit html report. Below is an example of the tests I just ran here:

picture-16

So far we’ve covered a lot of ground over the last three posts. We’ve defined a data model with 5 separate entities, created validation rules, defined relationships between entities, and created some basic automated tests. But how much code did we actually write so far? We can run the goal “grails stats” on our project to find out.

Base Directory: /Users/john/Documents/source/log4ora/trunk/log4oraui
Running script /opt/local/share/java/grails/scripts/Stats.groovy
Environment set to development

	+----------------------+-------+-------+
	| Name                 | Files |  LOC  |
	+----------------------+-------+-------+
	| Domain Classes       |     5 |    39 |
	| Unit Tests           |     5 |    55 |
	| Integration Tests    |     1 |    21 |
	+----------------------+-------+-------+
	| Totals               |    11 |   115 |
	+----------------------+-------+-------+

We have 115 lines of code, but 55 are in unit tests. So far, we have not written any unit tests. This is all code autogenerated when we created the Domain Classes. So, for all this functionality, we have about 60 lines of code. I hope you’re starting to see how productive this framework can be.

In the next post, we’ll generate a basic CRUD application for our data model.

Share/Save/Bookmark

Leave a Reply