我有一组共享一些基本检查的动作。我的代码如下所示:
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的每个子类编写测试,可能有很多情况。这也意味着子类的耦合测试与基类方法的测试。
答案 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”对象)。