我是Unit Testing的新手,因此想做一些实践练习来熟悉jUnit框架。
我创建了一个实现字符串乘数
的程序public String multiply(String number1, String number2)
为了测试乘数方法,我创建了一个包含以下测试用例的测试套件(包含所有需要的整数解析等)
public class MultiplierTest {
@Test
public void testMultiply() {
Multiplier multiplier = new Multiplier();
// Test for 2 positive integers
assertEquals("Result", 5, multiplier.multiply("5", "1"));
// Test for 1 positive integer and 0
assertEquals("Result", 0, multiplier.multiply("5", "0"));
// Test for 1 positive and 1 negative integer
assertEquals("Result", -1, multiplier.multiply("-1", "1"));
// Test for 2 negative integers
assertEquals("Result", 10, multiplier.multiply("-5", "-2"));
// Test for 1 positive integer and 1 non number
assertEquals("Result", , multiplier.multiply("x", "1"));
// Test for 1 positive integer and 1 empty field
assertEquals("Result", , multiplier.multiply("5", ""));
// Test for 2 empty fields
assertEquals("Result", , multiplier.multiply("", ""));
}
}
以类似的方式,我可以创建涉及边界情况的测试用例(考虑数字是int值)或甚至是虚数值。
1)但是,上面最后3个测试用例的预期值应该是多少? (一个特殊数字表示错误?)
2)我错过了哪些额外的测试用例?
3)assertEquals()方法是否足以测试乘数方法,还是需要其他方法,如assertTrue(),assertFalse(),assertSame()等
4)这是开发测试用例的正确方法吗?我如何“完全”从这项运动中获益?
5)测试乘数法的理想方法是什么?
我在这里很无能为力。如果有人可以帮助回答这些问题,我会非常感激。谢谢。
答案 0 :(得分:4)
首先,您的代码出错,因为您有一个类但没有函数。我假设所有这些测试都在一个功能中?如果是这样,我会建议反对。通常,您希望一个测试测试一件事:
public class MultiplierTests {
@Test
public void testSimpleMultiple() {
assertEquals(...);
}
...
}
其次,你在这里传递一个int作为结果:
assertEquals("Result", 5, multiplier.multiply("5", "1"));
但Multiplier.multiply()
会返回String
?
所以你如何测试这取决于结果是什么。如果传入空字符串会引发异常吗?如果是这样,您可以定义@Test
注释以表示它期望抛出异常:
@Test(expected = IllegalArgumentException.class)
public void test() {
multiplier.multiply("", "5");
}
答案 1 :(得分:3)
1)但是,上面最后3个测试用例的预期值应该是多少? (一个特殊数字表示错误?)
正如其他回答者所解释的那样,它取决于乘数的接口合约。您应该考虑一下您(或其客户)应该如何使用它,在特定错误或极端情况下应该发生什么等等。在Java中,惯例是在这种情况下抛出异常。
2)我错过了哪些额外的测试用例?
我想到了几个案例:
// test commutativity
assertEquals("0", multiplier.multiply("0", "5"));
assertEquals("-1", multiplier.multiply("1", "-1"));
assertEquals("149645", multiplier.multiply("173", "865"));
assertEquals("149645", multiplier.multiply("865", "173"));
// test some more unusual cases of multiplying with 0
assertEquals("0", multiplier.multiply("-5", "0"));
assertEquals("0", multiplier.multiply("0", "-0"));
// test with numbers starting with '+'
assertEquals("368", multiplier.multiply("+23", "+16"));
assertEquals("-368", multiplier.multiply("-23", "+16"));
// test multiplying huge values without overflow
assertEquals("18446744073709551616", multiplier.multiply("4294967296", "4294967296"));
assertEquals("18446744073709551616", multiplier.multiply("-4294967296", "-4294967296"));
3)assertEquals()方法是否足以测试乘数方法,还是需要其他方法,如assertTrue(),assertFalse(),assertSame()等
在这种情况下,您只需比较两个值是否相等。在其他测试中,您可能需要不同类型的断言。
4)这是开发测试用例的正确方法吗?我如何“完全”从这项工作中受益?
单元测试没有单一的“正确”方式。最接近的可能是test driven development,如果您从头开始编写代码,这是许多人(包括我自己)推荐的。
这项练习的好处可能是您熟悉了JUnit并尝试了“测试帽”一段时间。
5)测试乘数法的理想方法是什么?
这个问题与前一个问题有什么不同?
答案 2 :(得分:2)
您应该考虑使用@Expected批注添加验证异常工作正常的测试用例。基本上,写一个你知道应该生成异常然后看到测试通过的案例。
确定您是否错过了复杂方法中的任何情况的好方法是通过代码覆盖率工具运行它们。运行所有测试,然后查看代码覆盖率结果。如果您的代码中有部分代码未被您的测试用例访问过,那么您可能会遗漏一些代码。
你可以找到一本好的指南here。
答案 3 :(得分:1)
如果你真的测试边缘条件,并且你期望数字的字符串表示,也许你可以测试传递字符串到测试下的函数方法
@Test(expected= NumberFormatException.class)
public void test() {
multiplier.multiply("a", "b");
}
我不同意cletus的实现,因为他的测试用例期望包含IllegalArgumentException,我认为测试特定的子类比使用父异常更好。