Enovyne
Enovyne

Reputation: 195

Unit Testing Java

I am new to JUnit testing.

For example, I have a Misc class in a project:

public class Misc{

   public static int computeValue(int x,int y,int z)
   {
      int value = 0;

      if((x==y)||(z==0))
          value = x+2;

      else if(x>y)
          value = y+4;

      else 
          value = z;

      return value;
  }
}

I gave it a try in the JUnit class but I'm not too sure if I have done it correctly.

public class MiscTest {

@Test
public void testXEqualToY() {

    //Only X is equal to Y and z is not zero
    int x = 5,y=5;
    int value = 0;
    value = Misc.computeValue(5, 5, 10);
    assertEquals("test error",x,y,value);
}

@Test
public void testZEqualZero(){
    //Only z is 0
    int x=4,y=8,z=0;

    int value = 0;
    value = Misc.computeValue(11,5,0);
    assertEquals("test error",z,value);

}

What should I put in the test case methods to test the values?

Upvotes: 2

Views: 199

Answers (3)

John B
John B

Reputation: 32969

The would be a great use of Parameterized. Parameterized is really great when you want to specify the expected result for a bunch of different input cases. You only need one @Test here and can add a new test condition with the simple addition of { 0, 0, 0, 2 },

Now test every case:

  • when x=y, expect X+2
  • when z=0, expect x+2
  • when x > y, expect y+4
  • otherwise, expect z

Here is the basic structure

 @RunWith(Parameterized.class)
class MyTest{

    @Parameters
    public static Collection<Object[]> data() {
            return Arrays.asList(new Object[][] {
                            { { 0, 0, 0, 2 },... });
    }


     int x,y,z, expectedResult;

   // add constructor here

   @Test
   public void testYEqualToZ(){
      int actualResult = Misc.computeValue(x,y,z);
      assertEquals(actualResult, expectedResult);
     }
}

Then use the following test cases:

  • 1, 1, 5, 3 // x y equal case
  • 2, 2, 8, 4 // again
  • 3, 6, 0, 5 // z is 0 case
  • 3, 2, 8, 6 // x > y case
  • 3, 4, 8, 8 // x < y case

Keep adding cases till you have every possible case tested

Upvotes: 1

piotrek
piotrek

Reputation: 14550

you have to test all possible execution flows (verify it using coverage tools). it's easiest to do using parameterized testsing. there is plenty of such frameworks in java. choose the one that has best ratio power/simplicity for your case. for example:

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.runner.RunWith;
import com.googlecode.zohhak.api.TestWith;
import com.googlecode.zohhak.api.runners.ZohhakRunner;

@RunWith(ZohhakRunner.class)
public class MyTest {

    @TestWith({
        "5,5,0,     7",
        "4,8,0,     6",
        "11,5,0,    13"
    })
    public void should_be_valid_point(int x, int y, int z, int expected) {
        assertThat(Misc.computeValue(x, y, z)).isEqualTo(expected);
    }
}

Upvotes: 0

Lo&#239;c Decloedt
Lo&#239;c Decloedt

Reputation: 76


The way you design your test needs to be revised. You need to consider all the cases you want to validate. For each, case, you have to define the expected value and compare it with the result from your function.
For example, I would consider 4 cases to test:
- x == y
- z == 0
- x > y
- x < y
I would write it like this

@Test
public void testXEqualToY() {
  //Only X is equal to Y and z is not zero
  int x = 5,y=5;
  int z=0;
  int ref = 7;
  assertEquals(ref, Misc.computeValue(x, y, z));
}

@Test
public void testYEqualToZ(){
  //Only z is 0
  int x=4,y=8,z=0;
  int ref = 6;
  assertEquals(ref, Misc.computeValue(x, y, z));
}
Etc...

That said, defining the cases to test should be done prior to writing the code, to ensure that your tests are avalidating what you want to achieve and not what you just wrote.

Regards, Loic.

Upvotes: 1

Related Questions