Tuesday, January 29, 2008

Parameters & JUnit Tests

I ran across one trouble with Junit tests recently. The point is that you can't pass parameters to JUnit tests directly (only using external storages such as file system objects, databases etc, but it's not always the best way for this), to be more precise you couldn't until JUnit 4. Besides new syntax technics, now it supports so called "parameterized tests" - this means you write a test once and it's possible to run it with a set of defined parameters. Before, you should write a particular test method for each parameter.

For example, you got a class that has a method summing two numbers and you wanna test it using 3 different parameters.
Before, you had to write three separate JUnit methods, it looked something like this:

public TestClass extends TestCase {
public void setUp() {
}

public void test1() {
assertEquals(new MyClass.sum(1, 2), 3);
}

public void test2() {
assertEquals(new MyClass.sum(3, 4), 7);
}

public void test3() {
assertEquals(new MyClass.sum(5, 6), 11);
}

public void tearDown() {
}
}

Since JUnit 4 you can do this simpler:

@RunWith(Parameterized.class)
public TestClass {
int a;
int b;
int res;

// Here you describe a method that returns parameters you wanna use to test "sum()" method
@Parameters
public static Collection getParameters() {
return Arrays.asList(new Object[][] = {{1, 2, 3}, {3, 4, 7}, {5, 6, 11}});
}

public TestClass(int a, int b, int res) {
this.a = a;
this .b = b;
this.res = res;
}

// implements the test method
@Test
public void sumTester() {
assertEquals(new MyClass.sum(a, b), res);
}
}

So, for making parameterized test work, you need:
1) describe method that returns parameters (using @Parameters javadoc)
2) implement public constructor that takes the parameters (source data + probably a right result to make an assert) and saves them into private fields.
3) implement test method

No comments: