rcmdnk's blog
Last update

20140909_coverallsbagde_200_200

Travis CIを使ってみた に引き続き、Travis CIのバッジとセットでよく見る Coveralls も使ってみました。

Coveralls

Coverallsはプログラムのテストなどを行った時に、 どれ位の範囲が実際にテストされているか調べて表示する サービスです。

このサービスはローカルなどでテストコマンドを実行して、 その結果をCoverallsへ送って結果を見る、といった形です。

基本的にはGitHub用のサービスで、 特にTravis CIと連携すると、 Travis CIでテストを行う際にCoverallsコマンドでWrapしてカバーされてる範囲を調べ、 その結果をTravis CI内のコマンドでCoverallsへ送る、と言った事が出来るので 良い感じです。

これも基本的にPublicなレポジトリを使う分には無料で、 プライベートのレポジトリを使いたいときには有料になるような体系をとっています。

Subscribe Coveralls: https://coveralls.io/pro_subscribes/select_plan

追記: 2015/06/01

上のページが消えてたので。今は下のページで料金プランが見れます。

Coveralls - Test Coverage History & Statistics

追記ここまで

Coveralls側での設定

CoverallsではTravis CI同様GitHubのアカウントでSign Upする様になっているので、 Sign UpするとGitHubのアカウントと紐付けられてレポジトリ一覧を取得してきます。

coverallsrepos

ADD REPOを選んでレポジトリ一覧の中でCoverallsで使いたいもののスイッチを ONにすればCoveralls側での準備は終了です。

coverallsaddrepo

実際に実行するとこんな感じの結果が出てきます。

simple test

FILESの欄に

COVERAGE FILE LINES RELEVANT COVERED MISSED HITS/LINE
81.82% test.py 21 11 9 2 1.0

な感じの結果がありますが、

  • COVERAGE: 実際どれだけの部分がカバーされてるかの結果。
  • FILE: カバー度をテストしたファイル。
  • LINES: テストしたファイルの全行数。
  • RELEVANT: 実際にカバー度を図るための母数。
    • shebangや空白行、コメント行、また、無視するように指定された所以外の行数。
  • COVERED: テストで使われた行数。
  • MISSED: テストで使われなかった行数。
  • HITS/LINE: 各行が何回使われたか。
    • ただ、下で行うpython-coverallsではサポートされてないので常に1になる?

と言った感じで結果が見れます。

レポジトリ側での設定

レポジトリ側では上に書いたようにTravis CIとの連携で行うように設定をします。

まず、テストに使いたい言語毎に解析用のプログラムも違うものが用意されているので 何を使えば良いのか公式Documentページから調べます。

Documentation Getting Started Coveralls

RubyなんかからスタートしたみたいでRubyに関しては公式のページに Documentが載っています。

今回はPythonを使いますが、Pythonに関しては

z4r/python-coveralls

coagulant/coveralls-python

の2つのGitHubのレポジトリが紹介されていて、 後はそちらのREADMEを読むように、となっています。

2つとも同じような使い方な感じですが(名前もpythoncoverallsが前後しているだけという。。。)、 coveralls-pythonの方はTravis CIを使う限りレポジトリ用のTokenを使わないでも そのまま連携してくれるようなので今回はcoveralls-pythonを使いました。

上で少し触れましたが、PythonのこれらのテストではHits Per Lineは 実装されてない感じです。

coveralls-pythonの方ではIssueに少し話が出ています。

Hits per line · Issue #3 · coagulant/coveralls-python

テスト用スクリプト

まず、今回テストしたPythonスクリプトはこんな感じ。

test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python

def func1():
    print 1

def func2():
    print 2

def func3(): # pragma: no cover
    print 3

if __name__ == "__main__":
    import sys
    #func1()
    #func2()
    if len(sys.argv) > 1:
        if sys.argv[1] == "1":
            func1()
        if sys.argv[1] == "2":
            func2()

単純に

$ python test.py 1
1

と返す様な事を1,2でやるだけのスクリプトです。

また、コードの中でテストの必要のない部分や絶対にテストでは辿り着かない 部分など、無視したい所がある場合は # pragma: no coverというコメントを付けます。 関数などならその右に、 if文やelse文などでもその右に書くことにより、 そのブロック全体が無視されます。

なので、上の場合はfunc3の部分が全て無視されます(カバー度の計算に入れない)。

Ned Batchelder: Excluding code from coverage

python-coverallsを.travis.ymlで設定

基本的な設定

次にTravis CIで実際にCoverallsを使う設定です。

一番単純な.travis.ymlはこんな感じになります。

.travis.yml
1
2
3
4
5
6
7
language: python
install:
  - pip install coveralls
script:
  - coverage run test.py 1
after_success:
  - coveralls

まず、python-coverallsをインストールしないといけませんが、 これはpipcoverallsの名前でインストールできます 1。 なので、pip installinstallの中で行います。

そうすると、coverageというコマンドとcoverallsというコマンドが使えるようになります。

coverageの方がテストコマンドをラップしたりしてカバー度のチェック結果を作るコマンド。

coverallsコマンドはその結果をCoverallsのサイトへ送ります。

このcoverageコマンドでrunという引数の後にPythonスクリプト(+スクリプトへの引数)を与えると そのスクリプトを実行し、その実行時にそのスクリプト内のどれだけの部分を 使っているか、当計測を行って.coverageというファイルを作ります。

この.coverageにある結果をCoverallsに送るため、最後にafter_successの部分で coverallsコマンドを実行しています。

この結果が上にも出したsimple test です。

ラインの数など数えてみると、実際、有効な部分が11行あって、 func2が呼ばれてないので2行がMISSEDになってるのがわかると思います。

2つ以上のテストの結果を統合して送りたい場合

script内で、いくつかコマンドを実行して それら合わせた結果を送りたい場合は --parallell-modeというオプションを使います。

もし、このオプションを使わずに複数coverage runを実行すると、 単に最後のコマンドの結果だけが.coverageに残るようになるので ほしい結果が得られません。

このオプションを使うと 結果が**.coverage..XXX.YYY**みたいなファイルに出力されます。

これらのファイルを統合して1つの.coverage にするためには coverage combineを実行すれば良いだけ。 このコマンドはディレクトリ内の.coverage.* **を探してそれらをまとめた **.coverageファイルを作ります。

.travis.yml
1
2
3
4
5
6
7
8
9
language: python
install:
  - pip install coveralls
script:
  - coverage run --parallel-mode test.py 1
  - coverage run --parallel-mode test.py 2
after_success:
  - coverage combine
  - coveralls

こんな感じでやってあげれば良いだけ。

今度はfunc2も呼んでいるのできちんと100%カバーになっています。

Paralled test

coverallsbadge

その他coverageコマンドの高度な使い方

上の例では1つのスクリプトを実行してそのスクリプトの中身をチェックする、 と言ったことだけを行いましたが、 実際には幾つかファイルの有るプロジェクトなどでチェックを行うことも多いと思います。

その場合には、--sourceオプションを使って実際に測定したいファイルやディレクトリを 指定した上でテストスクリプトを走らせる、なんていうことも出来ます。

$ coverage run --source=lib_dir,example.py test.py

Multi-file test

その他詳しいことは作者のページで。

Ned Batchelder: coverage.py

Homebrew-fileで試してみた

Homebrew-fileのPythonブランチで試してみた結果。

rcmdnk/homebrew-file

65%くらい。 そもそもテストと言っても適当にコマンドを打って結果を検証してるわけでもないのであれですが、 それでも半分ちょっとしか見れてないということですね。。。

まとめ

次はPythonなら nosetests とか使ってちゃんとテストを作る事をやってみたいところです。

Coverallsに関してはシェルスクリプトでのテストをするツールは無いみたいですが、 簡単に作れそうなら作ってみたい所。 (ただ、そもそもそんなデカイものはシェルスクリプトで書くな、と言う感じもあるのかも。。。)

シェルスクリプトにも shunit2 とかテストフレームワークはあったりします。

Sponsored Links
  1. もし、Mac OSX環境(language: objective-c)にしている場合は、 pipによるインストール先が管理者権限が必要な領域になってるので sudo pip install coverallsとする必要があります。 (sudoにパスワードは要らない。)

Sponsored Links

« Travis CIを使ってみた: GitHubのレポジトリにバッジを貼りたかったから sedで改行を出力する »

}