できない.dev

pytest でテストが見つからず実行できない(collected 0 items / no tests ran)

pytest は命名規則に合うファイル・関数・クラスだけを集める。
test_*.py か *_test.py のファイル、test で始まる関数、__init__ の無い Test で始まるクラスに揃え、pytest --collect-only で何が集まるかを確かめる。

公開:

要約

テストを書いたのに、pytest が 1 件も実行しないまま終わる。

============================= test session starts ==============================
rootdir: /app
collected 0 items
 
============================ no tests ran in 0.00s =============================

pytest は、決まった命名規則に合うものだけをテストとして集める。
既定の規則は次のとおりだ。

  • ファイル: test_*.py または *_test.py
  • 関数: 名前が test で始まるもの(クラスの外)
  • クラス: 名前が Test で始まり、__init__ を持たないもの。
    その中の test で始まるメソッドが対象になる

1 件も集まらないとき、pytest は終了コード 5 で終わる。
CI ではこれが失敗として扱われるので、「テストは通っているはずなのにジョブが赤い」という形でも気付く。

よくある原因

  1. ファイル名が規則に合っていない: check_math.py や tests.py は収集されない。
  2. 関数名・クラス名が規則に合っていない: def check_add(): や class UserTest: は、ファイル名が正しくても対象にならない。
  3. テストクラスに __init__ がある: クラスごと外され、PytestCollectionWarning: cannot collect test class 'TestThing' because it has a __init__ constructor という警告だけが出る。
    警告の一覧は結果の下にまとめて出るので見落としやすい。
  4. 設定や引数で外している: python_files に独自のパターンだけを書いた、norecursedirs に tests を入れた、-k の条件にどのテストも合わない、のいずれでも 0 件になる(-k のときは 1 deselected のように表示される)。

解決策

1. 名前を規則に揃える

# tests/test_calc.py
def test_add():
    assert 1 + 1 == 2
 
 
class TestCalc:
    def test_sub(self):
        assert 2 - 1 == 1

2. クラスの前準備は init 以外で行う

テストクラスではインスタンスの初期化を pytest に任せる。
前準備はフィクスチャか、各テストの前に呼ばれる setup_method に書く。

class TestThing:
    def setup_method(self):
        self.x = 1
 
    def test_x(self):
        assert self.x == 1

3. 収集結果を先に確かめる

pytest --collect-only -q

テストを実行せずに、集まったテストの一覧だけを表示する。
0 件なら no tests collected と出るので、名前を直すたびにこれで確かめる。

4. 独自の命名を使うなら既定も並べて書く

check_*.py も集めたい場合は、python_files に既定の test_*.py と並べて書く。

# pytest.ini
[pytest]
python_files = test_*.py check_*.py

既定の規則は、python_files を書いた時点で使われなくなる。check_*.py だけを書くと、今度は test_*.py が集まらなくなる。

この記事は役立ちましたか?