Pytest should by default terminate on exceptions that inherit from BaseException and related changes to exception handling #3702
Labels
type: proposal
proposal for a new feature, often to gather opinions or design the API around the new feature
Uh oh!
There was an error while loading. Please reload this page.
At the moment if I use the signal module to catch SIGTERM and raise an exception, like the Python interpreter does by default for SIGINT and KeyboardInterrupt, sending SIGTERM will only cause one test to fail: pytest will catch the exception and continue running tests. This seems like the wrong behavior to me: there should be way to raise an exception that pytest won't continue on that isn't KeyboardInterrupt.
The reason I want to do this is that Jenkins, when it aborts a job, seems to send SIGTERM to its subprocesses, and when I abort a job, I almost always want the test clean-up code to run. I could call
pytest.exit
, except that then the signal handler is only useful when pytest itself is running, not when other Python code is running. I could write two signal handlers, one for pytest and one for everything else and then try to make sure that the correct signal handler is always set (note that the pytest signal handler also has to ensure that clean up is run outside pytest as well), or do stack introspection in the signal handler to try to determine if pytest is running, but both of those solutions look fragile and hard to get right; complexity is the last thing I want in my signal-handling code. I could raise KeyboardInterrupt, but KeyboardInterrupt when directly raised in code that pytest is executing causes pytest to terminate without running clean-up, unlike when SIGINT is sent to the Python interpreter, which defeats the purpose. This would also overload KeyboardInterrupt, which seems like bad style to me: KeyboardInterrupt should mean SIGINT, not other termination signals.It seems to me the natural way to get Python to do clean-up correctly when handling SIGTERM is the way KeyboardInterrupt is handled by default, raise an exception. Thus, I'd propose that:
pytest should terminate on exceptions that inherit from BaseException, except for GeneratorExit. (This doesn't normally terminate the interpreter.) Of the built-in exceptions, this means only SystemExit and KeyboardInterrupt.
pytest.raises should remain able to catch SystemExit, KeyboardInterrupt, and other exceptions that inherit from BaseException and not terminate, so there's still a way to test expected instances of those exceptions, while allowing unexpected instances to cause pytest to exit.
pytest should allow clean-up code to run when KeyboardInterrupt is raised in Python code rather than via a signal for consistency in behavior.
(All my testing was done on pytest 3.6.0).
The text was updated successfully, but these errors were encountered: