Skip to content

Commit 4dff67c

Browse files
committed
testing: improve test coverage NodeStackTest
1 parent 3304cf2 commit 4dff67c

File tree

1 file changed

+180
-1
lines changed

1 file changed

+180
-1
lines changed

src/test/java/com/thealgorithms/datastructures/stacks/NodeStackTest.java

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,25 @@
44
import static org.junit.jupiter.api.Assertions.assertFalse;
55
import static org.junit.jupiter.api.Assertions.assertThrows;
66
import static org.junit.jupiter.api.Assertions.assertTrue;
7+
import static org.junit.jupiter.api.Assertions.assertNull;
78

89
import org.junit.jupiter.api.Test;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.DisplayName;
912

1013
class NodeStackTest {
1114

15+
private NodeStack<Integer> intStack;
16+
private NodeStack<String> stringStack;
17+
18+
@BeforeEach
19+
void setUp() {
20+
intStack = new NodeStack<>();
21+
stringStack = new NodeStack<>();
22+
}
23+
1224
@Test
25+
@DisplayName("Test push operation")
1326
void testPush() {
1427
NodeStack<Integer> stack = new NodeStack<>();
1528
stack.push(10);
@@ -18,6 +31,7 @@ void testPush() {
1831
}
1932

2033
@Test
34+
@DisplayName("Test pop operation")
2135
void testPop() {
2236
NodeStack<String> stack = new NodeStack<>();
2337
stack.push("First");
@@ -27,12 +41,14 @@ void testPop() {
2741
}
2842

2943
@Test
44+
@DisplayName("Test pop on empty stack throws exception")
3045
void testPopOnEmptyStack() {
3146
NodeStack<Double> stack = new NodeStack<>();
3247
assertThrows(IllegalStateException.class, stack::pop, "Popping an empty stack should throw IllegalStateException.");
3348
}
3449

3550
@Test
51+
@DisplayName("Test peek operation")
3652
void testPeek() {
3753
NodeStack<Integer> stack = new NodeStack<>();
3854
stack.push(5);
@@ -43,12 +59,14 @@ void testPeek() {
4359
}
4460

4561
@Test
62+
@DisplayName("Test peek on empty stack throws exception")
4663
void testPeekOnEmptyStack() {
4764
NodeStack<String> stack = new NodeStack<>();
4865
assertThrows(IllegalStateException.class, stack::peek, "Peeking an empty stack should throw IllegalStateException.");
4966
}
5067

5168
@Test
69+
@DisplayName("Test isEmpty method")
5270
void testIsEmpty() {
5371
NodeStack<Character> stack = new NodeStack<>();
5472
assertTrue(stack.isEmpty(), "Newly initialized stack should be empty.");
@@ -59,6 +77,7 @@ void testIsEmpty() {
5977
}
6078

6179
@Test
80+
@DisplayName("Test size method")
6281
void testSize() {
6382
NodeStack<Integer> stack = new NodeStack<>();
6483
assertEquals(0, stack.size(), "Size of empty stack should be 0.");
@@ -70,4 +89,164 @@ void testSize() {
7089
stack.pop();
7190
assertEquals(0, stack.size(), "Size should be 0 after popping all elements.");
7291
}
73-
}
92+
93+
@Test
94+
@DisplayName("Test push and pop with null values")
95+
void testPushPopWithNull() {
96+
stringStack.push(null);
97+
stringStack.push("not null");
98+
stringStack.push(null);
99+
100+
assertEquals(3, stringStack.size(), "Stack should contain 3 elements including nulls");
101+
assertNull(stringStack.pop(), "Should pop null value");
102+
assertEquals("not null", stringStack.pop(), "Should pop 'not null' value");
103+
assertNull(stringStack.pop(), "Should pop null value");
104+
assertTrue(stringStack.isEmpty(), "Stack should be empty after popping all elements");
105+
}
106+
107+
@Test
108+
@DisplayName("Test LIFO (Last In First Out) behavior")
109+
void testLifoBehavior() {
110+
int[] values = {1, 2, 3, 4, 5};
111+
112+
// Push values in order
113+
for (int value : values) {
114+
intStack.push(value);
115+
}
116+
117+
// Pop values should be in reverse order
118+
for (int i = values.length - 1; i >= 0; i--) {
119+
assertEquals(values[i], intStack.pop(), "Elements should be popped in LIFO order");
120+
}
121+
}
122+
123+
@Test
124+
@DisplayName("Test peek doesn't modify stack")
125+
void testPeekDoesNotModifyStack() {
126+
intStack.push(1);
127+
intStack.push(2);
128+
intStack.push(3);
129+
130+
int originalSize = intStack.size();
131+
int peekedValue = intStack.peek();
132+
133+
assertEquals(3, peekedValue, "Peek should return top element");
134+
assertEquals(originalSize, intStack.size(), "Peek should not change stack size");
135+
assertEquals(3, intStack.peek(), "Multiple peeks should return same value");
136+
assertFalse(intStack.isEmpty(), "Peek should not make stack empty");
137+
}
138+
139+
@Test
140+
@DisplayName("Test mixed push and pop operations")
141+
void testMixedOperations() {
142+
// Test interleaved push/pop operations
143+
intStack.push(1);
144+
assertEquals(1, intStack.pop());
145+
assertTrue(intStack.isEmpty());
146+
147+
intStack.push(2);
148+
intStack.push(3);
149+
assertEquals(3, intStack.pop());
150+
intStack.push(4);
151+
assertEquals(4, intStack.peek());
152+
assertEquals(2, intStack.size());
153+
154+
assertEquals(4, intStack.pop());
155+
assertEquals(2, intStack.pop());
156+
assertTrue(intStack.isEmpty());
157+
}
158+
159+
@Test
160+
@DisplayName("Test stack with duplicate values")
161+
void testStackWithDuplicates() {
162+
intStack.push(1);
163+
intStack.push(1);
164+
intStack.push(1);
165+
166+
assertEquals(3, intStack.size(), "Stack should handle duplicate values");
167+
assertEquals(1, intStack.peek(), "Peek should return duplicate value");
168+
169+
assertEquals(1, intStack.pop(), "Should pop first duplicate");
170+
assertEquals(1, intStack.pop(), "Should pop second duplicate");
171+
assertEquals(1, intStack.pop(), "Should pop third duplicate");
172+
assertTrue(intStack.isEmpty(), "Stack should be empty after popping all duplicates");
173+
}
174+
175+
@Test
176+
@DisplayName("Test stack with different data types")
177+
void testDifferentDataTypes() {
178+
NodeStack<Character> charStack = new NodeStack<>();
179+
NodeStack<Boolean> booleanStack = new NodeStack<>();
180+
181+
// Test with Character
182+
charStack.push('A');
183+
charStack.push('Z');
184+
assertEquals('Z', charStack.peek(), "Should handle Character values");
185+
186+
// Test with Boolean
187+
booleanStack.push(true);
188+
booleanStack.push(false);
189+
assertEquals(false, booleanStack.peek(), "Should handle Boolean values");
190+
}
191+
192+
@Test
193+
@DisplayName("Test stack state consistency after exceptions")
194+
void testStateConsistencyAfterExceptions() {
195+
// Stack should remain consistent after exception-throwing operations
196+
intStack.push(1);
197+
intStack.push(2);
198+
199+
// Try to peek and pop normally first
200+
assertEquals(2, intStack.peek());
201+
assertEquals(2, intStack.pop());
202+
assertEquals(1, intStack.size());
203+
204+
// Pop remaining element
205+
assertEquals(1, intStack.pop());
206+
assertTrue(intStack.isEmpty());
207+
208+
// Now stack is empty, operations should throw exceptions
209+
assertThrows(IllegalStateException.class, intStack::peek);
210+
assertThrows(IllegalStateException.class, intStack::pop);
211+
212+
// Stack should still be in valid empty state
213+
assertTrue(intStack.isEmpty());
214+
assertEquals(0, intStack.size());
215+
216+
// Should be able to push after exceptions
217+
intStack.push(3);
218+
assertFalse(intStack.isEmpty());
219+
assertEquals(1, intStack.size());
220+
assertEquals(3, intStack.peek());
221+
}
222+
223+
@Test
224+
@DisplayName("Test single element stack operations")
225+
void testSingleElementStack() {
226+
intStack.push(2);
227+
228+
assertFalse(intStack.isEmpty(), "Stack with one element should not be empty");
229+
assertEquals(1, intStack.size(), "Size should be 1");
230+
assertEquals(2, intStack.peek(), "Peek should return the single element");
231+
assertEquals(1, intStack.size(), "Peek should not change size");
232+
233+
assertEquals(2, intStack.pop(), "Pop should return the single element");
234+
assertTrue(intStack.isEmpty(), "Stack should be empty after popping single element");
235+
assertEquals(0, intStack.size(), "Size should be 0 after popping single element");
236+
}
237+
238+
@Test
239+
@DisplayName("Test toString method if implemented")
240+
void testToString() {
241+
// This test assumes NodeStack has a toString method
242+
// If not implemented, this test can be removed or NodeStack can be enhanced
243+
intStack.push(1);
244+
intStack.push(2);
245+
intStack.push(3);
246+
247+
String stackString = intStack.toString();
248+
// Basic check that toString doesn't throw exception and returns something
249+
assertTrue(stackString != null, "toString should not return null");
250+
assertTrue(stackString.length() > 0, "toString should return non-empty string");
251+
}
252+
}

0 commit comments

Comments
 (0)