我对单元测试有点困惑。我看到了自动化测试等方面的价值。我想也许一个很好的例子是帮助我理解的最好方法。假设我有一个二元搜索功能,我想要进行单元测试。
现在在测试中,我想知道的事情:搜索是否找到第一个元素,最后一个元素和其他元素?搜索是否正确比较unicode字符。搜索是否处理符号和其他“痛苦”字符。单元测试会覆盖这个,还是我错过了?您如何为我的二分查找编写单元测试?
function search(collection, value){
var start = 0, end = collection.length - 1, mid;
while (start <= end) {
mid = start + ((end - start) / 2);
if (value == collection[mid])
return mid;
if (collection[mid] < value)
end = mid - 1;
else
start = mid + 1;
}
return mid;
}
单位测试的Psuedo代码很可爱。
所以,我们可能会:
function testFirst(){
var collection = ['a','b','c','x','y','z'],first = 'a', findex = 0;
assert(seach(collection,first),findex);
}
function testLast(){
var collection = ['a','b','c','x','y','z'], last = 'z', lindex = 5;
assert(seach(collection,last),lindex);
}
答案 0 :(得分:3)
不,你没有错过它,这就是单元测试旨在告诉你的。通过测试好的和坏的输入,边缘情况等,你有正确的想法。每个条件都需要一个测试。测试将设置任何先决条件,然后断言您的计算(或任何可能的计算)符合您的期望
答案 1 :(得分:2)
是的,就是这样。您提出的每个问题都可以用作测试。将单元测试视为三个步骤。设置一些前提条件,运行一些“测试中”的代码,并编写一个记录您期望的断言。
在您的情况下,设置具有某些特定值(或没有值)的“集合”是设置前提条件。
使用特定参数调用搜索方法正在运行测试中的代码。
检查方法返回的值是否与断言步骤匹配。
给这三个东西一个名称来描述你想要做的事情(DoesTheSearchMethodFailIfCollectionIsEmpty),并且你有一个单元测试。
答案 2 :(得分:2)
您对单元测试的期望是正确的;它非常关于验证和验证预期的行为。
我认为许多人对单元测试错过的一个价值是它的价值随着时间的推移而增加。当我编写一段代码并编写单元测试时,我基本上只是测试了代码执行了我认为它应该做的事情,它没有以任何方式失败我选择检查等等。这些都很好事物,但它们的价值有限,因为它们表达了你当时对系统的了解;他们无法帮助你处理你不了解的事情(我的算法中是否存在一个我不知道并且没想到要测试的漏洞?)。
在我看来,单位测试的真正价值在于他们随着时间的推移所获得的价值。这个值有两种形式;文件价值和验证价值。
文档值是单元测试的值,说“这是代码的作者期望这段代码要做的事情”。很难夸大这类事物的价值;当你进入一个有大量未记录的遗留代码的项目时,让我告诉你,这种文档价值就像一个奇迹。
另一个值是验证;当代码存在于项目中时,事情会被重构,更改和转移。单元测试可以验证您认为以某种方式工作的组件是否以这种方式继续工作。这对于帮助发现蔓延到项目中的错误非常有用。例如,更改数据库解决方案有时可以透视,但有时,这些更改可能会导致某些工作方式发生意外变化;单元测试依赖于ORM的组件可以捕获基础行为的关键细微变化。当你有一大堆代码已经多年来一直运行良好时,这真的很有用,没有人会考虑在失败中考虑它的潜在作用;这些类型的错误可能需要花费很长时间才能找到,因为你要看的最后一个地方是在很长一段时间内坚如磐石的组件。单元测试提供了“Rock Solidity”的验证。