ひよっこ。

I want to…

Emma+Antをofflineモードで実行する

Posted by hikaruworld : 2009 5月 3

EMMAとは

Javaのカバレッジ測定ツール。On-the-flyモードとofflineモードの二つを持つ(詳細は後述)。
ダウンロードは以下から。
今回試したバージョンは2.0系
Eclipseプラグインとして、EclEmmaというプラグインも公開されている。

On-the-FlyモードとOfflineモード

簡単に言うと、OnTheFlyはファイルそのまま実行可能で、
Offlineモードは一旦既存のコードにEmmaのカバレッジ用のコードを埋め込んだファイルを吐き出した後に再実行が必要。
詳細は公式サイトの説明(英語)を見るべし。(概要はイントロに書いてある。)

EMMA+JUnitをAntで実行するためには

EMMA自体はJUnit自体に特別に対応しているわけではないので、
JUnit実行時にJUnitのパラメータであるjvmargを利用して引数を渡す必要がある。

なぜ、JUnitに特別対応しないかに関しては、FAQの2.3. Does EMMA integrate with {JUnit, Cactus, …}?でコメントされている。

また、上述したOn-the-FlyモードはJUnitをAntで実行する際には対応していない模様(英語なので自信ないけど)。

構成

テストを実行するプロジェクトの構成は以下の通り。

プロジェクト構成

EmmaSample/
|-- build.xml					--- buildで使用されるAntファイル(コンパイル→EMMAビルド→Junit実行→レポート出力)
|-- lib
|   |-- emma.jar				--- emmaのjarファイル
|   |-- emma_ant.jar			--- emmaをAntで利用する際のjarファイル
|   `-- junit-4.6.jar			--- Junitを実行するのに必要なライブラリ
|-- result
|   `-- TEST-TargetTest.xml		--- JUnitの結果出力先
|-- src
|   `-- Target.java				--- テスト対象ファイル
|-- test
|   `-- TargetTest.java			--- テストファイル(テストコードが書かれている)
`-- work						--- 作業用ディレクトリ
    |-- classes
    |   `-- Target.class		--- コンパイル済みソースファイル(javacで単純にコンパイルされたもの)
    |-- convert
    |   |-- classes			
    |   |   `-- Target.class	--- EMMAが組み込まれたclassファイル(容量が通常のjavacでコンパイルされたものに比べて2倍程度になる)
    |   `-- lib
    |-- emma
    |   |-- coverage.emma		--- コマンド実行後(Mainクラスや)に出力されるメタデータファイル(おそらく実行後にふんだ行を保持しているデータのはず)
    |   `-- metadata.emma		--- Antタスクによって生成されるメタデータファイル(このクラスを実行パスに通す事で、実行後にcoverage.emmaの実行後データを出力するものと思われる。)
    |-- report
    |   |-- _files
    |   |   |-- 0.html
    |   |   `-- 1.html
    |   |-- coverage.html		--- html形式で出力されたカバレッジレポート(./_fileはリンク先)
    |   `-- coverage.xml		--- xml形式で出力されたカバレッジレポート。人間では読みづらいのでHudson先生などに翻訳してもらう。
    `-- test
        `-- TargetTest.class	--- コンパイル済みテストファイル

テスト対象となるクラス

public class Target {

	public int cal(int i, int j) {
		return i + j;
	}
}

テストクラス

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

import static org.junit.Assert.*;

public class TargetTest {
	private static Target target;
	
	@BeforeClass
	public static void init() {
		target = new Target();
	}
	@Test
	public void calc1() {
		int result = target.cal(1, 2);
		 assertEquals(3, result);
	}
}

ビルドファイル

どこを参照するかで結構混乱するので注意。正確にパスを通していないと、メタデータが出力されない。

<?xml version="1.0" encoding="UTF-8"?>
<!-- ====================================================================== 
     2009/04/14 20:13:26                                                        

     emma-build    
     EMMAのJUnitを用いたビルドを行う。
                   
     morizou                                                                
     ====================================================================== -->
<project name="emma-build" default="emma-report" basedir=".">
    <description>
            EMMAのビルドを行う。
    </description>
	
	<!-- EMMA関連ビルドプロパティ -->
	<property name="emma.dir" value="${basedir}/lib" />
	<path id="emma.lib" >
		<pathelement location="${emma.dir}/emma.jar" />
		<pathelement location="${emma.dir}/emma_ant.jar" />
	</path>

	<!-- 新規タスク(つまり<emma>)を有効化 -->
	<taskdef resource="emma_ant.properties" classpathref="emma.lib" />

	<!-- emmaを用いて実行するかのプロパティ -->
	<property name="emma.enable" value="true"/>

	<!-- JUnitへパスを通す -->
	<property name="JUNIT_PATH" value="${basedir}/lib/junit-4.6.jar"/>

	<!-- 各種プロパティを定義 -->
	<property name="src.target" value="${basedir}/src" description="ソースのディレクトリ"/>
	<property name="test.target" value="${basedir}/test" description="テストソースのディレクトリ"/>
	<property name="src.output" value="${basedir}/work/classes" description="ソースのコンパイル結果出力先"/>
	<property name="test.output" value="${basedir}/work/test" description="テストソースのコンパイル出力先"/>
	<property name="convert.output" value="${basedir}/work/convert" description="emma組み込み後のclassファイル"/>
	<property name="emma.output" value="${basedir}/work/emma" description=".emmaメタデータの出力先"/>
	<property name="report.output" value="${basedir}/work/report" description="emmaのレポート出力先"/>


    <!-- ================================= 
          target: compile ソースのコンパイルを行う。             
         ================================= -->
    <target name="compile" description="ソースのコンパイルを行う。">
    	<javac srcdir="${src.target}" 
			destdir="${src.output}"
		    debug="on"
    		description="ソースのコンパイル"	>
    		<classpath>
    		</classpath>
    	</javac>
    	<javac srcdir="${test.target}" 
			destdir="${test.output}"
		    debug="on"
    		description="テストソースのコンパイル">
    		<classpath>
    			<pathelement location="${src.output}"/>
    			<path path="${JUNIT_PATH}" />
    		</classpath>
    	</javac>
    </target>

    <!-- ================================= 
          target: emma emmaをクラスファイルに組み込んだ形でコンパイルを行い、メタデータファイルを出力する。
         ================================= -->
    <target name="emma" depends="compile">
        <emma enabled="${emma.enable}">
	    <instr instrpath="${src.output}"
	            destdir="${convert.output}"
		    metadatafile="${emma.output}/metadata.emma"
		    merge="yes"
		    mode="fullcopy">
            </instr>
        </emma>
    </target>
	
    <!-- ================================= 
          target: junit junitの実行
         ================================= -->
    <target name="junit" depends="emma">
    	<junit printsummary="on" fork="yes">
                        <!-- jvmargを利用して、emmaの設定を行う -->
			<jvmarg value="-Demma.coverage.out.file=${emma.output}/coverage.emma" />
			<jvmarg value="-Demma.coverage.out.merge=true" />
            <jvmarg value="-Demma.verbosity.level=quiet" />
            <jvmarg value="-Dcoverage.enabled=true" />
    		<classpath>
    			<pathelement location="${convert.output}/classes"/>
    			<pathelement location="${test.output}"/>
    			<pathelement location="${emma.output}"/>
    			<path refid="emma.lib" />
    			<path path="${JUNIT_PATH}" />
    		</classpath>
    		<formatter type="xml"/>
    		<batchtest fork="true" todir="${basedir}/result">
    			<fileset dir="${test.target}">
    				<include name="**/TargetTest.java"/>
    			</fileset>
    		</batchtest>
    	</junit>
    </target>

	<target name="emma-report" depends="junit">
	    <!-- 計測結果のレポートの出力 -->
	    <emma enabled="true">
	        <property name="report.html.out.encoding" value="UTF-8" />
	        <report>
	            <sourcepath>
	                <pathelement location="${src.target}" />
	            </sourcepath>
	            <fileset dir="${emma.output}">
	                <include name="*.emma" />
	            </fileset>
	            <xml outfile="${report.output}/coverage.xml" />
	            <html outfile="${report.output}/coverage.html" />
	        </report>
	    </emma>
	</target>
</project>

レポートの参照

HTMLでの出力レポートも行単位で、GUIで参照できるので結構便利。
Emma-report-html
XMLに関しても、Hudsonなどを利用してレポートをだすと便利に使える。
画像はこっちにはないので省略。。。

余談

そんなに頻繁にアップデートされていない感じがちょっと気になる。

参考サイト

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

 
%d人のブロガーが「いいね」をつけました。