单元测试新手,如何编写出色的测试?
我对单元测试领域相当陌生,并且我决定本周为现有应用添加测试覆盖率。
这是一项艰巨的任务,主要是因为要测试的类的数量,而且还因为编写测试对我来说都是新的。
我已经为一堆课程编写了测试,但现在我想知道我是否正确地做了。
当我为一种方法编写测试时,我有第二次重写我已经在方法本身写过的内容的感觉。
我的测试似乎与方法紧密相关(测试所有代码路径,期望某些内部方法被多次调用,并带有某些参数),似乎如果我重构了方法,测试将会失败,即使该方法的最终行为没有改变。
这只是一种感觉,如前所述,我没有测试经验。 如果一些更有经验的测试人员可以给我提供关于如何为现有应用编写出色测试的建议,那将不胜感激。
编辑:我很想感谢Stack Overflow,在15分钟内我有很好的投入,回答了我刚才在线阅读的更多时间。
我的测试似乎与方法紧密相关(测试所有代码路径,期望某些内部方法被多次调用,并带有某些参数),似乎如果我重构了方法,测试将会失败,即使该方法的最终行为没有改变。
我认为你做错了。
单元测试应该:
它不应该看内部方法来看看它在做什么,所以更改内部部件不应该导致测试失败。 你不应该直接测试被调用的私有方法。 如果您有兴趣了解您的私人代码是否正在测试,请使用代码覆盖工具。 但是不要被这个迷惑: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);
}
请注意,如何计算结果不会被检查 - 只是结果是正确的。 继续添加更多更简单的测试用例,如上所述,直到您已经覆盖尽可能多的场景。 使用您的代码覆盖工具来查看您是否错过了任何有趣的路径。
对于单元测试,我发现测试驱动(测试第一,代码第二)和代码第一,测试第二是非常有用的。
而不是写代码,然后写测试。 编写代码,然后看看你认为代码应该做什么。 考虑它的所有预期用途,然后为每个用户编写测试。 我发现编写测试比编码本身更快,但涉及更多。 测试应该测试意图。 同时考虑你在测试写作阶段找到角落案例的意图。 当然,在编写测试时,您可能会发现少数用途之一会导致一个错误(我经常发现这个错误,而且我很高兴这个错误不会破坏数据并且不会被检查)。
然而测试几乎就像编码两次。 事实上,我有应用程序,其中有更多的测试代码(数量)比应用程序代码。 一个例子是一个非常复杂的状态机。 我必须确保在为其添加更多逻辑之后,整个事情始终对所有以前的用例都起作用。 而且由于这些案例很难通过查看代码来追踪,所以我最终为这台机器提供了这样一个好的测试套件,我相信它在修改之后不会中断,并且测试还是省了几次屁股。 当用户或测试人员发现错误的流量或角落案例时,可以猜测出什么,添加到测试中并且再也没有发生过。 除了使整个事情超级稳定之外,这确实给了用户对我工作的信心。 由于性能方面的原因,必须重新编写它时,请猜测它是如何的,由于测试的原因,它在所有输入上按预期工作。
所有简单的例子,如function square(number)
是伟大的,所有的,可能是不好的候选人花费大量的时间测试。 那些重要的商业逻辑,这就是测试是重要的。 测试要求。 不要只测试管道。 如果需求改变,那么猜测是什么,测试也必须。
测试不应该从字面上测试该函数foo调用的函数栏3次。 那是错的。 检查结果和副作用是否正确,而不是内在机制。
值得注意的是,对现有代码进行改装的单元测试要比首先通过测试创建代码困难得多。 这是处理遗留应用程序的重大问题之一......如何进行单元测试? 这已经被问过很多次了(所以你可能会被当作愚蠢的问题关闭),人们通常会在这里结束:
将现有代码移至测试驱动开发
我第二次接受答案的书籍推荐,但除此之外,还有更多的信息与答案有关。
链接地址: http://www.djcxy.com/p/50807.html