Skip to content

gh-102812: unittest's addError/addFailure/addSubTest accept an exception instance in addition to (typ, val, tb) as paramter #102814

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

Closed
wants to merge 3 commits into from

Conversation

iritkatriel
Copy link
Member

@iritkatriel iritkatriel commented Mar 18, 2023

…exception instance in addition to (typ, val, tb) as paramter
else:
result.addError(test, exc_info)
result.addError(test, exc)
Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe I should revert this change, in case there are use-defined subclasses of TestResult that expect the tuple?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think the folks still using unittest are often in interesting and subtle places (Twisted's trial springs to mind...) so I think we really want to make sure 100% backwards compatibility (even in internal APIs sigh) is preserved if at all possible.

I'm curious: where are you finding yourself calling addError and friends in your code?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not calling addError in my code. We're trying to remove the (typ, exc, tb) triplet from the language. The interpreter doesn't need it anymore, it only exists for backwards compatibility.

Copy link
Member Author

Choose a reason for hiding this comment

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

I made this a draft PR, it need more thought. If we can't make unittest use the new APIs then I'm not sure there is a point committing this. We would need a plan for how to migrate off the triplet.

This is related to the PEP707 discussion, so we could wait to see what comes out of that.

except _UnexpectedSuccess:
result.addFailure(self, sys.exc_info())
except _UnexpectedSuccess as e:
result.addFailure(self, e)
Copy link
Member Author

Choose a reason for hiding this comment

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

ditto.

self._createClassOrModuleLevelException(
result, exc_info[1], 'setUpClass', className,
info=exc_info)
err=exc)
Copy link
Member Author

Choose a reason for hiding this comment

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

ditto

Comment on lines +393 to +394
:meth:`~unittest.TestResult.addSubTest` now accept either an exception
instance or a ``(typ, val, tb)`` tuple. (Contributed by Irit Katriel in
Copy link
Member

@terryjreedy terryjreedy Mar 18, 2023

Choose a reason for hiding this comment

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

Make clear what is new while being clear that still only 1 is passed.

Suggested change
:meth:`~unittest.TestResult.addSubTest` now accept either an exception
instance or a ``(typ, val, tb)`` tuple. (Contributed by Irit Katriel in
:meth:`~unittest.TestResult.addSubTest` now accept an exception instead of
a ``(typ, val, tb)`` tuple. (Contributed by Irit Katriel in

Do you want to say that an exception is in some sense preferred?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think "instead of" may sound like the old format is no longer accepted. But agree I would emphasise what is new and what is old.

Comment on lines +78 to 81
if isinstance(err, subtest.failureException):
self._write_status(subtest, "FAIL")
else:
self._write_status(subtest, "ERROR")
Copy link
Member

@terryjreedy terryjreedy Mar 18, 2023

Choose a reason for hiding this comment

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

Factor out minimal difference in the two branches depending on the condition.

Suggested change
if isinstance(err, subtest.failureException):
self._write_status(subtest, "FAIL")
else:
self._write_status(subtest, "ERROR")
status = "FAIL" if isinstance(err, subtest.failureException) else "ERROR"
self._write_status(subtest, status)

There might be a better word than 'status'. Note: if the statement were not already being edited, this would be an unrelated change and I would not suggest it here. But since you are ...

Comment on lines +83 to 86
if isinstance(err, subtest.failureException):
self.stream.write('F')
else:
self.stream.write('E')
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if isinstance(err, subtest.failureException):
self.stream.write('F')
else:
self.stream.write('E')
dot = 'F' if isinstance(err, subtest.failureException) else 'E'
self.stream.write(dot)

error = _ErrorHolder(errorName)
addSkip = getattr(result, 'addSkip', None)
if addSkip is not None and isinstance(exception, case.SkipTest):
addSkip(error, str(exception))
else:
if not info:
result.addError(error, sys.exc_info())
if not err:
Copy link
Member

Choose a reason for hiding this comment

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

It is not clear why the assert it needed, but with it, a possible refactoring (which cannot be marked as a multi-line suggestion).

            if not err:
                err = sys.exc_info()[1]
            else:
                assert not isinstance(err, tuple)
            result.addError(error, err)

Comment on lines +3 to +4
:meth:`~unittest.TestResult.addSubTest` now accept either an exception
instance or a ``(typ, val, tb)`` tuple.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
:meth:`~unittest.TestResult.addSubTest` now accept either an exception
instance or a ``(typ, val, tb)`` tuple.
:meth:`~unittest.TestResult.addSubTest` now accept an exception instance
instead of a ``(typ, val, tb)`` tuple.

@iritkatriel iritkatriel marked this pull request as draft March 19, 2023 11:14
@cjw296 cjw296 removed their request for review June 9, 2023 13:02
Copy link
Member

@terryjreedy terryjreedy left a comment

Choose a reason for hiding this comment

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

My turn to ping ;-). Too late for 3.12 I guess, hence new suggestion(s). Please accept the suggestions you are sure of, and resolve when appropriate. I fixed the merge conflict (easy).


The default implementation appends a tuple ``(test, formatted_err)`` to
the instance's :attr:`errors` attribute, where *formatted_err* is a
formatted traceback derived from *err*.

.. versionchanged:: 3.12
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.. versionchanged:: 3.12
.. versionchanged:: 3.13


The default implementation appends a tuple ``(test, formatted_err)`` to
the instance's :attr:`failures` attribute, where *formatted_err* is a
formatted traceback derived from *err*.

.. versionchanged:: 3.12
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.. versionchanged:: 3.12
.. versionchanged:: 3.13


The default implementation does nothing when the outcome is a
success, and records subtest failures as normal failures.

.. versionadded:: 3.4

.. method:: addDuration(test, elapsed)
.. versionchanged:: 3.12
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
.. versionchanged:: 3.12
.. versionchanged:: 3.13

@iritkatriel
Copy link
Member Author

Thanks, @terryjreedy . I have some doubts about this PR because I think there might be user-defined subclasses of unittest that override these functions (essentially callbacks expecting (typ, exc, tb) triplets). I'm not sure how to move us on from that.

@iritkatriel
Copy link
Member Author

Closing because I think this is more complicated than I thought. (See previous comment).

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

Successfully merging this pull request may close these issues.

4 participants