pytest.raisesでmatch使う時の注意点

調べるきっかけ

  • pytestでテストをしていて、例外発生時のメッセージが合っているはずなのにテストが通らなかった
  • 今までは通ってたのに、なぜかと思った時に、今までエラーメッセージには使っていなかった f文字列 を今回、使っているのが怪しいと思い調査

具体的に困ったところ

  • 例えば↓のようにf文字列を使用して例外メッセージを出しているとき
# テスト対象
# 引数が0より大きくないと例外を飛ばすようにする関数があったとする
def calc(self, a, b):
    
    if 0 < a and 0 < b: 
        return a/b
    
    # InvalidErrorは独自に定義したErrorクラス
    raise InvalidError(f'a={a} or b={b} is invalid.')
# テスト

import pytest

with pytest.raises(InvalidError, match='a=0 or b=2 is invalid.'):
    calc(0, 2)
  • ↑の書き方では、合っているのに、テストが通らない
  • 手元で出たエラーはこんな感じだった
AssertionError: Regex pattern '例外メッセージ' does not match '例外メッセージ'. 
Did you mean to `re.escape()` the regex?

regexってなに?

  • 日本語に略すと 正規表現 の意味

解決方法

  • エラーメッセージに書いてあるとおり、 re.escape() を使うとテストが通るようになる
# テスト(修正版)

import pytest

with pytest.raises(InvalidError, match=re.escape('a=0 or b=2 is invalid.')):
    calc(0, 2)
  • こちらを見て解決

  • raw文字列(バックスラッシュを文字として扱う)raw文字列使ってるのに、メッセージが一致しないっていう内容っぽい

公式にはなんとなく使ってくださいとの記載がある・・・

  • 公式ドキュメントにこんな文面が・・・(スクショ

    f:id:YukiMatsu88:20210601193932p:plain
    pytest公式ドキュメントから引用

  • 公式ドキュメントはこちら

  • 特殊文字を含む可能性がある文字列を使ってる時は、 re.escape正規表現を無効にしないといけないっぽい?

  • f文字列って特殊文字なのか・・何者なのか?と疑問が残るが、深追いせずにとりあえず今後気をつけることにする