Is there a way to force a Python 3 unittest to fail, rather than simply print a warning to stderr, if it causes any ResourceWarning?
I've tried the following:
import warnings
warnings.simplefilter(action='error', category=ResourceWarning)
Which results in this output from unittest:
my_test (__main__.MyTest) ... Exception ignored in: <socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54065), raddr=('127.0.0.1', 27017)>
ResourceWarning: unclosed <socket.socket fd=9, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 54065), raddr=('127.0.0.1', 27017)>
ok
----------------------------------------------------------------------
Ran 1 test in 0.110s
Note the "Exception ignored" message. I'd rather the test failed, instead of requiring me to read its output looking for ResourceWarnings.
anywhere in your code for a run time error to occur, specifically in this case a ZeroDivisionError: integer division or modulo by zero . This is the simplest way to get an exception by embedding something in your code (as you mentioned in your post). You can of course raise your own Exceptions too ..
How do you hide errors in Python? Use the filterwarnings() Function to Suppress Warnings in Python. Use the -Wignore Option to Suppress Warnings in Python. Use the PYTHONWARNINGS Environment Variable to Suppress Warnings in Python.
In Python 3. x, str(e) should be able to convert any Exception to a string, even if it contains Unicode characters.
Here's a unit test that fails if ResourceWarning
is generated by the code in with catch_warning()
statement:
#!/usr/bin/env python3
import gc
import socket
import unittest
import warnings
class Test(unittest.TestCase):
def test_resource_warning(self):
s = socket.socket()
####s.close() #XXX uncomment to pass the test
# generate resource warning when s is deleted
with warnings.catch_warnings(record=True) as w:
warnings.resetwarnings() # clear all filters
warnings.simplefilter('ignore') # ignore all
warnings.simplefilter('always', ResourceWarning) # add filter
del s # remove reference
gc.collect() # run garbage collection (for pypy3)
self.assertFalse(w and str(w[-1])) # test fails if there
# are warnings
if __name__=="__main__":
unittest.main()
Unfortunately, it doesn't appear to be possible. That "Exception ignored in:" message is produced by the CPython function PyErr_WriteUnraisable
in Python/errors.c
. The comment before that function states:
/* Call when an exception has occurred but there is no way for Python
to handle it. Examples: exception in __del__ or during GC. */
The ResourceWarning
is indeed being generated during garbage collection, and Python prints a message because it doesn't have a way to raise an exception at that point. This has to do with the core CPython implementation and there is nothing that unittest can do to override it.
Update: while the above is a correct technical analysis, there is another approach that will actually solve the OP's problem. See the answer by J.F. Sebastian for more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With