Coberturaの原理
Coberturaの原理
Coberturaは基本的なコードを検出し、テストパッケージの実行時にどのコードが実行されているかを確認し、どのコードが実行されていないかを測定するオープンソースツールです.
公式アドレス:http://sourceforge.net/projects/cobertura/ 日本のダウンロード:http://sourceforge.jp/projects/sfnet_cobertura/releases/
CoberturaはMavenコンパイルプラットフォームに対応するcobertura-maven-pluginプラグインがあり、コードのコンパイル、検出、集積などの各周期が流れ線式に自動化できます.
プラグインのアドレス:http://mojo.codehaus.org/cobertura-maven-plugin/
Coberturaの原理と過程
cobertura実行過程は大体以下の通りです. 1,
1,instruument
coberturaは
デモのソースコードは以下の通りです.
テストケース実行時に、coberturaが修正した.classコマンドを呼び出します.classipath設定時、instructed clasesはorial(uninstructed)clasesの前にあります.こうやってテストする時はcoberturaの修正したクラスを引用します.テスト情報はcobertura.serファイルに書き込みます.
コマンド実行時の注意事項は、次のantのセグメントを参照してください.
cobertura.serからオーバーレイレートデータを取得し、srcで提供されたソースコードに関連して最終的なカバーレート報告を生成し、
Coberturaは基本的なコードを検出し、テストパッケージの実行時にどのコードが実行されているかを確認し、どのコードが実行されていないかを測定するオープンソースツールです.
公式アドレス:http://sourceforge.net/projects/cobertura/ 日本のダウンロード:http://sourceforge.jp/projects/sfnet_cobertura/releases/
CoberturaはMavenコンパイルプラットフォームに対応するcobertura-maven-pluginプラグインがあり、コードのコンパイル、検出、集積などの各周期が流れ線式に自動化できます.
プラグインのアドレス:http://mojo.codehaus.org/cobertura-maven-plugin/
Coberturaの原理と過程
cobertura実行過程は大体以下の通りです. 1,
instrument
を使って、コンパイルしたクラスファイルを修正します. 2,テストを実行して、テストデータをxx.serに出力します. 3,report
を用いてカバーレート報告を生成する.1,instruument
coberturaは
instrument
を使って私達がコンパイルしたクラスファイルを修正して、コードの中にcoberturaの統計コードを入れます.そして、一つの.serファイル(上書きデータの出力用)を生成します.instrument
を使用して実行される過程で、CoberturaInstrumenter
は、まず分析モニターを呼び出し、所与のコンパイルされたclassを分析し、touch Point(ソースコードのカバーされている行に対応すると考えられる)と必要な他の情報を得る.その後、インジェクションモニタを呼び出して、新しいclassに情報を注入し、\target\generated-classes
ディレクトリに保存する.デモのソースコードは以下の通りです.
public class FeeCodeTranslate {
private static final Map<String, String> FEECODEMAP = new HashMap<String, String>();
static{
FeeCodeTranslate.FEECODEMAP.put(" ", "JJFY");
FeeCodeTranslate.FEECODEMAP.put(" ", "DKFY");
FeeCodeTranslate.FEECODEMAP.put(" ", "CSFY");
}
public static String nameToCode(String name){
String code = FeeCodeTranslate.FEECODEMAP.get(name);
return code == null ? "" : code;
}
}
ソースコード生成.classファイルの後、逆コンパイルは以下の通りです.public class FeeCodeTranslate {
private static final Map FEECODEMAP;
public FeeCodeTranslate() //
{
}
public static String nameToCode(String name){
String code = (String)FEECODEMAP.get(name);
return code != null ? code : "";
}
static {
FEECODEMAP = new HashMap();
FEECODEMAP.put(" ", "JJFY");
FEECODEMAP.put(" ", "DKFY");
FEECODEMAP.put(" ", "CSFY");
}
}
instrument
を使って実行したら、新しいクラスが得られます.public class FeeCodeTranslate {
public static final transient int __cobertura_counters[]; //
private static final Map FEECODEMAP;
public FeeCodeTranslate()
{
int i = 0;
__cobertura_counters[1]++; //
super();
}
public static String nameToCode(String name){
String code;
__cobertura_init(); // ,
int i = 0;
__cobertura_counters[7]++; //
code = (String)FEECODEMAP.get(name);
__cobertura_counters[8]++; //
code;
int j = 10;
JVM INSTR ifnonnull 67;
goto _L1 _L2
_L1:
__cobertura_counters[9]++; //
j = 0;
"";
goto _L3
_L2:
__cobertura_counters[j]++; //
j = 0;
code;
_L3:
return;
}
public static void __cobertura_init() { //
if (__cobertura_counters == null) {
__cobertura_counters = new int[11];
TouchCollector.registerClass("com/baidu/idc/base/FeeCodeTranslate");
}
}
//
public static void __cobertura_classmap_0(LightClassmapListener lightclassmaplistener) {
lightclassmaplistener.putLineTouchPoint(11, 1, "<init>", "()V");
lightclassmaplistener.putLineTouchPoint(13, 2, "<clinit>", "()V");
lightclassmaplistener.putLineTouchPoint(15, 3, "<clinit>", "()V");
lightclassmaplistener.putLineTouchPoint(16, 4, "<clinit>", "()V");
lightclassmaplistener.putLineTouchPoint(17, 5, "<clinit>", "()V");
lightclassmaplistener.putLineTouchPoint(18, 6, "<clinit>", "()V");
lightclassmaplistener.putLineTouchPoint(21, 7, "nameToCode", "(Ljava/lang/String;)Ljava/lang/String;");
lightclassmaplistener.putLineTouchPoint(22, 8, "nameToCode", "(Ljava/lang/String;)Ljava/lang/String;");
lightclassmaplistener.putJumpTouchPoint(22, 10, 9);
LightClassmapListener = lightclassmaplistener;
}
//
public static void __cobertura_classmap( LightClassmapListener lightclassmaplistener) {
lightclassmaplistener.setClazz("com/baidu/idc/base/FeeCodeTranslate");
lightclassmaplistener.setSource("FeeCodeTranslate.java");
__cobertura_classmap_0(lightclassmaplistener);
LightClassmapListener = lightclassmaplistener;
}
//
public static int[] __cobertura_get_and_reset_counters(){
int ai[] = __cobertura_counters;
__cobertura_counters = new int[__cobertura_counters.length];
return ai;
}
static {
__cobertura_init(); //
int i = 0;
__cobertura_counters[2]++; //
FEECODEMAP = new HashMap();
__cobertura_counters[3]++; //
FEECODEMAP.put(" ", "JJFY");
__cobertura_counters[4]++; //
FEECODEMAP.put(" ", "DKFY");
__cobertura_counters[5]++; //
FEECODEMAP.put(" ", "CSFY");
__cobertura_counters[6]++; //
}
}
2,テストを実行しますテストケース実行時に、coberturaが修正した.classコマンドを呼び出します.classipath設定時、instructed clasesはorial(uninstructed)clasesの前にあります.こうやってテストする時はcoberturaの修正したクラスを引用します.テスト情報はcobertura.serファイルに書き込みます.
コマンド実行時の注意事項は、次のantのセグメントを参照してください.
<target name="test" depends="init,compile">
<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
<!--
Specify the name of the coverage data file to use.
-->
<sysproperty key="net.sourceforge.cobertura.datafile" file="${reports.dir}/coverage.ser" />
<!--
Note the classpath order: instrumented classes are before the
original (uninstrumented) classes. This is important.
-->
<classpath location="${instrumented.dir}" />
<classpath location="${classes.dir}" />
<!--
The instrumented classes reference classes used by the
Cobertura runtime, so Cobertura and its dependencies
must be on your classpath.
-->
<classpath refid="cobertura_classpath" />
<formatter type="xml" />
<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
<batchtest todir="${reports.xml.dir}" unless="testcase">
<fileset dir="${src.dir}">
<include name="**/*Test.java" />
</fileset>
</batchtest>
</junit>
<junitreport todir="${reports.xml.dir}">
<fileset dir="${reports.xml.dir}">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${reports.html.dir}" />
</junitreport>
</target>
3,レポートを生成するcobertura.serからオーバーレイレートデータを取得し、srcで提供されたソースコードに関連して最終的なカバーレート報告を生成し、
target\site\cobertura
パスの下に置く.java -cp "%COBERTURA_HOME%cobertura.jar;..."
net.sourceforge.cobertura.reporting.Main --format html
--datafile cobertura.ser --destination cobertura-site src
最終的にカバー率報告データを下図に示します.