Consider the following block of code (developed inside a Jupyter notebook), for which it is expected that an AssertionError is raised because a UserWarning is not triggered:
%%writefile Game/tests/tests.py
import unittest
import pandas as pd
class TestGame(unittest.TestCase):
def test_getters(self):
print('Just before the critical line.')
with self.assertWarns(UserWarning):
print('Just testing...')
suite = unittest.TestLoader().loadTestsFromTestCase(TestGame)
unittest.TextTestRunner().run(suite)
For those unfamiliar with jupyter notebooks, the first line simply exports all following lines into the specified file.
Now if I execute the command:
python3 tests.py
from the terminal (I am using Python 3.5.1 on Ubuntu 14.04), I get a Runtime Error - the stack trace follows:
Just before the critical line:
E
======================================================================
ERROR: test_getters (__main__.TestGame)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 8, in test_getters
with self.assertWarns(UserWarning):
File "/opt/anaconda3/lib/python3.5/unittest/case.py", line 225, in __enter__
for v in sys.modules.values():
RuntimeError: dictionary changed size during iteration
----------------------------------------------------------------------
Ran 1 test in 0.004s
FAILED (errors=1)
Obviously the results are not as expected. However, I notice that either of the following options gets the expected results.
%%writefile ... and running the code snippet with the Jupyter notebook (which uses the same python interpreter).import pandas as pd line and running from terminal with the previously given command.Does anyone understand what's going on here?
For reference, the relevant lines in case.py in the unittest module are
for v in sys.modules.values():
if getattr(v, '__warningregistry__', None):
v.__warningregistry__ = {}
which would seem to be benign code (which I would also presume is tested enough to say that it's not the source of the problem).
This bug has been filed on Python's bug tracker.
The problem is in the iteration over
sys.modulesinunittest.case._AssertWarnsContext.__enter__()and accessing every module's__warningregistry__attribute. On this access, the module-like objects may perform arbitrary actions including importing of further modules which extendssys.modules.
sys.modules is a dict mapping module names to loaded modules.
This problem is difficult to reproduce because there's "something platform dependent" about how the test runner orders the tests.
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