Java Unit Testing with JUnit

Image Source: https://junit.org/

In this tutorial post, i have written about unit testing and use of JUnit framework for Testing in Java programming. The first section of this article includes the unit testing example outside the IDE and second section includes the unit testing example using IntelliJ IDEA.

What is Unit Testing?

Unit testing is a software development process where smallest testable parts are individually and independently tested. Purpose of unit testing is to validate each unit of the program / software are functioning as designed. Also, This fixes bugs early in development.

What is JUnit?

junit.org : "JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks".

JUnit is a unit testing framework for Java programming. JUnit is open source and popular unit testing framework for Java programming.

Approach " test a little, code a little, test a little, code a little ".

How do we perform unit testing ?

  • Make a testing plan
  • Prepare Test cases
    • A unit test case is actually a part of code itself which ensures the another part of code is working or not.
    • For effective testing, at least two test cases are prepared, Positive and Negative.
  • Test
I assumed that you have already install JDK and configure environment variables. Lets perform unit testing with Interest calculator example which calculates the interest using formula:

I = PTR / 100

Unit Testing ( No IDE)

  1. Download JUnit.jar and Hamcrest-core.jar.
    • junit-4.12.jar ( link )
    • hamcrest-core-1.3.jar ( link )
  2. Create a project directory, copy these jars to the newly created directory. All java files and classes are stored inside the directory.
  3. Create Calculator.java, that includes the main logic of calculating the Interest and logic will be like this, private declared variables, one constructor to update these values and a method to calculate Interest.
    1. public class Calculator{
      
       // default values
       double p = 0.0;
       double t = 0.0;
       double r = 0.0;
      
       // constructor that updates the values
       public Calculator(double p, double t, double r){
        this.p = p;
        this.t = t;
        this.r = r;
       }
      
       // method that calculates the interest
       public double calculateInterest(){
        return p*t*r / 100;
       }
      }
      
  4. Create TestCalculator.java, this is where you compare the results. This is our test class to test Calculator's calculateInterest() logic. Annotation @Before tells that to executes before every test executes, and @Test identifies test method. ( Other annotations are also described at bottom of the page)

    We simply take known values of principal amount(P), time(T) and rate(R), Assume, P = 10000, T = 1 year, R = 10.

    Manual calculation, Interest (I) = P * T * R  / 100;
    I = 10000 * 1 * 10 / 100 = 1000

    So, if calculateInterest() has correct logic of calculation interest then it must return 1000 as I for these assumed P, T, R values. assertEquals throws an exception if mismatched occurs.
    1. import org.junit.Test;
      import org.junit.Before;
      import static org.junit.Assert.assertEquals;
      
      public class TestCalculator{
      
       Calculator calculator = null;
      
       // values for your test case
       double p = 10000.0;
       double t = 1.0;
       double r = 10.0;
      
       // this run at every test, look Annotations
       @Before
       public void setUp() throws Exception{
        calculator = new Calculator(p, t, r);
       }
      
       // TEST, look Annotations
       @Test
       public void testCalculateInterest(){
        assertEquals(1000.0, calculator.calculateInterest(), 0.0);
       }
      }
      
  5. Create TestRunner.java, this includes the test classes to perform test. This class is created to include all test classes that we need to test. You can select multiple classes to perform test and included as runClasses( testClass1.class, testClass2.class, .. )
    1. import org.junit.runner.JUnitCore;
      import org.junit.runner.Result;
      import org.junit.runner.notification.Failure;
      
      public class TestRunner{
      
       public static void main(String[] str){
      
        // Run test classes and grab result
        Result result = JUnitCore.runClasses(TestCalculator.class);
      
        // Test result
        System.out.println(result.wasSuccessful());
      
        // print the failure message if failure
        for(Failure failure : result.getFailures()){
         // print string 
         System.out.println(failure.toString());
        }
      
       }
      }
      
  6. Compile with JUnit and hamcrest.
    javac -classpath junit-4.12.jar;hamcrest-core-1.3.jar;. Calculator.java TestCalculator.java TestRunner.java 
  7. Now run, reminder : TestRunner includes the main method,
    java -classpath junit-4.12.jar;hamcrest-core-1.3.jar;. TestRunner
    
    
  8. And yey,test is successful, now try to change the values of P, T, R or change logic of calculateInterest() and see what failure messages are reported.


Annotations: (imported as import org.junit.*)
  1. BeforeClass : Executes only one time before any test starts.
  2. Before : Executes every time before any test.
  3. Test : Identifies as test method.
    1. Test(expected = Exception )
      • Used when an exception is expected of type Exception, fails otherwise
    2. Test(timeout = milliseconds
      • Used when test needs to be completed within the defined milliseconds, fails otherwise.
  4. Ignore : Identifies as not to include in current test, or not implemented yet.
  5. After: Executes every time after any test.
  6. AfterClass : Executes only one time after all test finishes.


Continue (IntelliJ IDEA for Unit Testing)

References:

Comments

Popular Posts