LoginSignup
14
14

More than 5 years have passed since last update.

GitHubにpush済みのpythonコードのテストカバレッジを計測してみる。

Posted at

DIY太陽光発電システム監視用のPythonドライバをCIしてみた記事の続編で、今回はpythonコードのカバレッジ(テストのカバー率)を計測します。

コマンドラインでカバレッジを計測する

まずはテストを実行

以下のようなtest runnerコードを毎回書くのは面倒なので、noseパッケージをpip installし、nosetestsコマンドを使います。

import unittest

if __name__ == "__main__":
    all_tests = unittest.TestLoader().discover("./", "test_*.py")
    unittest.TextTestRunner(verbosity=1).run(all_tests)

nosetestsは、noseパッケージをpip installすると使えるようになるコマンドです。

nosetestsのテストケースの見つけ方を見ると分かりますが、とりあえずunittest.TestCaseのサブクラスをかき集めて実行してくれるようです。

tsmppt60_driver $ nosetests -v
test_init (test_base_controller.TestChargeControllerStatus) ... ok
test_compute_scaler_current (test_base_management.TestMb) ... ok
test_compute_scaler_voltage (test_base_management.TestMb) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.230s

OK

setup.pyのtest_suiteに以下のように書いておき、noseにtest suiteをかき集めてもらって、setup.py経由でテスト実行することも可能です。

setup (
    # ...
    test_suite='nose.collector'
)
$ python setup.py test

テストカバレッジ計測

カバレッジを計測するには、以下の--with-coverageオプションをつけます。

tsmppt60_driver $ nosetests -h | grep coverage
  --with-coverage       Enable plugin Coverage:  Activate a coverage report

tsmppt60_driver $ nosetests -v --with-coverage
test_init (test_base_controller.TestChargeControllerStatus) ... ok
test_compute_scaler_current (test_base_management.TestMb) ... ok
test_compute_scaler_voltage (test_base_management.TestMb) ... ok

Name                                                       Stmts   Miss  Cover   Missing
----------------------------------------------------------------------------------------
minimock.py                                                  197     79    60%   51-57, 63-66, 108-109, 113, 229, 231-232, 237-238, 241-242, 258, 264-265, 290, 294, 297, 300, 325, 335-341, 364, 388-393, 408, 417-418, 455-465, 479-487, 493, 506, 517, 526, 528, 530-533, 537, 540-548, 551-565, 643-644
...

カバレッジを計測結果は、同ディレクトリ下の.coverageファイルに記録されます。

tsmppt60_driver $ cat .coverage | head
!coverage.py: This is a private format, don't read it directly!{"lines": {"/Users/

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

coverageパッケージとコマンドを使って、カバレッジレポートを生成します。
pip installしてヘルプ表示すると、以下のようなサブコマンドが用意されていることが分かります。

$ pip install coverage
$ coverage --help
Coverage.py, version 4.0.3
Measure, collect, and report on code coverage in Python programs.

usage: coverage <command> [options] [args]

Commands:
    annotate    Annotate source files with execution information.
    combine     Combine a number of data files.
    erase       Erase previously collected coverage data.
    help        Get help on using coverage.py.
    html        Create an HTML report.
    report      Report coverage stats on modules.
    run         Run a Python program and measure code execution.
    xml         Create an XML report of coverage results.

カバレッジを計測結果が記録された.coverageファイルを読み込み、レポートを表示することができます。

--includeオプションで対象モジュールを絞らないと、テスト対象以外の依存モジュールも一緒くたにレポートしてしまい、煩雑になるのでご注意を。

tsmppt60_driver $ coverage report --include=tsmppt60_driver/*
Name                          Stmts   Miss  Cover
-------------------------------------------------
tsmppt60_driver/__init__.py      28     16    43%
tsmppt60_driver/base.py         117     51    56%
tsmppt60_driver/status.py        60     37    38%
-------------------------------------------------
TOTAL                           205    104    49%

コード内のどのパスがカバーできて、どのパスがカバーできていないのかを視覚的に確認できる、HTML形式のレポートも生成できます。

tsmppt60_driver $ coverage html --include=tsmppt60_driver/*
tsmppt60_driver $ open htmlcov/index.html

こんな感じです。

Webサービスを使って自動的にカバレッジを計測する

前置きが長くなりましたが、ここからが本題です。

前回紹介したTravisCIと連携しやすいCoverallsを使います。

.travis.ymlが設定済みであれば以下のような内容だったと思いますが、

language: python
python:
  - "2.7"
# - "3.2"
# TODO:
# dest.write(u'  ')
# ^
# SyntaxError: invalid syntax
  - "3.3"
  - "3.4"
  - "3.5"
  # does not have headers provided, please ask https://launchpad.net/~pypy/+archive/ppa
  # maintainers to fix their pypy-dev package.
  - "pypy"
# command to install dependencies
install:
  - pip install .
  - pip install -r requirements.txt -r test-requirements.txt

これに以下を追記して、

script:
  - coverage run --source=tsmppt60_driver setup.py test
after_success:
  - coveralls

test-requirements.txtには以下を追記します。

nose
coverage
coveralls

ほとんどcoveralls-pythonのREADMEに従うだけなんですけどね。

これでgithubリポジトリにpushする度、自動的にTravisCIでテストを回し、自動的にCoverallsでカバレッジ計測してくれます。

バッジの表示

Coverallsのカバレッジ計測結果バッジ

coverallsのREPOSで、カバレッジ計測後に対象のリポジトリのリンクに飛び、画面上の方に「BADGE YOUR REPO: TSMPPT60_DRIVER」というリンクがあるので、そこでバッジのURLを取得できます。

MARKDOWN形式他、一通り揃っているので、環境に合わせてコピペして使ってください。

GitHubのREADMEにも、以下のようなバッジを貼ることができます。

Coverage Status

いろいろなバッジ

TravisCIやCoverallsのようなバッジをREADMEに貼ると、なんだか他の情報も同じようなバッジで表示したくなります。よね?

そこで、shields.ioというサービスがあります。

上記リンク先の通り、以下のようなフォーマットで様々なバッジを自分で作ることができます。

https://img.shields.io/badge/<SUBJECT>-<STATUS>-<COLOR>.svg

例えば以下のようにすると、

https://img.shields.io/badge/python-3.3,3.4,3.5-blue.svg

以下のように表示されます。

python

あまり意味はないですが、こんなバッジも作れちゃいます。

hoge
hoge
hoge

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14