Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add matching the error message to pytest.raises #2227

Merged
merged 2 commits into from
Feb 3, 2017

Conversation

Kriechi
Copy link
Contributor

@Kriechi Kriechi commented Feb 1, 2017

pytest.raises can now assert that the error message contains a certain text.
Example:

with raises(ValueError, match_info='must be 0'):
    raise ValueError("value must be 0 or None")

This is a more compact and IMHO cleaner way of doing it like this:

with raises(ValueError) as exc_info:
    raise ValueError("value must be <= 10")
assert "value must be <= 10" in str(exc_info.value)

@The-Compiler
Copy link
Member

This PR should go to the features branch, as it's a new feature - you can change the branch of the existing PR, and then you might need to rebase and force-push your changes too (not sure about the latter).

@Kriechi Kriechi changed the base branch from master to features February 1, 2017 12:45
@Kriechi
Copy link
Contributor Author

Kriechi commented Feb 1, 2017

Sorry about that - I changed it as requested.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.838% when pulling dd4d61a on Kriechi:raises-info into 0931fe2 on pytest-dev:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling 06fae84 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@The-Compiler
Copy link
Member

No worries! You'll also need to change the changelog to add this to a 3.1.0 section (I think?).

Looking at https://travis-ci.org/pytest-dev/pytest/jobs/197286855#L214 I also think you should use ... instead of .... in your docstring.

LGTM otherwise from a quick look, but I'm a bit in a hurry currently.

@Kriechi Kriechi force-pushed the raises-info branch 2 times, most recently from 3bca688 to cfb7bec Compare February 1, 2017 13:19
@Kriechi
Copy link
Contributor Author

Kriechi commented Feb 1, 2017

fixed & fixed 😄

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling cfb7bec on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling cfb7bec on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling 5d6a2e3 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@nicoddemus
Copy link
Member

Thanks for the PR! But I believe we already have similar functionality with excinfo.match (sorry I can't provide a link now because I'm on my phone)

@RonnyPfannschmidt
Copy link
Member

@nicoddemus would it make sense to make "with raises(..., match=...)" a shortcut for the turnaround?

@nicoddemus
Copy link
Member

IMHO it does not add much... that would be two ways to accomplish the same thing with little gain. For now I'm -0 on the idea.

@nicoddemus
Copy link
Member

But by all means if other people think this is a good idea we should move this forward, of course,

@mhils
Copy link

mhils commented Feb 2, 2017

We use these kind of assertions quite a lot - IMHO, a declarative "we expect this error with this message" style would be a bit nicer than the current

    with pytest.raises(ValueError) as excinfo:
        myfunc()
    excinfo.match(r'.* 123 .*')

construct where our expectations about the error object are split before and after the statement. It might just be me, but I'm always slightly irritated by using excinfo after the with context is closed.

@RonnyPfannschmidt
Copy link
Member

im +1 on having match as kwarg and encouraging its usage over exceptioninfo

@nicoddemus
Copy link
Member

@mhils thanks for the feedback, appreciate it!

@RonnyPfannschmidt OK then, let's go ahead with it. 👍

I would just suggest to call the keyword argument match so it matches (:grin:) the excinfo method.

with pytest.raises(ValueError, match=r'.* 123 .*'):
    myfunc()

@Kriechi
Copy link
Contributor Author

Kriechi commented Feb 2, 2017

At the moment this PR only does substring matching 'foo' in 'foobar'.
Do you think Regex-based matching makes sense here?
I'm happy to amend this PR to also handle regex's!

@nicoddemus
Copy link
Member

Do you think Regex-based matching makes sense here?
I'm happy to amend this PR to also handle regex's!

I think so, mostly to be consistent with excinfo.match.

@nicoddemus
Copy link
Member

@Kriechi also, it would be nice if you could review the relevant documentation and change the examples to use the new match keyword instead of excinfo.match as suggested by @RonnyPfannschmidt .

@Kriechi Kriechi force-pushed the raises-info branch 2 times, most recently from bc904f0 to 9377784 Compare February 2, 2017 15:55
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.005%) to 92.719% when pulling bc904f0 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.002%) to 92.722% when pulling 9377784 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

int('asdf')

msg = "with base 16"
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for mind-bending fun we could nest pytest.rasies here 🤣

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done 😃

Copy link
Member

@RonnyPfannschmidt RonnyPfannschmidt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done, good work :)

@coveralls
Copy link

Coverage Status

Coverage increased (+0.008%) to 92.732% when pulling 6170607 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.008%) to 92.732% when pulling 79ec87f on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@@ -1246,6 +1260,11 @@ def __exit__(self, *tp):
suppress_exception = issubclass(self.excinfo.type, self.expected_exception)
if sys.version_info[0] == 2 and suppress_exception:
sys.exc_clear()
if self.match_expr:
try:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this bare try/except makes me a little uneasy... why is it needed? Wouldn't be enough to just call self.excinfo.match(self.match_expr)?

if self.match_expr:
    self.excinfo.match(self.match_expr)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure how to handle this properly, because ExceptionInfo.match raises an AssertionError if no match is found, but we want to call pytest.fail in that case...
Is there a better way of handling this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just calling self.excinfo.match should be enough, as this will produce the same behavior as:

with pytest.raises(...) as excinfo:
    func()
excinfo.match(text)

Or am I missing something?

I guess one issue in that case is that the traceback will point to pytest's internals, but to prevent that we just need to declare a __tracebackhide__ variable:

__tracebackhide__ = True
if self.match_expr:
    self.excinfo.match(self.match_expr)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The __tracebackhide__ is already there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks! 👍

CHANGELOG.rst Outdated
@@ -13,6 +13,9 @@ New Features
* ``pytest.warns`` now checks for subclass relationship rather than
class equality. Thanks `@lesteve`_ for the PR (`#2166`_)

* ``pytest.raises`` now asserts that the error message matches a text or regex
with the `match` keyword argument. Thanks `@Kriechi`_ for the PR.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nitpick, but "match" should be surrounded by double back ticks to get a monospaced font, like you did with "pytest.raises"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - fixed now.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.008%) to 92.732% when pulling 3c4c6f0 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Kriechi for the patience and following through with the PR! 👍

I will merge as soon as CI passes!

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling 43662ce on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

Copy link
Member

@The-Compiler The-Compiler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this turned out, definitely also prefer this more declaritive/simple API! Just a simple fix for Python 2.6 left, LGTM otherwise.

int('asdf')

msg = "with base 16"
expr = r"Pattern '{}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be {0} for Python 2.6 compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, pushed a quick fix. 👍

@The-Compiler
Copy link
Member

oh, right - I always forget about that "maintainers can push too" feature 😄

@coveralls
Copy link

Coverage Status

Coverage increased (+0.006%) to 92.73% when pulling abbff68 on Kriechi:raises-info into 3b47cb4 on pytest-dev:features.

@nicoddemus nicoddemus merged commit 208fae5 into pytest-dev:features Feb 3, 2017
@Kriechi Kriechi deleted the raises-info branch February 3, 2017 09:02
@RonnyPfannschmidt
Copy link
Member

the py26 env broke due to a zero-length format spec

@RonnyPfannschmidt
Copy link
Member

RonnyPfannschmidt commented Feb 3, 2017

whops, reload lag, sorry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants