Running JUnit Tests Repeatedly Without Loops

Recently I came across a problem where I had to write tests for a method that calculates randomly distributed values within a certain range of possibilities 1. More precisely if you assume a signature that looks like
 
 
 
 
 
 
 
 

interface RandomRangeValueCalculator {
  long calculateRangeValue( long center, long radius );
}

a test might verify the following2:

public class RandomRangeValueCalculatorImplTest {

  @Test
  public void testCalculateRangeValue() {
    long center = [...];
    long radius = [...];
    RangeValueCalculator calculator = [...];

    long actual = calculator.calculateRangeValue( center, radius );

    assertTrue( center + radius >= actual );
    assertTrue( center - radius <= actual );
  }
}

However calculating range values for the same center and radius multiple times will return different results (at least most of the time). Therefore the solution seemed somewhat brittle in a sense that a poor implementation might easily produce intermittent failures. On the other hand I did not want to descend into the depths of actually messuring the value distribution. The latter (random, gaussian or the like) was provided by a collaborator and its proper usage was already confirmed by additional tests.

It occurred to me that a more pragmatic solution could be to actually run the test above automatically over and over again to make it more ‘significant’. Of course the easiest way to achieve this would be to put the test’s content into a loop and go on living.

But for a start it looked somewhat wrong having the asserts within a loop and mixing two aspects into one test run. And even more important the covered problem domain required more tests of the kind. So given the intent of reducing redundancy I remembered my post about JUnit-Rules and implemented a simple repeat rule3. With this rule in place the test above could be gently amended to:

public class RandomRangeValueCalculatorImplTest {

  @Rule
  public RepeatRule repeatRule = new RepeatRule();

  @Test
  @Repeat( times = 10000 )
  public void testCalculateRangeValue() {
    long center = [...];
    long radius = [...];
    RangeValueCalculator calculator = [...];

    long actual= calculator.calculateRangeValue( center, radius );

    assertTrue( center + radius >= actual );
    assertTrue( center - radius <= actual );
  }
}

I think it is quite easy to understand that the testCalculateRangeValue method will be executed 10000 times while running the test case. The following snippet shows the implementation of the RepeatRule, which is straight forward:

public class RepeatRule implements TestRule {

  @Retention( RetentionPolicy.RUNTIME )
  @Target( {
    java.lang.annotation.ElementType.METHOD
  } )
  public @interface Repeat {
    public abstract int times();
  }

  private static class RepeatStatement extends Statement {

    private final int times;
    private final Statement statement;

    private RepeatStatement( int times, Statement statement ) {
      this.times = times;
      this.statement = statement;
    }

    @Override
    public void evaluate() throws Throwable {
      for( int i = 0; i < times; i++ ) {
        statement.evaluate();
      }
    }
  }

  @Override
  public Statement apply(
    Statement statement, Description description )
  {
    Statement result = statement;
    Repeat repeat = description.getAnnotation( Repeat.class );
    if( repeat != null ) {
      int times = repeat.times();
      result = new RepeatStatement( times, statement );
    }
    return result;
  }
}

So far the RepeatRule serves it purpose and the system functionalities based on the mentioned implementation is working like a charm. Nevertheless sometimes someone misses the forest for the trees and so I thought it might be a good idea to share this solution to see what other people come up with.

  1. Actually this was only one part of the problem domain but I consider it as a sufficient motivation for this post.
  2. Formalistically spoken: f(n,m)∈{e|e≥n-m∧e≤n+m}, for all e,n,m ∈ ℕ
  3. A short google search only came up with a similar solution available in Spring, which was not available in my set of libraries.

 

Reference: Running JUnit Tests Repeatedly Without Loops from our JCG partner Frank Appel at the Code Affine blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

One Response to "Running JUnit Tests Repeatedly Without Loops"

  1. Anuj Kumar says:

    Hi Frank,
    Did you try EasyTest framework(https://github.com/EaseTech/easytest-core/blob/master/README.md) which gives you the ability to repeat JUnit tests out of the box(without having you to provide your own Rule). And it provides its users a lot more than traditional JUnit framework.

    Give it a try and I am sure you will like it.

Leave a Reply


× 6 = eighteen



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close