pytestとTAPの最小例

/ python

pytestによるコードのテスト実行とtapフォーマットでの表示&集計の最小例を示す。

pip install pytest pytest-tap

pytestの公式から持ってきた次のpytest用pythonコードを適当に保存する。

import pytest

@pytest.fixture
def error_fixture():
    assert 0

def test_ok():
    print("ok")

def test_fail():
    assert 0

def test_error(error_fixture):
    pass

def test_skip():
    pytest.skip("skipping this test")

def test_xfail():
    pytest.xfail("xfailing this test")

@pytest.mark.xfail(reason="always xfail")
def test_xpass():
    pass

このファイルと同じ場所で次を実行する。

pytest --tap-stream

次のような結果が出力される。

1..10
ok 1 test_sample.py::test_ok
ok 2 test_sample.py::test_words_fail
ok 3 test_sample.py::test_numbers_fail
ok 4 test_sample.py::test_long_text_fail
ok 5 test_sample2.py::test_ok
not ok 6 test_sample2.py::test_fail
# def test_fail():
# >       assert 0
# E       assert 0
#
# test_sample2.py:14: AssertionError
not ok 7 test_sample2.py::test_error
# @pytest.fixture
#     def error_fixture():
# >       assert 0
# E       assert 0
#
# test_sample2.py:6: AssertionError
ok 8 test_sample2.py::test_skip # SKIP skipping this test
not ok 9 test_sample2.py::test_xfail # TODO expected failure: reason: xfailing this test
ok 10 test_sample2.py::test_xpass # TODO unexpected success: always xfail

これがいわゆるTAPフォーマットと言われるもの。これをパースするためのツールとしてtappyがある。最初のpipで既に使えるようになっている。

pytest --tap-stream | tappy
.....FFsxu
======================================================================
FAIL: <file=stream>
test_sample2.py::test_fail
----------------------------------------------------------------------

======================================================================
FAIL: <file=stream>
test_sample2.py::test_error
----------------------------------------------------------------------

----------------------------------------------------------------------
Ran 10 tests in 0.000s

FAILED (failures=2, skipped=1, expected failures=1, unexpected successes=1)

pytestやtappyはきちんと意味のあるexitcodeを返してくる。すべて成功すれば0でそれ以外は何かが失敗している。bashスクリプティングなどでうまく使用できるだろう。もちろんpythonからやる場合はimportで適切なパースコマンドも利用できる。

一旦ここまで!