Files
routstr-core/tests/unit
9qeklajc f96acbb99c fix: address model-paths review findings
Provider scoping (items 1/2/6):
- Key visibility maps on (model_id.lower(), upstream_provider_id), matching
  refresh_model_maps, so a disable/override row on one provider never leaks
  onto another provider's model, and matching is case-insensitive.

Data safety (items 3/5):
- Degraded OpenRouter fetches (network error, 429, non-200, bad payload)
  return None (unknown) instead of []; a provider whose path set is unknown
  keeps its previously persisted rows instead of being wiped.
- Endpoint payload parsing moved fully inside try, with a list guard, so
  endpoints:null or non-list shapes are swallowed as documented.
- refresh with an empty live upstream list is a no-op; the unfiltered
  DELETE in the prune path is gone (prune now keys off enabled DB rows).

Hot path (items 4/12/14):
- Persist uses chunked bulk INSERTs (one statement per 500 rows) instead of
  per-row ORM adds; redundant ix_model_paths_model_id index dropped.
- Read routes filter in SQL instead of materializing the whole table, and
  output ordering is deterministic (public id + path), independent of rowid.
- Visibility no longer rebuilds fully priced Model objects per override row;
  it reads id/forwarded_model_id/canonical_slug straight off ModelRow.

Path/id contract (items 7/8/9/11):
- discovery_path_for_subprovider/discovery_base_paths hooks on
  BaseUpstreamProvider, overridden by OpenRouterUpstreamProvider, mirror
  _apply_provider_field so discovery and response stamping cannot drift
  (openrouter:OpenRouter now correctly maps to unknown).
- openrouter_author_slug falls back to a slash-containing forwarded_model_id,
  so admin-created alias rows are discoverable.
- public_model_id splits on the first slash, same as get_base_model_id, so
  discovery ids can be sent to chat completions verbatim.

Lifecycle (items 10/13):
- ENABLE_MODEL_PATHS_REFRESH kill switch; interval and flag re-read every
  loop iteration, and the task idles (not exits) while disabled.
- First 429 latches and aborts the remaining fan-out for the cycle; a
  per-cycle cache dedupes fetches across providers sharing a base URL.
- refresh_model_maps prunes paths of disabled/deleted providers so admin
  mutations take effect immediately; rows carry updated_at and both
  endpoints expose it.

Tests (item 15) rewritten through the public refresh entry point with
transport-level httpx.MockTransport fakes, FK enforcement on, and coverage
for the periodic loop. Migration re-chained onto 9c4d8e2f1a6b.
2026-07-26 13:23:31 +02:00
..
2025-08-03 20:35:59 -03:00
2025-08-09 14:55:26 -03:00
2026-06-13 23:40:39 +02:00
2026-06-27 22:53:35 +02:00
2026-07-22 23:10:27 +02:00
2026-07-05 23:35:10 +02:00
fmt
2025-10-24 16:40:37 +02:00
2026-07-05 23:35:10 +02:00
2026-07-01 17:08:28 +02:00
2026-07-01 16:53:52 +02:00
2026-05-14 15:40:49 +02:00
2026-07-22 23:10:27 +02:00
2026-07-22 23:10:27 +02:00

FastAPI Async Unit Tests

This directory contains async unit tests for the Routstr proxy FastAPI application.

Installation

First, ensure you have the development dependencies installed:

uv pip install -e ".[dev]"

Running Tests

To run all tests:

pytest

To run tests with coverage:

pytest --cov=routstr --cov-report=html

To run specific test files:

pytest tests/test_main.py
pytest tests/test_models.py
pytest tests/test_proxy.py

To run only async tests:

pytest -m asyncio

Test Structure

  • conftest.py - Pytest fixtures and configuration
  • test_main.py - Tests for main app endpoints
  • test_account.py - Tests for wallet/account management endpoints
  • test_proxy.py - Tests for the proxy functionality with mocked upstream
  • test_models.py - Tests for model pricing and data structures

Key Fixtures

  • async_client - Async HTTP client for testing FastAPI endpoints
  • test_session - In-memory SQLite database session for tests
  • test_api_key - Pre-configured API key with balance
  • api_key_with_balance - API key with sufficient balance for proxy tests

Environment Variables

The tests automatically set up required environment variables in conftest.py. No manual configuration needed.

Writing New Tests

  1. Use @pytest.mark.asyncio for async tests
  2. Use the provided fixtures for database and client access
  3. Mock external dependencies (like upstream API calls)
  4. Test both success and error cases
  5. Verify database state changes when applicable