【问题标题】:Conflict between Pandas and Unittest?熊猫和单元测试之间的冲突?
【发布时间】:2016-12-09 20:12:22
【问题描述】:

考虑以下代码块(在 Jupyter 笔记本中开发),由于未触发 UserWarning,因此预计会引发 AssertionError

%%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)

对于那些不熟悉 jupyter notebooks 的人来说,第一行只是将以下所有行导出到指定的文件中。

现在如果我执行命令:

python3 tests.py

从终端(我在 Ubuntu 14.04 上使用 Python 3.5.1),我得到一个 Runtime Error - 堆栈跟踪如下:

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)

显然结果不如预期。但是,我注意到以下任一选项都获得了预期的结果。

  1. %%writefile ... 注释掉第一行并使用 Jupyter 笔记本(使用相同的 Python 解释器)运行代码 sn-p。
  2. 注释掉import pandas as pd 行并使用之前给出的命令从终端运行。

有人明白这里发生了什么吗?

供参考,unittest模块中case.py中的相关行是

for v in sys.modules.values():
    if getattr(v, '__warningregistry__', None):
        v.__warningregistry__ = {}

这似乎是良性代码(我也认为它已经过足够的测试,可以说它不是问题的根源)。

【问题讨论】:

  • 你有没有设法追根究底?
  • 不,我不得不使用解决方法:(
  • 我无法复制这个。此外,问题的描述令人费解且无益于您编写它的方式。当将代码作为脚本运行 (tests.py) 和在笔记本中运行代码时,会发生不同的行为。
  • 而且错误似乎是在循环期间正在修改sys.modules。我不知道是什么原因造成的。如果可能,请发布您的解决方法
  • 如果您注释最后两行并从命令行运行测试如下:python -m unittest tests.py?

标签: python-3.x pandas python-unittest


【解决方案1】:

此错误已提交至Python's bug tracker

问题在于在unittest.case._AssertWarnsContext.__enter__() 中迭代sys.modules 并访问每个模块的__warningregistry__ 属性。在此访问中,类模块对象可以执行任意操作,包括导入扩展 sys.modules 的其他模块。

sys.modules 是一个将模块名称映射到已加载模块的字典。

这个问题很难重现,因为有“something platform dependent”关于测试运行程序如何排序测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多