我是单元测试领域的新手,我刚刚决定在本周为我现有的应用添加测试范围。
这是一项艰巨的任务,主要是因为要测试的类的数量很多,而且还因为编写测试对我来说是全新的。
我已经为一堆类编写了测试,但现在我想知道我是否做对了。
当我为一个方法编写测试时,我有一种再次重写我已经在方法中编写的内容的感觉。
我的测试似乎与该方法紧密相关(测试所有代码路径,期望一些内部方法被调用多次,带有某些参数),似乎如果我重构该方法,即使该方法的最终行为没有改变。
这只是感觉,前面说了,我没有测试经验。如果一些更有经验的测试人员可以就如何为现有应用程序编写出色的测试提供建议,我将不胜感激。
编辑:我很想感谢 Stack Overflow,我在不到 15 分钟的时间内得到了很好的输入,回答了我刚刚完成的更多时间的在线阅读。
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.
我认为你做错了。
单元测试应该:
- 测试一种方法
- 为该方法提供一些具体参数
- 测试结果是否符合预期
它不应该查看方法内部以查看它在做什么,因此更改内部结构不应导致测试失败。您不应该直接测试是否正在调用私有(private)方法。如果您有兴趣了解您的私有(private)代码是否正在接受测试,请使用代码覆盖工具。但不要沉迷于此:100% 的覆盖率不是必需的。
如果您的方法调用其他类中的公共(public)方法,并且这些调用由您的接口(interface)保证,那么您可以使用模拟框架测试这些调用是否正在进行。
您不应使用该方法本身(或它使用的任何内部代码)来动态生成预期结果。预期结果应该硬编码到您的测试用例中,这样它就不会在实现发生变化时发生变化。下面是单元测试应该做什么的简化示例:
testAdd()
{
int x = 5;
int y = -2;
int expectedResult = 3;
Calculator calculator = new Calculator();
int actualResult = calculator.Add(x, y);
Assert.AreEqual(expectedResult, actualResult);
}
请注意,不会检查结果的计算方式 - 只会检查结果是否正确。像上面一样继续添加越来越多的简单测试用例,直到您涵盖了尽可能多的场景。使用您的代码覆盖工具查看您是否遗漏了任何有趣的路径。