意外结果:从错误的函数调用中断言TypeError时,带有match参数的pytest.raises()

时间:2019-05-04 11:51:28

标签: python pytest

请进行健全性检查!

当包含从错误的函数调用返回到match的{​​{1}}参数的确切消息时,我试图理解意外的测试失败。

The docs state

  

match –如果指定,则断言该异常与文本或   正则表达式

下面的repl中的指令序列几乎说明了一切,但是由于某种原因,最后的测试失败了。

pytest.raises()

我认为PS C:\Users\peter_000\OneDrive\git\test> pipenv run python Loading .env environment variables… Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> >>> >>> import pytest >>> pytest.__version__ '4.4.1' >>> >>> with pytest.raises(TypeError, match='a string'): ... raise TypeError('a string') # passes ... >>> def func(): ... pass ... >>> func(None) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: func() takes 0 positional arguments but 1 was given >>> >>> >>> with pytest.raises(TypeError, match='func() takes 0 positional arguments but 1 was given'): ... func(None) # fails ... Traceback (most recent call last): File "<stdin>", line 2, in <module> TypeError: func() takes 0 positional arguments but 1 was given During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 2, in <module> File "C:\Users\peter_000\.virtualenvs\test-_0Fb_hDQ\lib\site-packages\_pytest\python_api.py", line 735, in __exit__ self.excinfo.match(self.match_expr) File "C:\Users\peter_000\.virtualenvs\test-_0Fb_hDQ\lib\site-packages\_pytest\_code\code.py", line 575, in match assert 0, "Pattern '{!s}' not found in '{!s}'".format(regexp, self.value) AssertionError: Pattern 'func() takes 0 positional arguments but 1 was given' not found in 'func() takes 0 positional arguments but 1 was given' >>> 可能在正则表达式中可能会导致字符串不匹配而是:

'()'

...通过。

2 个答案:

答案 0 :(得分:2)

匹配采用regular expression模式,某些字符如()是特殊的。您需要逃脱它们:

>>> with pytest.raises(TypeError, match=r'func\(\) takes 0 positional arguments but 1 was given'):
... #                                   ^     ^^^^
...     func(None)  # succeeds
>>>

之前失败的原因是正则表达式中的()对应一个空组,因此您的模式将与字符串func takes 0 positional arguments but 1 was given相匹配。

通过match='func()'的原因是特定的正则表达式正在字符串中的任何位置寻找func:它的后面可以是任何文本。

答案 1 :(得分:0)

如果传入的整数太大,我有一个方法会引发 ValueError。我的测试方法是这样的:

import pytest

def test_func_exceeding_max_value():
    with pytest.raises(ValueError, match="maximum value of (2**32)-1 exceeded"):
        func(2**32)

这个测试遇到了错误:

re.error: multiple repeat at position 20

位置 20 对应这个字符:

maximum value of (2**32)-1 exceeded
                    ^

正如错误所暗示的那样,它是由 regex 表达式中的错误引发的。我最初没有意识到 match 中的 pytest.raises 参数是一个正则表达式,而不是文字字符串匹配。在 pytest 文档中,它指出:

<块引用>

您可以将匹配关键字参数传递给上下文管理器 [pytest.raises] 以测试正则表达式是否与异常的字符串表示匹配...

您需要在特殊字符 \\(、{ 之前使用两个反斜杠 (*) 而不是一个 {1}} 等。这是因为当 ) 参数发送到 match 方法时,反斜杠本身需要转义,以便 re.match 将该反斜杠解释为文字字符然后将转义正确的字符:

re.match