单元测试:测试父对象方法有意义吗?
假设我在使用一个框架,这个框架里有一个叫做Animal的类。
class Animal(object):
def speak(self):
logging.info(self.sound)
为了使用这个类,我需要创建一个它的子类,可能看起来像这样:
class Dog(Animal):
def __init__(self):
self.sound = 'Woof Woof'
我觉得我可以做两件事情。第一种方法是这样做:
dog = Dog()
assert dog.sound == 'Woof Woof'
第二种选择是模拟一下logging.info,看看它有没有被调用。我对这两种方法都有些犹豫。
第一种方法让我感觉像是在测试我的配置,而第二种方法又让我觉得我并没有真正测试我想要的对象。
我用这个简单的例子是因为我希望那些不使用Django的人能给我一些建议。其实我遇到的真正问题是关于Django的通用视图。
比如说,我可以有这样一个模板视图:
class HomeView(TemplateView):
template_name = 'home.html'
我应该只是测试template_name是否有正确的值,还是用测试客户端做一个更高级的测试,来测试整个视图呢?
3 个回答
1
你展示的测试是完全正确的——你在测试中重复了字符串 'Woof Woof'
。
你也可以为 Animal
做一个类似的测试:
animal = Animal()
animal.sound = 'sound'
animal.speak()
# test that detects log contains 'sound'
你还可以做一个测试,传入一个动物的列表,比如 [Dog, Cat, ...]
,然后检查每个动物实例是否能发出它们各自的声音。
for animalClass in AnimalList:
animal = animalClass()
animal.speak()
# test that detects log contains animal.sound
3
在你这个简单的例子中,我可能会测试父类的方法。但是在你提到的Django的情况下,这就意味着要测试Django本身。而这不是你的工作!;-) 对我来说,这就是单元测试的一个大问题:不要去测试别人写的代码或者第三方的库。要确保你自己写的部分是正确的。这听起来可能很明显,但在实际操作中并没有那么简单——至少在我的经验里是这样。
5
不,确保父对象经过了正确的测试(如果需要,可以使用模拟技术),并且要单独测试子对象的方法。这符合封装的概念(把事情局部化)。
如果不这样做,一个包含很多类的大项目会耗尽你所有的编码资源,但并没有带来额外的价值。