Groovy performance testing - No Fluff Just Stuff

Groovy performance testing

Posted by: Andrew Glover on April 3, 2006

Most hip JUnit extension frameworks integrate easily with Groovy. For example, one can easily employ XMLUnit, DbUnit, and jWebUnit via JUnit tests written in Groovy as these frameworks expose an API that facilitates delegation. Decorator based frameworks, however, are slightly more challenging to utilize within Groovy.

JUnitPerf is an extension framework for JUnit that offers the neat-o ability to ascertain fine grained performance and scalability (i.e. at a method level). For instance, JUnitPerf enables scenarios such as “the findUsers method must return a collection of User objects within one second or the test fails (even if the test did return a valid collection of User objects).” The framework also adds scalability via threading. Using the above scenario, one can add the trippin? requirement that under a load of 100 invocations, the findUsers method must return a collection of User objects within one second.

Understandably, there are scenarios within Groovy where this type of framework could come in quite handy:

  • testing the performance and scalability of Groovy applications
  • testing the performance and scalability of normal Java code in tests written in Groovy

But, because JUnitPerf is a decorator based framework that requires test cases define a suite method, integration with Groovy can cause some misleading results. Groovy’s available test runners, GroovyTestSuite and AllTestSuite create suite methods themselves, which appears to override individually defined suite methods within Groovy test cases. Therefore, when running a test case, written in Groovy, that contains a suite method it appears the method is ignored. This means that test cases themselves are run; however, they are not decorated.

To solve this issue and successfully run a test case written in Groovy, which contains a suite method, there are two steps that must be followed:

  • define a constructor which takes a String and have that constructor call super(yourString)
  • compile the Groovy test case into normal Java byte code and run it via JUnit?s normal runners.

For example, the following smokin? test case, written in Groovy, utilizes JUnitPerf via a suite method to verify that invoking testOr 20 times (each thread staggered by 100 milliseconds) returns within 2300 milliseconds.

package test.com.acme.seda.impl.perf

import junit.framework.TestCase
import com.acme.seda.impl.RegexPackageFilter
import junit.framework.Test
import junit.textui.TestRunner
import com.clarkware.junitperf.ConstantTimer
import com.clarkware.junitperf.LoadTest
import com.clarkware.junitperf.TimedTest
import com.clarkware.junitperf.Timer

class RegexFilterPerfGTest extends TestCase {

 RegexFilterPerfGTest(test){
  super(test)
 }

 void testOr() {
  def filr = new RegexPackageFilter("java|org")
  assertTrue("value should be true",
    filr.applyFilter("org.sf.String"))
 }

 static void main(String[] args) {
  TestRunner.run(RegexFilterPerfGTest.suite())
 }

 static Test suite() {
  def testCase = new RegexFilterPerfGTest("testOr")
  //20 users for load staggered at 100 ms
  def loadTest = new LoadTest(testCase, 20,
    new ConstantTimer(100))
  //each thread must return within 2300 ms
  return new TimedTest(loadTest, 2300)
 }
}

Running this test requires it first be complied into Java byte code and invoked via JUnit, which can be done quite easily with the Maven Groovy Test plug-in. By typing the groovytest:test command, the plug-in will compile any Groovy tests into byte code and then invoke the test:test command, which internally invokes the venerable junit Ant task.

For instance, below is the output from running the groovytest:test command in Maven.

test:test:
 [junit] Running test.com.acme.seda.frmwrk.
   filter.impl.ClassInclusionFilterTest
 [junit] Tests run: 3, Failures: 0, Errors: 0, 
   Time elapsed: 0 sec
 [junit] Running test.com.acme.seda.frmwrk.
   filter.impl.misc.ConcurrentFilteringTest
 [junit] Tests run: 10, Failures: 0, Errors: 0, 
   Time elapsed: 0.031 sec
 [junit] Running test.com.acme.seda.frmwrk.
   filter.impl.perf.RegexFilterPerfGTest
   TimedTest (WAITING): LoadTest (NON-ATOMIC): 
   ThreadedTest: testOr(test.com.acme.seda.
   frmwrk.filter.impl.perf.RegexFilterPerfGTest): 
   2015 ms
 [junit] Tests run: 20, Failures: 0, Errors: 0, 
   Time elapsed: 2.031 sec
 [junit] Running test.com.acme.seda.frmwrk.
   filter.impl.SimpleFilterTest
 [junit] Tests run: 1, Failures: 0, Errors: 0, Time 
   elapsed: 0.016 sec

The next time it?s your bag to figure out the performance of some Groovy code or you want to test the performance and scalability of your hip Java application with Groovy, give JUnitPerf a try! It?s a trip!

Andrew Glover

About Andrew Glover

Andrew is the Engineering Manager for Netflix's Delivery Engineering Team. He and his team are building the next generation Continuous Delivery platform that is facilitating Netflix's rapid global expansion. Before joining Netflix, he served as the CTO of App47, where he lead the development of a SaaS Mobile Application Management platform. Andrew is also the co-author of Addison Wesley's “Continuous Integration” and he actively blogs about software at thediscoblog.com.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »