38 / 80 · 12 Programming for QA · Functional Patterns for Testing← prev⊞ allnext →☰ Read as one page
5.4Higher-Order Functions
A higher-order function takes a function as an argument or returns a function. They are the building blocks of flexible test utilities.
Custom Assertion Builder
def assert_response(response, status=None, contains=None, excludes=None):
"""Flexible response assertion."""
if status is not None:
assert response.status_code == status, \
f"Expected {status}, got {response.status_code}: {response.text[:200]}"
if contains is not None:
body = response.json()
for key in contains:
assert key in body, f"Response missing field: {key}"
if excludes is not None:
body = response.json()
for key in excludes:
assert key not in body, f"Response contains forbidden field: {key}"
# Usage
assert_response(r, status=200, contains=["id", "name"], excludes=["password"])
Test Data Generator
def make_user_factory(defaults: dict):
"""Creates a factory that generates user data with overrides."""
counter = 0
def create(**overrides):
nonlocal counter
counter += 1
user = {**defaults, **overrides}
user["email"] = user.get("email", f"testuser{counter}@test.com")
return user
return create
create_user = make_user_factory({"role": "viewer", "active": True})
# Each call creates a unique user with defaults
user1 = create_user() # testuser1@test.com, viewer, active
user2 = create_user(role="admin") # testuser2@test.com, admin, active
user3 = create_user(email="custom@test.com") # custom@test.com, viewer, active