【Coverage.py】Pythonでカバレッジを取得する
訳ありで手動でカバレッジをとりたい人向けです。
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については、ドキュメントに記載があります。
Discussion