保存重载的Python模块以进行测试目的

时间:2014-01-10 19:40:28

标签: python reload python-2.6 python-2.x python-unittest

我正在测试一个Python模块,并且由于模块的工作方式(它在导入时进行了一些初始化)已经在测试初始化​​的每个unittest期间重新加载模块。 reload是在setUp方法中完成的,因此所有测试实际上都在重新加载模块,这很好。

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

围绕SO有类似问题,例如this one,但这些问题都涉及重新加载后更新对象。我想要做的是在初始导入后保存模块的状态,运行我执行所有重新加载的测试,然后在测试discover中将初始引用放回模块以便测试使用该模块的下游运行仍然具有正确的引用。请注意,我没有对模块进行任何更改,我只是重新加载它以测试它所做的一些初始化部分。

还有一些解决方案包含我不感兴趣的模块代码中的钩子。我不想让开发人员将内容推送到代码库中,以便测试可以运行。我使用的是Python 2.6和tearDown。我看到有些项目存在,如process-isolation,虽然我不确定这是否完全符合我的要求,但它不适用于Python 2.6,我不想在我们的堆栈中添加新包。可能。存根代码如下:

unittest

1 个答案:

答案 0 :(得分:0)

不幸的是,没有简单的方法可以做到这一点。如果你的模块的初始化有副作用(并且通过它的外观 - 钩子等),没有自动的方法来撤消它们,没有完全重新启动Python进程。

类似地,如果代码中的任何内容从模块而不是模块本身导入(例如from my_package.my_module import some_object而不是import my_package.my_module),则重新加载模块将不会对导入的对象执行任何操作({ {1}}将引用执行some_object语句时引用的my_package.my_module.some_object,无论您重新加载什么以及磁盘上有什么内容。

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

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

如果您的模块的初始化副作用有限,您可以尝试使用Nose而不是Unittest运行测试(测试兼容,您不必重写任何内容),其Isolate插件尝试执行您想要的操作: http://nose.readthedocs.org/en/latest/plugins/isolate.html

但由于我上面所说的,所以不能保证在一般情况下工作。