pix*_*tic 252 testing unit-testing
我对单元测试世界还很陌生,我刚刚决定在本周为我现有的应用添加测试覆盖率.
这是一项艰巨的任务,主要是因为要测试的课程数量,还因为编写测试对我来说都是新的.
我已经为一堆课程编写了测试,但现在我想知道我是否做得对.
当我为一个方法编写测试时,我感觉第二次重写我已经在方法本身中编写的内容.
我的测试似乎与方法紧密相关(测试所有代码路径,期望一些内部方法被调用多次,带有某些参数),似乎如果我重构该方法,即使该方法的最终行为没有改变.
这只是一种感觉,如前所述,我没有测试经验.如果一些更有经验的测试人员可以给我建议如何为现有应用程序编写出色的测试,那将非常感激.
编辑:我很想感谢Stack Overflow,我在15分钟内获得了很多投入,这些投入回答了我刚才在线阅读的更多时间.
Mar*_*ers 175
我的测试似乎与方法紧密相关(测试所有代码路径,期望一些内部方法被调用多次,带有某些参数),似乎如果我重构该方法,即使该方法的最终行为没有改变.
我觉得你做错了.
单元测试应该:
它不应该查看方法内部以查看它正在做什么,因此更改内部不应导致测试失败.您不应该直接测试正在调用的私有方法.如果您有兴趣了解您的私人代码是否正在测试,那么请使用代码覆盖工具.但不要为此着迷:100%的覆盖率不是必需的.
如果您的方法在其他类中调用公共方法,并且这些调用由您的接口保证,那么您可以使用模拟框架测试这些调用是否正在进行.
您不应该使用方法本身(或它使用的任何内部代码)动态生成预期结果.预期结果应该硬编码到您的测试用例中,以便在实现更改时不会更改.以下是单元测试应该做的简化示例:
testAdd()
{
int x = 5;
int y = -2;
int expectedResult = 3;
Calculator calculator = new Calculator();
int actualResult = calculator.Add(x, y);
Assert.AreEqual(expectedResult, actualResult);
}
Run Code Online (Sandbox Code Playgroud)
请注意,不检查结果的计算方式 - 仅检查结果是否正确.继续添加越来越多的简单测试用例,直到您已经涵盖尽可能多的方案为止.使用代码覆盖率工具查看是否遗漏了任何有趣的路径.
Dmi*_*ten 30
对于单元测试,我发现测试驱动(测试第一,代码第二)和代码优先,测试第二是非常有用.
而不是编写代码,然后编写测试.编写代码然后看看你认为代码应该做什么.考虑它的所有预期用途,然后为每个用途编写测试.我发现编写测试比编码本身更快但更复杂.测试应测试意图.还考虑了在测试编写阶段找到极端情况的意图.当然,在编写测试时,您可能会发现少数几种用法之一会导致错误(我经常发现这种错误,而且我很高兴这个错误不会破坏数据并且不加以检查).
然而,测试几乎就像编码两次.事实上,我的应用程序中存在比应用程序代码更多的测试代码(数量).一个例子是一个非常复杂的状态机.我必须确保在添加更多逻辑之后,整个事情始终适用于所有以前的用例.由于通过查看代码非常难以理解这些情况,我最终为这台机器配备了这么好的测试套件,我相信它在进行更改后不会破坏,并且测试节省了我的屁股几次.并且当用户或测试人员发现错误的流量或角落案件下落不明时,猜猜是什么,添加到测试中并且从未再次发生过.除了让整个事物变得超级稳定之外,这确实让用户对我的工作充满信心.当出于性能原因需要重新编写时,猜猜是什么,
所有简单的例子function square(number)都很棒,而且可能都是花费大量时间进行测试的不良候选人.那些做重要业务逻辑的人,那就是测试很重要的地方.测试要求.不要只是测试管道.如果要求改变然后猜测什么,测试也必须.
测试不应该字面上测试函数foo调用函数栏3次.那是错的.检查结果和副作用是否正确,而不是内部机制.
Dav*_*vid 18
值得注意的是,对现有代码进行改编的单元测试比首先通过测试驱动创建代码要困难得多.这是处理遗留应用程序的一个重大问题......如何进行单元测试?之前已经多次询问过(所以你可能会因为欺骗问题而被关闭),人们通常会在这里结束:
我接受了接受的答案的书籍推荐,但除此之外,答案中还有更多信息.
Jon*_*eid 14
不要编写测试来全面覆盖您的代码.编写保证您要求的测试.您可能会发现不必要的代码路径.相反,如果它们是必要的,它们就是满足某种要求的; 找到它是什么并测试要求(而不是路径).
保持测试小:每个要求一次测试.
之后,当您需要进行更改(或编写新代码)时,请先尝试编写一个测试.只有一个.然后,您将迈出测试驱动开发的第一步.
fre*_*oma 13
单元测试是关于从函数/方法/应用程序获得的输出.结果如何产生并不重要,重要的是它是正确的.因此,计算对内部方法的调用的方法是错误的.我倾向于做的是坐下来写一个方法应该返回给定某些输入值或某个环境,然后编写一个测试,将返回的实际值与我想出的值进行比较.
在编写要测试的方法之前尝试编写单元测试.
这肯定会迫使你对事情的完成方式略有不同.您将不知道该方法将如何工作,只是它应该做什么.
您应始终测试方法的结果,而不是方法如何获得这些结果.
测试应该是为了提高可维护性。如果您更改方法并且测试中断,那可能是一件好事。另一方面,如果您将您的方法视为一个黑匣子,那么方法内部的内容应该无关紧要。事实是您需要为某些测试模拟一些东西,在这些情况下,您真的不能将方法视为黑匣子。你唯一能做的就是编写一个集成测试——你加载一个被测试服务的完全实例化的实例,让它像在你的应用程序中运行一样做它的事情。然后你可以把它当作一个黑匣子。
When I'm writing tests for a method, I have the feeling of rewriting a second time what I
already wrote in the method itself.
My tests just seems so tightly bound to the method (testing all codepath, expecting some
inner methods to be called a number of times, with certain arguments), that it seems that
if I ever refactor the method, the tests will fail even if the final behavior of the
method did not change.
Run Code Online (Sandbox Code Playgroud)
这是因为您是在编写代码之后编写测试的。如果你反过来做(先写测试),它不会有这种感觉。
| 归档时间: |
|
| 查看次数: |
108700 次 |
| 最近记录: |