この記事で切り分けられること
pytest の実行結果の末尾に「passed」が並んでいて一見問題なさそうに見えるのに、実は一部のテストが一度も実行されていないケースを切り分けられる。特に tmp_path を使うテストが Windows 環境で収集時点から失敗する場合の見分け方と直し方を扱う。
症状
pytest tests/ -q を実行すると毎回「6 errors」が出ていたが、最終行だけを見て「ほぼ通っている」と判断していた。実際の出力は次のような形だった。
1 failed, 207 passed, 4 skipped, 6 errors
errors の中身を見ると、次のようなエラーが並んでいた。
PermissionError: [WinError 5] アクセスが拒否されました。: 'C:/Users/<あなたのユーザー名>/AppData/Local/Temp/pytest-of-<あなたのユーザー名>'
tmp_path を使うテストが、実行前の収集の時点で落ちていた。落ちていたのは次の4本で、いずれも公開前の安全検査だった。
- 秘密の値が公開物に混ざっていないかを確認するテスト
- 消したページへの転送が循環していないかを確認するテスト
- 承認していない価格が本番に出ないかを確認するテスト
- 参照先のファイルとアンカーが実在するかを確認するテスト
これらは「検査に失敗していた」のではなく、「検査そのものが一度も走っていなかった」。緑の「207 passed」の隣で、公開物の安全検査だけが空振りしていた。
原因
pytest は既定で %LOCALAPPDATA%\Temp\pytest-of-<あなたのユーザー名> に一時フォルダを作る。このフォルダが読めない状態(権限)になっていたため、tmp_path フィクスチャを使うテストがすべて収集の段階でエラーになっていた。
pytest の結果表示は「エラー」も含めて末尾にまとめて出すため、1 failed, 207 passed, 4 skipped, 6 errors の末尾だけを見ていると、エラーの存在に気づきにくい。
直し方
リポジトリの中に一時フォルダを作り、そこを使うように pytest.ini を新設した。
[pytest]
addopts = --basetemp=tmp/pytest
tmp/pytest は .gitignore に追加済みのパスにした。この設定で4本とも実行され、通ることを確認した。
11 passed
このとき、4本のうち1件は実在する不具合だった。tests/test_annai_evidence.py の失敗で、11/1 に追加した期限つきの見本(fresh_evidence)を証拠の先頭に入れていたため、案件に直接合う実物のデモが押し出されていた。
見本の当たり判定が「AI|エージェント|自動化|セキュリティ|鍵|権限|API」と広く、受付AIの案件6件すべてで /demos/annai/ が応募文の材料から消えていた。修正として、案件の語に当たった実物を先に2件、時事の見本は後ろに並べるようにした。クリニックの受付AIの案件では /ai/ と /demos/annai/ が先に出て、Zenn の鍵の記事は後になることを確認した。
それでも駄目なときに次に見る場所
テストの結果は「passed の数」ではなく failed + errors が 0 かどうかで見る。errors は「走らなかった」であって「通った」ではない。
pytest tests/ -q
# 末尾の failed と errors の数字だけを見る
一時フォルダ関連のエラーが出ている場合は、まず %LOCALAPPDATA%\Temp\pytest-of-<あなたのユーザー名> の権限を確認し、読めない場合は --basetemp でリポジトリ内の別フォルダに切り替える。
既存の出力リストの先頭に新しい層(見本やサンプルなど)を足すときは、その追加によって既存の項目が押し出されていないかを検査で固定する。当たり判定が広い条件分岐は、意図しない件数で発火していないかを件数ベースで確認する。

Claude Codeとは何か、実際に投げた依頼文と直し方から説明する
CSVの文字化けと列ずれが止まる場所をPythonのコードで具体的に潰す手順
OpenAI APIキー発行の手順と予算上限を実測の実費から決める方法