Reputation: 3148
I am new to Unit Testing and therefore wanted to do some practical exercise to get familiar with the jUnit framework.
I created a program that implements a String multiplier
public String multiply(String number1, String number2)
In order to test the multiplier method, I created a test suite consisting of the following test cases (with all the needed integer parsing, etc)
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("", ""));
}
}
In a similar fashion, I can create test cases involving boundary cases (considering numbers are int values) or even imaginary values.
1) But, what should be the expected value for the last 3 test cases above? (a special number indicating error?)
2) What additional test cases did I miss?
3) Is assertEquals() method enough for testing the multiplier method or do I need other methods like assertTrue(), assertFalse(), assertSame() etc
4) Is this the RIGHT way to go about developing test cases? How am I "exactly" benefiting from this exercise?
5)What should be the ideal way to test the multiplier method?
I am pretty clueless here. If anyone can help answer these queries I'd greatly appreciate it. Thank you.
Upvotes: 1
Views: 6876
Reputation: 116246
1) But, what should be the expected value for the last 3 test cases above? (a special number indicating error?)
As explained by the other answerers, it depends on the interface contract of your multiplier. You should think through how you (or its clients, in general) are supposed to use it, what should happen in case of specific errors or extreme cases, etc. In Java, the convention is to throw an exception in such cases.
2) What additional test cases did I miss?
A couple of cases which come to my mind:
// 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) Is assertEquals() method enough for testing the multiplier method or do I need other methods like assertTrue(), assertFalse(), assertSame() etc
In this case all you need is to compare two values for equality. In other tests you may need different kinds of asserts.
4) Is this the RIGHT way to go about developing test cases? How am I "exactly" benefiting from this exercise?
There is no single "right" way to unit testing. What comes closest is probably test driven development, which is recommended by many (including myself) if you write your code from scratch.
Your benefit from this exercise is probably that you got familiar with JUnit and tried the "tester hat" on for a while.
5)What should be the ideal way to test the multiplier method?
How is this question different from the previous one?
Upvotes: 3
Reputation: 2609
If you are really testing edge conditions, and you are expecting string representation of numbers, perhaps you can test passing strings to the function method under test
@Test(expected= NumberFormatException.class)
public void test() {
multiplier.multiply("a", "b");
}
I disagree with cletus on his implementation, as his test case expects an all encompassing IllegalArgumentException, I think it is better to test for specific sub classes than using a parent exception.
Upvotes: 1
Reputation: 193
You should consider adding test cases that verify your exceptions are working fine using the @Expected annotation. Basically, write a case that you know should generate a exception and then see that the test passes.
A good way to determine if you have missed any cases in complex methods is to run them through a code coverage tool. Run all your tests and then look at the code coverage result. If there are parts of your code that are not visited by your test cases, you are probably missing some.
You can find a good guide here.
Upvotes: 2
Reputation: 625007
Firstly, your code is in error because you have a class but no functions. I'm assuming all these tests are in one function? If so, I would advise against it. Generally you want one test to test one thing so:
public class MultiplierTests {
@Test
public void testSimpleMultiple() {
assertEquals(...);
}
...
}
Secondly, you're passing an int as the result here:
assertEquals("Result", 5, multiplier.multiply("5", "1"));
but Multiplier.multiply()
returns a String
?
So how you test this depends on what the result is. If passed in an empty string does it throw an exception? If so you can define your @Test
annotation to say it expects an exception to be thrown:
@Test(expected = IllegalArgumentException.class)
public void test() {
multiplier.multiply("", "5");
}
Upvotes: 4