🤖

【Coverage.py】Pythonでカバレッジを取得する

2023/03/16に公開

訳ありで手動でカバレッジをとりたい人向けです。

Coverage.pyのインストール

Pythonでカバレッジを取得するなら、Coverage.pyを使いましょう。pip install coverageでインストールすると使えるようになります。

>pip install coverage

テストするプログラム

テストするプログラムにtest.pyという、以下のPythonファイルがあるとします。

import sys
 
if len(sys.argv) > 1 and sys.argv[1] == "1":
    print("a")
else:
    print("b")

このプログラムは、1つ目のコマンドライン引数に1が指定されていた場合、標準出力にaを出力します。それ以外は、標準出力にbを出力します。

以降、このtest.pyをテストするプログラムとして、Coverage.pyの便利な機能を紹介します。

カバレッジの取得

それでは、test.pyのカバレッジを取得してみます。

コマンドプロンプトから以下の通り実行します。

>coverage run --append test.py

実行後、.coverageというファイルが作成されます。.coverageファイルにカバレッジの情報が書き込まれています。

カバレッジを見える化

カバレッジの情報が書き込まれた.coverageファイルを見える化してみます。

HTMLファイルにして、見やすくしてみましょう。

コマンドプロンプトから以下の通り実行します。

>coverage html

実行後、htmlcovというフォルダが作成されます。htmlcovフォルダにindex.htmlがあり、開くとカバレッジが見れます。

カバレッジ情報を追加する

coverage runのオプション--appendは、.coverageファイルにカバレッジ情報を追加します。

コマンドプロンプトから以下の通り実行します。

coverage run --append test.py 1

実行後、以下を実行し、カバレッジレポートをHTMLファイルとして作成します。

coverage html

htmlcovフォルダのindex.htmlを開くと以下の通りになっていると思います。


test.pyのカバレッジが75%から100%になっています。
前回実行したtest.pyのカバレッジに今回実行したtest.pyのカバレッジが追加されました。

Djangoのカバレッジの取得

Djangoについても、カバレッジを取得することができます。

コマンドプロンプトから以下の通り実行します。

coverage run --append manage.py runserver --noreload

test.pyのとき同様に、.coverageファイルが作成されます。

.coverageファイルの結合

複数の.coverageファイルを結合して、一つの.coverageファイルを作成することもできます。

取得した複数の.coverageファイルがあるとします。

それら.coverageファイルを.coverage.xxx(.coverageの後に . を付けて、任意の文字列をつなげる)にリネームし、以下のコマンドを実行します。

coverage combine

複数人で並行してカバレッジを取得

複数人で並行してカバレッジを取得することもできます。

コマンドプロンプトから以下の通り実行します。

coverage run --parallel-mode test.py

以下ファイル名の.coverageファイルが作成されます。

.coverage.{マシン名}.{プロセスID}.{乱数}
(例).coverage.DESKTOP-0K5792H.10744.544743

これらの.coverageファイルは、coverage combineを使って結合できます。

Pythonプログラムの中でcoverageを使う

これまで、coverage runでPythonプログラムを実行することでカバレッジを取得していました。

Pythonプログラムの中でcoverageを使うこともできます。

from coverage import Coverage
 
def exec(arg):
    if arg == "1":
        print("a")
    else:
        print("b")
 
# data_suffix=Trueは、.coverageファイルの末尾に.{マシン名}.{プロセスID}.{乱数}を追加
cov = Coverage(data_suffix=True)
 
# カバレッジ取得開始
cov.start()
 
# 関数化しておかないと、カバレッジを取得できない
exec("1")
 
# カバレッジ取得終了
cov.stop()
 
# .coverageファイルとして保存
cov.save()

なお、coverage runにあったappendはないようです。

しかし、data_suffix=Trueをセットして、coverage combineで一つの.coverageファイルにまとめることで代替できると思います。

APIについては、ドキュメントに記載があります。
https://coverage.readthedocs.io/en/coverage-5.5/api_coverage.html

Discussion