Junior Programmer study materials
Junior Programmer study resources

Junior Programmer: Error Handling, Debugging, and Basic Testing Practices

Junior Programmer · Work through your exam, one topic at a time.

All guide sections

Error Handling, Debugging, and Basic Testing Practices

Error handling, debugging, and testing cover what happens when code does not do what you intended. The exam tests the difference between error categories, correct use of exceptions, and how to write a test that would actually catch a regression.

Error categories

Syntax errors stop the program from running at all. Runtime exceptions occur during execution: ZeroDivisionError, IndexError, KeyError, TypeError, FileNotFoundError. Logic errors run but produce the wrong answer. Recognising the category narrows the search immediately.

Exceptions

try/except/finally (or try/catch/finally) lets you handle anticipated failures. Catch the specific exception you expect, and let the rest propagate. finally runs whether or not an exception occurred, including when the try block returns. raise re-raises or throws deliberately; custom exception classes express domain failures. Reading a traceback from the bottom up gives the exception type and message, then the call chain.

Debugging and testing

Debugging is systematic: reproduce, isolate, inspect state (print, logging, breakpoint), form a hypothesis, change one thing, retest. Unit tests call a function with known inputs and assert on the output. Good tests cover normal cases, boundaries (0, empty, maximum), and invalid input, and they fail for the right reason.

Worked example

def safe_div(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        return None
    finally:
        print('done')

Calling safe_div(1, 0) returns None and still prints 'done', because finally executes before the function actually returns. Replacing the specific clause with a bare except: would also hide a TypeError from bad input, masking a real bug.

Traps

  • A bare except: swallowing every error, including typos.
  • Ordering handlers so a parent exception catches before the specific one.
  • Using assert for user-facing validation, since assertions can be disabled.
  • Testing only the happy path.
  • Fixing the symptom without reproducing the cause.