Refactor codebase following Clean Code principles and add 229 tests
- Extract helpers to reduce function sizes (listing_tasks, app.py, query.py, listing_fetcher) - Replace nonlocal mutations with _PipelineState dataclass in listing_tasks - Fix bugs: isinstance→equality check in repository, verify_exp for OIDC tokens - Consolidate duplicate filter methods in listing_repository - Move hardcoded config to env vars with backward-compatible defaults - Simplify CLI decorator to auto-build QueryParameters - Add deprecation docstring to data_access.py - Test count: 158 → 387 (all passing)
This commit is contained in:
parent
7e05b3c971
commit
150342bb9e
48 changed files with 5029 additions and 990 deletions
72
crawler/tests/unit/test_route_serializer.py
Normal file
72
crawler/tests/unit/test_route_serializer.py
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
"""Unit tests for rec/route_serializer.py."""
|
||||
from models.listing import DestinationMode, Route, RouteLegStep
|
||||
from rec.route_serializer import RouteSerializer
|
||||
from rec.routing import TravelMode
|
||||
|
||||
|
||||
def _make_sample_routing_info() -> dict[DestinationMode, list[Route]]:
|
||||
destination_mode = DestinationMode(
|
||||
destination_address="London Bridge",
|
||||
travel_mode=TravelMode.TRANSIT,
|
||||
)
|
||||
routes = [
|
||||
Route(
|
||||
legs=[
|
||||
RouteLegStep(
|
||||
distance_meters=500,
|
||||
duration_s=120,
|
||||
travel_mode=TravelMode.WALK,
|
||||
),
|
||||
RouteLegStep(
|
||||
distance_meters=4000,
|
||||
duration_s=480,
|
||||
travel_mode=TravelMode.TRANSIT,
|
||||
),
|
||||
],
|
||||
distance_meters=4500,
|
||||
duration_s=600,
|
||||
)
|
||||
]
|
||||
return {destination_mode: routes}
|
||||
|
||||
|
||||
class TestRouteSerializer:
|
||||
def test_serialize_then_deserialize_roundtrip(self) -> None:
|
||||
routing_info = _make_sample_routing_info()
|
||||
serialized = RouteSerializer.serialize(routing_info)
|
||||
deserialized = RouteSerializer.deserialize(serialized)
|
||||
|
||||
assert len(deserialized) == 1
|
||||
dest_mode = list(deserialized.keys())[0]
|
||||
assert dest_mode.destination_address == "London Bridge"
|
||||
assert dest_mode.travel_mode == TravelMode.TRANSIT
|
||||
|
||||
routes = deserialized[dest_mode]
|
||||
assert len(routes) == 1
|
||||
assert routes[0].distance_meters == 4500
|
||||
assert routes[0].duration_s == 600
|
||||
assert len(routes[0].legs) == 2
|
||||
assert routes[0].legs[0].distance_meters == 500
|
||||
assert routes[0].legs[0].travel_mode == TravelMode.WALK
|
||||
assert routes[0].legs[1].travel_mode == TravelMode.TRANSIT
|
||||
|
||||
def test_deserialize_sample_json(self) -> None:
|
||||
import json
|
||||
import dataclasses
|
||||
|
||||
routing_info = _make_sample_routing_info()
|
||||
# Build the JSON manually to test deserialize independently
|
||||
json_str = json.dumps(
|
||||
{
|
||||
json.dumps(dataclasses.asdict(dm)): [
|
||||
json.dumps(dataclasses.asdict(r)) for r in routes
|
||||
]
|
||||
for dm, routes in routing_info.items()
|
||||
}
|
||||
)
|
||||
|
||||
result = RouteSerializer.deserialize(json_str)
|
||||
assert len(result) == 1
|
||||
dest_mode = list(result.keys())[0]
|
||||
assert dest_mode.destination_address == "London Bridge"
|
||||
assert result[dest_mode][0].duration_s == 600
|
||||
Loading…
Add table
Add a link
Reference in a new issue