Thursday, June 3, 2010

Making JUnit tests run parallely

If you use Selenium tests or other JUnit based tests with long execution time and low CPU usage you will eventually try to make them run concurrently. The good thing is that this is extremely easy thing to do with Apache Ant.

That why I am extremely surprised nobody still does it. Most people try to invent the wheel and try to use other frameworks like TestNG, write new experimental parallel computer classes for JUnit, or even configurable versions of the same classes. This all is a time waste for the people who just want to run some concurrent tests.

Here is how you do that:

1. Make sure that you have "ant-contrib" package installed. Usually it is enough if the appropriate JAR file is in the ant class path.

2. Turn the tasks of "ant-contrib" library. You can do this by adding the following lines to your "build.xml" file.
<taskdef
  resource="net/sf/antcontrib/antcontrib.properties"
/>
3. Add the new target that will execute exactly one test. You will have something like following.
<target name="execute.test">

  <!-- we need to have relative path -->
  <pathconvert property="test.source.relative">
    <fileset file="${test.source.absolute}" />
    <map from="${test.sources}/" to="" />
  </pathconvert>

  <!-- run one particular test -->
  <junit fork="true" printsummary="true">

    <classpath>
      <path refid="${test.classes}" />
    </classpath>

    <formatter type="xml" />

    <batchtest todir="${test.reports}">
      <fileset dir="${test.sources}">
        <filename name="${test.source.relative}" />
      </fileset>
    </batchtest>
  </junit>

</target>
4. Now use built-in "foreach" concurrent execution capabilities to execute this target. You would have to add something like following to your other target.
<foreach
target="execute.test"
maxthreads="5"
inheritall="true"
inheritrefs="true"
parallel="true"
param="test.source.absolute">
  <path>
    <fileset dir="${test.sources}">
      <include name="**/*.java"/>
    </fileset>
  </path>
</foreach>
5. That's all. Easy and nice. You will have all your tests executing in 5 nice threads. You can use any number of threads you want. No additional configuration, classes, code is needed.