4

我正在编写一个测试套件,而我正在测试的代码过度使用延迟的模块导入。所以有可能对同一个方法有 5 个不同的输入,这最终可能会导入 5 个额外的模块。我想做的是设置测试,以便我可以断言使用一个输入运行该方法会导致一个导入,而不会导致其他 4 个。

我有一些关于如何开始的想法,但到目前为止还没有一个成功的。我已经有一个自定义导入器,我可以将日志记录代码放在导入器中。但这不起作用,因为 import 语句只运行一次。无论模块之前是否已导入,我都需要执行日志语句。只是运行del sys.modules['modname']也不起作用,因为它在测试代码中运行,并且我无法在正在测试的代码中重新加载模块。

我尝试的下一件事是子类dict化来进行监控,并用这个子类替换 sys.modules。这个子类有一个重新实现的__getitem__方法,但是调用import module似乎不会触发__getitem__子类中的调用。我也不能直接分配给sys.modules.__getitem__,因为它是只读的。

我想要做的甚至可能吗?

更新

nneonneo 的答案似乎仅在 的实现与logImports()使用它的模块位于同一模块中时才有效。如果我创建一个包含此功能的基本测试类,它就会出现问题。首先是它找不到 just __import__,错误如下:

#     old_import = __import__
# UnboundLocalError: local variable '__import__' referenced before assignment

当我将其更改为 时__builtin__.__import__,出现另一个错误:

我的单元测试.py:

import unittest
class TestCase(unittest.TestCase):
    def logImports(self):
        old_import = __builtins__.__import__
        def __import__(*args, **kwargs):
            print args, kwargs
            return old_import(*args, **kwargs)

        __builtins__.__import__ = __import__

测试.py:

import myunittest
import unittest
class RealTest(myunittest.TestCase):
    def setUp(self):
        self.logImports()
    def testSomething(self):
        import unittest
        self.assertTrue(True)
unittest.main()

#     old_import = __builtins__.__import__
# AttributeError: 'dict' object has no attribute '__import__'
4

2 回答 2

4

尝试

old_import = __import__
def __import__(*args, **kwargs):
    print args, kwargs
    return old_import(*args, **kwargs)

__builtins__.__import__ = __import__

这完全覆盖__import__,允许您监视import.

于 2012-09-17T22:33:20.520 回答
-1

基于先前的答案,在 Python 3 中,我在以下方面取得了成功。

import builtins
old_import = __import__

def importWithLog(*args, **kwargs):
    print(args[0]) # This is the module name
    print(args, kwargs)
    return old_import(*args, **kwargs)

builtins.__import__ = importWithLog

# Rest of the code goes here.
import time
import myModule
...
于 2021-05-17T15:15:07.837 回答