Practically Groovy: Unit test your Java code faster with Groovy
//
//
var emailAbstract = "Not long ago, developerWorks contributor Andrew Glover penned an article introducing Groovy, a new proposed standard language for the Java platform, as part of our alt.lang.jre series. Reader response was fantastic, so we've decided to launch this column to offer a practical guide to using this hot new technology. This first installment introduces a simple strategy for unit testing Java code with Groovy and JUnit."; Skip to main content Country/region[ select ] All of dW----------------- AIX and UNIX Information Mgmt Lotus Rational Tivoli WebSphere----------------- Architecture Autonomic computing Java technology Linux Multicore acceleration Open source SOA & Web services Web development XML----------------- dW forums -----------------alphaWorks-----------------All of IBM HomeBusiness solutionsIT servicesProductsSupport & downloadsMy IBM developerWorksMore in this series:Practically Groovy In this article: No more Java purism! Why unit test with Groovy? JUnit and Groovy Groovy extends JUnit Fun with GroovyTestCase More ways to play Testing with Ant and Maven Reviewing today's lesson Resources About the author Rate this page Related links Java technology technical library
  developerWorks > Java technology > Practically Groovy: Unit test your Java code faster with Groovy   Document options Document options requiring JavaScript are not displayedRate this page Help us improve this contentLevel: IntroductoryAndrew Glover, CTO, Vanward Technologies 09 Nov 2004Not long ago, developerWorks contributor Andrew Glover penned an article introducing Groovy, a new proposed standard language for the Java platform, as part of our alt.lang.jre series. Reader response was fantastic, so we've decided to launch this column to offer a practical guide to using this hot new technology. This first installment introduces a simple strategy for unit testing Java code with Groovy and JUnit.
//
I'll start with a confession: I'm a unit testing addict. In fact, Ijust can't write enough unit tests. If I'm developing for long stretchesof time without having written corresponding unit tests, I getthe jitters. Unit tests give me the confidence that my code works andthat I can change it, at a moment's notice, without the fear of itbreaking. Furthermore, as an addict, I tend to write a plethora of test cases. My high,however, isn't from writing the test cases; it's in seeingtheir results. Consequently, if I can write the tests in a rapid manner,I can view their results quicker. That way I feel better. Quicker. Of late, I've been looking to Groovy to appease my unit testingaddiction, and so far I'm impressed. The agility this new language brings tounit testing is quite exciting and worthy of some serious exploration.In this article, the first in a new series introducing the practicalaspects of Groovy, I'll introduce you to the pleasures of unit testingwith Groovy. I'll start with an overview of Groovy's unique contributions to development on the Java platform, then move on to discuss the particulars of unit testing with Groovy and JUnit, with special emphasis on Groovy's extension of JUnit's TestCase class. I'll conclude with a working example that shows you, first hand, how to integrate these groovy features with Eclipse and Maven. No more Java purism!Before I launch into the practical aspects of unit testing with Groovy, I think it's important to talk about the more general issue of its place in your development toolbox. The fact is, Groovy isn't the only scripting language that runs on the Java Runtime Environment (JRE), it's just the only one that has been proposed as a standard language for the Java platform. As some of you will have learned from the alt.lang.jre series (see Resources), there are myriad options when it comes to scripting for the Java platform, most of them presenting highly agile environments for rapid application development. Despite this abundance of choices, many developers choose to stick with their favorite and most-familiar paradigm: the Java language. While Java programming is a fine choice for most situations, there is one very important shortcoming to wearing Java-only blinders. As a wise person once put it: If the only tool you have is a hammer, you tend to see every problem as a nail. I think there's a lot of truth to this saying that is applicable to software development. Just as I hope to convince you with this series that the Javalanguage is not and should not be your only choice for developingapplications, it's also true that scripting languages make sense in somescenarios and not in others. What separates the professional from thetyro is knowing when to apply the power of scripting andwhen to eschew it. About this seriesThe key to incorporating any tool into your development practice is knowing when to use it and when to leave it in the box. Scripting languages can be an extremely powerful addition to your toolkit, but only when applied properly to appropriate scenarios. To that end, Practically Groovy is a series of articles dedicated to exploring the practical uses of Groovy, and teaching you when and how to apply them successfully. For example, scripting is typically not such a good fit forhigh-performance, transaction-intensive, enterprise-wide applications;for these cases your best bet could be a normal J2EE stack. Onthe other hand, scripting -- and particularly scripting with Groovy --can make a lot of sense when it comes to rapid prototyping of small,highly specific applications that are not performance intensive, such asconfiguration systems and/or build systems. It's also a near-perfectfit for reporting applications and, most importantly, unit testing. Why unit test with Groovy?What makes Groovy particularly appealing with respect to otherscripting platforms is its seamless integration with the Java platform. Because it's based on the Java language (unlike other alternate languages for the JRE, which tend to be based on earlier predecessors), Groovy presents an incredibly short learning curve for the Java developer. And once that learning curve has straightened out, Groovy can offer an unparalleled rapid development platform.The secret to Groovy's success, in this regard, is its syntax,which is Java syntax, but with far fewer rules. For example,Groovy doesn't require semicolons, and it makes variable types andaccess modifiers optional. Moreover, Groovy makes use of the standardJava libraries you're already familiar with, including Collections and File/IO.And, finally, you can utilize any Java library from within Groovy,including JUnit.The fact is, Groovy's relaxed Java-like syntax, its reuse of standardJava libraries, and its rapid build-and-run cycle make it an idealcandidate for rapidly developing unit tests. But don't just take my word for it; let's see it in code! Back to topJUnit and GroovyUnit testing Java code in Groovy couldn't be easier, and there are many options for getting started. The most straightforward choice is to stick with the industry standard, JUnit. The simplicity and power of JUnit are unrivaled, its ubiquity as a helpful Java development tool is unparalleled, and there's nothing stopping the combination of JUnit and Groovy, so why reinvent the wheel? In fact, once you've seen JUnit and Groovy together in action, I'll bet you'll never turn back! The key thing to remember here is that you can do all the same things with JUnit in Groovy that you can do in the Java language; albeit with far fewer keystrokes.Getting startedOnce you've downloaded JUnit and Groovy (see Resources) you can proceed in one of two ways. The first option is to write normal JUnit test cases just as you've been doing all along by extending JUnit's commendable TestCase. The second option is to apply Groovy's nifty GroovyTestCase extension, which will consequently extend JUnit's TestCase. The first option is your quickest path to success with maximum Java-esque familiarity. The second option, on the other hand, pushes you into the Groovy world with maximum agility.To get started, imagine a Java object that applies a filter to a givenstring and returns a boolean value corresponding to a match. This filtercould be a simple string operation such asindexOf() or, more powerfully, it could be aregular expression. The desired filter is set at runtime via a setFilter() method and the apply() method takes the string to be filtered. Listing 1 showsthis example Filter interface in plain Java code:Listing 1. A simple Java Filter interfacepublic interface Filter { void setFilter(String fltr); boolean applyFilter(String value);}The idea is to use this feature to filter out desired or undesiredpackage names from a large list. Consequently, I've created twoimplementations: RegexPackageFilter and SimplePackageFilter. Combining the power and simplicity of Groovy and JUnit yieldsthe elegant test suite shown in Listing 2: Listing 2. A Groovy RegexFilterTest using JUnitimport junit.framework.TestCaseimport com.vanward.sedona.frmwrk.filter.impl.RegexPackageFilterclass RegexFilterTest extends TestCase { void testSimpleRegex() { fltr = new RegexPackageFilter() fltr.setFilter("java.*") val = fltr.applyFilter("java.lang.String") assertEquals("value should be true", true, val) }}The code in Listing 2 should look familiar to you regardless of whether you're familiar with Groovy, because it's simply Java code without any semicolons, access modifiers, or variable types! The above JUnit test has one testcase, testSimpleRegex(), which attempts toassert that the RegexPackageFilter has correctly found a match with "java.lang.String" using the regular expression "java.*".  Back to topGroovy extends JUnitExtending JUnit's TestCase class to addadditional features is a common technique utilized in virtually everyJUnit extension. The DbUnit framework (see Resources), for example, offers a handyDatabaseTestCase that makes managing the stateof a database easier than ever, and the indispensable MockStrutsTestCase (from the StrutsTestCase framework; see Resources) yields a virtual servlet container for executing struts code. Bothof these powerful frameworks have elegantly extended JUnit to providefeatures otherwise not found in its core code; and now Groovy has goneand done it too!Like StrutsTestCase and DbUnit, Groovy's extension of JUnit's TestCase brings some important new features to your developer toolbox. This particular extension lets you run test suites via the groovy command, and also offers up a host of new assert methods. These methods can be handy when it comes to asserting that a script correctly runs, asserting the lengths of various array types and the contents of various array types, and more.  Back to topFun with GroovyTestCaseThere's no better way to learn what GroovyTestCase can do for you than to see it in action. In Listing 3, I've written a new SimpleFilterTest, but this time I've extended GroovyTestCase to do it:Listing 3. An actual GroovyTestCaseimport groovy.util.GroovyTestCaseimport com.vanward.sedona.frmwrk.filter.impl.SimplePackageFilterclass SimpleFilterTest extends GroovyTestCase { void testSimpleJavaPackage() { fltr = new SimplePackageFilter() fltr.setFilter("java.") val = fltr.applyFilter("java.lang.String") assertEquals("value should be true", true, val) } }Note that this test suite can be run via the command line without themain() method you would need in order to runJava-based JUnit test suite. In fact, if I wrote the above SimpleFilterTest in Java code, it would looksomething like the one shown in Listing 4:Listing 4. The same test case in Java codeimport junit.framework.TestCase;import com.vanward.sedona.frmwrk.filter.Filter;import com.vanward.sedona.frmwrk.filter.impl.SimplePackageFilter;public class SimplePackageFilterTest extends TestCase { public void testSimpleRegex() { Filter fltr = new SimplePackageFilter(); fltr.setFilter("java."); boolean val = fltr.applyFilter("java.lang.String"); assertEquals("value should be true", true, val); } public static void main(String[] args) { junit.textui.TestRunner.run(SimplePackageFilterTest.class); }}Testing with assertionsIn addition to letting you run tests via the command line, GroovyTestCase gives you some particularly handyassert methods. assertArrayEquals, for example, asserts that twoarrays are equal by checking their individual values and respectivelengths. You can see Groovy assertions in action starting with theexample in Listing 5, a nifty Java-based method that splits strings into arrays. (Note that I could have usedJava 1.4's added string features to write theexample class below. I used the Jakarta Commons StringUtils class to ensure backward-compatibilitywith Java 1.3.)Listing 5. Defining a Java StringSplitter classimport org.apache.commons.lang.StringUtils;public class StringSplitter { public static String[] split(final String input, final String separator){ return StringUtils.split(input, separator); }}Listing 6 shows how simple it is to test this class with the Groovy test suite and its corresponding assertArrayEquals method:Listing 6. Using assertArrayEquals in a GroovyTestCaseimport groovy.util.GroovyTestCaseimport com.vanward.resource.string.StringSplitterclass StringSplitTest extends GroovyTestCase { void testFullSplit() { splitAr = StringSplitter.split("groovy.util.GroovyTestCase", ".") expect = ["groovy", "util", "GroovyTestCase"].toArray() assertArrayEquals(expect, splitAr) } } Back to topMore ways to playGroovy lets you run tests singly or in batches. With the GroovyTestCase extension, running a single test iseffortless. Simply run the groovy commandfollowed by the desired test suite and you're good to go, as shownin Listing 7: Listing 7. Running a GroovyTestCase via the groovy command$./groovy test/com/vanward/sedona/frmwrk/filter/impl/SimpleFilterTest.groovy.Time: 0.047OK (1 test)Groovy also offers a standard JUnit test suite called GroovyTestSuite. Simply run this test suite andpass in the path to your script. This test suite will run your scriptmuch like the groovy command. The nice thingabout this technique is that it lets you run scripts in an IDE. Forexample, in Eclipse, I simply create a new run configuration forthe example project (being sure to check "Include external jars whensearching for a main class,") and then locate the main class groovy.util.GroovyTestSuite, as shown in Figure 1:Figure 1. Using Eclipse to run GroovyTestSuite In Figure 2, you see what happens when I click the Arguments tab and write the path to my script: Figure2. Specifying a Path to a Script in Eclipse Running a favorite JUnit Groovy script really is as easy as locatingthe corresponding run configuration within Eclipse.  Back to topTesting with Ant and Maven The beauty of a framework like JUnit is that it can run anentire suite of tests as part of a build without requiring human intervention. As more and more people add test cases to the code base, the overall testsuite grows, serving as an excellent regression platform. What's more,build frameworks like Ant and Maven have added reporting features thatsummarize a JUnit batch run. The easiest way to incorporate a host of Groovy test cases into abuild is to compile them into normal Java byte code and include them inthe standard JUnit batch commands offered by Ant and Maven. Fortunately,Groovy offers an Ant tag that incorporates compiling Groovy scripts intobyte code, so the process of transforming scripts into functional bytecode couldn't be any more straightforward. For example, if you happen tobe utilizing Maven for builds, you simply need to add two new goals toyour maven.xml file, two new dependencies in your project.xml file, one simple flag in your build.properties file, and you're set to go. I'll start by updating my maven.xml file with the new goal tocompile the example scripts, as shown in Listing 8: Listing 8. Sample maven.xml file defining a Groovyc goal <goal name="run-groovyc" prereqs="java:compile,test:compile"> <path id="groovy.classpath"> <pathelement path="${maven.build.dest}"/> <pathelement path="target/classes"/> <pathelement path="target/test-classes"/> <path refid="maven.dependency.classpath"/> </path> <taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"> <classpath refid="groovy.classpath"/> </taskdef> <groovyc destdir="${basedir}/target/test-classes" srcdir="${basedir}/test/groovy" listfiles="true"> <classpath refid="groovy.classpath"/> </groovyc> </goal>A few things are happening in the above code. First, I've defined anew goal named run-groovyc. This goal has twoprerequisites, java:compile, which compilesthe example source code and test:compile,which compiles the any normal Java-JUnit classes. Next, I've created aclasspath with the <path> tag. In thiscase, the classpath incorporates the build directory (where the compiledsource resides) and all its associated dependencies (that is, JAR files).Next, I've defined the groovyc task with the<taskdef> Ant tag.Notice, also, how I've told Maven where to find the class org.codehaus.groovy.ant.Groovyc in the classpath.In the last lines of the example I've defined a <groovyc> tag that compiles all Groovyscripts found in the test/groovy directoryand places the resulting .class files in the target/test-classes directory. Some important detailsIn order to compile Groovy scripts and run their resulting byte code, I would have to define two new dependencies (groovy and asm) via the project.xml file, as shown in Listing 9:Listing 9. New dependencies for a project.xml file <dependency> <groupId>groovy</groupId> <id>groovy</id> <version>1.0-beta-6</version> </dependency> <dependency> <groupId>asm</groupId> <id>asm</id> <version>1.4.1</version> </dependency>Once the scripts are compiled to normal Java bytecode they can berun by any standard JUnit runner. Because Ant and Maven have a JUnit runnertag, the next step is to have JUnit pick up the newly compiled Groovyscripts. And because the Maven JUnit runner uses pattern matching to find test suitesto run, I need to add a special flag in the build.properties file, asshown in Listing 10, which tells Maven to search classes insteadof .java files: Listing 10. A Maven project build.properties file maven.test.search.classdir = trueLastly, I define a test goal in themaven.xml file shown in Listing 11. Doing so ensures the Groovy scripts will be compiled with the new run-groovyc goal before any unit tests are run. Listing 11. A new goal for maven.xml <goal name="test"> <attainGoal name="run-groovyc"/> <attainGoal name="test:test"/> </goal>Last but not least ...With the two new goals defined (one to compile scripts andthe other to run the combined Java and Groovy JUnit tests), the only thingleft to do is run them and verify that everything is working!In Listing 12, you see what happens when I run Maven and pass in the test goal, which first attains the run-groovyc goal (which also happens to attain thejava:compile and test:compile goals) then attains the standardout-of-the-box Maven test:test goal. Noticehow the test:test goal picks up both of thenewly created Groovy scripts -- or in this case, the newly compiledGroovy scripts -- and the normal Java JUnit test. Listing 12. Running the new goal$ ./maven testtest:java:compile: [echo] Compiling to /home/aglover/dev/target/classes [javac] Compiling 15 source files to /home/aglover/dev/target/classestest:compile: [javac] Compiling 4 source files to /home/aglover/dev/target/test-classesrun-groovyc: [groovyc] Compiling 2 source files to /home/aglover/dev/target/test-classes [groovyc] /home/aglover/dev/test/groovy/test/RegexFilterTest.groovy [groovyc] /home/aglover/dev/test/groovy/test/SimpleFilterTest.groovytest:test: [junit] Running test.RegexFilterTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.656 sec [junit] Running test.SimpleFilterTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.609 sec [junit] Running test.SimplePackageFilterTest [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.578 sec BUILD SUCCESSFULTotal time: 42 secondsFinished at: Tue Sep 21 17:37:08 EDT 2004 Back to topReviewing today's lessonIn this first installment of Practically Groovy, you've learned about one of the most practical applications of this exciting new scripting language. For a growing number of developers, unit testing is an essential part of the development process; and with Groovy and JUnit, unit testing Java code is a snap.Groovy's simple syntax and built-in agility make it an excellent platform for quickly writing effective JUnit tests and incorporating them into an automated build. For a code-quality addict like myself, this combination drastically reduces the heebie-jeebies and allows me to get to what I like doing best: writing bullet-proof software. Quickly. Because this is a new series, you're strongly encouraged to help steer its progress. If there's something you want to know about Groovy, drop me a line and let me know! In the meantime, I hope you'll tune in for the next installment in which I'll be talking about Ant scripting with Groovy.ResourcesSee the complete listing of Practically Groovy articles by Andy Glover.Download Groovy from the Groovy open source project page, where you can also learn more about such topics as compilation, unit testing, regular expressions, and more.Don't miss the author's first foray into Groovy in his contribution to the alt.lang.jre series with "Feeling Groovy" (developerWorks, August 2004)Download JUnit from The JUnit home page.Download DbUnit from The DbUnit home page.Download StrutsTestCase from The StrutsTestCase home page.Learn more about unit testing Java (and hence Groovy) applications withJUnit, with Malcolm Davis's "Incremental development with Ant and JUnit" (developerWorks, November 2000).In "Automating the build and test process" (developerWorks, August 2001),Erik Hatcher shows you how Ant and JUnit can be combined to bring you onestep closer to XP nirvana.Maven is an alternative to Ant that works especially well for project management tasks. Learn more about Maven with Charles Chan's"Project management: Maven makes it easy" (developerWorks, April 2003).Learn more about DbUnit with Philippe Girolam's "Control your test-environment with DbUnit and Anthill" (developerWorks, April 2004).If you still want to learn more about DdUnit, read Andrew Glover's "Effective Unit Testing with DbUnit" (OnJava, February 2004).Bruce Tate, the author of Bitter Java and Better, Faster, Lighter Java, is an advocate of agility and always has an interesting Blog to read.One of Groovy's most powerful features is its agility. Learn more aboutthe underlying principles of agile development (or XP) with Roy Miller's Demystifying Extreme Programming series (developerWorks, August 2002).Richard Hightower and Nicholas Lesiecki's Java tools for extreme programming is a practitioner's guide to agile development on the Java platform, including a chapter on "Building Java applications with Ant" (excerpted for developerWorks, July 2002).You'll find articles about every aspect of Java programming inthe developerWorks Java technologyzone.Browse for books on these and other technical topics.About the author  Andrew Glover is the President of Stelligent Incorporated, a Washington, DC, metro area company specializing in the construction of automated testing frameworks, which lower software bug counts, reduce integration and testing times, and improve overall code stability.Rate this pagedocument.write(''); Please take a moment to complete this form to help us better serve you. Did the information help you to achieve your goal? YesNoDon't know  Please provide us with comments to help improve this page:  How useful is the information? 12345Notuseful  Extremelyuseful  
Share this....
|
|