Test Your Code in a Coding Interview Before the Interviewer Has To

- Validation bias makes you reach for happy-path inputs; fight it with a fixed three-category framework run every single time.
- Typical case, boundary case, adversarial case in that order: catch obvious crashes before hunting subtle bugs.
- Derive edge cases from your loop invariant rather than guessing; anything that threatens the invariant is a test case.
- Write variable values down at each step; candidates who declare correctness by inspection miss bugs at an alarming rate.
- Pattern-specific checklists for arrays, linked lists, trees, graphs, and sorting mean you never blank on what to verify.
- Proactive corner case testing before the interviewer prompts scores as "Leaning Hire"; waiting until prompted scores as "Leaning No Hire".
- Catching and fixing your own bug in 30 seconds looks dramatically better than submitting untested code the interviewer then breaks.
You finish writing your solution. The provided example passes. You say "I think this looks correct" and lean back slightly, doing that thing where you stare at your own code with quiet satisfaction.
The interviewer types something. "What happens if the array is empty?"
Your function crashes on line three.
You just handed the interviewer a "Strong No Hire" data point for free. The Testing dimension of the rubric literally reads: "Did not even test code against typical cases. Did not spot glaring bugs in the code." The fix costs you three minutes. Most candidates skip it anyway.
Your Brain Is Working Against You
When you write code, you already believe it works. That belief is the problem.
Confirmation bias makes you unconsciously reach for test cases that confirm your implementation rather than expose its failures. You wrote a two-pointer solution that swaps left and right toward the middle, so naturally you test an array where the traversal goes smoothly. You skip the case where left and right start at the same index. You skip the empty array. You skip the single-element array. Those are exactly where your loop condition is probably wrong.
This is why QA engineers exist as a separate profession. The person who wrote the code is literally the worst person to test it. You wrote it with a mental model, so you test it with that same mental model, and the inputs that expose the flaw are the ones that fall outside the model you can't see past.
The fix is not "try harder to think of edge cases." The fix is a framework you run every time, one that does not depend on inspiration or self-awareness in the moment.
Cherry-picking the happy path in tests. Then running everything. Then discovering your mistake in real time.
Three Categories, Always in This Order
Every solution you write needs coverage across exactly three buckets.
The typical case. A medium-sized input that exercises the main path of your algorithm. If the problem gives you an example, this is usually it. Run it first. If the basic case is broken, nothing else matters.
The boundary cases. The inputs at the edges of the valid range. The empty input. The single-element input. The all-negative numbers case if your problem involves summing. The all-same-value case if your algorithm partitions or sorts. Boundary cases are where loop conditions go wrong, where off-by-one errors live, and where null pointer dereferences happen.
The adversarial case. The input specifically designed to break the pattern your algorithm assumes. If you wrote a left-to-right algorithm, test an input where the answer lives at the very end. If you wrote a greedy algorithm, construct a case where the greedy choice looks locally wrong, or verify the proof holds. If your solution handles duplicates, test a list that is all duplicates.
Work through them in that order. Typical first, boundary second, adversarial third. Catch obvious crashes before you spend time on subtle ones.
Derive From Your Invariant, Not Your Intuition
Instead of guessing which edge cases exist, derive them from the invariant your algorithm maintains.
Every correct algorithm has a loop invariant: a property that stays true before the first iteration and after every subsequent one. If you can state the invariant, you can mechanically generate the test cases that threaten it.
Binary search maintains the invariant that the answer, if it exists, lives within [left, right]. That invariant is threatened by: an empty array, a single-element array where left == right immediately, a target that does not exist, and a target at position 0 or n-1. You do not have to guess these. They fall directly out of "what could make my invariant false before I expect it to be?"
A sliding window maintains the invariant that the window contains a valid subproblem. Test it with: all elements satisfying the condition (window never shrinks), no elements satisfying the condition (window never expands), a single element, and a window that reaches the last index before finding the answer.
# Testing a sliding window for max sum subarray of length k def max_subarray_sum(nums: list[int], k: int) -> int: window = sum(nums[:k]) best = window for i in range(k, len(nums)): window += nums[i] - nums[i - k] best = max(best, window) return best # Typical case assert max_subarray_sum([2, 1, 5, 1, 3, 2], 3) == 9 # Boundary: k equals length (single window) assert max_subarray_sum([1, 2, 3], 3) == 6 # Boundary: all negatives assert max_subarray_sum([-1, -2, -3, -4], 2) == -3 # Adversarial: answer at the end assert max_subarray_sum([1, 1, 1, 10, 10, 10], 3) == 30
You do not have to write assertion statements in an interview. Trace through each case in your head or on the shared editor, narrating what the variables hold at each step.
Write the Variables Down
When you walk through a test case, do not just stare at the code and nod. Staring at code and nodding is not testing. It is hoping.
Pick your test input. For each iteration or meaningful step, write the current values of every variable that changes. The interviewer sees a column-by-column accounting of your algorithm's state, which proves you understand what your code actually does rather than just what you intended.
Candidates who declare correctness by inspection miss bugs in their own code at a rate that is genuinely uncomfortable to think about.
Test: nums = [2, 1, 5, 1, 3, 2], k = 3
Initial: window = 2+1+5 = 8, best = 8
i=3: window = 8 + 1 - 2 = 7, best = 8
i=4: window = 7 + 3 - 1 = 9, best = 9
i=5: window = 9 + 2 - 5 = 6, best = 9
Result: 9 ✓
Three lines. Thirty seconds. If your trace produces a different value than you anticipated, you found a bug. That is the point.
For linked list problems, draw the nodes. For tree problems, sketch the two or three node examples that reveal your recursion's base case behavior. The habit of externalizing state is what matters. If you find a bug this way, the approach for fixing it under pressure is in Debugging in a Coding Interview.
Every Pattern Has Predictable Failures
Know these cold and you will never blank on what to test.
Arrays and strings: empty input, length 1, all-same elements, input already in the target state, negative numbers if you are summing.
Linked lists: null head, single node, two nodes, target at the head, target at the tail. If the problem involves cycles, test a list with no cycle and one where the cycle begins at the head.
Binary trees and BSTs: null root, single node, a tree that degenerates into a linked list (all left or all right children), a perfect binary tree. For BSTs, test the minimum and maximum value nodes.
Graphs: no edges, a single isolated node, a disconnected graph, source equals destination.
Sorting or partition: all elements equal, already sorted, reverse sorted, two elements.
You will not hit every case in a 45-minute interview. Pick the three most likely to expose a bug in your specific implementation and say so out loud: "I want to check the empty case, the single-element case, and an input where the answer is at index zero, because that is where my left-pointer logic is most likely wrong."
That narration is itself a scoring signal.
How to Test Before They Ask
The Tech Interview Handbook rubric says it plainly. A candidate who does not test code against typical cases before prompting is a "Strong No Hire." A candidate who tests typical cases but misses corner cases is "Leaning No Hire." A candidate who proactively identifies and handles corner cases, and catches their own bugs independently, is "Leaning Hire" to "Strong Hire." Testing is one of the five signals beyond the answer that interviewers score, and it is the easiest one to get right with a system.
The dividing line is before versus after the interviewer prompts you.
When you finish coding, do not say "I think that looks right." Say "Let me walk through a few test cases before we move on." Then run your three categories. If you find a bug, fix it calmly and narrate the fix. The write-up your interviewer submits has a field for "did the candidate self-correct bugs" and another for "did they handle corner cases." Those boxes do not fill themselves. What Your Interviewer Is Writing While You Think walks through what ends up in that document.
SpaceComplexity mock interviews score the Testing dimension explicitly, so you get feedback after every session on whether your verification was proactive and comprehensive, not just whether your final code was correct.
The behavior you practice is the behavior you execute under pressure. Running three test categories every time you finish a problem, even in casual practice, makes it automatic in the interview.
Why Proactive Testing Feels Hard
Most candidates skip testing because they are afraid of finding a bug. The logic goes: if your code passes and you declare done, there is a chance the interviewer will not probe further. If you test your own code and break it, you have to fix it, and now you might run out of time.
This logic is completely backwards, and everyone who has interviewed a lot knows it.
"I think this looks correct" is the interview equivalent of "it works on my computer." Endearing. Terminal.
Interviewers expect bugs. What they do not expect is a candidate who catches and fixes them independently. A candidate who tests proactively, finds a bug, says "my loop condition should be < n not <= n," and fixes it in 30 seconds looks dramatically more capable than a candidate who submits untested code and waits.
The interviewer is going to find the bug either way. The only question is whether you find it first.
Further Reading
- Software Testing: Boundary Value Analysis vs Equivalence Partitioning - GeeksforGeeks
- How candidates are evaluated in coding interviews at top tech companies - Tech Interview Handbook
- Off-by-one error - Wikipedia
- Linked list cheatsheet for coding interviews - Tech Interview Handbook
- Coming up with good test cases for coding interviews - Educative