SoftwareEngineering/ProgramLanguage/Java/UnitTest/JMockit
JMockit Java用の自動テストツールキット [前の章] [内容] コードカバレッジの測定
コードカバレッジは、一連のソフトウェアメトリックで構成され、特定のテストスイートでどのくらいの量のプロダクションコードがカバーされているかを示すことができます。 これは純粋に量的なものであり、プロダクションコードまたはテストコードの品質については何も言及していません。 つまり、コードカバレッジレポートの調査では、到達不能なコードが発見されることがあり、これを排除することができます。 しかしもっと重要なのは、このようなレポートは、欠落しているテストの発見のためのガイドとして使用できることです。 これは、既存のプロダクションコードのテストを作成するときだけでなく、TDD(テスト駆動開発)のようにテストを初めて作成するときにも便利です。
JMockitカバレッジは、 ラインカバレッジ 、 パスカバレッジ 、 データカバレッジの 3つの相補的なコードカバレッジメトリックを提供します。
ライン・カバレッジ・メトリックは、ソース・ファイル内の実行可能コードがテストによってどの程度実行されたかを示します。 コードの各実行可能な行は、 覆われているか、 覆われているか、 部分的に覆われています。 最初のケースでは、実行可能コードはまったく実行されませんでした。 2番目のコードでは、 すべてのコードが少なくとも1回は完全に実行されました。 3番目のケースでは、行内の実行可能コードの一部だけが実行されました。 これは、たとえば、複雑なブール式の中に複数の論理条件を含むコードの行で発生する可能性があります。 JMockitカバレッジは、3つすべてのケースを識別し、実行可能な各コードラインのカバレッジ率を計算します。 カバーされていないラインの場合は0% 、カバードラインの場合は100% 、部分的にカバーされたラインの場合は、
分岐ポイントは、プログラムが2つの可能な実行パスの間で決定を下すたびに存在します。 論理条件を含むコード行は、少なくとも2つの実行可能セグメントに分割され、それぞれが別々のブランチに属します。 分岐点のない実行可能なソースコード行には、単一のセグメントが含まれています。 1つまたは複数の分岐点を有する線は、線の連続する分岐点によって分離された2つ以上の実行可能セグメントを含む。
NS >= 1は、与えられた行の実行可能セグメントの数です。 NEが、テスト実行中に少なくとも1回実行された(つまり、それらがカバーされているセグメント )その行のセグメント数である場合、そのラインのカバレッジ率を100 * NE / NSとして計算できます。
同様に、ファイル内のすべての実行可能コード行を考慮して、実行可能なセグメントの総数とカバーされたセグメントの総数から、ソースファイル全体の行カバレッジ率が計算されます。 パッケージのパーセンテージは、 パッケージに属するソースファイル全体のセグメントの合計数とカバーされた数から計算されます。 最後に、 総コードカバレッジ率は、すべてのパッケージの合計で同じ式によって計算されます。
まったく異なるメトリックは、コードの行またはセグメントではなく、メソッドおよびコンストラクター本体で計算されるパスカバレッジです。 テスト実行中に、メソッドまたはコンストラクタを介して実行可能な実行パスのうち、 エントリから終了までの実行パスの数が少なくとも1回実行されたことを示します。
各メソッドまたはコンストラクターには単一のエントリポイントがありますが、複数の出口を持つことができます。 exitは、 return文またはthrow文が実行されたときに発生します。 これらはもちろん、 通常の出口です。 メソッド呼び出しの結果としてスローされた例外(またはエラー)、 null参照へのアクセス、または意図しないプログラムの失敗を引き起こす他のアクションを伝播することによって、メソッド/コンストラクタの実行を突然終了させることもできます。
可能な各パスは、完全に実行される(カバーされる)か、またはカバーされない(カバーされない)ことができます。 部分的にしか実行されないパス(すなわち、突然終了したパス)は、単にカバーされていないパスとみなされます。
メソッドまたはコンストラクタ本体のパスカバレッジ率は、ラインカバレッジ計算と同様の方法で計算されます。 NPがインプリメンテーション本体を通る可能なパスの数であり、 NPEがエントリから出口に実行されるパスの数である場合、メトリックは100 * NPE / NPとして計算されます。 また、ライン・カバレッジ・メトリックと同様に、この式をソース・ファイル全体、パッケージ全体、およびテスト実行によって触れられたパッケージ全体に拡張します。
テスト実行によってインスタンスおよび静的非最終フィールドの数が完全に行使された回数を測定します。 完全に行使されるためには、フィールドに少なくとも1つのテストで読み取られた最後の値が割り当てられていなければなりません。 パーセンテージは100 * NFE / NFとして計算され100 * NFE / NFは非最終フィールドの数で、 NFEは完全に実行されたフィールドの数です。
JMockit Coverageツールは、次のタイプの出力を生成できます。
カバレッジツールを使用してテストスイートを実行する場合、オプションの「コールポイント」情報があり、ユーザーが選択したとおりに収集できます。 コール・ポイントは、ソース・テスト・コード内の特定の行の実動コードが実行されたポイントです。
この余分な情報でカバレッジを生成すると、時間がかかり、出力が大幅に増加します。 テスト実行中に特定の行の生産コードを実行させたテストコードの行を知ることは有用です。 HTMLレポートに含めると、コールポイントのリストは最初は非表示になっていますが、各実行可能コード行をクリックすると簡単に表示できます。
JUnit / TestNGテスト実行でJMockit Coverageツールを有効にするには、ランタイムクラスパスにjmockit-1.x.jarを追加し、少なくとも " coverage-output|metrics|classes "システムプロパティを1つ指定します。 JUnitでは、 jmockit-1.x.jarがクラスパスの最初に表示されていることを確認してjmockit-1.x.jar 。 ( JMockitによるテストの実行の詳細については、チュートリアルの該当するセクションを参照してください)。
JMockitモーキングAPIを使用しない場合、クラスパスにjarファイルを追加しなくてもコードカバレッジを有効にできます。 代わりに、JVM初期化パラメータとして " -javaagent:<proper path>/jmockit-1.x.jar=coverage "を実行します。
ほとんどの場合、カバレッジツールは追加の設定を使用する必要はありません。 ただし、ツールの動作にはいくつかの側面がありますが、これらの動作はオプションでテスト実行のために構成することができます。 これは、テストスイートを実行しているJVMインスタンスに対して、複数の「 coverage- xyz 」 システムプロパティのうちの1つ以上を設定することによって行われます。
JUnitまたはTestNGのいずれかを使用して、Antターゲット、Maven surefireプラグイン設定、または選択したJava IDE用のテスト実行設定内でこれらのプロパティを簡単に指定できる必要があります。 JMockit固有のプラグインは必要ありません。
使用可能な構成プロパティーは次のとおりです。
カバレッジツールは、テスト実行の終了時にレポートを生成すると、以前のレポートを常に上書きします。 通常、レポートが生成されるカバレッジデータには、現在のテスト実行中に収集されたものだけが反映されます。 今度は、複数のテストスイートまたはテスト実行構成があり、一連のテストでカバーされているコード用の単一の集約HTMLレポートを生成したいとします。 ここには、 "coverage.ser"というシリアル化されたデータファイルが入っています。
これらのファイルの生成を有効にするには、 coverage-outputシステムプロパティを " serial "または " serial-append "を含む値に設定するだけです。 これらの2つの値が示唆するように、複数のカバレッジデータファイルを組み合わせる方法はいくつかあります。 次のサブセクションでは、それぞれのケースの詳細を示します。
複数のテスト・ランからカバレッジ・データを収集し、後ですべてのテスト・ランからの結果をまとめて集約したHTMLレポートを生成するとします。 各テスト実行では、独自のcoverage.serファイルを生成する必要があります。 これにより、後でレポートを作成する最後のステップでマージすることができます。 したがって、各テスト実行は、 " coverage-output=serial "で構成する必要があります。 各テスト実行によって生成された元のcoverage.ser出力ファイルを保存するには、それらを異なる出力ディレクトリに書き込むかコピーする必要があることに注意してください。
2つ以上のcoverage.serファイルが別々のディレクトリで使用可能であると仮定すると、 mockit.coverage.CodeCoverage.mainメソッド(通常のJavaの「main」メソッド)を実行することによって、集約レポートを生成できます。 これを容易にするために、 jmockit-1.x.jarファイルが実行可能です。 例として、次のAntタスクを使用できます。
<java fork="yes" dir="myBaseDir" jar="jmockit-1.x.jar"> <jvmarg line="-Dcoverage-output=html"/> <arg line="module1-outDir anotherOutDir"/> </java>
上記の例では、別のJVMインスタンスが実行されるベースディレクトリとして " myBaseDir "が使用されています。 コマンドライン引数として、 " coverage.ser "データファイルを含む2つの出力ディレクトリが指定されています。 その他の設定パラメータは、 " coverage-xyz "システムプロパティで指定できます。 この個別のJVMインスタンスは、各 " coverage.ser "データファイルを読み込み、メモリ内のカバレッジデータをマージし、終了する前に集約HTMLレポートを生成します。
複数のテスト実行の実行から集約カバレッジレポートを取得する別の方法は、すべてのテストのカバレッジデータを単一のデータファイルに蓄積することです。 これは、すべてのテスト実行に同じ作業ディレクトリを使用するか、 coverage-outputDirを共有ディレクトリに指定して、各テスト実行に対してcoverage-output= serial-appendを実行することで実現できます。 さらに、シーケンス内の最後のテストでは、 coverage-outputプロパティのhtmlまたはhtml-nocpをserial-appendと一緒に指定する必要があります。 もちろん、最初のテスト実行では、このファイルからデータを読み取ってはなりません 。 したがって、最初のテスト実行の前にファイルを削除するか、または最初のテスト実行でcoverage-output=serial使用することによってファイルを削除する必要があります。
したがって、出力モード「 serial 」と「 serial-append 」の違いは、最初に複数の「 coverage.ser 」ファイル(別々のテスト実行で使用される別のディレクトリにあります)を持ち、すべてのテスト実行の間に単一のデータファイル。
必要に応じて、JMockit Coverageは、テスト実行の最後のカバレッジパーセンテージが任意の最小値を満たしていることを確認できます。 そのようなチェックは、 " coverage-check "システムプロパティに割り当てられた1つ以上のチェックルールによって指定できます(複数の場合は、 ";"文字で区切る必要があります)。
各検査ルールは、「[ スコープ :]最小行パーセント[、最小パスパーセント[、最小データパーセント]]」の形式でなければなりません。 スコープには3つのタイプがあります。
すべての検査(ある場合)は、テスト実行の最後に実行されます(JVMシャットダウン時)。 他の形式の出力(HTMLレポート、シリアライズされたファイル)は影響を受けません。 個々のチェックが失敗すると、説明的なメッセージが標準出力に出力されます。 1つ以上のチェックが失敗した場合は、2つの最終的なアクションが実行され、事実が報告されます。 まず、 coverage.check.failed 。 チェック不能な名前の空のファイルが現在の作業ディレクトリに作成されます。 AssertionError 、エラー(具体的にはAssertionError )がスローされます。 チェックが実行されてもすべてが合格すると、カレントディレクトリに存在する " coverage.check.failed "ファイルが削除されます。
カバレッジチェックの成功または失敗をマークするためのファイルの使用は、ファイルが存在するときにビルドに失敗することによって、ビルドツールがそれに応じて反応することを可能にすることを目的としています。 たとえば、Antビルドスクリプトでは次のことができます。
<fail message="Coverage check failed"> <condition><available file="coverage.check.failed"/></condition> </fail>
Mavenのpom.xmlファイルでは次のようになります。
<plugin> <artifactId>maven-enforcer-plugin</artifactId> <executions> <execution> <id>coverage.check</id> <goals><goal>enforce</goal></goals> <phase>test</phase> <configuration> <rules> <requireFilesDontExist> <files><file>target/coverage.check.failed</file></files> </requireFilesDontExist> </rules> </configuration> </execution> </executions> </plugin>
Mavenの "テスト"目標を使ってテストを実行する場合、 pom.xmlファイルに " jmockit.version "プロパティが適切に定義されていると仮定して、 "jmockit"依存関係が必要になります。
<dependency> <groupId>org.jmockit</groupId> <artifactId>jmockit</artifactId> <version>${jmockit.version}</version> <scope>test</scope> </dependency>
Maven 2/3では、 surefireプラグインは、通常、実際にテストを実行する責任があります。 カバレッジツールをアクティブにして設定するには、適切な " coverage-xyz "システムプロパティの値を指定します。
<plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <systemPropertyVariables> <!-- At least one of the following needs to be set: --> <coverage-output>html</coverage-output> <!-- or: html-nocp, serial, serial-append --> <coverage-metrics>all</coverage-metrics> <!-- or: line, path, data --> <coverage-classes>loaded</coverage-classes> <!-- or a "*" expression for class names --> <!-- Other properties, if needed: --> <coverage-outputDir>my-dir</coverage-outputDir> <!-- default: target/coverage-report --> <coverage-srcDirs>sources</coverage-srcDirs> <!-- default: all "src" directories --> <coverage-excludes>some.package.*</coverage-excludes> <!-- default: empty --> <coverage-check>80</coverage-check> <!-- default: no checks --> </systemPropertyVariables> </configuration> </plugin>
最後に、テストでJMockitモーキングAPIを実際に使用しない場合でも、 "jmockit"依存関係がなくてもカバレッジツールを使用することは可能です。 必要なのは、 surefireプラグインを次のように設定することだけです。
<plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine> -javaagent:"${settings.localRepository}"/org/jmockit/jmockit/${jmockit.version}/ jmockit-${jmockit.version}.jar=coverage <!-- coverage properties --> </argLine> </configuration> </plugin>
生成されたMavenサイトのドキュメントにJMockit Coverage HTMLレポートを含めるには、 src/site/site.xml記述子ファイルを提供する必要があります。 内容は以下のようになります。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/DECORATION/1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd"> <body> <menu ref="reports"/> <menu> <item name="Code Coverage Report" href="../../coverage-report/index.html"/> </menu> </body> </project>
特定のテスト実行でカバレッジを一時的にオフにするには、 coverage-outputシステムのプロパティを " -Dcoverage-output= none "のような未知の出力形式に設定します。 " -Dcoverage-metrics= none "または " -Dcoverage-classes= none "を設定すると、同じ効果が得られます。
もう1つ、よりインタラクティブな方法は、関連する出力ファイルがすでに生成されている場合に、その出力ファイルの読み取り専用属性を操作することです。 作業ディレクトリ内で常に操作される特定のファイルは、シリアル出力の場合は " coverage-report/index.html "、HTML出力の場合は " coverage-report/index.html "です。 ファイル属性は起動時にJMockitによってチェックされます。 読み取り専用としてマークされている場合は上書きできないため、JMockitはその試みを完全に回避します。 作業ディレクトリは、通常、Java IDEのテスト実行構成ごとに個別に選択することができます。 また、Java IDEは通常、プロジェクト内のファイルの読み取り専用ステータスを切り替える簡単なメカニズムを提供します。 IntelliJ IDEAでは、ステータスバーをダブルクリックして、エディタで目的のファイルを開き、 Eclipseではエディタで選択されたテキストファイルの "プロパティ"画面( "Alt + Enter"と入力すると開くことができます)に "読み取り専用"チェックボックスがあります。