[pytest-dev] how to fail on exceptions in other threads and destructors
Nikolaus Rath
Nikolaus at rath.org
Mon Jun 3 19:30:49 CEST 2013
On 06/03/2013 02:42 AM, holger krekel wrote:
> Hi Nikolaus,
>
> On Sat, Jun 01, 2013 at 14:41 -0700, Nikolaus Rath wrote:
>> Hello,
>>
>> I would like to make sure that a test fails when it results in an
>> uncaught exception - even if the exception happens in a destructor or in
>> a separate thread.
>>
>> What's the best way to do this?
>>
>> My idea is to modify sys.excepthook such that it keeps a list of all the
>> exceptions encountered during a test run. Then, at the end of every
>> test, I could check this list and raise an exception if there were any
>> calls to sys.excepthook.
>>
>> However, I'm not quite sure how to do this properly without having to
>> request an explicit fixture in every test. Is there a way to have
>> initialization and finalization code run for every test function? And
>> what kind of exception would I need to raise in the finalization code
>> for py.test to recognize that it is the test that failed (rather than a
>> bug in the finalization code)?
>
> You could use an "autouse" fixture which gets called without naming
> the fixture in test/fixture function arguments.
Ah, that's useful. Thanks for the pointer!
> To fail the actual test, you might look into implementing the
> pytest_pyfunc_call() hook. It is responsible for calling a python test
> function. You would want to wrap the existing hook implementation and
> add your exception-detection logic like this:
>
> # content of conftest.py in your testing dir
>
> import pytest
>
> @pytest.mark.tryfirst
> def pytest_pyfunc_call(__multicall__):
> ret = __multicall__.execute() # if this raises we don't care
> # perform extra checks and raise if there is a problem
> return ret # return whatever our wrapped hook impl returns
>
> The ``__multicall__`` bit is for interacting with other hook
> implementations so that we don't have to replicate their logic.
> You could also use the "pytest_runtest_call" hook if you
> also have doctests or other non-function types of tests.
Could you elaborate on the difference between pytest_pyfunc_call and
pytest_runtest_call? The former doesn't seem to be mentioned anywhere in
the docs. (Some of my tests are unittest.TestCases.)
I'm also not sure about the tryfirst decorator. Why is that needed? Do I
also need it when using pytest_runtest_call?
As a side note, I just tried to set up something based on an autouse
fixture and found that sys.excepthook is ignored both for threads and
destructors. There is a workaround for threads
(http://bugs.python.org/issue1230540), but __del__ seems to be a
hopeless case -- I believe it prints directly to stderr from C code. So
what I'll try instead is to make my extra tests check if a test resulted
in any (or maybe any suspicious) output to stderr.
Best,
Nikolaus
More information about the Pytest-dev
mailing list