bigonotes
DSA: Python & HacksInterview Approach

Test Your Solution Live

A copy-paste test harness for live coding rounds, and how to choose test cases that catch real bugs.

3 min readLast updated Interview Approach

When the interview lets you run code, a small table-driven test harness is the fastest way to show your solution works. Paste it under your solution, fill in a handful of cases grouped by category, and run it. It shows you think about correctness systematically, and when a case fails it prints exactly what went wrong.

Picking test cases#

Aim for 6–10 cases that each test something different:

Category Examples
Happy path The examples from the problem statement
Smallest inputs Empty input, a single element
Boundaries Answer at the very start or end; maximum or minimum values
Repeats All elements the same, many duplicates, zeros
Signs Negative numbers, mixed signs
No answer No valid result exists: does it return 0, -1, []?
Problem-specific traps Whatever made the naive approach wrong (e.g. negatives breaking a sliding window)

Write a short description for each case so a failure explains itself.

The template#

Paste this below your solution. It runs every case, reports crashes separately from wrong answers, and prints a summary.

def run_tests(func, test_cases):
    """test_cases: list of (args_tuple, expected, description)."""
    bar = "=" * 10
    name = func.__name__
    print(f"\n{bar} Running {len(test_cases)} tests for {name} {bar}")
    passed = 0
    for i, (args, expected, desc) in enumerate(test_cases, start=1):
        try:
            result = func(*args)
        except Exception as e:  # crash: report it and keep going
            print(f"ERROR  case {i}: {desc}")
            print(f"       {type(e).__name__}: {e}")
            continue
        if result == expected:
            print(f"PASS   case {i}: {desc}")
            passed += 1
        else:
            print(f"FAIL   case {i}: {desc}")
            print(f"       input:    {args}")
            print(f"       expected: {expected}")
            print(f"       got:      {result}")
    print(f"{bar} {passed}/{len(test_cases)} passed {bar}")

# Usage:
# sol = Solution()
# run_tests(sol.your_method, [
#     ((arg1, arg2), expected, "description"),
#     ...
# ])

A few design choices make this robust:

  • Calling the function outside the comparison means a crash in one case is reported, not mistaken for a failed assertion, and the run continues.
  • Passing the bound method (sol.subarraySum) keeps the harness generic across problems.
  • If the order of the output doesn't matter, compare sorted(result) to sorted(expected) in the case or wrap the function.

Example: Subarray Sum Equals K#

Here is the harness applied to a real problem, with cases grouped by category.

from collections import defaultdict
from typing import List


class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        seen = defaultdict(int)
        # the empty prefix, so subarrays starting at index 0 count
        seen[0] = 1
        prefix = count = 0
        for x in nums:
            prefix += x
            count += seen[prefix - k]
            seen[prefix] += 1
        return count


test_cases = [
    # Happy path
    (([1, 1, 1], 2), 2, "two overlapping [1,1] subarrays"),
    (([1, 2, 3], 3), 2, "[1,2] at the start and [3] at the end"),
    # Smallest inputs
    (([1], 1), 1, "single element equals k"),
    (([5], 1), 0, "single element does not equal k"),
    (([], 0), 0, "empty array"),
    # Repeats / zeros
    (([0, 0, 0], 0), 6, "every subarray of zeros sums to 0"),
    # Negatives: why sliding window fails here
    (([1, -1, 1], 1), 3, "running sum goes down and up"),
    (([1, -1, 0], 0), 3, "negatives and zeros mixed"),
    # No answer
    (([1, 2, 3], 100), 0, "no subarray reaches k"),
]

run_tests(Solution().subarraySum, test_cases)

(run_tests is the function from the template above.)

When you can't run code#

Use the same table as a checklist and dry-run it by hand: trace the variables for one happy-path case, then talk through each edge case. Saying "with an empty array the loop never runs, so we return 0" is often enough.

Key takeaways#

  • Group cases by category: happy path, smallest inputs, boundaries, repeats, signs, no answer.
  • Give each case a description so failures explain themselves.
  • Call the function separately from the comparison so crashes are reported clearly.
  • Include the case that breaks the naive approach; it shows you know why your solution works.
  • Without a runner, dry-run the same table out loud.

Found a mistake? Tell me on LinkedIn ↗

Further reading#