メモの日々


2009年02月02日(月) [長年日記]

[java] NetBeans の Code Coverage Plugin が NullPointerException になる

NetBeans 6.5でカバレッジを取りたいと思い「使用可能なプラグイン」画面で探したら、Code Coverage Plugin(たぶんこれ)というプラグインがあったのでインストールしてみた。

問題点

んが、これをインストールすると「プロジェクト」のツリービューでプロジェクトを右クリックしたときのコンテキストメニューが表示されなくなってしまった。ウィンドウの右下で赤丸が点滅しているのでクリックすると、

java.lang.NullPointerException
	at org.netbeans.modules.coverage.config.Config.getProjectType(Config.java:163)
	at org.netbeans.modules.coverage.config.Config.isNbModuleProject(Config.java:188)
	at org.netbeans.modules.coverage.config.Config.isSupportedProject(Config.java:192)
	at org.netbeans.modules.coverage.ProjectMenuAction$ProjectContextAwareMenuAction$ProjectMenuItems.<init>(ProjectMenuAction.java:146)
	at org.netbeans.modules.coverage.ProjectMenuAction$ProjectContextAwareMenuAction.getPopupPresenter(ProjectMenuAction.java:126)
	at org.openide.util.Utilities.actionsToPopup(Utilities.java:2676)
	at org.openide.util.Utilities.actionsToPopup(Utilities.java:2756)
	at org.openide.explorer.view.TreeView.createPopup(TreeView.java:953)
	at org.openide.explorer.view.TreeView$PopupAdapter.showPopup(TreeView.java:1427)
	at org.openide.awt.MouseUtils$PopupMouseAdapter.maybePopup(MouseUtils.java:182)
	at org.openide.awt.MouseUtils$PopupMouseAdapter.mouseReleased(MouseUtils.java:177)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:273)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
	at java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:272)
	at java.awt.Component.processMouseEvent(Component.java:6134)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
	at java.awt.Component.processEvent(Component.java:5899)
	at java.awt.Container.processEvent(Container.java:2023)
	at java.awt.Component.dispatchEventImpl(Component.java:4501)
	at java.awt.Container.dispatchEventImpl(Container.java:2081)
	at java.awt.Component.dispatchEvent(Component.java:4331)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4301)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3965)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3895)
	at java.awt.Container.dispatchEventImpl(Container.java:2067)
	at java.awt.Window.dispatchEventImpl(Window.java:2458)
	at java.awt.Component.dispatchEvent(Component.java:4331)
[catch] at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
	at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:104)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

というスタックトレースが表示された。Code Coverage Pluginはプロジェクトを右クリックして設定するようなので、これでは使うことができない。

解決方法

色々いじっていると、右クリックしてもエラーにならずコンテキストメニューが表示されるプロジェクトもあった。

どうやら、「主プロジェクト」に設定したものだけ右クリック時にエラーになるようだ。だから、主プロジェクトを解除する、というのが解決方法。

主プロジェクトの解除は、別のプロジェクトを主プロジェクトにするか、プロジェクトを一旦閉じて開きなおせばできるみたい。

使用感

使えるようになったので試してみたが、あまり便利じゃなかった。

プラグインをActivateした後でテストを実行するとカバレッジが計測されて結果画面にカバレッジ率が表示されるけど、それだけ。結果画面は見難いし、そこからソースコードにジャンプできないようで不便。

[java] JMockitでカバレッジ結果の一部が表示されない

Code Coverage Plugin が気に入らなかったので、NetBeans上でカバレッジを計測するのは諦めた。Antに組み込んで計測するのでいいやと思ってカバレッジツールを探すと、

が見つかった。EMMAは2005年、Coberturnalは2007年から更新されていないようだが、JMockitは2008年10月に更新されていたので、JMockitを使ってみることにした。

問題点

頑張って設定し、計測結果のHTMLが出力できて喜んでいたが、よく見るとHTMLに出力されていないクラスがあった。

正しいかどうかわからないけれど、「aaa.bb」「aaa.bbc」のように先頭部分が一致するパッケージがあったときに、「aaa.bbc」の方が結果画面に出力されないみたい。

解決方法は分からない。のでJMockitも諦める。せっかく設定したので設定方法を以下にメモ。

インストール

jmockit-0.95.zip(トップページにあるDownloadのリンクは0.94を指しているので注意)をダウンロードして展開すると、 トップディレクトリにjarファイルが4つある。用途に応じてこれらのうち必要なものをクラスパスに含めればいいのだと思う。

Antに組み込んでカバレッジを測る

JUnitを使ってテストを行うAntターゲットが既にあるとして、その中のjunitタスクに

<jvmarg value="-javaagent:/pathpath/jmockit.jar=coverage=AAA:BBB:CCC:DDD"/>

のようなjvmarg要素を追加すればいいようだった。

  • javaagentの後ろにはjmockit.jarへのパスを指定
  • coverageの後ろには、classSelectionRegex、outputFormat、outputDir、srcDirsの4つを指定する。コロン区切りで指定するみたい。省略も可能。
  • classSelectionRegexで計測対象のクラスを指定するみたいだが、上に書いたように「aaa.*」と指定しても aaa.bbc 配下のクラスはHTMLに出力されなかった(正確に言うと、クラス個別のHTMLファイルは生成されているが、index.htmlに必要なリンクが出力されない)。正規表現を書けるようなので、ここをうまく書けば問題が解決するのかも。
  • outputFormatはxml, xml-nocp, html, html-nocpから選べる。nocpの意味はよく分からない。
  • outputDirは結果の出力ディレクトリ。
  • srcDirsはソースファイルの在処。カンマ区切りで複数書いてみたら認識してくれた。

詳しくは(あまり詳しくもないけど)ドキュメントのHow to run tests with code coverageを参照のこと。

junitタスク自体の書き方にあまり自信がないが、次のような感じで書いていた。クラスパスには jmockit.jar だけでなく coverage.jar も含める必要がある。

    <target name="coverage" depends="...">
        <junit fork="yes">
            <formatter type="plain" usefile="no"/>
            <classpath>
                <pathelement location="..."/>
            </classpath>
            <jvmarg value="-javaagent:${basedir}/lib/jmockit.jar=coverage=abc.*:html::nantoka/src,kantoka/src"/>
            <batchtest fork="yes">
                <fileset dir="...">
                    <include name="**/*Test.java"/>
                </fileset>
            </batchtest>
        </junit>
    </target>