Pytest: Improvement to documentation of pytest.raises() match parameter.

Created on 4 May 2019  ·  4Comments  ·  Source: pytest-dev/pytest

The need for testing code doesn't necessarily come after the need for groking regex (at least for me it didn't). I posted this Q on Stackoverflow today and totally understand the answer, however I did spend quite a bit of time trying to wrap my head around what was going on before I was sure that I wouldn't get flamed for putting up an obvious question on SO.

As the message I'm passing to match is a built in error message which includes braces, and the current documentation uses the term text or regex, would it be considered an improvement to the documentation to note that the string that is passed to match will be treated as a regex pattern, and certain special characters in the string might cause unexpected results?

If so, I'd be happy to try to piece something together.

pip list:

PS C:\Users\peter_000\OneDrive\git\pytestenv> pipenv run pip list

Package        Version
-------------- -------
atomicwrites   1.3.0
attrs          19.1.0
colorama       0.4.1
more-itertools 7.0.0
pip            19.1
pluggy         0.9.0
py             1.8.0
pytest         4.4.1
setuptools     41.0.1
six            1.12.0
wheel          0.33.1

pytest ver and os:

pytest 4.4.1, windows 10.

Example:

>>> 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'
easy docs

Most helpful comment

Hi @5uper5hoot,

would it be considered an improvement to the documentation to note that the string that is passed to match will be treated as a regex pattern, and certain special characters in the string might cause unexpected results?

Definitely, thanks for pointing that out.

I think we should make it explicit that match expects a regex, and users that want to match a text exactly might want to use re.escape to escape special regex characters.

Your example then becomes:

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

All 4 comments

This passes:

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

Hi @5uper5hoot,

would it be considered an improvement to the documentation to note that the string that is passed to match will be treated as a regex pattern, and certain special characters in the string might cause unexpected results?

Definitely, thanks for pointing that out.

I think we should make it explicit that match expects a regex, and users that want to match a text exactly might want to use re.escape to escape special regex characters.

Your example then becomes:

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

Thanks @nicoddemus, does this sound OK?

match – if specified, a string containing a regular expression, or a regular expression object that is tested against the string representation of the exception using re.match. To match a literal string that may contain special characters, the pattern can first be escaped with re.escape.

Looks great, thanks! 👍

Was this page helpful?
0 / 5 - 0 ratings