Refactoring safely with tests

Refactoring means changing the internal structure of code to make it easier to understand and change, without changing what it does. It is done in small steps, and after each step you check that behavior is still the same. Without checks, refactoring turns into risky rewriting.

Python
def shipping_before(weight, express):
    if express == True:
        if weight <= 1:
            return 15
        else:
            if weight <= 5:
                return 25
            else:
                return 40
    else:
        if weight <= 1:
            return 5
        else:
            if weight <= 5:
                return 10
            else:
                return 20


RATES = [(1, 5, 15), (5, 10, 25)]


def shipping_after(weight, express):
    for limit, standard, fast in RATES:
        if weight <= limit:
            return fast if express else standard
    return 40 if express else 20


cases = [(w, e) for w in (0, 1, 1.5, 5, 5.1, 50) for e in (False, True)]
assert all(shipping_before(w, e) == shipping_after(w, e) for w, e in cases)
print(len(cases), "cases identical")
print(shipping_after(3, True), shipping_after(30, False))
Read the full lesson