A few weeks ago, I introduced Timetracer in my previous post: "I Got Tired of 'It Works on My Machine' So I Built a Time-Travel Debugger".
The tool allows you to record API interactions (including dependencies like databases and external APIs) and replay them locally to debug production issues.
The initial version focused on FastAPI and Flask. However, the most frequent feedback I received was the need for Django support and better integration with pytest suites.
I just released v1.4.0, which adds both.
Here is why this matters and how it works.
Why This Matters
1. No More "Enterprise Setup" Pain
Django is often used for large, mature applications. These apps tend to have complex dependencies, specific database states, VPN-locked APIs, or legacy SOAP services that are a pain to run locally.
With Timetracer's new middleware, you can record a session from a staging environment (or a colleague's machine that actually works) and replay it on your machine. You get the full app behavior without needing the full enterprise infrastructure running on localhost.
2. Tests That Don't Lie
We've all written tests with unittest.mock where we guess what the API returns. Then the API changes, our mock stays the same, the test passes, but production breaks.
The new pytest integration replaces brittle mocks with real, recorded interactions. Your tests run against actual data snapshots, making them far more reliable than manual mocks.
Django Support
Timetracer now includes middleware that works with Django 3.2 LTS and newer. It supports both standard synchronous views and the newer async views in Django 4.1+.
The integration captures:
- Incoming HTTP requests
- Outbound API calls (requests, httpx, aiohttp)
- Database queries (via SQLAlchemy for now, native ORM soon)
- Redis operations
Setting it up
First, install the package with Django dependencies:
pip install timetracer[django,requests]
Then add the middleware in your settings.py. It usually works best near the top of the list so it can capture everything:
# settings.py
MIDDLEWARE = [
'timetracer.integrations.django.TimeTracerMiddleware',
# ... other middleware
]
# Optional configuration
TIMETRACER = {
'MODE': 'record', # 'record', 'replay', or 'off'
'CASSETTE_DIR': './cassettes',
}
If your app makes external API calls, you should enable the plugins in your AppConfig or settings.py:
# myapp/apps.py or settings.py
from timetracer.integrations.django import auto_setup
# Enable recording for the requests library
auto_setup(plugins=['requests'])
Workflow
- Run your server:
python manage.py runserver - Browse your site. Timetracer saves JSON "cassettes" for each request.
- To debug a specific request later, restart with
TIMETRACER_MODE=replay. - The server will now mock all external calls using the recorded data.
pytest Integration
Previously, using recorded cassettes in tests required manual setup. v1.4.0 adds a pytest plugin that automatically registers fixtures when you install the package.
This allows you to write integration tests that don't need live external APIs but still exercise your full stack.
Using the Fixtures
The plugin provides three main fixtures:
1. timetracer_replay
Use this to run a test against a pre-recorded session. It guarantees the test runs exactly the same way every time.
def test_user_profile(timetracer_replay, client):
# 'user_profile.json' contains the recorded interaction
with timetracer_replay("cassettes/user_profile.json"):
response = client.get("/api/users/123")
assert response.status_code == 200
assert response.json()['username'] == 'testuser'
2. timetracer_record
Use this when writing a new test case. It captures the interaction so you can save it as a cassette.
def test_new_feature(timetracer_record, client):
# This will execute real network calls and save the result
with timetracer_record("cassettes/new_feature.json"):
response = client.get("/api/new-feature")
assert response.status_code == 200
3. timetracer_auto
This is useful for TDD. If the cassette doesn't exist, it records. If it does exist, it replays.
def test_checkout_flow(timetracer_auto, client):
# Records first time, replays subsequently
with timetracer_auto("cassettes/checkout.json"):
response = client.post("/api/checkout", {'cart_id': 'abc'})
assert response.status_code == 200
Async Support (aiohttp)
We also added a plugin for aiohttp. Building high-concurrency apps often requires async HTTP clients, and aiohttp is a popular choice alongside httpx.
Timetracer now correctly intercepts and records aiohttp.ClientSession requests, capturing the full async flow.
What's Next
The goal remains effective local debugging. If you are using Django or pytest, I'd appreciate you trying this out and letting me know if it helps simplify your debugging workflow.
Repositories and Docs:
- GitHub: https://github.com/usv240/timetracer
- PyPI: pip install timetracer
Top comments (0)