View Javadoc
1   /**
2   
3   @file CalculatorTest.java
4   @brief This file contains the test cases for the Calculator class.
5   @details This file includes test methods to validate the functionality of the Calculator class. It uses JUnit 5 (Jupiter) for unit testing.
6   */
7   package com.ucoruh.calculator;
8   
9   import static org.junit.jupiter.api.Assertions.assertEquals;
10  import static org.junit.jupiter.api.Assertions.assertThrows;
11  
12  import org.junit.jupiter.api.BeforeEach;
13  import org.junit.jupiter.api.DisplayName;
14  import org.junit.jupiter.api.Nested;
15  import org.junit.jupiter.api.Test;
16  import org.junit.jupiter.params.ParameterizedTest;
17  import org.junit.jupiter.params.provider.CsvSource;
18  
19  /**
20  
21  @class CalculatorTest
22  @brief This class represents the test class for the Calculator class.
23  @details The CalculatorTest class provides test methods to verify the behavior of the Calculator class: normal
24           operation, boundary values (zero, negative numbers, Integer.MIN_VALUE/MAX_VALUE) and invalid input
25           (division by zero).
26  @author ugur.coruh
27  */
28  class CalculatorTest {
29  
30    private Calculator calculator;
31  
32    @BeforeEach
33    void setUp() {
34      calculator = new Calculator();
35    }
36  
37    @Nested
38    @DisplayName("add")
39    class Add {
40  
41      @Test
42      @DisplayName("adds two positive numbers")
43      void addsPositiveNumbers() {
44        assertEquals(5, calculator.add(2, 3));
45      }
46  
47      @Test
48      @DisplayName("adds a negative and a positive number")
49      void addsNegativeAndPositive() {
50        assertEquals(-1, calculator.add(-4, 3));
51      }
52  
53      @Test
54      @DisplayName("zero is the additive identity")
55      void addZero() {
56        assertEquals(7, calculator.add(7, 0));
57      }
58    }
59  
60    @Nested
61    @DisplayName("subtract")
62    class Subtract {
63  
64      @Test
65      @DisplayName("subtracts two positive numbers")
66      void subtractsPositiveNumbers() {
67        assertEquals(1, calculator.subtract(4, 3));
68      }
69  
70      @Test
71      @DisplayName("result can be negative")
72      void subtractResultingInNegative() {
73        assertEquals(-5, calculator.subtract(0, 5));
74      }
75    }
76  
77    @Nested
78    @DisplayName("multiply")
79    class Multiply {
80  
81      @Test
82      @DisplayName("multiplies two positive numbers")
83      void multipliesPositiveNumbers() {
84        assertEquals(12, calculator.multiply(3, 4));
85      }
86  
87      @Test
88      @DisplayName("multiplying by zero yields zero")
89      void multiplyByZero() {
90        assertEquals(0, calculator.multiply(123, 0));
91      }
92  
93      @Test
94      @DisplayName("multiplying two negatives yields a positive")
95      void multiplyTwoNegatives() {
96        assertEquals(6, calculator.multiply(-2, -3));
97      }
98    }
99  
100   @Nested
101   @DisplayName("divide")
102   class Divide {
103 
104     @Test
105     @DisplayName("divides two positive numbers exactly")
106     void dividesEvenly() {
107       assertEquals(2.0, calculator.divide(6, 3), 0.0001);
108     }
109 
110     @Test
111     @DisplayName("division that does not divide evenly keeps the fraction")
112     void dividesWithRemainder() {
113       assertEquals(1.0 / 3.0, calculator.divide(1, 3), 0.0001);
114     }
115 
116     @Test
117     @DisplayName("dividing by zero throws ArithmeticException (invalid input)")
118     void divideByZeroThrows() {
119       ArithmeticException thrown = assertThrows(ArithmeticException.class, () -> calculator.divide(10, 0));
120       assertEquals("Division by zero", thrown.getMessage());
121     }
122 
123     @Test
124     @DisplayName("zero dividend with a non-zero divisor is zero, not an error")
125     void zeroDividend() {
126       assertEquals(0.0, calculator.divide(0, 42), 0.0001);
127     }
128   }
129 
130   @ParameterizedTest(name = "boundary: {0} {1} {2} = {3}")
131   @DisplayName("boundary values: Integer.MIN_VALUE / Integer.MAX_VALUE")
132   @CsvSource({
133     "2147483647, add, 0, 2147483647",       // Integer.MAX_VALUE + 0
134     "-2147483648, add, 0, -2147483648",      // Integer.MIN_VALUE + 0
135     "0, subtract, 2147483647, -2147483647",  // 0 - Integer.MAX_VALUE
136   })
137   void boundaryValues(int a, String operation, int b, int expected) {
138     int result;
139 
140     switch (operation) {
141       case "add":
142         result = calculator.add(a, b);
143         break;
144 
145       case "subtract":
146         result = calculator.subtract(a, b);
147         break;
148 
149       default:
150         throw new IllegalArgumentException("Unsupported operation in test data: " + operation);
151     }
152 
153     assertEquals(expected, result);
154   }
155 }