Software Testing: Unit Tests, Integration Tests, and TDD

Testing Is Insurance

Untested code is broken code waiting to happen. Testing gives you confidence to change code without fear.

The Testing Pyramid

Many fast unit tests at the base. Some integration tests in the middle. Few E2E tests at the top.

Unit Testing with pytest

def calculate_total(items, discount=0):
    subtotal = sum(i["price"] * i["quantity"] for i in items)
    return subtotal * (1 - discount)

# Tests
def test_basic():
    items = [{"price": 10.00, "quantity": 2}]
    assert calculate_total(items) == 20.00

def test_discount():
    items = [{"price": 100.00, "quantity": 1}]
    assert calculate_total(items, discount=0.1) == 90.00

def test_empty():
    assert calculate_total([]) == 0

JavaScript Testing with Jest

// math.test.js
const { add, divide } = require("./math");

describe("Math utilities", () => {
    test("adds two numbers", () => {
        expect(add(2, 3)).toBe(5);
    });
    
    test("throws on division by zero", () => {
        expect(() => divide(5, 0)).toThrow();
    });
});

TDD: Red-Green-Refactor

  1. Red: Write a failing test
  2. Green: Write minimum code to pass
  3. Refactor: Clean up while tests stay green

Best Practices

  • Each test tests ONE thing
  • Tests should be fast (under 1 second each)
  • Use descriptive test names
  • Test edge cases: empty input, null, extremes
  • Test behavior, not implementation details

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top