twitter
rss

Since most of the testing scenarios data are in the form of table, a Data Driven testing approach can be employed for carrying out unit testing using TestNg/Junit. For Example, Consider the example of testing a simple integer division method. 


   1:      Class Divide{
   2:        public static int divide(int a, int b) {
   3:          if (b == 0) {
   4:              throw new ArithmeticException();
   5:          } else
   6:              return a / b;
   7:      }
   8:  }

For testing this simple method itself properly, we need to test the following scenarios.


Test Case Objective

Input number 1

Input number 2

Expected Result

Zero/Zero 0 0 ArithmeticException
Zero/positive 0 2 0
Zero/negative 0 -2 0
Positive/zero 5 0 ArithmeticException
Negative/zero -2 0 ArithmeticException
Positive/positive 5 2 2
Positive/negative 5 -2 -2
Negative/positive -5 2 -2
Negative/negative -5 -2 2
No/same number 5 5 1

To test the above scenarios we have to call the same method with different arguments (something like below) or need to have different method for testing each scenario.


   1:  public class TestDivide {
   2:   
   3:      @Test
   4:      public void testDivide() throws Exception {
   5:          // Zero/Zero 0 0 ArithmeticException
   6:          testDivideByZero(0, 0);
   7:          // Zero/positive 0 2 0
   8:          assertEquals(0, Divide.divide(0, 2));
   9:          // Zero/negative 0 -2 0
  10:          assertEquals(0, Divide.divide(0, -2));
  11:          // Positive/zero 5 0 ArithmeticException
  12:          testDivideByZero(5, 0);
  13:          // Negative/zero -2 0 ArithmeticException
  14:          testDivideByZero(-2, 0);
  15:          // Positive/positive 5 2 2
  16:          assertEquals(2, Divide.divide(5, 2));
  17:          // Positive/negative 5 -2 -2
  18:          assertEquals(-2, Divide.divide(5, -2));
  19:          // Negative/positive -5 2 -2
  20:          assertEquals(-2, Divide.divide(-5, 2));
  21:          // Negative/negative -5 -2 2
  22:          assertEquals(2, Divide.divide(-5, -2));
  23:          // No/same number 5 5 1
  24:          assertEquals(1, Divide.divide(5, 5));
  25:      }
  26:   
  27:      private void testDivideByZero(int a, int b) throws Exception {
  28:          try {
  29:              Divide.divide(a, b);
  30:              fail("My method didn't throw when I expected it to");
  31:          } catch (ArithmeticException e) {
  32:          } catch (Exception e) {
  33:              fail("My method throws different Exception when I expect ArithmeticException");
  34:          }
  35:      }
  36:  }
The above approach makes the Test class cumbersome and difficult for other developers to understand the test scenarios. To avoid this, We can load the test data from an Excel/CSV/WIKI and validate the output instead of running the same TestNg/Junit test method with different inputs. And also this helps in the Documentation of the test cases that we have already identified and tested.

Proposed Method :


   1:  @RunWith(Parameterized.class)
   2:  public class DataDrivenTestsWithSpreadsheetTest { 
   3:   
   4:      private int a;
   5:      private int b;
   6:      private int aDivideB;
   7:     
   8:      @Parameters
   9:      public static Collection<Object[]> spreadsheetData() throws IOException {
  10:          InputStream spreadsheet = new FileInputStream("src/test/resources/aDivideB.xls");
  11:          return new SpreadsheetData(spreadsheet).getData();
  12:      }
  13:   
  14:      public DataDrivenTestsWithSpreadsheetTest(int a, int b, int aDivideB) {
  15:          super();
  16:          this.a = a;
  17:          this.b = b;
  18:          this.aDivideB = aDivideB;
  19:      }
  20:      
  21:      private void testDivideByZero(int a, int b) throws Exception {
  22:          try {
  23:              Divide.divide(a, b);
  24:              fail("My method didn't throw when I expected it to");
  25:          } catch (ArithmeticException e) {
  26:          } catch (Exception e) {
  27:              fail("My method throws different Exception when I expect ArithmeticException");
  28:          }
  29:      }
  30:   
  31:      @Test
  32:      public void shouldCalculateADivideB() {
  33:        if(b==0){
  34:            testDivideByZero(a, b);
  35:        }
  36:        else
  37:            assertEquals(aDivideB, Divide.divide(a, b));
  38:      }
  39:  }

Advantages: 
  1.  Adding new Test scenarios is easy as it requires just adding a new row in the excel/csv/wiki.
  2. Helps in the documentation of the test cases that we have identified and tested.