单元测试方法包装器

时间:2012-11-07 17:17:53

标签: python unit-testing

我有一组共享一些基本检查的动作。我的代码如下所示:

def is_valid(param): …some pretty complex things unit-tested on their own…

class BaseAction(object):
    def run(self, param):
        if not is_valid(param):
            raise ValueError(…)

        return self.do_run(param)

class Jump(BaseAction):
    def do_run(self, param): …

class Sing(BaseAction):
    def do_run(self, param): …

我应该如何对BaseAction.run执行验证的事实进行单元测试?

我想我可以对Jump.run和Sing.run进行单元测试,但是为了正确地完成它,我需要为BaseAction的每个子类编写测试,可能有很多情况。这也意味着子类的耦合测试与基类方法的测试。

2 个答案:

答案 0 :(得分:2)

您将对is_valid()函数本身进行单元测试。然后,您只需测试.run()在传递无效输入时引发ValueError异常的事实:

with self.assertRaises(ValueError):
    objectundertest.run(invalid_parameter)

由于您已经为is_valid()本身进行了单元测试,因此.run()的单元测试无需关注其功能。您可以专注于.run()独有的功能。

在您的情况下,BaseAction是一个向子类提供服务的单位;我将它测试为一个模拟子类:

class MockAction(BaseAction):
    run_called = None

    def do_run(self, param):
        self.run_called = param

因此,您可以检查run是否确实称为do_run,其值为param

答案 1 :(得分:1)

如果您想将逻辑保留在Base类中,请参阅Martijn Pieters的回答。

但是,一种可能性是重构代码以使验证发生在不属于Base类的函数/类中。也许真正运行动作的类可以检查那些......

class Jump(object):
    def run(self, param):
        ...

def run_action(action, param):
    if not is_valid(param):
        raise ValueError(…)

    return action.run(param)

单元测试操作更容易(您不必担心基本逻辑),如果“BaseAction”以某种方式被破坏,它也不会破坏所有“跳转”单元测试。 “run_action”(如果你愿意的话,你可以把它变成一个类而不是一个函数)本身可以很容易地测试(你可以创建一个虚假的“Action”对象)。