PythonでUnitTestのカバレッジレポートを出力する方法

2021年05月25日

前回の続き。

概要

unittestのカバレッジレポートを出力する方法を紹介します。Pythonにはデフォルトでカバレッジレポートを生成するモジュールは存在しないので、外部ライブラリの「coverage」をインストールしてテスト実行プロセスに組み込む形となります。

インストール

coverageをインストールします。
pipでサクッと入るので、以下の通りインストール&確認します。

$ pip install coverage

$ pip freeze | grep coverage
coverage==5.5

テストコード作成

テスト対象となる簡単なプログラムとテストコードを実装します。短いのでフルコード。
この内容を mytest3.py という名前で保存します。

from unittest import TestCase


def add(x, y):
    '''足し算'''
    if not isinstance(x, int):
        raise TypeError('x must be an integer')

    if not isinstance(y, int):
        raise TypeError('y must be an integer')

    return x + y


def substract(x, y):
    '''引き算'''
    return x - y


class AddTest(TestCase):
    def test_normal(self):
        '''正常系'''
        self.assertEqual(
            add(1, 1),
            2
        )

    def test_error(self):
        '''異常系 - 型不一致'''
        with self.assertRaises(TypeError):
            add(1, '文字')


if __name__ == '__main__':
    add('a', 1)

テスト実行

上記のコードをテストします。
今回導入したcoverageライブラリにはコマンドもバンドルされており、カバレッジデータを取得しつつテストランナーを起動することができます。普通にunittestを実行してしまうと、カバレッジ生成用データが作られないのでご注意ください。

$ coverage run -m unittest mytest3.py
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

テスト実行して2つとも成功です。

coverageコマンド経由でテストを実行すると、コマンドを実行したディレクトリに「.coverage」という隠しディレクトリが生成されます。この中に、カバレッジのメタデータが格納されます。

メタデータのままではあまり価値がないので、標準出力やHTMLファイルに結果を出力します。

標準出力レポート

以下コマンドで標準出力に結果がprintされます。

$ coverage report
Name         Stmts   Miss  Cover
--------------------------------
mytest3.py      17      3    82%
--------------------------------
TOTAL           17      3    82%

82%のカバレッジでした。実行行数:17、未実行行数:3 となります。

HTMLレポート

標準出力でも全体的なカバレッジ度合いは把握できますが、HTMLレポートではコードレベルで実行行を可視化してくれます。

$ coverage html

実行すると、「htmlcov」というディレクトリが生成されます。中にhtml形式のレポートが格納されているので、Finder(エクスプローラー)で index.html をダブルクリックしてブラウザで開きます。

カバレッジレポートトップ

トップ画面はさきほど標準出力した内容がそのままHTML化されていますね。
「mytest3.py」がリンクになっているので、クリックしましょう。実行行と未実行行が色分けされて表示されます

カバレッジ詳細

赤背景行の17行目、確かに今回のテストコードでは subtract関数はテストしていないので正しく未実行行として判定されてます。

まとめ

いかがでしたでしょうか。

coverageはシンプルで使い勝手が良いので、実務でPythonコード書く方は使い方を知っておくと便利です。CIの継続ビルドのテスト工程に組み込んで、常に最新のテストカバレッジレポートが見える状態を作っておくと良いでしょう。

それでは、今日はここまで。

良きPythonライフを!


Web系エンジニアでPython好き。バックエンド/フロントエンド問わずマルチな方面でエンジニアリングしています。