pytestのkオプションは、マーカー名でマッチしているものもテスト対象だった

pytestでテストを実行する時、今までは

  • -m オプションは、マーカー(@pytest.marker.xxx)に一致するもの
  • -k オプションは、テストクラス名やテストメソッド名でマッチするもの

を対象のテストコードとして実行するものと考えていました。

 
ただ、最近 -k オプションは、マーカー名でマッチするものもテスト対象になることを知ったため、挙動を調べてみました。

 
目次

 

環境

 

テストコード例

以下のテストコードに対し、 foo という文字列で -m オプションと -k オプションを実行してみます。

import pytest


@pytest.mark.foo
class TestHam:
    """クラスにマーカーあり"""
    def test_spam_method(self):
        assert True

    def test_egg_method(self):
        assert True


class TestHoge:
    @pytest.mark.foo
    def test_spam_method(self):
        """このテストメソッドだけマーカーあり"""
        assert True

    def test_egg_method(self):
        assert True


class TestHogefoo:
    """テストクラス名に foo が含まれる"""
    def test_spam_method(self):
        assert True

    def test_egg_method(self):
        assert True


@pytest.mark.foo
def test_bar_function():
    """テスト関数にマーカーあり"""
    assert True


def test_foo_function():
    """テスト関数に foo が含まれる"""
    assert True


def test_baz_function():
    assert True

 

mオプションの場合

mオプションの場合

  • マーカーがあるテストクラスのテストメソッド:2件
  • テストクラスのうち、マーカーがあるテストメソッド:1件
  • マーカーがあるテスト関数:1件

の合計4テストが実行されると考えていました。

 
実行すると、想定通り、対象は4テストでした。

$ pytest -m foo -v
...
collected 9 items / 5 deselected                                                                                                                                                  

test_k_option_marker.py::TestHam::test_spam_method PASSED
test_k_option_marker.py::TestHam::test_egg_method PASSED
test_k_option_marker.py::TestHoge::test_spam_method PASSED
test_k_option_marker.py::test_bar_function PASSED

==== 4 passed, 5 deselected in 0.03 seconds 

 

kオプションの場合

kオプションの場合、

  • foo が含まれるテストクラスのテストコード:2件
  • foo が含まれるテスト関数:1件

の合計3テストが実行されると考えていました。

 
実行すると、対象は7テストでした。

$ pytest -k foo -v
...
collected 9 items / 2 deselected                                                                                                                                                  

test_k_option_marker.py::TestHam::test_spam_method PASSED
test_k_option_marker.py::TestHam::test_egg_method PASSED
test_k_option_marker.py::TestHoge::test_spam_method PASSED
test_k_option_marker.py::TestHogefoo::test_spam_method PASSED
test_k_option_marker.py::TestHogefoo::test_egg_method PASSED
test_k_option_marker.py::test_bar_function PASSED
test_k_option_marker.py::test_foo_function PASSED

==== 7 passed, 2 deselected in 0.05 seconds

 
よく見ると、mオプションで対象だった

  • マーカーがあるテストクラスのテストメソッド:2件
    • test_k_option_marker.py::TestHam::test_spam_method
    • test_k_option_marker.py::TestHam::test_egg_method
  • テストクラスのうち、マーカーがあるテストメソッド:1件
    • test_k_option_marker.py::TestHoge::test_spam_method
  • マーカーがあるテスト関数:1件
    • test_k_option_marker.py::test_bar_function

も実行されていました。

 
なお、kオプションは部分一致なので、 -k oo としても同じ結果になりました。

$ pytest -k oo -v
...
==== 7 passed, 2 deselected

 
ドキュメントでは -k オプションがマーカーも対象にしているとは明示されていなかったため、新たな発見でした。

 

ソースコード

GitHubにあげました。 e.g._k_option_and_marker ディレクトリ以下が、今回のテストコードです。
https://github.com/thinkAmi-sandbox/python_pytest-sample