JUnit – Building a Test Suite for Calculator

In this tutorial, you will learn how to build a JUnit test suite for a simple calculator application, how to create test classes for different calculator operations, combine them into a test suite, and execute all tests simultaneously using JUnit.

A test suite allows you to group multiple related test classes and run them together as a single unit. This approach is particularly useful for testing modular applications like a calculator, where individual functionalities such as addition, subtraction, multiplication, and division can be tested independently and collectively.


What is a Test Suite?

A test suite in JUnit is a way to group multiple test classes into a single unit, enabling you to execute all related tests together. It is particularly useful for modular applications, as it ensures that all functionalities are tested collectively and no feature is overlooked.

  • Modular Testing: Groups tests for individual components.
  • Efficient Execution: Runs all related tests together, saving time.
  • Regression Testing: Ensures that changes in one module do not affect others.

Steps to Build a Test Suite for Calculator

1 Define the Calculator Class

Create a simple Calculator class that implements basic arithmetic operations:

</>
Copy
public class Calculator {

    public int add(int a, int b) {
        return a + b;
    }

    public int subtract(int a, int b) {
        return a - b;
    }

    public int multiply(int a, int b) {
        return a * b;
    }

    public double divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Cannot divide by zero");
        }
        return (double) a / b;
    }
}

2 Create Test Classes

Write individual test classes for each operation: addition, subtraction, multiplication, and division.

Addition Test Class

</>
Copy
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class AdditionTest {

    private final Calculator calculator = new Calculator();

    @Test
    void testAddition() {
        assertEquals(5, calculator.add(2, 3));
        assertEquals(0, calculator.add(-1, 1));
        assertEquals(-3, calculator.add(-1, -2));
    }
}

Subtraction Test Class

</>
Copy
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class SubtractionTest {

    private final Calculator calculator = new Calculator();

    @Test
    void testSubtraction() {
        assertEquals(1, calculator.subtract(3, 2));
        assertEquals(-2, calculator.subtract(-1, 1));
        assertEquals(1, calculator.subtract(-1, -2));
    }
}

Multiplication Test Class

</>
Copy
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;

class MultiplicationTest {

    private final Calculator calculator = new Calculator();

    @Test
    void testMultiplication() {
        assertEquals(6, calculator.multiply(2, 3));
        assertEquals(-3, calculator.multiply(-1, 3));
        assertEquals(2, calculator.multiply(-1, -2));
    }
}

Division Test Class

</>
Copy
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class DivisionTest {

    private final Calculator calculator = new Calculator();

    @Test
    void testDivision() {
        assertEquals(2.0, calculator.divide(6, 3));
        assertEquals(-0.5, calculator.divide(-1, 2));
    }

    @Test
    void testDivisionByZero() {
        assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0));
    }
}

3 Create the Test Suite

Create a test suite to group all the test classes:

</>
Copy
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({ AdditionTest.class, SubtractionTest.class, MultiplicationTest.class, DivisionTest.class })
class CalculatorTestSuite {
    // No implementation needed, annotations handle the suite execution.
}

4 Run the Test Suite

Execute the CalculatorTestSuite class from your IDE or build tool. JUnit will automatically detect and run all the tests in the specified classes.


Best Practices for Test Suites

  • Modular Tests: Keep each test class focused on a specific functionality.
  • Isolate Tests: Ensure that each test is independent and does not rely on others.
  • Run Frequently: Include test suites in your CI/CD pipeline for continuous validation.
  • Use Meaningful Names: Name your test classes and suite descriptively to reflect their purpose.
  • Combine Suites: Create nested test suites for grouping related suites, such as “Arithmetic Tests” and “Advanced Tests.”