今更ながらAntでdjUnitタスクを実行する方法です。
Eclipseが新しくなりdjUnitを使用できなくなってしまったが、プロジェクトではdjUnitのテストを使い続けたい場合に役に立つと思います。
##動作環境
Ant 1.9.7
jp.co.dgic.eclipse.jdt.djunit_3.5.x_0.8.6.zip
jUnit4
Eclipse Release 4.7.0 (Oxygen)
##プロジェクトの構造
テスト対象クラス、テストクラスを各2つ作成し、Ant、djUnit、jUnitから必要なjarをtest/libフォルダにコピーします。
###テスト対象クラス
package com.example;
public class HelloService {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public String getMessage() {
return String.format("Hello %s!", this.getName());
}
public void sayHello() {
System.out.println(this.getMessage());
}
}
package com.example;
public class CalculateService {
public enum Operation {
ADD,
SUBTRACT,
MULTIPLY,
DIVIDE
};
private int v1;
private int v2;
private Operation op;
public void setValue1(int value) {
this.v1 = value;
}
public void setValue2(int value) {
this.v2 = value;
}
public void setOperation(Operation op) {
this.op = op;
}
public float getResult() {
switch (this.op) {
case ADD:
return this.v1 + this.v2;
case SUBTRACT:
return this.v1 - this.v2;
case MULTIPLY:
return this.v1 * this.v2;
case DIVIDE:
if (this.v2 == 0) throw new IllegalArgumentException("value2 must not be zero.");
return (float)this.v1 / this.v2;
}
throw new IllegalArgumentException("operation isn't specified.");
}
public void calculate() {
String opString = "?";
switch (this.op) {
case ADD:
opString = "+";
break;
case SUBTRACT:
opString = "-";
break;
case MULTIPLY:
opString = "*";
break;
case DIVIDE:
opString = "/";
break;
}
System.out.println(String.format("%d %s %d = %.3f", this.v1, opString, this.v2, this.getResult()));
}
}
###テストクラス
package com.example;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import jp.co.dgic.testing.common.virtualmock.MockObjectManager;
public class HelloServiceTest {
@Before
public void init() {
MockObjectManager.initialize();
}
@Test
public void test001() {
HelloService service = new HelloService();
service.setName("Japan");
assertThat(service.getMessage(), is("Hello Japan!"));
MockObjectManager.setReturnValueAtAllTimes(HelloService.class, "getName", "World");
assertThat(service.getMessage(), is("Hello World!"));
service.sayHello();
MockObjectManager.assertCalled(HelloService.class, "sayHello");
}
}
package com.example;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import com.example.CalculateService.Operation;
import jp.co.dgic.testing.common.virtualmock.MockObjectManager;
public class CalculateServiceTest {
@Before
public void init() {
MockObjectManager.initialize();
}
@Test
public void test001() {
CalculateService service = new CalculateService();
service.setValue1(100);
service.setValue2(50);
service.setOperation(Operation.ADD);
service.calculate();
assertThat(service.getResult(), is(150f));
MockObjectManager.assertCalled(CalculateService.class, "calculate");
MockObjectManager.setReturnValueAtAllTimes(CalculateService.class, "getResult", 777f);
service.calculate();
assertThat(service.getResult(), is(777f));
}
}
###build.xml
build.xmlはEclipseのエクスポート機能で原形を作成し、djUnitのタスクを追加しています。
djunitタスクの「usenoverify="true"」はJava8で実行する際に必要です。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project basedir="." default="coverage.report" name="testproject">
<taskdef classpath="./test/lib/djunit.jar" resource="djunittasks.properties"/>
<property environment="env"/>
<property name="ECLIPSE_HOME" value="../../eclipse/eclipse/"/>
<property name="src.main" value="./src/main/java"/>
<property name="test.src.main" value="./test/src/main/java"/>
<property name="junit.output.dir" value="junit"/>
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.8"/>
<property name="source" value="1.8"/>
<path id="testproject.classpath">
<pathelement location="bin"/>
<pathelement location="test/lib/ant-junit4.jar"/>
<pathelement location="test/lib/asm-3.1.jar"/>
<pathelement location="test/lib/asm-attrs-1.5.3.jar"/>
<pathelement location="test/lib/jakarta-oro-2.0.7.jar"/>
<pathelement location="test/lib/jcoverage-djunit-1.0.5.jar"/>
<pathelement location="test/lib/djunit.jar"/>
<pathelement location="test/lib/junit.jar"/>
<pathelement location="test/lib/hamcrest-core-1.3.jar"/>
</path>
<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src/main/java">
<exclude name="**/*.launch"/>
<exclude name="**/*.java"/>
</fileset>
</copy>
<copy includeemptydirs="false" todir="bin">
<fileset dir="test/src/main/java">
<exclude name="**/*.launch"/>
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>
<target name="clean">
<delete dir="bin"/>
</target>
<target depends="clean" name="cleanall"/>
<target depends="build-subprojects,build-project" name="build"/>
<target name="build-subprojects"/>
<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
<src path="src/main/java"/>
<src path="test/src/main/java"/>
<classpath refid="testproject.classpath"/>
</javac>
</target>
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects"/>
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
<copy todir="${ant.library.dir}">
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</copy>
<unzip dest="${ant.library.dir}">
<patternset includes="jdtCompilerAdapter.jar"/>
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
</unzip>
</target>
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
<antcall target="build"/>
</target>
<target name="HelloServiceTest" depends="build">
<mkdir dir="${junit.output.dir}"/>
<djunit printsummary="withOutAndErr" targetsrcdir="${src.main};${test.src.main}" virtualmock="yes" coverage="no" usenoverify="true">
<formatter type="xml"/>
<test name="com.example.HelloServiceTest" todir="${junit.output.dir}"/>
<jvmarg line="-ea"/>
<classpath refid="testproject.classpath"/>
</djunit>
</target>
<target name="CalculateServiceTest" depends="build">
<mkdir dir="${junit.output.dir}"/>
<djunit printsummary="withOutAndErr" targetsrcdir="${src.main};${test.src.main}" virtualmock="yes" coverage="no" usenoverify="true">
<formatter type="xml"/>
<test name="com.example.CalculateServiceTest" todir="${junit.output.dir}"/>
<jvmarg line="-ea"/>
<classpath refid="testproject.classpath"/>
</djunit>
</target>
<target name="TestAll" depends="build">
<mkdir dir="${junit.output.dir}"/>
<djunit printsummary="withOutAndErr" targetsrcdir="${src.main};${test.src.main}" virtualmock="yes" coverage="yes" usenoverify="true">
<formatter type="xml"/>
<jvmarg line="-ea"/>
<classpath refid="testproject.classpath"/>
<batchtest todir="${junit.output.dir}">
<fileset dir="./bin">
<include name="**/*Test.class"/>
</fileset>
</batchtest>
</djunit>
</target>
<target name="coverage.report" depends="TestAll">
<djunit-coverage-report serFile="./jcoverage.ser" srcdir="${src.main}" destdir="${junit.output.dir}">
<classpath refid="testproject.classpath"/>
</djunit-coverage-report>
</target>
</project>
##実行
Eclipse、あるいはコマンドラインから実行できます。ただし、test/libにコピーしたant-junit4.jarのバージョンと同じAntを使ってください。以下にコマンドラインから実行した結果を記します。
###カバレッジレポート
カバレッジレポートも作成されるんですが、なんか変なんですよね・・・
##まとめ
古いからかdjUnitの情報が少ないのでこの記事を書きました。
修正すべき箇所等あるかと思いますので、何か気づきましたらご指摘いただければ幸いです。
##追記 2019/8/27
Eclipseでリモートデバッグする方法です。
build.xmlのdjunitタスクのjvmargを以下のようにします。-eaはなくてもかまいません。
<jvmarg line="-ea -agentlib:jdwp=transport=dt_socket,suspend=y,server=y,address=8000"/>
実行すると以下のように途中で停止します。
続いてEclipseからtestprojectを選択して[右クリック]→[デバッグ]→[デバッグの構成]→[リモートJavaアプリケーション]を選択し、図のように入力したらデバッグボタンを押します。これでデバッグ実行できます。
ブレイクポイントの設定をお忘れなく。