Epitaph
Epitaph

Reputation: 3148

Defining jUnit Test cases Correctly

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

Answers (4)

Péter Török
Péter Török

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

Kartik
Kartik

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

Prachi
Prachi

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

cletus
cletus

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

Related Questions