ユニットテストの並列実行

経緯

現場でのJunit実践入門の読書会にてユニットテストの並列実行について話題になったので調べてみました。
JUnit、Ant、Maven、Gradleでの実現方法をメモ。

全てのコードはgithubに置きましたので興味のある方はどうぞ。(今更ながらgithubに初push)
尚、build.gradleも置いてますが、構文が間違っているのか正しく動きません。。。orz

概要

↓こんな感じのテスト実行に時間がかかるクラスが複数あった場合に、並列で実行することでテストの実行時間を短縮したいと思います。

package com.yamap55.sample.parallel;

import java.util.Date;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class ParallelSampleTest {

    private static long starttime = 0L;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        Date d = new Date();
        starttime = d.getTime();
        System.out.println("start : " + d);
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        Date d = new Date();
        long l = d.getTime() - starttime;
        System.out.println("end   : " + d + ", time : " + l);
    }

    @Test
    public void test1()throws Exception {
        Thread.sleep(5000);
    }

    @Test
    public void test2()throws Exception {
        Thread.sleep(5000);
    }
}

JUnit4としてテストを並列実行

JUnitは単体ではテストケースの並列実行はサポートしていません。
Suiteを拡張して実行するコードがありましたのでこれをそのまま使用させて頂きました。(コードは↓を参照)

2009-07-09

尚、これらはクラス単位の並列実行になり、メソッド単位では実行できません。
上記記事の追記記事でメソッド単位での並列実行も可能と記載がありますが、記載されているソースがコンパイルできなかったため確認できませんでした。(使用しているjunitのコードがprivateになっており呼び出せませんでした、)

2009-07-10

JUnit3を使用する場合にはjenkinsの川口さん作成した「Parallel Junit」というライブラリがあるそうです。(簡単に検索したけどみつからず。。。)

AntでJunitのテストを並列実行

JUnitでのテストケースで解決するのではなく、antで並列実行を行うという解決方法。
ただ、AntもJUnitタスクで並列実行のオプションはないので、タスクを追加します。
テストクラスの一覧を取得し、1つずつスレッドに渡す的な方法なのでこの方法もクラス単位での並列実行になります。

  1. 「ant-contrib-0.6.jar」を取得。
  2. 取得した「ant-contrib-0.6.jar」のtaskを定義
  3. 実行したいテストクラスを取得
  4. foreachタスクを利用して1クラスずつ実行。
  <target name="execute.test">
    <junit fork="true" printsummary="true">

      <classpath>
        <path refid="compile.test.classpath" />
        <path path="${classes}" />
      </classpath>

      <formatter type="xml" />

      <batchtest todir="${reports}">
        <filelist dir="${src.test}" files="${test.source.absolute}" />
      </batchtest>
    </junit>
  </target>

  <target name="execute.tests.parallel">
    <foreach target="execute.test" maxThreads="5" inheritall="true" inheritrefs="true" parallel="true" param="test.source.absolute">
      <path>
        <fileset dir="${src.test}">
          <include name="com/yamap55/sample/parallel/*Test.java" />
        </fileset>
      </path>
    </foreach>
  </target>

MavenJUnitのテストを並列実行

Mavenはデフォルトで並列実行をサポートしているので要素を加えるだけ!

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-surefire-plugin</artifactId>
	<version>2.14</version>
	<configuration>
		<includes>
			<include>com/yamap55/sample/parallel/*Test.java</include>
		</includes>
<!-- この2つの要素を加えるだけで並列実行 -->
		<parallel>classes</parallel>
		<threadCount>6</threadCount>
	</configuration>
</plugin>
参考

2013-03-09