使这个测试更可读
做为一条普遍的测试原则,你应当“对使用者隐去不重要的细节,以便更重要的细节会更突出”。
前一节中的测试代码明显违反了这条原则。该测试的所有细节都摆在那里,比如像建立一个vector<ScoredDocument>这样不重要的细枝末节。例子中大部分代码都包含url、score和docs[],这些只是背后的C++对象如何创建的细节,不是关于所测试内容的高层次描述。
作为清理这些代码的第一步,可以创建一个这样的辅助函数:
使用这个函数,测试代码变得紧凑一点了:
但是它还是不够好——在我们面前还是有不重要的细节。例如,参数"http://example.com"看着很不自然。它每次都是一样的,而且具体URL是什么根本没关系——只要填进一个有效的ScoredDocument就可以了。
我们被迫要看的另一个不重要的细节是docs.resize(5)和&docs[0]、&docs[1]等。让我们修改辅助函数来做更多事情,并给它命名为AddScoredDoc():
使用这个函数,测试代码更紧凑了:
这段代码已经好多了,但仍然不满足“高度易读和易写”测试的要求。如果你希望增加一个测试,其中用到一组新的scored docs,这会需要大量的拷贝和粘贴。那么,我们怎么样来进一步改进它呢?
创建最小的测试声明
要改进这段测试代码,让我们使用从第12章学来的技巧。让我们用自然语言来描述我们的测试要做什么:
如你所见,在描述中没有在任何地方提及vector<ScoredDocument>。这里最重要的是分数数组。理想的情况下,测试代码应该看起来这样:
我们可以把这个测试的基本内容精练成一行代码!
然而这没什么大惊小怪的。大多数测试的基本内容都能精练成“对于这样的输入/情形,期望有这样的行为/输出”。并且很多时候这个目的可以用一行代码来表达。这除了让代码紧凑而又易读,让测试的表述保持很短还会让增加测试变得很简单。
实现定制的“微语言”
注意到CheckScoresBeforeAfter()需要两个字符串参数来描述分数数组。在较新版本的C++中,可以这样传入数组常量:
因为当时我们还不能这么做,所以我们就把分数都放在字符串中,用逗号分开。为了让这个方法可行,CheckScoresBeforeAfter()就不得不解析这些字符串参数。
一般来讲,定义一种定制的微语言可能是一种占用很少的空间来表达大量信息的强大方法。其他例子包含printf()和正则表达式库。
在本例中,编写一些辅助函数来解析用逗号分隔的一系列数字应该不会非常难。下面是CheckSocresBeforeAfter()的实现方式:
为了更完善,下面是用来在string和vector<ScoredDocument>之间转换的辅助函数:
乍一看这里有很多代码,但是它能带给你难以想象的能力。因为你可以只调用CheckScoresBeforeAfter()一次就写出整个测试,你会更倾向于增加更多的测试(就像我们在本章后面要做的那样)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论