Thursday, April 2, 2009

Running Grails unit tests in Intellij IDEA

In my previous post, I suggested that I'd have some useful ideas to share with you. In this post, I hope to deliver on that promise by explaining the frustrations I encountered while unit testing a Grails project with IntelliJ IDEA, and the workaround I came up with to ease my pain.

First, some background. I like Grails - a lot. It dispenses with a lot of the gunk that makes developing web apps in Java so tedious: XML configuration files, repetitive boilerplate code, tag library descriptors. Grails utilizes proven technologies like Spring, Hibernate, and SiteMesh for its core functionality rather than re-inventing the wheel. And it stole, um, borrowed, lots of great ideas from Ruby on Rails, including the use of a dynamic language, i.e. Groovy, to underpin the whole framework.

Grails also has the best testing support of any framework I've used: automatic generation of test classes, an integrated test environment with an in-memory database, and with version 1.1, comprehensive mocking support for unit testing. The Grails team seems determined to eliminate every conceivable hindrance to testing, and that's an admirable goal.

However, I don't love absolutely everything about Grails testing. In particular, Grails' mechanism for running unit tests is painfully slow. The Grails test-app command runs both unit and integration tests by default, but with the -unit parameter, it runs just the unit tests and doesn't bootstrap an integration test environment. This speeds up the test cycle considerably, but it's still pretty slow; on my machine it takes Grails 10 seconds to run the unit tests - even for a project with no tests!

Ten seconds may not seem like a lot of time, but if you're trying to practice a "test a little, code a little" style of TDD, it's like sand in the gears. When I'm working with unfamiliar code or attempting a tricky refactoring, I like to run the unit tests after every change that could conceivably work. That way, if the tests fail, I can undo my change without having wasted much time or effort.

However, when it takes 10 seconds to run a unit test, there's a temptation to skip the tests, stay in the flow, and keep coding. When I finally run the tests, there's always a failure of some kind, and fixing it usually necessitates a substantial reworking of the code. The longer it's been since I ran the tests, the more rework is required.

After getting bit by this a few times, I started looking for a better way to run Grails unit tests. My first instinct was to run the tests from within my IDE: there's nothing more convenient than firing off your tests with a keyboard shortcut. Unfortunately, I discovered that IntelliJ's "Grails Tests" run configuration just delegates to Grails' test-app script. While running the unit tests from within IntelliJ was a improvement, it wasn't any faster than using the command line.


Since Grails tests inherit from junit.framework.TestCase, my next tactic was to run the tests with IntelliJ's JUnit test runner:


This was a considerable improvement. The tests ran significantly faster - two or three seconds instead of ten - and the results appeared in IntelliJ's Run window, with a summary of failed tests and clickable links in the stack traces. Very nice!


There was one problem, though. As you can see from the above screenshot of the JUnit run configuration, IntelliJ has three options for selecting which tests to run: a single test method, a single test class, or all tests in a package. None of these options works very well for unit testing Grails projects. A single class was too limiting, since I didn't want to maintain a test suite with a reference to each unit test class. Conversely, the "all tests in a package" option was too permissive: it would run both the unit and integration tests, and without a Grails test environment, most of the integration tests would fail.

I wanted an option that would run just the tests in the test/unit directory, but IntelliJ's built-in test runner couldn't be configured to do that. After much fruitless searching, I finally found the solution on the Groovy website. Groovy has a utility class named AllTestSuite that finds all the tests that match a filename pattern in a given directory and aggregates them in a test suite. Normally, AllTestSuite gets the base directory and the filename pattern from the system properties, but it's easy enough to extend the class and specify the directory and pattern with static variables, like so:

import junit.framework.Test

public class AllUnitTestSuite extends AllTestSuite {

private static final String BASEDIR = "./test/unit"
private static final String PATTERN = "**/*Tests.groovy"

public static Test suite() {
return suite(BASEDIR, PATTERN)
}

}

I put the above code in a file named AllUnitTestSuite.groovy in the project's test/unit directory, ran it with IntelliJ's JUnit test runner, and it worked perfectly. Fast, convenient, and exactly what I want: problem solved!



A nice bonus here is that under the covers, AllTestSuite uses a Gant script to collect the tests, so if you're familiar with Ant FileSets, you can tweak the matching pattern to customize your test suites.

22 comments:

  1. Helpful hint. Thanks !
    You might want to try domainMock-ing to simulate db crud types of things in unit test mode.. I finally figured out how to get that working with intellij. see > http://buildchimp.com/wordpress/?p=25

    regards -
    chris bedford
    lead lackey
    build lackey labs...

    ReplyDelete
  2. Thanks, Chris. Actually mockDomain and mockForConstraintsTests are the main reason I looked into using IntelliJ's test runner; I didn't understand why it was taking so long to run tests that didn't need an integration test environment.

    I haven't run into any problems using mockDomain with IntelliJ, but that might be because I don't use Maven. ;)

    ReplyDelete
  3. Thanks,

    Your posting helped to save me some time. I ran into the same issue. Also, running the tests like this will allow generating code coverage data.

    Ben

    ReplyDelete
  4. I found a good site, the main thing is that here I am not cheating everything honestly honest gambling machines I sit play, have fun

    ReplyDelete

  5. I have read your blog its very attractive and impressive. Nice information. It helped me alot.
    Government vacancy
    Govt Jobs
    Sarkari nokri
    latest sarkari vacancy
    Online Form
    latest govt jobs

    ReplyDelete
  6. This is the best post I have ever seen. Very clear and simple. Mid-portion Is quite interesting though. Keep doing this. I will visit your site again. Ben 10 Jacket

    ReplyDelete
  7. You will enjoy many years of pleasure in a Ben ten Jacket in a fashionable cut that fits perfectly. At ABOUT YOU, you will find a wide range of modern men’s jackets in many cuts and lengths. In Ben 10 Jacket with unusual zippers or sophisticated seams, you are sure to attract attention at the next party. 

    ReplyDelete
  8. Hi , Thank you so much for writing such an informational blog. If you are Searching for latest Jackets, Coats and Vests, for more info click on given link-Biker Boyz Jacket

    ReplyDelete
  9. Thanks for sharing the article.

    ReplyDelete
  10. Thanks for sharing such a informative blog with us thank you. power 50 cent jacket

    ReplyDelete
  11. lilnasxmerch Fantastic blog i have never ever read.

    ReplyDelete
  12. Outstanding: I am so eager to peruse this Outstanding post. juicewrldofficial.com

    ReplyDelete
  13. Visit Our Website To grab high quality Hoodies Shop here

    ReplyDelete
  14. And Ignition is broadly recognized for being probably the greatest on the earth when it comes to of|in relation to} 배당 토토 the quality of their iGaming software program. Ignition Casino makes use of state-of-the-art software program to deliver an unbeatable roulette experience on your cell device. After the completion of the betting round and finish result} of the white ball, verify whether or not the winning quantity an element of|is part of} your bet. There are 37 pockets on a European Roulette wheel, comparability with} 38 on an American Roulette wheel.

    ReplyDelete
  15. The report went on to quote the source as saying that if Pyongyang forges forward with on line casino projects, Beijing might take tougher measures, including prohibiting the flow of Chinese capital and vacationers into North Korea. The RFA report also quoted one other unnamed source as saying that if related reports are true, the Sinuiju hotel project could resume within the near future, without a a|with no} on line casino. Citing unnamed Chinese sources with connections to North Korea, RFA reported that Kim halted the construction of a hotel, the plans for which 1xbet embody a on line casino, in Sinuiju, North Pyongang Province, end result of} Beijing’s disapproval. The hotel, which would be 30 stories once as} completed, presently stands incomplete at about 20 stories, according to reports.

    ReplyDelete
  16. learned more knowledge to read this post thanks for sharing this informative post.
    Playboy hoodie

    ReplyDelete