【问题标题】:Unit-test a method wrapper对方法包装器进行单元测试
【发布时间】:2012-11-07 17:17:52
【问题描述】:

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

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 的每个子类编写测试,可能有很多情况。这也意味着对子类的耦合测试与对基类方法的测试。

【问题讨论】:

    标签: python unit-testing


    【解决方案1】:

    您将对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 是否确实使用预期的 param 值调用了 do_run

    【讨论】:

    • objectundertest 应该怎么做? BaseAction() (可能是一种抽象类)?一个子类?
    • @liori:我扩展了一点;子类BaseAction() 仅用于单元测试。这使您可以单独关注基类单元。
    【解决方案2】:

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

    但是,一种可能性是重组您的代码以使验证发生在不属于基类的函数/类中。也许实际运行动作的类本身可以检查那些......

    class Jump(object):
        def run(self, param):
            ...
    
    def run_action(action, param):
        if not is_valid(param):
            raise ValueError(…)
    
        return action.run(param)
    

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

    【讨论】:

    • 是的,这个公式使它更明确。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多