使用Python 3在unittest中测试未知模块

时间:2013-08-02 09:33:02

标签: python unit-testing python-3.x python-import

我观察到Python 3 unittest的奇怪行为。在函数testValue中测试用例测试不存在的模块。

import sys
import unittest

class ModuleTest(unittest.TestCase):

    def testValue(self):
        import unknown_module
        result = unknown_module.value

        self.assertEqual(0.0, result)


if __name__ == "__main__":
    print(sys.version)
    unittest.main()

Python2正确地给出了以下输出:

2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)]
E
======================================================================
ERROR: testValue (__main__.ModuleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\bin\WinPython-64bit-2.7.5.1\workspace\unknown_module_test.py", line 7, in testValue
    import unknown_module
ImportError: No module named unknown_module

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)

但是当引用unknown_module.value时,Python 3声称存在AttributeError。

3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (Intel)]
E
======================================================================
ERROR: testValue (__main__.ModuleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "unknown_module_test.py", line 8, in testValue
    result = unknown_module.value
AttributeError: 'module' object has no attribute 'value'

----------------------------------------------------------------------
Ran 1 test in 0.016s

FAILED (errors=1)

为什么不像Python 2那样抛出Python 3 ImportError

1 个答案:

答案 0 :(得分:3)

您正在导入隐式命名空间包。引自Python 3.3 What's New page

  

对不需要__init__.py标记文件的包目录的本机支持,并且可以自动跨越多个路径段(受各种第三方方法命名空间包的启发,如PEP 420中所述)

PEP 420 Implicit Namespace Packages

  

如果扫描完成而未返回模块或包,并且至少记录了一个目录,则会创建命名空间包。新的命名空间包:

     
      
  • __path__属性设置为扫描期间找到并记录的可迭代路径字符串。
  •   
  • 没有__file__属性。
  •   

  

命名空间包和常规包非常相似。不同之处是:

     
      
  • 命名空间包的部分不一定都来自相同的目录结构,甚至来自同一个加载器。常规包是自包含的:所有部分都存在于同一目录层次结构中。
  •   
  • 命名空间包没有__file__属性。
  •   
  • 命名空间包'__path__属性是字符串的只读可迭代,在修改父路径时会自动更新。
  •   
  • 命名空间包没有__init__.py模块。
  •   
  • 命名空间包为__loader__属性提供了不同类型的对象。
  •   

unknown_module中删除sys.path目录,您的测试将会像在早期Python版本中那样失败。