2011-09-29 36 views
3

我有一个使用RealClass的模块,所以它是我无法访问的内部依赖项。如何在Python模块中对类进行桩测试?

我希望能够创建一个FakeClass来替代RealClass的测试功能。我不想取代个别方法,而是取代整个班级。

我看着stubble这似乎是我想要的,但我想知道如果mox或任何其他嘲笑框架有这个功能?或者你会建议使用什么?也许fudge,猴子补丁?只是寻找这些东西的最佳做法。另外任何有用的例子都会很棒。

伪代码:

from module import RealClass 

class FakeClass 
    methodsFromRealClassOverridden 

class Test(unittest.TestCase): 
    setup() 
    teardown() 

test1() 
    stub(RealClass, FakeClass) // something like this, but really just want the functionality 
    classThatUsesRealClass // now will use FakeClass 

UPDATE:

这里有一种方法我发现做到这一点。这不是完美的,但它的工作原理。

例子:

fake = FakeClass() 
stub = stubout.StubOutForTesting() 
stub.Set(RealClass, 'method_1', fake.method_1) 
stub.Set(RealClass, 'method_2', fake.method_2) 
+0

你也许看看'嘲讽'也 – Daenyth

+0

我并不真的需要嘲笑,不需要验证方法被称为等,真的只需要存根功能。 – dre

+0

会像'从FakeClass导入FakeClass作为RealClass'吗? –

回答

6

我想你想的意见/经验,所以我只是给我的2美分。

正如你所注意到的那样,有一些Python测试工具/类/框架,但大多数时候考虑到Python的简单性/动态性/开放性,你将限制自己使用临时相关测试用例,接口级别和一些unittest ...直到你开始使用框架。

没有什么贬义约猴子修补,尤其是当它涉及到进行测试/存根:

#!/usr/bin/env python 
# minimal example of library code 

class Class: 
    """ a class """ 
    def method(self, arg): 
     """ a method that does real work """ 
     print("pouet %s" % arg) 

#!/usr/bin/env python 
# minimal example for stub and tests, overriding/wrapping one method 
from Class import Class 

Class._real_method = Class.method 
def mymethod(self, arg): 
    # do what you want 
    print("called stub") 
    # in case you want to call the real function... 
    self._real_method(arg) 
Class.method = mymethod 

# ... 

e = Class() 
e.method("pouet") 

命名空间可以让你修补的东西导入模块内的导入模块内...

请注意,上述方法不适用于C模块中的类。 对于他们,您可以使用一个包装类,它使用getattr/setattr过滤类成员名称,并从包装类返回重新定义的成员。

#!/usr/bin/env python 
# Stupid minimal example replacing the sys module 
# (not very useful/optimal, it's just an example of patching) 

import sys 

class SysWrap(): 
    real = sys 
    def __getattr__(self, attr): 
     if attr == 'stderr': 
      class StdErr(): 
       def write(self, txt): 
        print("[err: %s]" % txt) 
      return StdErr() 
     print("Getattr %s" % attr) 
     return getattr(SysWrap.real, attr) 

sys = SysWrap() 
# use the real stdout 
sys.stdout.write("pouet") 
# use fake stderr 
sys.stderr.write("pouet") 

一旦你变得疲倦进行即席测试,你会发现更高层次的东西比如你提到的(茬,软糖)有用的,但享受他们和有效地使用他们,你必须首先看到他们解决的问题,并接受他们在引擎盖下做的所有自动化的东西。

临时猴子补丁的一部分很可能会保留下来,只是更容易理解,而且所有工具都有一些限制。

工具赋予你权力,但你必须深刻理解他们才能有效地使用它们。

当决定是否使用工具时,一个重要的方面是当您传输一段代码时,传输整个环境(包括测试工具)。 下一个人可能不像你那么聪明,并且跳过测试,因为你的测试工具对他来说太复杂了。 通常你想避免在你的软件中使用很多依赖。

最后,我想如果你只是使用单元测试和临时测试/猴子补丁,只要你的东西有效,没有人会打扰你。 您的代码可能不是无论如何。

+0

感谢您的信息和示例,我面临的问题是,在您的示例中,sys模块在另一个模块/类中调用,但在unittest中,我无法直接创建sys模块。 – dre

相关问题