DEV Community

Nico Reyes
Nico Reyes

Posted on

My Python tests passed. Production still broke.

Deployed yesterday. Tests green. Production crashed 3 hours later.

The bug? A datetime object I created in tests wasn't aware of timezones. Production API expects UTC timestamps. My test just used datetime.now() which returns naive datetime. Code looked fine, tests passed, production exploded.

# What I was doing (broken)
from datetime import datetime

def get_report_timestamp():
    return datetime.now()  # naive datetime, no timezone

# Tests passed because I compared it to another naive datetime
assert get_report_timestamp() < datetime.now()
Enter fullscreen mode Exit fullscreen mode

Production error logs just said "invalid timestamp format". Took me 2 hours to figure out the datetime was missing timezone info. The API rejected it, my code couldn't parse the error properly, whole system stalled.

# What actually works
from datetime import datetime, timezone

def get_report_timestamp():
    return datetime.now(timezone.utc)  # aware datetime with UTC

# Better test that would've caught this
assert get_report_timestamp().tzinfo is not None
Enter fullscreen mode Exit fullscreen mode

Ended up changing a few things.

Always use datetimes with timezones now. datetime.now(timezone.utc) instead of datetime.now(). Adds 15 characters. Prevents production fires.

Test timezone behavior directly. Added assert dt.tzinfo is not None to every datetime test. Catches naive datetimes before deploy.

Log the actual datetime object, not just "timestamp invalid". Now I do logger.error(f"Bad timestamp: {dt} (tzinfo: {dt.tzinfo})"). Makes debugging way faster when things break.

Still annoyed tests didn't catch this. The assertion passed because Python lets you compare two naive datetimes. Both wrong in the same way so comparison works. Production API was stricter.

Probably a linter rule for this somewhere.

Top comments (0)