2016年06月06日(月) [長年日記]
■ [java] JUnitでparameterized testなどを使うサンプル
6月からJavaを使っている。JUnitのパラメータ化テストなどの機能を使ったので忘れないようにメモ。
- テストケースを束ねるEnclosed。
- テストケースをパラメータ化して複数のテストデータを与えたテストを行うParameterized tests。
- 例外を捕捉するExpectedException Rules。
を使った。パラメータ化テストは以前にTheoriesを使ったことがあるのだけれど、今回はParameterized testsを使ってみた。
次のサンプルでは、テストメソッドは testAdd(), testAdd2(), testDivide() の3つだけだけれどパラメータ化により15件のテストが実行される。testDivide()の実装はいまいち。
// テスト対象のクラス
public class Calculator {
public static int add(int x, int y) {
return x + y;
}
public static int divide(int x, int y) {
return x / y;
}
}
import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import static org.hamcrest.CoreMatchers.is;
import org.junit.Rule;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.ExpectedException;
import org.junit.runners.Parameterized.Parameter;
// Calculatorのadd()とdivide()のテストを束ねるクラス。
@RunWith(Enclosed.class)
public class CalculatorTest {
// Calculator::add のテスト
@RunWith(Parameterized.class)
public static class AddTest {
// AddTest用のテストパラメータ
@Parameters(name = "{index}: {0}")
public static Iterable<P> data() {
return Arrays.asList(
new P(1, 1, 2),
new P(1, 2, 3),
new P(0, 1, 1),
new P(-1, 1, 10), // わざとテストを失敗させる
new P(-1, 1, 0)
);
}
// AddTest用テストパラメータを保持するクラス
public static class P {
int x;
int y;
int expected;
P(int x, int y, int expected) {
this.x = x;
this.y = y;
this.expected = expected;
}
@Override
public String toString() {
return String.format("x=%d, y=%d", x, y);
}
}
// テストパラメータはメンバ変数に保持することになる
@Parameter
public P p;
// これがテスト本体
@Test
public void testAdd() {
assertThat(Calculator.add(p.x, p.y), is(p.expected));
}
@Test
public void testAdd2() {
assertThat(Calculator.add(p.y, p.x), is(p.expected));
}
}
// Calculator::divide のテスト
@RunWith(Parameterized.class)
public static class DivideTest {
@Parameters(name = "{index}: {0}")
public static Iterable<P> data() {
return Arrays.asList(
new P(1, 1, 1),
new P(1, 2, 0),
new P(0, 1, 0),
new P(-1, 0, null), // 例外が投げられるケース
new P(-1, 1, null) // わざとテストを失敗させる
);
}
public static class P {
int x;
int y;
Integer expected;
P(int x, int y, Integer expected) {
this.x = x;
this.y = y;
this.expected = expected;
}
@Override
public String toString() {
return String.format("x=%d, y=%d", x, y);
}
}
@Parameter
public P p;
// 例外を捕捉するのにExpectedExceptionルールを使う
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testDivide() {
// expectedがnullなら例外を捕捉することにする
if (p.expected == null) thrown.expect(ArithmeticException.class);
int result = Calculator.divide(p.x, p.y);
if (p.expected != null) assertThat(result, is(p.expected));
}
}
}
Testsuite: CalculatorTest
Tests run: 15, Failures: 3, Errors: 0, Skipped: 0, Time elapsed: 0.047 sec
Testcase: testDivide[4: x=-1, y=1](CalculatorTest$DivideTest): FAILED
Expected test to throw an instance of java.lang.ArithmeticException
junit.framework.AssertionFailedError: Expected test to throw an instance of java.lang.ArithmeticException
Testcase: testAdd[3: x=-1, y=1](CalculatorTest$AddTest): FAILED
Expected: is <10>
but: was <0>
junit.framework.AssertionFailedError:
Expected: is <10>
but: was <0>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at CalculatorTest$AddTest.testAdd(CalculatorTest.java:56)
Testcase: testAdd2[3: x=-1, y=1](CalculatorTest$AddTest): FAILED
Expected: is <10>
but: was <0>
junit.framework.AssertionFailedError:
Expected: is <10>
but: was <0>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at CalculatorTest$AddTest.testAdd2(CalculatorTest.java:61)
[ツッコミを入れる]