Epi*_*aph 8 java junit unit-testing
我正在测试一个String乘数类,其multiply()方法是将2个数作为输入(as String)并返回结果数(as String)
public String multiply(String num1, String num2);
Run Code Online (Sandbox Code Playgroud)
我已经完成了实现并创建了一个测试类,其中包含以下测试用例,其中包含输入String参数
现在我的问题是:
我想知道"每个"assertEquals()是否应该在它自己的测试方法中?或者,我可以将类似测试用例(如testInvalidArguments())分组以包含涉及无效字符的所有断言,因为它们都会抛出相同的NumberFormatException吗?
如果测试像字符("a")这样的输入值,我是否需要包含所有场景的测试用例?"a"作为第一个参数"a"作为第二个参数"a"和"b"作为2个参数
根据我的理解,这些单元测试的好处是找出用户输入可能失败并导致异常的情况.然后,我们可以为用户提供有意义的消息(要求他们提供有效的输入)而不是异常.那是对的吗?而且,这是唯一的好处吗?
上面提到的11个测试案例是否足够?我错过了什么?我过头了吗?什么时候够了?
从上述观点出发,我是否成功测试了multiply()方法?
单元测试很棒(在我正在工作的200 KLOC项目中,我有与常规代码一样多的单元测试代码)但是(假设正确的单元测试):
想一想:
意识到这一点非常重要.
在此之上:
然后,当你重构时:
但:
这是非常基础的,应该是单元测试101.
1)我认为限制每次测试中断言的数量是个好主意.JUnit仅报告测试中的第一次失败,因此如果您有多个断言,则可能会屏蔽某些问题.能够看到通过的所有内容和失败的一切更有用.如果你assertEquals在一个测试中有10 个并且第一个测试失败了,那么你只是不知道另一个测试会发生什么.这些将是调试时的好数据点.
2)是的,您应该包括所有输入的测试.
3)不仅需要测试最终用户输入.您将要为可能失败的任何公共方法编写测试.在JUnit常见问题解答中,有一些很好的指导方针,尤其是关于getter和setter的指南.
4)我认为你已经很好地覆盖了它.(至少我想不出别的,但看到#5).
5)给一些用户测试一下.他们总能找到我从未想过测试的样本数据.:)
1) 测试的粒度(因此易于诊断)和单元测试代码的冗长程度之间需要权衡。我个人很乐意采用相对粗粒度的测试方法,尤其是在测试和测试代码稳定下来之后。粒度问题仅在测试失败时才相关。(如果我在多断言测试用例中失败,我要么修复第一个失败并重复,要么根据需要暂时破解测试用例以弄清楚发生了什么。)
2)运用你的常识。根据您对代码编写方式的理解,设计测试以执行所有性质不同的子情况。认识到除了最微不足道的情况之外,不可能测试所有可能的输入。
3) 单元测试的目的是提供一定程度的保证,确保被测方法能够完成其要求的任务。这意味着什么取决于正在测试的代码。例如,如果我对一个sort方法进行单元测试,则用户输入的验证是无关紧要的。
4)覆盖范围似乎合理。然而,如果没有详细说明您的班级需要做什么,也没有检查实际的单元测试,就不可能说您是否已经涵盖了所有内容。例如,您的方法是否应该处理前导/尾随空白字符、带小数点的数字、“123,456”等数字、使用非拉丁数字表示的数字、以 42 为基数的数字?
5) 定义“成功测试”。如果你的意思是,我的测试证明代码没有错误,那么答案肯定是“否”。除非单元测试枚举每一个可能的输入,否则它们不能构成正确性的证明。(在某些情况下,甚至测试所有输入都不够。)
除了最微不足道的情况外,在所有情况下,测试都无法证明不存在错误。它唯一可以证明的是错误的存在。如果你需要证明一个程序没有bug,你需要诉诸“形式化方法”;即,将形式化定理证明技术应用到您的程序中。
而且,正如另一个答案指出的那样,您需要将其提供给真实用户,看看他们可能会以意想不到的输入方式想出什么。换句话说……所陈述或推断的用户需求是否实际上完整且有效。