simplified test pipeline
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m38s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 17m36s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 35s
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m38s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 17m36s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 35s
This commit is contained in:
parent
37926e68ec
commit
54bc9028ad
File diff suppressed because one or more lines are too long
@ -1,324 +0,0 @@
|
|||||||
"""Collection of tests to ensure correct implementation and track progress."""
|
|
||||||
import time
|
|
||||||
from fastapi.testclient import TestClient
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from .test_utils import load_trip_landmarks, log_trip_details
|
|
||||||
from ..main import app
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def client():
|
|
||||||
"""Client used to call the app."""
|
|
||||||
return TestClient(app)
|
|
||||||
|
|
||||||
|
|
||||||
def test_turckheim(client, request): # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°1 : Custom test in Turckheim to ensure small villages are also supported.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 20
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 0},
|
|
||||||
"shopping": {"type": "shopping", "score": 0},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [48.084588, 7.280405]
|
|
||||||
# "start": [45.74445023349939, 4.8222687890538865]
|
|
||||||
# "start": [45.75156398104873, 4.827154464827647]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert isinstance(landmarks, list) # check that the return type is a list
|
|
||||||
assert len(landmarks) > 2 # check that there is something to visit
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
# assert 2!= 3
|
|
||||||
|
|
||||||
def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°2 : Custom test in Lyon centre to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 120
|
|
||||||
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 5},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [45.7576485, 4.8330241]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_cologne(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°3 : Custom test in Cologne to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 240
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 5},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [50.942352665, 6.957777972392]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°4 : Custom test in Strasbourg to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 180
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 5},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [48.5846589226, 7.74078715721]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_zurich(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°5 : Custom test in Zurich to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 180
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 5},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [47.377884227, 8.5395114066]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_paris(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°6 : Custom test in Paris (les Halles) centre to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 200
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 0},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [48.85468881798671, 2.3423925755998374]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_new_york(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°7 : Custom test in New York to ensure proper decision making in crowded area.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 600
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
|
||||||
"nature": {"type": "nature", "score": 5},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [40.72592726802, -73.9920434795]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
|
|
||||||
|
|
||||||
def test_shopping(client, request) : # pylint: disable=redefined-outer-name
|
|
||||||
"""
|
|
||||||
Test n°8 : Custom test in Lyon centre to ensure shopping clusters are found.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
client:
|
|
||||||
request:
|
|
||||||
"""
|
|
||||||
start_time = time.time() # Start timer
|
|
||||||
duration_minutes = 240
|
|
||||||
|
|
||||||
response = client.post(
|
|
||||||
"/trip/new",
|
|
||||||
json={
|
|
||||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 0},
|
|
||||||
"nature": {"type": "nature", "score": 0},
|
|
||||||
"shopping": {"type": "shopping", "score": 5},
|
|
||||||
"max_time_minute": duration_minutes,
|
|
||||||
"detour_tolerance_minute": 0},
|
|
||||||
"start": [45.7576485, 4.8330241]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
result = response.json()
|
|
||||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
|
||||||
|
|
||||||
# Get computation time
|
|
||||||
comp_time = time.time() - start_time
|
|
||||||
|
|
||||||
# Add details to report
|
|
||||||
log_trip_details(request, landmarks, result['total_time'], duration_minutes)
|
|
||||||
|
|
||||||
# checks :
|
|
||||||
assert response.status_code == 200 # check for successful planning
|
|
||||||
assert comp_time < 30, f"Computation time exceeded 30 seconds: {comp_time:.2f} seconds"
|
|
||||||
assert duration_minutes*0.8 < result['total_time'], f"Trip too short: {result['total_time']} instead of {duration_minutes}"
|
|
||||||
assert duration_minutes*1.2 > result['total_time'], f"Trip too long: {result['total_time']} instead of {duration_minutes}"
|
|
@ -14,43 +14,43 @@ def client():
|
|||||||
return TestClient(app)
|
return TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
@pytest.mark.parametrize(
|
||||||
"""
|
"sightseeing, shopping, nature, max_time_minute, start_coords, end_coords",
|
||||||
Test n°2 : Custom test in Lyon centre to ensure proper decision making in crowded area.
|
[
|
||||||
|
# Edge cases
|
||||||
Args:
|
(0, 0, 5, 240, [45.7576485, 4.8330241], None), # Lyon, Bellecour - test shopping only
|
||||||
client:
|
|
||||||
request:
|
# Realistic
|
||||||
"""
|
(5, 0, 0, 20, [48.0845881, 7.2804050], None), # Turckheim
|
||||||
|
(5, 5, 5, 120, [45.7576485, 4.8330241], None), # Lyon, Bellecour
|
||||||
|
(5, 5, 5, 240, [50.9423526, 6.9577780], None), # Cologne, centre
|
||||||
|
(5, 5, 5, 180, [48.5846589226, 7.74078715721], None), # Strasbourg, centre
|
||||||
|
(5, 5, 5, 180, [47.377884227, 8.5395114066], None), # Zurich, centre
|
||||||
|
(5, 0, 5, 200, [48.85468881798671, 2.3423925755998374], None), # Paris, centre
|
||||||
|
(5, 5, 5, 600, [40.72592726802, -73.9920434795], None), # New York, Lower Manhattan
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_trip(client, request, sightseeing, shopping, nature, max_time_minute, start_coords, end_coords):
|
||||||
|
|
||||||
start_time = time.time() # Start timer
|
start_time = time.time() # Start timer
|
||||||
|
|
||||||
# Step 0: Define the trip preferences
|
|
||||||
prefs = Preferences(
|
prefs = Preferences(
|
||||||
sightseeing = Preference(
|
sightseeing=Preference(type='sightseeing', score=sightseeing),
|
||||||
type='sightseeing',
|
shopping=Preference(type='shopping', score=shopping),
|
||||||
score=5
|
nature=Preference(type='nature', score=nature),
|
||||||
),
|
max_time_minute=max_time_minute,
|
||||||
shopping = Preference(
|
|
||||||
type='shopping',
|
|
||||||
score=5
|
|
||||||
),
|
|
||||||
nature = Preference(
|
|
||||||
type='nature',
|
|
||||||
score=5
|
|
||||||
),
|
|
||||||
max_time_minute=120,
|
|
||||||
detour_tolerance_minute=0,
|
detour_tolerance_minute=0,
|
||||||
)
|
)
|
||||||
|
start = start_coords
|
||||||
# Define the starting coordinates
|
end = end_coords
|
||||||
start = [45.7576485, 4.8330241]
|
|
||||||
|
|
||||||
# Step 1: request the list of landmarks in the vicinty of the starting point
|
# Step 1: request the list of landmarks in the vicinty of the starting point
|
||||||
response = client.post(
|
response = client.post(
|
||||||
"/get/landmarks",
|
"/get/landmarks",
|
||||||
json={
|
json={
|
||||||
"preferences": prefs.model_dump(),
|
"preferences": prefs.model_dump(),
|
||||||
"start": start
|
"start": start_coords,
|
||||||
|
"end": end_coords,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
landmarks = response.json()
|
landmarks = response.json()
|
||||||
@ -61,7 +61,8 @@ def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
|||||||
json={
|
json={
|
||||||
"preferences": prefs.model_dump(),
|
"preferences": prefs.model_dump(),
|
||||||
"landmarks": landmarks,
|
"landmarks": landmarks,
|
||||||
"start": start
|
"start": start,
|
||||||
|
"end": end,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
"""Helper methods for testing."""
|
"""Helper methods for testing."""
|
||||||
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
from functools import wraps
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
|
||||||
from ..structs.landmark import Landmark
|
|
||||||
from ..cache import client as cache_client
|
from ..cache import client as cache_client
|
||||||
|
from ..structs.landmark import Landmark
|
||||||
|
from ..structs.preferences import Preferences, Preference
|
||||||
|
|
||||||
|
|
||||||
def landmarks_to_osmid(landmarks: list[Landmark]) -> list[int] :
|
def landmarks_to_osmid(landmarks: list[Landmark]) -> list[int] :
|
||||||
@ -91,3 +94,34 @@ def log_trip_details(request, landmarks: list[Landmark], duration: int, target_d
|
|||||||
request.node.trip_details = trip_string
|
request.node.trip_details = trip_string
|
||||||
request.node.trip_duration = str(duration) # result['total_time']
|
request.node.trip_duration = str(duration) # result['total_time']
|
||||||
request.node.target_duration = str(target_duration)
|
request.node.target_duration = str(target_duration)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def trip_params(
|
||||||
|
sightseeing: int,
|
||||||
|
shopping: int,
|
||||||
|
nature: int,
|
||||||
|
max_time_minute: int,
|
||||||
|
start_coords: tuple[float, float] = None,
|
||||||
|
end_coords: tuple[float, float] = None,
|
||||||
|
):
|
||||||
|
def decorator(test_func):
|
||||||
|
@wraps(test_func)
|
||||||
|
def wrapper(client, request):
|
||||||
|
prefs = Preferences(
|
||||||
|
sightseeing=Preference(type='sightseeing', score=sightseeing),
|
||||||
|
shopping=Preference(type='shopping', score=shopping),
|
||||||
|
nature=Preference(type='nature', score=nature),
|
||||||
|
max_time_minute=max_time_minute,
|
||||||
|
detour_tolerance_minute=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
start = start_coords
|
||||||
|
end = end_coords
|
||||||
|
|
||||||
|
# Inject into test function
|
||||||
|
return test_func(client, request, prefs, start, end)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
Loading…
x
Reference in New Issue
Block a user