| 2021-02-16
下面的测试用例遵循了 DRY 原则 (“Don’t Repeat Yourself”), 它是鼓励重用,消除重复的一个最佳实践,例如, 通过抽取 helper 函数 或 通过使用循环的方式。 但是,它真的是一个 写得好的测试用例?
def setUp(self):
# users 这个字段可以在多个测试用例中复用。
self.users = [User('alice'), User('bob')]
self.forum = Forum()
def testCanRegisterMultipleUsers(self):
self._RegisterAllUsers()
# 使用一个 for 循环 来验证所有用户都是已注册用户。
for user in self.users:
self.assertTrue(self.forum.HasRegisteredUser(user))
# 注册用户的 helper 方法,可在多个测试用例中复用.
def _RegisterAllUsers(self):
for user in self.users:
self.forum.Register(user)
虽然上面的测试用例是简洁的,但读者需要花上一些心力,才能更好地理解它。
比如,从 setUp() 方法,看 RegisterAllUsers()时,self.users 要跟踪到 setUp() 方法才知道。
因为测试用例本身通常是没有测试的,所以,人们必须要能做到:很容易地手动检查它们的正确性,即使是以更大的代码重复为代价。这意味 DRY 原则通常不适合于单元测试,尽管它是生产代码的最佳实践。
在这些测试用例中,我们可以使用**DAMP 原则 (即:Descriptive and Meaningful Phrases,描述性且有意义的短语)**, 它强调可读性要高于不重复性。使用这一原则可能会带来重复代码(例如,类似的代码片段),但是,它可能让测试的语义表达更加恰当。让我们使用 DAMP 对上面的测试用例改造一下:
def setUp(self):
self.forum = Forum()
def testCanRegisterMultipleUsers(self):
# 在测试用例中创建用户,而不是在 setUp() 中
user1 = User('alice')
user2 = User('bob')
# 在测试用例中进行注册,而不是使用 helper 方法,并且也不使用 for 循环。
self.forum.Register(user1)
self.forum.Register(user2)
# 一个一个的单独验证,而非使用 for 循环。
self.assertTrue(self.forum.HasRegisteredUser(user1))
self.assertTrue(self.forum.HasRegisteredUser(user2))
注意:
在测试用例中,DRY 原则仍然是有效的;
例如,使用 helper 函数创建值对象,从而把测试主体中的冗余细节抽取出来,从而使测试用例的表达更清晰。
“具有可读性且唯一性的测试代码”为最佳,但有时需要权衡。
在编写单元测试时,要在 DRY 和 DAMP 原则之间做出选择,应更倾向于 DAMP 原则。
发表时间:December 03, 2019
原文作者:Derek Snyder and Erik Kuefler
原文链接:谷歌TotT:让测试DAMP