Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么是单元测试_Java_Unit Testing_Testing_Junit - Fatal编程技术网

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或具有值 重复可以是负数、正数或零
这似乎已经是3*2*3=18种测试方法了。如果其他函数也需要测试特殊字符、Integer.MIN\u值、Integer.MAX\u值等,则可以在其他函数上进行更多的测试。 我的停车路线应该是什么? 为了我自己的计划,我应该假设: strB只能为空或有值 c有价值 重复只能为空或正


抱歉打扰了。我真的很困惑,我应该如何偏执地进行一般的单元测试。我应该保持在我的假设范围内,还是这是一种糟糕的做法,我应该为每种潜在的情况提供一种方法,在这种情况下,单元测试方法的数量将以指数的方式非常快地扩展。

一般的经验法则通常是,代码中的每个“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的
    @理论
    就是这方面的一个实现。它允许您测试像“
    plus(x,y
    )这样的断言,它为任何正x和正y返回一个正数”

您开发的测试用例集是黑盒测试设计方法的结果,事实上,它们看起来就像您应用了分类树方法一样。虽然在进行单元测试时暂时采用黑盒的观点是很好的,但将自己局限于黑盒测试可能会产生一些不期望的效果:首先,正如您所观察到的,您可能最终得到每个输入的所有可能场景的笛卡尔积,其次,您可能仍然找不到特定于所选实现的bug

通过(也)采用玻璃盒(又名白盒)的视角,您可以避免创建无用的测试:知道您的代码作为第一步处理重复次数为负的特殊情况
if (x != null) {
  if (x.length > 100) {
    // do something  
  } else {
    // do something else
  }
} else {
  // do something completely else
}