如何在Python中的模块中存根类以进行测试?

2024-04-23 13:42:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个使用RealClass的模块,所以它是一个我无权访问的内部依赖项。

我希望能够创建一个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

更新:

这是我发现的一种方法。它不是完美的,但它是有效的。

示例:

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

Tags: 模块方法功能框架method建议fakeclass
1条回答
网友
1楼 · 发布于 2024-04-23 13:42:56

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

正如您所注意到的,有一些Python测试工具/类/框架,但是大多数情况下,考虑到Python的简单性/动态性/开放性,您将限制自己使用特别相关的测试用例,这些测试用例包括在接口级别执行stubing,以及一些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")

一旦你厌倦了执行特别的测试,你会发现更高层次的东西,比如你提到的那些有用的东西(胡茬,软糖),但是要享受它们并有效地使用它们,你必须首先看到它们解决的问题,接受它们在引擎盖下做的所有自动的事情。

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

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

决定是否使用工具的一个重要方面是,当您传输一段代码时,您将传输整个环境(包括测试工具)。 下一个家伙可能没有你聪明,因为你的测试工具对他来说太复杂了,所以就跳过了测试。 通常,您希望避免在软件中使用大量依赖项。

最后,我认为如果你只使用unittest和ad-hoc测试/monkey补丁,只要你的东西有效,没人会打扰你。 你的代码可能并不复杂。

相关问题 更多 >