Files
babymonitor/plan_5_prompt.md
2026-06-24 15:30:47 +02:00

5.0 KiB
Raw Permalink Blame History

Plan 5 — Observability & Test Coverage

Items covered: #10 (no logging), #12 (missing test coverage)


Context

You are working on a FastAPI backend for a baby monitor / sleep tracker app. The codebase lives under app/. This is the final plan. Plans 1–4 must already be complete — this plan assumes auth returns 401, malformed parameters return 422, and updated_at is updated on PATCH/PUT.

Do the logging setup first (it is quick), then work through the missing tests methodically. Add tests one group at a time and run pytest after each group.


Tasks

1. Add structured logging (app/main.py and other files)

Step 1 — Read app/config.py and app/main.py first

Confirm that LOG_LEVEL already exists in Settings (it does — it is currently defined but never consumed). Note its default value.

Step 2 — Configure logging in main.py

At the top of app/main.py, before the app is created, add:

import logging

logging.basicConfig(
    level=settings.LOG_LEVEL,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger(__name__)

Step 3 — Add request logging middleware

Add a simple middleware to log every request and response status:

import time
from fastapi import Request

@app.middleware("http")
async def log_requests(request: Request, call_next):
    start = time.time()
    response = await call_next(request)
    duration_ms = (time.time() - start) * 1000
    logger.info(
        "%s %s → %s (%.1fms)",
        request.method,
        request.url.path,
        response.status_code,
        duration_ms,
    )
    return response

Step 4 — Add business event logging

In the relevant router files, add a logger = logging.getLogger(__name__) at the module level and log the key business events:

  • Session started: logger.info("Session started id=%s", session.id)
  • Session ended: logger.info("Session ended id=%s duration_min=%.1f", session.id, ...)
  • Session deleted: logger.info("Session deleted id=%s", session_id)

Keep log messages concise. Do not log sensitive user data.

Step 5 — Verify

Run the tests:

pytest

Logging must not break any existing tests.


2. Add missing test coverage (tests/)

Read the existing test files before adding anything so you understand the test client setup, fixtures, and conventions already in use. Add all new tests to appropriate existing files (or a new file if clearly warranted — e.g. tests/test_stats.py if one does not exist).

Work through each group below. After adding each group, run pytest and fix any failures before continuing.


Group A — Stats endpoints: empty date ranges

For each stats endpoint (/api/stats/daily-summary, /api/stats/timetable, /api/stats/wake-sleep-times), add a test that:

  • Calls the endpoint with a valid date range that has no sessions
  • Asserts a 200 response
  • Asserts the response body represents an empty result (no days, empty list, etc.)

Group B — Stats endpoints: session spanning midnight

Add a test that:

  • Creates a session with start_time on day N at 23:00 and end_time on day N+1 at 07:00
  • Calls /api/stats/timetable for a range covering both days
  • Asserts that the session appears in both days' slot data

Group C — Stats endpoints: session partially overlapping the query range

Add a test that:

  • Creates a session that starts before the query range and ends inside it
  • Calls each stats endpoint with the range
  • Asserts the session is counted/included correctly (it should be, since it overlaps the range)

Group D — Stats endpoints: multiple sessions on the same day

Add a test that:

  • Creates two or more sessions on the same day
  • Calls /api/stats/daily-summary for that day
  • Asserts that the totals correctly aggregate across both sessions

Group E — Invalid query parameters return 422

These tests depend on Plan 2 (silent suppression replaced with 422). Add a parametrised test (or individual tests) for:

  • /api/stats/daily-summary with day_start=not-a-time → expect 422
  • /api/stats/timetable with day_start=not-a-time → expect 422
  • Any other endpoint that previously silently suppressed a ValueError

Group F — Bounded limit parameter

This test depends on Plan 4 (Query bound added). Add tests for:

  • GET /api/sessions?limit=0 → expect 422
  • GET /api/sessions?limit=1000001 → expect 422
  • GET /api/sessions?limit=1 → expect 200
  • GET /api/sessions?limit=1000 → expect 200

Group G — updated_at regression

This test depends on Plan 1 (updated_at bug fixed). Add a test that:

  • Creates a session
  • Records the updated_at value
  • Sends a PUT/PATCH request to update it
  • Asserts that updated_at in the response is strictly greater than the original value

Final verification

Run the complete test suite one last time:

pytest --tb=short

All tests must pass. Review the output for any warnings. This completes all 15 improvements from the backend improvement report.