Java 什么是单元测试
我有点困惑我应该在单元测试上投入多少精力 假设我有一个简单的函数,如:Java 什么是单元测试,java,unit-testing,testing,junit,Java,Unit Testing,Testing,Junit,我有点困惑我应该在单元测试上投入多少精力 假设我有一个简单的函数,如: appendRepeats(StringBuilder strB, char c, int repeats) [此函数将向strB追加字符c重复次数。 e、 g: ] 对于这个函数的单元测试,我觉得已经有很多可能性了: 追加重复0重复结束 附录重复\u否定重复\u结束 追加重复\u正重复\u追加 附录REPECTS_NULLSTRBZERO REPECTS_DONTAPEND 附录重复\u空STRB否定重复\u结束 Ap
appendRepeats(StringBuilder strB, char c, int repeats)
[此函数将向strB追加字符c重复次数。
e、 g:
]
对于这个函数的单元测试,我觉得已经有很多可能性了:
- 追加重复0重复结束
- 附录重复\u否定重复\u结束
- 追加重复\u正重复\u追加
- 附录REPECTS_NULLSTRBZERO REPECTS_DONTAPEND
- 附录重复\u空STRB否定重复\u结束
- AppendRepeats\u NullStrBPositiveRepeats\u Append
- 附录REPECTS\u EMPTYSTRBZERO REPECTS\u DontAppend
- 附录重复\u清空或否定重复\u结束
- 追加重复\u清空正重复\u追加
- 等等等等。 strB可以为null、空或有值。 c可以为null或具有值 重复可以是负数、正数或零
抱歉打扰了。我真的很困惑,我应该如何偏执地进行一般的单元测试。我应该保持在我的假设范围内,还是这是一种糟糕的做法,我应该为每种潜在的情况提供一种方法,在这种情况下,单元测试方法的数量将以指数的方式非常快地扩展。一般的经验法则通常是,代码中的每个“fork”都应该有一个测试,这意味着您应该涵盖所有可能的边缘情况 例如,如果您有以下代码:
if (x != null) {
if (x.length > 100) {
// do something
} else {
// do something else
}
} else {
// do something completely else
}
您应该有三个测试用例——一个为null,一个为小于100的值,一个为更长的值。
这是如果你是严格的,并希望得到100%的保障
不管是不同的测试还是参数化,都不太重要,这更多的是风格问题,你可以选择任何一种方式。我认为更重要的是覆盖所有情况。首先,使用代码覆盖工具。这将显示测试执行的代码行。IDE有用于代码覆盖工具的插件,这样您就可以运行测试并查看执行了哪些行。拍摄覆盖每一条线,这可能在某些情况下是困难的,但对于这种实用程序,它是非常可行的 使用代码覆盖工具使未覆盖的边缘案例脱颖而出。对于更难实现的测试,代码覆盖率会向您显示测试执行了哪些行,因此,如果测试中出现错误,您可以看到它有多远 下一步,了解没有测试覆盖所有内容。总会有你不测试的值。因此,选择有代表性的有意义的输入,避免那些看起来多余的输入。例如,传递一个空的StringBuilder真的是您关心的事情吗?它不会影响代码的行为。有些特殊值可能会导致问题,如null。如果您测试的是二进制搜索,那么您需要覆盖数组非常大的情况,以查看中点计算是否溢出。寻找那些重要的案例 如果您预先验证并排除了麻烦的值,那么您就不必做那么多的工作测试。传递了一个null StringBuilder测试以验证您是否抛出IllegalArgumentException,一个负重复值测试以验证您是否为此抛出了一些东西
最后,测试是为开发人员准备的。做对你有用的事 没有正确的答案,这是个人意见和感受的问题 然而,我认为有些事情是普遍的:
- 如果您采用测试驱动开发,除非您首先编写了一个失败的单元测试,否则您永远不会编写任何非测试代码,这将指导您编写的测试数量。有了TDD方面的一些经验,您将对此有所体会,因此即使您需要为没有TDD的旧代码编写单元测试,您也可以像编写测试一样编写测试
- 如果一个类有太多的单元测试,这表明该类做了太多的事情。然而,“太多”很难量化。但是当感觉太多的时候,试着把班级分成更多的班级,每个班级承担的责任更少
- 模拟是单元测试的基础——如果不模拟协作者,您的测试就不仅仅是“单元”。因此,学习使用模拟框架
- 检查空值并测试这些检查,可能会产生大量代码。如果您采用了从不生成null的样式,那么您的代码就不需要处理null,也不需要测试在这种情况下会发生什么。
- 也有例外情况,例如,如果您提供库代码,并且希望向调用者提供友好的无效参数错误
- 对于某些方法,属性测试是一种可行的方法,可以通过大量测试来命中代码。jUnit的
就是这方面的一个实现。它允许您测试像“@理论
)这样的断言,它为任何正x和正y返回一个正数”plus(x,y
if (x != null) {
if (x.length > 100) {
// do something
} else {
// do something else
}
} else {
// do something completely else
}