テストを書くモチベーションを上げるための、カバレッジレポート活用方法

f:id:okinaka:20181210121202j:plain
BASE Advent Calendar 2018 (13日目)

この記事は、「BASE Advent Calendar 2018」の13日目の記事です。

devblog.thebase.in

Backend Engineerの沖中 (@okinaka) です。

読者のみなさんはテストを書いてますか?テストが面倒くさいとか思ってませんか?(私はたまにあります)
そんな時、モチベーションをあげるには、どのような工夫をしていますか?

私の場合、カバレッジ計測の結果のレポートがとても役に立っています。 レポートを眺めると、視覚的に

  • 「どの行が実行された」とか
  • 「カバレッジ率が◯%」だとか
  • 「ここ複雑だけどテストがないクラスがあるよ」など、

いろいろ気づきがあります。

「ここマズイな、テスト書いて確認しなくちゃ!」という気持ちになるのでとても重宝しています。

とてもいいツールだと思うのですが、残念ながら BASE社内でもまだ十分に活用されていないのが現状です。ですので、この記事をきっかけに、広めていければいいのではないかと期待しています!

現状ではカバレッジレポート出力が時間がかかる問題があるのですが、今後、自動生成する仕組みを用意できればと考えています。

カバレッジレポートについて

BASEでは、主にCakePHPでサービスが構築されており、ユニットテストも、若干手を加えていますが基本的にはCakePHPに用意された仕組みを利用しています。カバレッジレポートは、その機能を利用して生成しています。

カバレッジについての簡単な説明は、CakePHP クックブックをご覧ください。
(内部的には PHPUnit を利用しています。詳細は こちら

カバレッジレポートには出力形式がいくつかあるのですが、今回はモチベーションアップが目的なので、人が見てわかりやすいHTML出力を紹介します。

出力されるHTMLページは大きく分けて3つに分類されます。

各ディレクトリ内のファイル一覧 (index.html)

  • ファイル毎の大まかなカバレッジ状況を一覧で確認できるページ*1

f:id:okinaka:20181210123856j:plain
ファイル一覧(index.html)

各ファイルのカバレッジ詳細 (PHPファイル名.html)

  • どの関数・行がテストされたかなど詳細を確認できるページ
  • 次にどんなテストが必要かを考える際に役立ちます

f:id:okinaka:20181210124020j:plain
カバレッジ詳細(PHPファイル名.html)

ダッシュボード (dashboard.html)

  • 以下のカバレッジ状況を俯瞰的に確認できるページ
    • クラス・メソッドのカバレッジ率 (Coverage)
    • コードの複雑度 (Complexity) の分布図
    • カバレッジ率の低い順のクラス・メソッド一覧
    • リスク (CRAP値) の高い順のクラス・メソッド一覧
  • 全体の状況を把握したり、次にどのファイルをテストすべきかをざっと見るのに便利!

f:id:okinaka:20181210124152j:plain
ダッシュボード(dashboard.html)

テスト作成とカバレッジレポート出力

では、実際にレポートを出力して内容を見てみましょう。

まず最初に、とあるメソッドに対してテストを1つ書いてみました。

<?php
    public function testView()
    {
        // テスト対象を実行
        $this->testAction('/posts/view/1', ['method' => 'get', 'return' => 'contents']);
        
        // とりあえず、ステータスコードの確認
        $this->assertSame(200, $this->controller->response->statusCode());
        
        // その他、なんらかの結果の確認...
    }

この時点で、カバレッジレポートを出力してみます。レポートを見ると、どうやら一部実行されていない行があるようです。 (注:緑の部分がテストされた行で、赤い部分が未テストな行です。赤い部分をなんとか消したくて、ウズウズしてきますね!)

f:id:okinaka:20181210124316j:plain
カバレッジ詳細(テスト1回目)

未テストだった行を確認してみると、$id が未指定 (null) だった場合と、 データーベースに未登録な $id だった場合の処理がテストされてないようです。 このレポートを受けてテストケースを追加してみます。

<?php
    /**
     * @expectedException NotFoundException
     * @expectedExceptionMessage Invalid post
     */
    public function testViewで、IDが未指定だった場合は例外発生()
    {
        $this->testAction('/posts/view/', ['method' => 'get', 'return' => 'contents']);
    }

    /**
     * @expectedException NotFoundException
     * @expectedExceptionMessage Invalid post
     */
    public function testViewで、未登録なIDを指定した場合は例外発生()
    {
        $this->testAction('/posts/view/999', ['method' => 'get', 'return' => 'contents']);
    }

結果がこれ。

f:id:okinaka:20181210124408j:plain
カバレッジ詳細(テスト2回目)

やりました!赤かったところが全部緑色に!これで安心です。

ここで、注意点があります。全部緑色になって喜んでいましたが、緑色の行を増やすよりもむしろテストの内容の方が重要です。 たとえテストが実行されたとしても、ちゃんと動作を確認していなければ意味がありません。あくまで、モチベーションを高め、テスト状況を確認するためのツールと捉えていただければと思います。

明日はデザイナーの森さんです!お楽しみに!

*1:注: CakePHP 公式のクックブックのチュートリアル を元に、独自のテストを実行した結果を表示しています。