我有点困惑我应该在单元测试上投入多少钱。
说我有一个简单的功能,例如:
appendRepeats(StringBuilder strB, char c, int repeats)
[此函数会将字符c重复附加到strB的次数。 例如:
strB = "hello"
c = "h"
repeats = 5
// result
strB = "hellohhhhh"
]
对于此功能的单元测试,我觉得已经有很多可能性:
似乎已经有3 * 2 * 3 = 18种测试方法。如果其他功能还需要测试特殊字符(例如Integer.MIN_VALUE,Integer.MAX_VALUE等),那么在其他功能上可能会涉及更多内容。 我应该停止的路线是什么? 我是否应该为自己的程序做以下假设: strB只能为空或有值 c具有价值 重复只能为空或正数
很抱歉打扰。只是真正地混淆了我一般应该对单元测试多大的疑惑。我应该处于假设范围之内还是该做法不好,并且在每种情况下都应该有一种方法,在这种情况下,单元测试方法的数量将迅速成倍增长。
答案 0 :(得分:3)
没有正确的答案,这是个人见解和感觉的问题。
但是,我认为有些事情是普遍的:
@Theory
是此实现的一种。它使您可以测试断言,例如'plus(x,y
)对于x的正数和y的正数都返回正数。答案 1 :(得分:1)
一般的经验法则通常是代码中的每个“ fork”都应进行测试,这意味着您应该涵盖所有可能的边缘情况。
例如,如果您具有以下代码:
if (x != null) {
if (x.length > 100) {
// do something
} else {
// do something else
}
} else {
// do something completely else
}
您应该有三个测试用例-一个用于null,一个用于小于100的值,一个用于较长的值。 这是如果您很严格并且想要100%被覆盖。
无论是不同的测试还是参数化的重要性都不那么重要,而更多的是样式问题,您可以选择其中一种。我认为更重要的是覆盖所有情况。
答案 2 :(得分:1)
首先,使用代码覆盖率工具。这将向您显示测试执行的代码行。 IDE具有用于代码覆盖率工具的插件,因此您可以运行测试并查看执行了哪些行。拍摄每条线,这在某些情况下可能很难,但是对于这种实用程序来说,它是非常可行的。
使用代码覆盖率工具可以使未发现的边缘情况突出。对于难以实现的测试,代码覆盖率会向您显示测试执行的行,因此,如果测试中存在错误,您可以查看测试的执行距离。
接下来,请了解没有任何测试涵盖所有内容。总会有您不测试的值。因此,请选择感兴趣的代表性输入,并避免看起来多余的输入。例如,传递空的StringBuilder真的是您关心的事情吗?它不会影响代码的行为。有一些可能引起问题的特殊值,例如null。如果您正在测试二进制搜索,则需要覆盖数组确实很大的情况,以查看中点计算是否溢出。寻找重要的案例。
如果您预先验证并剔除麻烦的值,则无需进行过多的工作测试。一项通过测试null StringBuilder来验证是否抛出IllegalArgumentException,另一项通过测试负重复值来验证是否为此抛出异常。
最后,测试是针对开发人员的。做对您有用的事情。
答案 3 :(得分:1)
您开发的测试用例集是黑盒测试设计方法的结果,实际上,它们看起来就像您已应用了分类树方法。虽然在进行单元测试时暂时采取黑匣子的观点是完全可以的,但将自己限制在黑匣子测试中只会产生一些不良影响:首先,正如您所观察到的,您可以得到所有笛卡尔积的笛卡尔积。每个输入的可能场景,其次,您可能仍将找不到特定于所选实现的错误。
通过(也)采用玻璃盒子(又称白盒子)的观点,您可以避免创建无用的测试:知道您的代码作为第一步就可以处理重复次数为负的特殊情况,这意味着您不必不必将此情况与所有其他情况相乘。当然,这意味着您正在利用对实现细节的了解:如果以后要更改代码,以便在多个地方进行负重复检查,那么最好也调整测试套件。
由于似乎对测试实现细节有广泛的关注:单元测试就是测试实现。不同的实现有不同的潜在错误。如果您不使用单元测试来发现这些错误,那么任何其他测试级别(集成,子系统,系统)绝对不适合系统地查找它们-在更大的项目中,您不希望实现级别的错误逃脱以后的开发阶段甚至是实地。附带一提,覆盖率分析意味着您采用了玻璃盒子的观点,而TDD也是这样做的。
但是,正确的是,测试套件或单个测试不应不必要地依赖于实现细节-但这与声明您根本不应该依赖实现细节完全不同。因此,一种可行的方法是,从黑盒的角度出发,进行一系列有意义的测试,以及旨在捕获那些特定于实现的错误的测试。更改代码时需要对后者进行调整,但是可以通过多种方式来减少工作量,例如使用测试助手方法等。
在您的情况下,采用玻璃箱透视图可能会将带有负重复的测试数减少为1,同时将null字符的情况也可能减少为NullStrB的情况(假设您通过将null替换为空来尽早处理该情况)字符串),等等。