Maven + JUnitのテンプレート

はじめに

MavenのプロジェクトでJUnitを利用するときに、毎回同じようなpom.xmlとテストコードを書いている。 なので、テンプレートとしてサンプルコードを書き残しておく。 このサンプルコードでは、割り算の処理をテストしている。

ディレクトリ構成

test-template
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- redj
    |           `-- junit
    |               `-- Calc.java
    `-- test
        `-- java
            `-- redj
                `-- junit
                    `-- CalcTest.java

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>redj-junit</groupId>
    <artifactId>test-template</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <properties>
        <!-- configurations -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        
        <!-- dependency versions -->
        <junit.version>4.12</junit.version>
        <hamcrest.version>1.3</hamcrest.version>
    </properties>
        
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
            <version>${hamcrest.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Calc.java

テスト対象のクラスで、割り算を行うクラス。 バグを表現するため、わざと絶対値をとってから割っている。

package redj.junit;

public class Calc {

    public static int divide(int x, int y) {
        return x / Math.abs(y); // BUG: This line should be "return x / y;"
    }
}

CalcTest.java

package redj.junit;

import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.core.Is.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Enclosed.class)
public class CalcTest {

    @RunWith(Parameterized.class)
    public static class DevideTest {

        @Parameters
        public static Iterable<Fixture> data() {
            List<Fixture> fixtures = new ArrayList<>();

            fixtures.add(new Fixture(4, 2, 2, null));
            fixtures.add(new Fixture(4, 0, 0, ArithmeticException.class));
            fixtures.add(new Fixture(4, -2, -2, null));

            return fixtures;
        }

        @Parameter
        public Fixture fixture;

        @Rule
        public ExpectedException expectedException = ExpectedException.none();

        @Before
        public void setUp() {
            if (fixture.exceptionClass != null) {
                expectedException.expect(fixture.exceptionClass);
            }
        }

        @Test
        public void test() {
            int actual = Calc.divide(fixture.x, fixture.y);

            assertThat(actual, is(fixture.expected));
        }

        public static class Fixture {

            public final int x;

            public final int y;

            public final int expected;

            public final Class<? extends Throwable> exceptionClass;

            public Fixture(int x, int y, int expected, Class<? extends Throwable> exceptionClass) {
                this.x = x;
                this.y = y;
                this.expected = expected;
                this.exceptionClass = exceptionClass;
            }
        }
    }
}

実行結果

$ mvn clean install
(略)
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running redj.junit.CalcTest
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.224 sec <<< FAILURE!
test[2](redj.junit.CalcTest$DevideTest)  Time elapsed: 0.012 sec  <<< FAILURE!
java.lang.AssertionError: 
Expected: is <-2>
     but: was <2>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:956)
    at org.junit.Assert.assertThat(Assert.java:923)
    at redj.junit.CalcTest$DevideTest.test(CalcTest.java:51)
(略)

Results :

Failed tests:   test[2](redj.junit.CalcTest$DevideTest): (..)

Tests run: 3, Failures: 1, Errors: 0, Skipped: 0
(略)