2014-01-10 149 views
0

我有一个我正在测试的Python模块,并且由于模块工作的方式(它在导入时会进行一些初始化)已在每个unittest期间重新加载模块,初始化。 reloadsetUp方法中完成,所以所有的测试实际上是重新加载模块,这很好。保存重新加载的Python模块用于测试目的

如果我只在任何给定的Python会话期间在该文件中运行测试,这一切都很好,因为我从不需要对模块的前一个实例的引用。但是当我使用Pydev或unittestdiscover时,我得到的错误与here一样,因为导入此模块的其他测试已经失去了对模块中对象的引用,因为它们是在测试中的所有重新加载业务之前导入的。

也有类似的问题,比如this one,但这些都是在重新加载后处理更新对象。我想要做的是在初始导入之后保存模块的状态,运行我的测试来完成所有重新加载,然后在测试tearDown中将模块的初始引用放回,以便下游运行的测试使用该模块仍然有正确的参考。请注意,我没有对模块进行任何更改,我只是重新加载它来测试它所做的一些初始化部分。

还有一些解决方案在模块代码中包含钩子,我不感兴趣。我不想要求开发人员将代码推入代码库,以便测试可以运行。我正在使用Python 2.6和unittest。我发现有些项目的存在类似process-isolation,尽管我不确定这是否完全符合我的要求,但它不适用于Python 2.6,并且我不想在可能的情况下将新包添加到我们的堆栈。存根编号如下:

import mypackage.mymodule 
saved_module = mypackage.mymodule 

class SomeTestThatReloads(unittest.TestCase): 
    def setUp(self): 
     reload(mypackage.mymodule) 

    def tearDown(self): 
     # What to do here with saved_module? 

    def test_initialization(self): 
     # testing scenario code 

回答

0

不幸的是,没有简单的方法来做到这一点。如果你的模块的初始化有副作用(并且看起来它有 - 挂钩等),那么没有自动的方法来撤销它们,而不是完全重新启动Python进程。

同样,如果任何事情在你的代码进口的东西从你的模块,而不是模块本身(以下EG from my_package.my_module import some_object代替import my_package.my_module),重装模块将不会做任何事情来导入对象(some_object将把任何my_package.my_module.some_object简称当执行import语句时,无论您重新加载什么以及磁盘上有什么)。

所有问题都归结为Python的模块系统通过执行模块(其中充满了副作用,类/函数/变量的定义只是其中的一个),然后暴露顶层他们创建的变量,而Python VM本身将模块视为全局状态的一大块,没有隔离。

因此,您的问题,一般的解决方法是每次测试后重新启动一个新的Python进程(很烂:()。

如果你的模块的初始化副作用是有限的,你可以尝试运行测试鼻子而不是单元测试(测试是兼容的,你不必重写任何东西),其Isolate插件试图做你想做的:http://nose.readthedocs.org/en/latest/plugins/isolate.html

但它不能保证在一般情况下工作,因为我如上所述。