Archive

Archive for the ‘JUnit’ Category

Testing a large variance of inputs using Parameterized JUnit tests

April 17, 2013 4 comments

Often in utility methods (e.g. your usual StringUtils) you find yourself writing the same test over and over again with different inputs.
You can do something like this:

public class TestSomeUtils
{
      @Test
      public void test_function1_input_1()
      {
            test_function1("some-output",  7, 2.6);
      }

      @Test
      public void test_function1_input_2()
      {
            test_function1("another-output",  9, -1.56);
      }

      @Test
      public void test_function1_input_3()
      {
            test_function1("no-output",  0, 768.2341);
      }

      private void test_function1(String expectedOutput, int inputA, double inputB)
      {
            String actualOutput = SomeUtils.function1(inputA, inputB);
            assertEquals(expectedOutput, actualOutput);
      }
}

However – JUnit has a much better way of doing it – org.junit.runners.Parameterized

@RunWith(Parameterized.class)
public class TestSomeUtils
{
      private String expectedOutput;
      private int inputA;
      private double inputB;

      @Parameters
      public static Collection<Object[]> prepareData()
      {
            Collection<Object[]> args = new ArrayList<Object[]>();

            args.add(new Object[]{"some-output",  7, 2.6});
            args.add(new Object[]{"another-output",  9, -1.56});
            args.add(new Object[]{"no-output",  0, 768.2341});

            return args;        
      }

      public TestSomeUtils(String expectedOutput, int inputA, double inputB)
      {
            this.expectedOutput = expectedOutput;
            this.inputA = inputA;
            this.inputB = inputB;
      }

      @Test
      public void testSomething()
      {
            String actualOutput = SomeUtils.function1(inputA, inputB);
            assertEquals(expectedOutput, actualOutput);
      }
}

Explenation:

@RunWith(Parameterized.class) tells the JUnit framework use a non-default test runner, in which case it is the Parameterized runner.
This runner will execute all the tests on all the given inputs. So if you have 3 test methods and nine sets of inputs – you actually get 27 distinct tests.

How does it do it?

  1. It calls the prepareData method since it is annotated with @Parameters.
  2. For each Object[] in the Collection it will instantiate the test class using the Object[] as constructor arguments (Using Reflection).
  3. It will execute all the test methods in the test class

Simple, isn’t it?

I use it mostly for simple utility methods that I want to cover from end to end, but I have also used it to execute other tests as well.

Advertisements
%d bloggers like this: