見出し画像

【Python3】VScode上で、pytestを使って例外を期待するテストをするときのimport問題を解決する

pytestの基本的な使い方はこちらの記事

にまとめたのですが、自作例外を期待するテストがうまく動かないことに気づいたので補足記事です。

自作例外を期待するテストがうまく動かない

ファイル構成がこう

PROJECTprojectappscount.pytestsappstest_count.py

こういう関数と自作例外を作っておいて

# project/apps/count.py

def count(n: int):
  if n > 0:
    return "正の数です"
  if n < 0:
    return "負の数です"
  if n == 0:
    raise ZeroExeption("0です")

class ZeroExeption(Exeption):
  pass

こういうテストを用意します

# tests/apps/test_count.py

import pytest
from project.apps.count import count, ZeroExeption

def test_send_zero_then_raise_zero_exeption():
  n = 0
  with pytest.raises(ZeroExeption):
    count(n)

これで本来ならテストが通るはずなのですが、実際にはこんな感じのエラーが出ます。

E apps.count.ZeroExeption:0です

いいんだよそれで。それを期待してるんだよ、と思うのですが、エラーで失敗扱いになってしまいます。

これがなんでかというと、送出されているのは「apps.count.ZeroExeption」で、テストが期待しているのは「project.apps.count.ZeroExeption」だから、ということになってしまうんですね。
そこはうまいことやってくれないんかーい!

で、お行儀の悪い解決方法は上の記事でちょっと紹介した、「実行ファイルの方をPROJECTフォルダ直下に置いて、projectフォルダ内のimportも全部project.から書く」っていうのがあるんですが、やだやだお行儀よくしたい。
ということで、VScodeの機能とfixture使って何とかしました。(fixtureの使い方も上記記事を見てください。)

ただ、本当にお行儀がいいのかはよくわかりません。

①fixtureで無理やりパスを通す

「python -m pytest」で実行する方法と本質的には(たぶん)同じです。カレントディレクトリを一時的にPathに加えて実行します。

# tests/conftest.py

import os
sys.path.append(os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../project"))

testsフォルダ直下にconftest.pyを作って、そこでパスを通す命令を出しておけば、すべてのテストの実行前にこれが自動で呼ばれてパスが通ります。

②.vscode/setting.jsonを使って、VScodeにフォルダ構成を認識させる

今まで、testsフォルダの中からprojectフォルダの中身を呼ぶときは

from project.apps.count import count

と、projectから記述していましたが、これのせいで自作例外のパスが変わってしまってちゃんと認識されないので、このproject.の記述を取り去ります。

from apps.count import count

①でパスを通しておけばこれでもちゃんとimportして実行できるのですが、VScodeくんはそのパスを認識していないので、コードリンクや自動補完がちゃんと動いてくれません。不便。
なので、VScodeくんにも「ここをルートだと思って探してみて」と教えてあげます。

# PROJECT/.vscode/setting.json
{
    "python.analysis.extraPaths": [
        "./PROJECT/project"
    ]
}

これでコードリンクも機能するようになり、自作例外を期待するテストがちゃんと動くようになります。


今回、うっかりprojectフォルダ内のimportもすべてproject.から書いてしまってて、でもずっとpytest経由での起動だけ試していたからそれでも動いちゃってたんですね。
で、全部できてから「python main.py」で起動してみたら、とたんにimportエラー⇒projectフォルダ内のimportからproject.を削除⇒上記の自作例外テストが軒並み落ちるようになった、という経緯で丸一日ハマりました。
毎回このあたりの仕様に引っかかって泣いてる気がする。


この記事が気に入ったらサポートをしてみませんか?