Archive

Monthly Archives: April 2016

We have a large Java/Groovy application with a JUnit test suite containing thousands of tests, that now takes several minutes to run. We wanted to try to reduce the test suite run time, and wanted a report of test times sorted longest to shortest, allowing us to focus on the worst offenders.

We used the JUnit RunListener facility to calculate the test run times and then sort and display a report at the end of the test suite. Specify the test suite class name in the testSuite property (field).

This class is implemented in Groovy, but the Java version would be very similar.

import org.junit.runner.Description
import org.junit.runner.JUnitCore
import org.junit.runner.Result
import org.junit.runner.notification.RunListener

/**
 * Run a JUnit test suite and build a list of all tests (test methods) sorted
 * by run time, in descending order. Run this class as a Java Application.
 * Specify the test suite class in the testSuite property (field).
 */
class RunTestSuiteTimingReport {

  private static Class testSuite = MyTestSuite
  private static long showTestTimesGreaterThanOrEqualToMilliseconds = 1000L

  private static class TimingListener extends RunListener {

    private Map<Description, Long> testStartTimes = [:]
    private Map<Description, Long> testRunTimes = [:]

    @Override
    void testStarted(Description description) throws Exception {
      testStartTimes[description] = System.currentTimeMillis()
    }

    @Override
    void testFinished(Description description) throws Exception {
      long startTime = testStartTimes[description]
      testRunTimes[description] = System.currentTimeMillis() - startTime
    }

    @Override
    void testRunFinished(Result result) throws Exception {
      println "Test suite finished; ${testRunTimes.size()} total tests"
      // descending order, so reverse comparison
      def sortedRunTimes = testRunTimes.sort { a, b -> b.value <=> a.value } 
      for(Description description: sortedRunTimes.keySet()) {
        long runTime = sortedRunTimes[description]
        if (runTime < showTestTimesGreaterThanOrEqualToMilliseconds) {
          break;
        }
        println " - $description: $runTime ms"
      }
    }
  }

  static void main(String... args) {
    JUnitCore core= new JUnitCore()
    core.addListener(new TimingListener())
    core.run(testSuite)
    Runtime.runtime.exit(0)
  }
}
Advertisements