#author("2021-12-14T01:53:15+00:00","","")
#topicpath
----
#contents


[[クライアントサイドのjcoverage>Java/jcoverage]]に関しては何とか動いたようです。いよいよサーバサイドのカバレッジ計測をやってみようと思います。確認は以下のような環境で行いました。

|BGCOLOR(#CCFFFF):LEFT:プロダクト|BGCOLOR(#CCFFFF):LEFT:バージョン|BGCOLOR(#CCFFFF):LEFT:役割|
|LEFT:WebSphere|LEFT:WebSphere 5.0.2テスト環境((Studioについてくるヤツ))|LEFT:WEBコンテナ|
|LEFT:Cactus|LEFT:1.7.1|LEFT:サーバサイドテスティングフレームワーク|
|LEFT:Junit|LEFT:3.8.1|LEFT:テスティングフレームワーク|
|LEFT:jcoverage|LEFT:1.0.5|LEFT:カバレッジツール|

[[Cactus>Java/Cactus]]とはサーバサイドのテスティングフレームワークです。JUnitのクラスを拡張して、WEBコンテナ上でテストを行うためのクラス群を提供します。

具体的には、requestパラメータにいろいろな値をセットしてブラウザのリクエストをシミュレーションすることや、ブラウザへ返却される画面に正しく値がセットされてるかをチェックするクラスなどを提供してくれます。

さて、[[前回>Java/jcoverage]]にJUnitとの連携まではやりましたが、今回がいままでと違うところは''WEBコンテナ上で稼働する箇所とクライアントで稼働する箇所がある''というところです。つまりリクエスト情報を構築してリクエストを放るまではクライアント側のJavaVM,リクエストを受けて処理をしてクライアントに返すまではWEBコンテナ上のJavaVM、という方式になります。クライアント側のカバレッジ計測についてはある意味いままでと変わらないのですが、WEBコンテナで稼働する部分のカバレッジ計測をどうするかというところがポイントになります。いろいろ調べた結果、以下のようなやり方でやればよい(ような気がする)事がわかりました。

-クライアント側はクライアント側で、コンテナ側はコンテナ側でそれぞれ計測して、マージする
-計測するにはデバッグ埋め込み済みのコードをデプロイする必要がある
-(特にWASだけかも?)WEBコンテナにjcoverageのjarをパスを通して認識させておく

難しいのは、デプロイするearにアーカイブされるクラスにどのようにデバッグを埋め込むか、ですね。通常開発環境でのコーディング・テストフェーズでは、自分でアーカイブを作ることはせず、開発環境が勝手にデプロイしてくれることが多いからです((WebSphereなどに限らず、最近の環境はどこでもそうですよね))。これに関してはclassesにデバッグ埋め込み済みのコードを配置するようビルドする、ことで解決できそうです。


#ref(result.png)

さて例でやってみます。


***準備 [#g4459cec]
**準備 [#g4459cec]
WebSphereのテスト環境でjcoverageを使うときにサーバ側でエラーが発生してしまうようで、
 WebSphereテスト環境 >> 環境 >> WebSphere特定クラスパス
でjcoverage.jarを追加する必要があるみたいです。Tomcatなどでやるときもcommon/libとかに入れておく必要があるのかな?

#ref(serversettiong.png)


***手順 [#oa26c415]
手順は、Eclipseでコンパイル -> AntでInstrument -> WEBコンテナ起動 -> EclipseでCactus起動 -> Antでレポート
**手順 [#oa26c415]
手順は、
- Eclipseでコンパイル 
- AntでInstrument 
- WEBコンテナ起動 
- EclipseでCactus起動 
- Antでレポート

となります。ポイントは
-デフォルトではclassesがクラスパスに設定されてしまうので、instrumentしたファイルがclassesに配置されるようビルドする
となります。ポイントは''デフォルトではclassesがクラスパスに設定されてしまうので、instrumentしたファイルがclassesに配置されるようビルドする''って事です。あと、Eclipseは自動的にビルドする機能がありますが、そうするとせっかくInstrumentしたファイルを上書きしてしまうので、自動ビルドをOFFにしておきました。

って事です。
*** プロジェクト作成 [#y4bf2953]
プロジェクト名はJCoverageTestWebとしました。CVSは[[こちら:http://www.masatom.in/cgi-bin/viewvc.cgi/JCoverageTestWeb/?root=cvs]]

*** Eclipseでコンパイル [#rb770184]
今回はAntではなくEclipse上のビルドを用いました。Antでやる場合はこんな感じ。
 <!-- 環境依存ファイルの読み込み-->
 <!-- 実際にファイルを参照してみてください -->
 <property file="build.win.properties" />
 <property file="build.properties" />
 
 <!-- クラスパス -->
 <path id="project.class.path">
   <pathelement location="${j2ee.jar}" />
   <pathelement path="${document.root}/${class.dir}" />
   <fileset dir="${document.root}/${jar.dir}">
   <include name="**/*.jar" />
   </fileset>
 </path>
 <!-- クラスパス名の定義 以上 -->
 
 <taskdef classpathref="project.class.path" resource="tasks.properties" />
 
 <target name="init">
   <tstamp>
   <format property="TODAY" pattern="yyyy/MM/dd" />
   </tstamp>
   <filter token="project.name" value="${ant.project.name}" />
   <echo>${ant.version}</echo>
   <echo>Java ver. ${ant.java.version}</echo>
   <echo>${ant.project.name}</echo>
   <echo>BaseDir: ${basedir}</echo>
   <echo>日付:${TODAY}</echo>
 </target>
 
 
 <!-- コンパイル -->
 <target name="javac.src" depends="init" description="ソースをビルドします">
   <mkdir dir="${document.root}/${class.dir}" />
   <copy todir="${document.root}/${class.dir}" preservelastmodified="yes">
   <fileset dir="${src.dir}">
   <include name="**" />
   <exclude name="**/**.java" />
   </fileset>
   </copy>
   <javac srcdir="${src.dir}" destdir="${document.root}/${class.dir}" 
     encoding="${compile.encoding}" 
     includeantruntime="no" memoryInitialSize="256M" fork="yes" memoryMaximumSize="256M" 
     includes="**" debug="true">
   <classpath refid="project.class.path" />
   </javac>
 </target>
 
 <!-- テストクラスのコンパイル -->
 <target name="test.javac" depends="javac.src" description="テスト用ソースをビルドします">
   <mkdir dir="${document.root}/${class.dir}" />
   <copy todir="${document.root}/${class.dir}" preservelastmodified="yes">
   <fileset dir="${test.src.dir}">
   <include name="**" />
   <exclude name="**/**.java" />
   </fileset>
   </copy>
   <javac srcdir="${test.src.dir}" destdir="${document.root}/${class.dir}" 
     encoding="${compile.encoding}" 
     memoryInitialSize="256M" fork="yes" memoryMaximumSize="256M" debug="true">
   <classpath refid="project.class.path" />
   </javac>
 </target>


*** AntでInstrument [#se61130a]
Instrumentはクライアント環境だけの場合もほとんど同じ。
 <target name="instrument" description="Add jcoverage instrumentation">
 <instrument todir="${document.root}/${class.instrumented.dir}">
 <ignore regex="org.apache.log4j.*" />
 <fileset dir="${document.root}/${class.dir}">
   <include name="**/*.class" />
 </fileset>
 <classpath refid="project.class.path" />
 </instrument>
 
 <copy todir="${document.root}/${class.instrumented.dir}" preservelastmodified="yes">
 <fileset dir="${document.root}/${class.dir}">
   <include name="**" />
   <exclude name="**/*.class" />
 </fileset>
 </copy>
 
 <delete dir="${document.root}/${class.dir}" />
 <mkdir dir="${document.root}/${class.dir}" />
 <copy todir="${document.root}/${class.dir}" preservelastmodified="yes">
 <fileset dir="${document.root}/${class.instrumented.dir}">
   <include name="**" />
 </fileset>
 </copy>
 
 <delete>
 <fileset dir="${ser.output.dir}">
   <include name="jcoverage.ser" />
 </fileset>
 </delete>
 <copy file="jcoverage.ser" todir="${ser.output.dir}" />
 
 </target>
ちとダサいんですが、Eclipseがコンパイルしたクラスがあるディレクトリ(classes)でInstrumentして(Insturumented-classesにコピーされる)、classesディレクトリを削除、んでInsturumented-classesディレクトリをclassesディレクトリにコピー、なんてことをやってます。これでWASのテスト環境がパスを通すclassesディレクトリにデバッグ埋め込み済みのコードが配置されたことになります。

あと、一点だけ異なるのがコンテナ上でもカバレッジを計測するので、ここで作成されるjcoverage.serをコンテナ上のVMが出力するディレクトリにもコピーをしなくてはいけないということです。そのディレクトリってのはWEBコンテナの起動ディレクトリっぽいですね。build.xmlの記述でいうと、コンテナ上のVMが出力するディレクトリというのが上の記述の
 ${ser.output.dir}
です。実体はbuild.propertiesに記述してあって、うちの環境では、
 ser.output.dir=D:/IBM/Rational/SDP/6.0
となっています。ちなみにbuild.propertiesはこんな感じになっています。
[[build.properties:http://www.masatom.in/cgi-bin/viewvc.cgi/JCoverageTestWeb/build.properties?root=cvs]]

そもそもクライアントVMもコンテナのVMも同じディレクトリに出力してくれればよいのですが、なんかうまくいきませんでした。



***WEBコンテナ起動 [#w844263f]
ここでWEBコンテナを起動します。ここでビルドがかかっちゃうと、またEclipseがclassesディレクトリを上書きしちゃうので、ビルドがかからないようにそおっと(??)コンテナを起動します。

***EclipseでCactus起動 [#bedad78b]
いつもEclipseでCactusを起動するのと変わりません。これで、クライアントで処理されるbeginXXXのメソッドの網羅率はプロジェクト内のディレクトリに出力されるし、コンテナで処理されるtestXXXのメソッドの網羅率は上に指定したディレクトリに出力されます((正確にはコンテナを落としたときに出力されているかな))。


***Antでレポート [#w6b33aeb]
WEBコンテナを落とした時点で、
-クライアントVM上のクラスが出力したjcoverage.ser(プロジェクトのルートにある)
-WEBコンテナのVM上のクラスが出力したjcoverage.ser(WEBコンテナの起動ディレクトリにある)

が存在することになります。最後にそれぞれのファイルをマージして一つのファイルにして、レポーティングすれば完成です。Antで以下のようにしました。

 <target name="coverage" >
   <report srcdir="${src.dir}" destdir="${build.coverage.dir}">
     <classpath refid="project.class.path" />
   </report>
   <report srcdir="${src.dir}" destdir="${build.coverage.dir}" format="xml">
     <classpath refid="project.class.path" />
   </report>
 </target>
 
 <target name="merge" >
   <delete file="jcoverage_server.ser" />
   <copy file="${ser.output.dir}/jcoverage.ser" tofile="jcoverage_server.ser" />
   <merge>
     <fileset file="jcoverage*.ser">
     </fileset>
   </merge>
 </target>

これを実行((ant merge coverage))すると、プロジェクトルートのserファイルとWEBコンテナ上のserファイルがマージされ、レポートhtmlが作成されます。。















----
この記事は
#vote(おもしろかった,そうでもない)
#vote(おもしろかった[22],そうでもない[4])
-Tomcatでうごかねー。。カバレッジ計測まではできてるっぽいんだけど、Tomcatをshutdownしたときにコンテナ上のjcoverage.serが0byteになっちゃう。 -- [[きの]] &new{2005-09-05 08:42:28 (月)};
-tomcat/binにおいたjcoverage.serはshutdownで0バイトになっちゃいますよね。解決ありました?bin以外にserを置いて、 com.jcoverage.rawcoverage.dirでVMに場所教えないといかんのかなあ。 -- [[みきさ]] &new{2005-12-08 17:40:21 (木)};
- VM引数に -Dcom.jcoverage.instrumentation.interval=5 を追加すると動くよ -- [[jun]] &new{2007-12-26 (水) 18:18:56};

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS