EMMA
EMMA
EMMA 公式サイト
ここでは、WindowsXP上でJDK1.4.2_06とEMMA 2.1.5320 (stable)を用いていろいろと試しています。
特徴
- Javaプログラムのカバレッジツールの1つ。
- 実際にアプリケーションを稼動させながらカバレッジのデータを収集できる。
- 例えば、サーバーアプリケーションを実際にTomcatなどの上で動かした状態でデータを収集可能。
- 実際のユーザー操作に基づいたカバレッジの追跡が可能。
- 単体テストを想定していない作りのアプリケーションにおけるカバレッジの測定も可能。
- JDK5.0でコンパイルしたプログラムも処理可能。
on the flyモード
カバレッジ情報を取得したいプログラム(jarファイルなど)を特に加工することなく、実行します。普通の(?)Javaアプリケーションなら、多くの場合この使い方で問題ないと思いますが、独自クラスローダーを用いたりするアプリケーションの場合、正しく動作しないことがあるようです。offlineモード
classファイル(jarファイル中に含まれるものも含む)にカバレッジ情報取得用のコードを埋め込みます。そのため、独自クラスローダーを用いているアプリケーションでも実行可能です(サーバー上で動作するアプリケーションのカバレッジ情報も取得可能です)。基本的な使い方
QuickStartでも取り扱われている、J2SE SDKのデモに含まれているSwingSet2.jarを使用します。EMMAをダウンロードし、アーカイブ内に含まれているemma.jarをSwingSet2.jarと同じフォルダにコピーし、コマンドプロンプトを開いてSwingSet2.jarがあるフォルダへ移動しておきます。。
on the fly
SwingSet2.jarを直接起動するのではなく、emmaを起動してemma経由でSwingSet2.jarを起動します。java.exe -cp emma.jar emmarun -r html -jar SwingSet2.jar |
アプリケーションを終了すると、カレントフォルダ内にcoverageフォルダが作成され、レポートhtmlが出力されます。なお、以下のように-spオプション付きで実行すると、ソースファイルの情報も含めたレポートが作成されます。
java.exe -cp emma.jar emmarun -r html -sp ./src -jar SwingSet2.jar |
※ソースコード中の日本語はそのままでは文字化けしてしまうようです。その場合、以下のようにreport.html.out.encodingパラメータをつけると正しく出力されます。
java.exe -Demma.report.html.out.encoding=UTF-8 -cp emma.jar emmarun -r html -sp ./src -jar SwingSet2.jar |
なお、MS932を使用した場合、日本語は問題なく出力されましたが、余白(スペース)部分が上手く出力されませんでした。
offline
SwingSet2.jarに対してカバレッジ情報測定用のコードを埋め込みます。この際、メタデータが保存されたcoverage.emファイルが生成されます。java.exe -cp emma.jar emma instr -m overwrite -cp SwingSet2.jar |
jarファイルを直接上書きせずに、別ファイルとして出力する場合はoverwriteではなくfullcopyを使用します。この場合、ファイルの出力先として-dオプションが必要となります(jarファイルの出力先は、-dで指定したフォルダ内のlibフォルダ内となります)。
java.exe -cp emma.jar emma instr -m fullcopy -d dist -cp SwingSet2.jar |
SwingSet2.jarを実行します。この際、emma.jarにもクラスパスを通しておく必要があります。
java.exe -cp SwingSet2.jar;emma.jar SwingSet2 |
あれこれ実行してからアプリケーションを終了すると、coverage.ecファイルが出力されているはずですので、jarファイルを処理した際に生成されたcoverage.emファイルと組み合わせてレポートを出力します。
java.exe -cp emma.jar emma report -r html -sp ./src -in coverage.em,coverage.ec |
レポート
その行は全て処理した |
その行の一部を処理した(if文で条件がfalseとなったために処理がスキップされた場合など?) |
その行は全く処理されていない |
その行は処理対象外である(コメントなど) |
分岐に関するカバレッジは行われていないような感じです(if (flag) System.out.println("Hoge"); というような処理の場合、flagがtrueの場合だけでも「その行は全て処理した」とみなされているような感じです)。
注意事項(?)
- ソースファイルを参照させる場合は、パッケージ構造に対応したフォルダ構造のルートを指定します(まぁ、当然といえば当然でしょうが)。
- ソースファイルに対して.jarファイルは指定できないようです(これができれば楽なのですが・・・Documentにも.javaファイルとしか書かれていないようです)。
リモート操作
EMMA 2.1.*から、リモートでのカバレッジ情報取得、カバレッジ情報クリアを行うことができるようになりました。カバレッジ情報を測定させながら長時間動かしていると、かなりメモリを消費することがありますが、こまめにカバレッジ情報取得&クリアを行うことでメモリ消費量の増大を抑えることができるような感じです。細かくテストしたわけではないのですが、クリアせずに処理を延々と行い続けると、タスクマネージャ上で400MB以上のメモリ使用量になって落ちてしまいました(一方、同じ処理を走らせた状態でこまめに情報取得&クリアを行うと、落ちることなく動き続けました)。
カバレッジ情報測定中のマシンに対して、以下のコマンドを実行することで、カバレッジ情報を取得できます。
java.exe -cp emma.jar emma ctl -connect localhost:47653 -command coverage.get,coverage.ec |
ここでは、localhostを指定していますが、IPアドレスなどで指定することにより、他のマシンに対しても適用可能(ファイアウォールなどでブロックされたりした場合はその限りではありませんが)。カバレッジ情報は、現在あるファイルに対して追記されるようです。ですので、実際にはカバレッジ情報取得&クリアをまとめて行うことになるかと思います。
java.exe -cp emma.jar emma ctl -connect localhost:47653 -command coverage.get,coverage.ec -command coverage.reset |
情報取得&クリアをまとめて行う場合は、上記のように-commandオプションを続けて書くとOKです。もちろん、分けて2回実行しても情報取得&クリアは可能ですが、2回の実行の間のカバレッジ情報をロストしてしまう危険性があります(1回のコマンドで処理した場合でも、もしかしたら数ms間のカバレッジ情報をロストしてしまう可能性があるのかもしれませんが)。
あとはofflineモードと同様にレポートファイルを作成すればOKです。なお、ソースフォルダは、カンマで区切ることで複数指定することもできます。Eclipseで、複数のソースフォルダを作成して使用している場合などに有用。
java.exe -cp emma.jar emma report -r html -sp ./src1,./src2 -in coverage.em,coverage.ec |
フィルター
実行の際に必要となるクラスがたくさんある場合、フィルターでカバレッジ情報測定対象となるクラスを絞り込むことができます。クラスの指定はフルパッケージで行い、*および?をワイルドカードとして指定することができます(ドキュメントからすると、パッケージ名の部分にワイルドカードは指定できないようです(試してはいませんが))。includeが指定されていない場合は、全てのクラスが処理対象となります。また、同じクラスをincludeとexcludeの双方に指定していた場合はEMMA Reference Manualに記載されているように、excludeの指定が優先となります。test.TestClass1, test.TestClass2, test.RunClass, test.RunTestClass の4つのクラスが存在したとして、以下のような感じになります。
include | exclude | 測定対象クラス |
---|---|---|
なし | なし | test.TestClass1 test.TestClass2 test.RunClass test.RunTestClass |
なし | test.Test* | test.RunClass test.RunTestClass |
なし | test.*Test* | test.RunClass |
test.Test* | なし | test.TestClass1 test.TestClass2 |
test.Test* | test.TestClass2 | test.TestClass1 |
on the fly
"-ix"オプションを指定してemmarunを実行します。"+"でinclude、"-"でexcludeを指定します。複数登録する場合は、","でつなげます(-ixを複数記述することもできます)。java.exe -cp emma.jar emmarun -r html -ix +S*,-Sw* -jar SwingSet2.jar |
あるいは
java.exe -cp emma.jar emmarun -r html -ix +S* -ix -Sw* -jar SwingSet2.jar |
のように指定して実行した場合、Java1.4.2の場合だとSplitPaneDemo.java, ScrollPaneDemo.java, SliderDemo.javaの3つのクラスのみがカバレッジ情報測定対象となります。
offline
instr処理を行う際に、-ixオプションを指定するだけです。java.exe -cp emma.jar emma instr -m fullcopy -d dist -ix +S*,-Sw* -cp SwingSet2.jar |
実際にクラスを実行する際は、-ixオプションを指定していない場合と同様です。
java.exe -cp SwingSet2.jar;emma.jar SwingSet2 |
得られるecファイルには、取得対象となっているクラスに関する情報のみが保管されることになります。サーバーにデプロイするクラスが大量にある場合などにフィルタリングを上手く適用すると、カバレッジ情報の取得に必要なメモリ量を減らすことができるなどのメリットが得られるかと思います。
別ファイルで定義
フィルタリングの対象となるクラスが多かったりする場合(ワイルドカードで上手く指定できない場合など)、対象となるクラスをテキストファイルに記述し、それを元にフィルタリングを行うことができます。例えば、以下のような内容のsampleFilter.txtファイルを作成したとします。
+S*
-Sw*
で、-ixオプションに対してこのテキストファイルを指定します。指定する場合、ファイル名の前に@を付加する必要があるので注意してください。
java.exe -cp emma.jar emma instr -m fullcopy -d dist -ix @sampleFilter.txt -cp SwingSet2.jar |
直接指定と、別ファイルによる指定の混在も可能です。
java.exe -cp emma.jar emma instr -m fullcopy -d dist -ix +C* -ix @sampleFilter.txt -cp SwingSet2.jar |
その他
複数ファイルをまとめて処理(instr)
instrコマンドでjarファイルを書き換える際、-cpには1つのjarファイルしか指定できないようです(ワイルドカードを使用しても、見つかった1つ目のファイルしか処理されない)が、forと組み合わせることでまとめて処理することができます。
for %i in (*.jar) do java.exe -cp emma.jar emma instr -m fullcopy -d dist -cp %i |
これだとカレントフォルダのjarファイルを全て処理してしまうため、emma.jarも処理してしまうことになります(カレントフォルダにemma.jarをおいて実行している場合)。
dir /b *.jar > jarlist.txt |
でjarファイルの一覧を格納したテキストファイルを作成し、そのファイルからemma.jarを取り除いて
for /F %i in (jarlist.txt) do java.exe -cp emma.jar emma instr -m fullcopy -d dist -cp %i |
とすることで、jarlist.txtに記述されているjarファイルのみを処理対象とすることが可能です(もちろん、emma.jar以外にも処理対象外としたいファイルがあれば、ファイルから除去しておくことで対応できます)。
ただ、毎回こんなコマンドを入力するのもあれなので、
for /F % %i in ('more') do java.exe -cp emma.jar emma instr -m fullcopy -d dist -cp % %i |
という内容のバッチファイル(例えばemmaxargs.bat)を作成しておけば、
emmaxargs < jarlist.txt |
のような感じで簡単に処理を行うことができます。
※上記はWikiで取り消し線となってしまわないように%の間に半角スペースを入力していますが、実際は%を2つ続けて入力します。
2006年06月11日(日) 11:50:33 Modified by syo1976