ねこじゃすり
猫を魅了する魔法の装備品!
Anker PowerCor
旅行には必須の大容量モバイルバッテリー!
ペヤング ソースやきそば 120g×18個
とりあえず保存食として買っておけば間違いなし!
モンスターエナジー 355ml×24本 [エナジードリンク]
脳を活性化させるにはこれ!
ドラゴンクエスト メタリックモンスターズギャラリー メタルキング
みんな大好き経験値の塊をデスクに常備しておこう!
BANDAI SPIRITS ULTIMAGEAR 遊戯王 千年パズル 1/1スケール
もう一人の僕を呼び覚ませ!!
サンディスク microSD 128GB
スマホからSwitchまで使える大容量MicroSDカード!
スポンサーリンク
ユニットテストのガバレッジを自動生成しよう
皆さんはユニットテスト書いていますか?
品質をあげるにはしっかりとユニットテストを書いて、CI環境でしっかり実施する事が大事です。
今回ご紹介するのは、ユニットテストの実施によって実行されたソース部分のガバレッジレポートをHTML形式で自動生成してくれるJaCoCoというプラグインをご紹介しようと思います。
出力対象のパッケージを制御する方法については以下でご紹介していますので、合わせてみて頂ければなと思います。
手順
sbt-jacocoプラグインの追加
まずはプロジェクトにsbt用のJaCoCoプラグインを追加しましょう。
project/plugins.sbt
に以下を追記してください。
1 2 3 4 5 6 7 8 9 |
// The Play plugin addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.0") // Defines scaffolding (found under .g8 folder) // http://www.foundweekends.org/giter8/scaffolding.html // sbt "g8Scaffold form" addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0") // JaCoCo ★追加 addSbtPlugin("com.github.sbt" % "sbt-jacoco" % "3.2.0") ★追加 |
設定はたったこれだけです!
実行方法
テスト実行時のコマンドをsbt jacoco
に変えて実行する事でJUnitの実行とレポートの生成を行なってくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
... (略) ... [info] ------- Jacoco Coverage Report ------- [info] [info] Lines: 58.49% (>= required 0.0%) covered, 44 of 106 missed, OK [info] Instructions: 46.5% (>= required 0.0%) covered, 635 of 1187 missed, OK [info] Branches: 22.92% (>= required 0.0%) covered, 37 of 48 missed, OK [info] Methods: 33.02% (>= required 0.0%) covered, 71 of 106 missed, OK [info] Complexity: 27.69% (>= required 0.0%) covered, 94 of 130 missed, OK [info] Class: 73.33% (>= required 0.0%) covered, 4 of 15 missed, OK [info] [info] Check /Users/blogenist/sample/java-sample/target/scala-2.13/jacoco/report for detailed report [info] [success] Total time: 5 s, completed 2020/02/21 21:11:02 |
生成ディレクトリは {プロジェクトルート}/target/scala-2.13/jacoco/report
です。
結果の中には、PlayFrameworkが自動で生成するパッケージ(router
やviews
、controller.javascript
などがありますがスルーしましょう。)
取り急ぎ、sbtが自動生成してくれたHomeController
クラスのテスト結果を見てみましょう。
緑色になっているところがユニットテストで実行されたコード部分になります。
ユニットテスト作成の一つの指標として、全てのコードを通っていることを担保するには良いガバレッジに使えそうですね♪
実行されていない場合
実行されていない場合はこのように赤くなります。
なので、まずは全ての行が緑色になるようにユニットテストやソースの修正をしましょう。
※今回は紹介するためにテスト元クラスをいじってJaCoCoの動きをご紹介していますorz
if文を網羅していない場合
また、以下のような引数の値によってif
文などの分岐が存在する場合に、ユニットテストで網羅できていない場合は以下のように黄色くなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package controllers; import play.mvc.*; /** * This controller contains an action to handle HTTP requests * to the application's home page. */ public class HomeController extends Controller { /** * An action that renders an HTML page with a welcome message. * The configuration in the <code>routes</code> file means that * this method will be called when the application receives a * <code>GET</code> request with a path of <code>/</code>. */ public Result index(Boolean isAvailable) { if( isAvailable ){ hello(); } return ok(views.html.index.render()); } private void hello(){ System.out.println("Hello World!!!"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package controllers; import org.junit.Test; import play.Application; import play.inject.guice.GuiceApplicationBuilder; import play.mvc.Http; import play.mvc.Result; import play.test.WithApplication; import static org.junit.Assert.assertEquals; import static play.mvc.Http.Status.OK; import static play.test.Helpers.GET; import static play.test.Helpers.route; public class HomeControllerTest extends WithApplication { @Override protected Application provideApplication() { return new GuiceApplicationBuilder().build(); } @Test public void testIndexByFalse() { Http.RequestBuilder request = new Http.RequestBuilder() .method(GET) .uri("/?isAvailable=false"); Result result = route(app, request); assertEquals(OK, result.status()); } } |
その場合は、ユニットテスト側で分岐を網羅するようなケースを追加してあげることでガバレッジが100%
になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package controllers; import org.junit.Test; import play.Application; import play.inject.guice.GuiceApplicationBuilder; import play.mvc.Http; import play.mvc.Result; import play.test.WithApplication; import static org.junit.Assert.assertEquals; import static play.mvc.Http.Status.OK; import static play.test.Helpers.GET; import static play.test.Helpers.route; public class HomeControllerTest extends WithApplication { @Override protected Application provideApplication() { return new GuiceApplicationBuilder().build(); } @Test public void testIndexByTrue() { Http.RequestBuilder request = new Http.RequestBuilder() .method(GET) .uri("/?isAvailable=true"); Result result = route(app, request); assertEquals(OK, result.status()); } @Test public void testIndexByFalse() { Http.RequestBuilder request = new Http.RequestBuilder() .method(GET) .uri("/?isAvailable=false"); Result result = route(app, request); assertEquals(OK, result.status()); } } |
ちなみに、分岐の中に入ってソースの全てが実行されたとしても、false
のパターンが実行されていないと判断されて黄色になりますのでご注意を。
終わりに
以上のように、ユニットテストと組み合わせる事でとても有能なガバレッジを自動生成してくれます。
ユニットテストの実施結果を残すことはとても大事なので、是非導入してみてください♪