implement basic testing fixtures and linting

This commit is contained in:
Remy Moll 2024-08-12 12:44:51 +02:00
parent bea3a65fec
commit acc7631c55
18 changed files with 404 additions and 720 deletions

@ -0,0 +1,27 @@
on:
pull_request:
branches:
- main
paths:
- backend/**
name: Run linting on the backend code
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: https://gitea.com/actions/checkout@v4
- name: Install dependencies
run: |
apt-get update && apt-get install -y python3 python3-pip
# only install dev-packages
pipenv install --categories=dev-packages
working-directory: backend
- name: Run linter
run: pipenv run pylint src
working-directory: backend

@ -0,0 +1,27 @@
on:
pull_request:
branches:
- main
paths:
- backend/**
name: Run linting on the backend code
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: https://gitea.com/actions/checkout@v4
- name: Install dependencies
run: |
apt-get update && apt-get install -y python3 python3-pip
# install all packages, including dev-packages
pipenv install --dev
working-directory: backend
- name: Run linter
run: pipenv run pytest src
working-directory: backend

6
.vscode/launch.json vendored

@ -14,9 +14,9 @@
"DEBUG": "true" "DEBUG": "true"
}, },
"args": [ "args": [
"--app-dir", // "--app-dir",
"src", // "src",
"main:app", "src.main:app",
"--reload", "--reload",
], ],
"jinja": true, "jinja": true,

2
backend/.pylintrc Normal file

@ -0,0 +1,2 @@
[MAIN]
max-line-length=240

@ -4,6 +4,8 @@ verify_ssl = true
name = "pypi" name = "pypi"
[dev-packages] [dev-packages]
pylint = "*"
pytest = "*"
[packages] [packages]
numpy = "*" numpy = "*"

945
backend/Pipfile.lock generated

File diff suppressed because it is too large Load Diff

0
backend/src/__init__.py Normal file

@ -1,14 +1,14 @@
import logging import logging
from fastapi import FastAPI, Query, Body, HTTPException from fastapi import FastAPI, Query, Body, HTTPException
from structs.landmark import Landmark from .structs.landmark import Landmark
from structs.preferences import Preferences from .structs.preferences import Preferences
from structs.linked_landmarks import LinkedLandmarks from .structs.linked_landmarks import LinkedLandmarks
from structs.trip import Trip from .structs.trip import Trip
from utils.landmarks_manager import LandmarkManager from .utils.landmarks_manager import LandmarkManager
from utils.optimizer import Optimizer from .utils.optimizer import Optimizer
from utils.refiner import Refiner from .utils.refiner import Refiner
from persistence import client as cache_client from .persistence import client as cache_client
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

@ -1,6 +1,6 @@
from pymemcache.client.base import Client from pymemcache.client.base import Client
import constants from .constants import MEMCACHED_HOST_PATH
class DummyClient: class DummyClient:
@ -15,11 +15,11 @@ class DummyClient:
return self._data[key] return self._data[key]
if constants.MEMCACHED_HOST_PATH is None: if MEMCACHED_HOST_PATH is None:
client = DummyClient() client = DummyClient()
else: else:
client = Client( client = Client(
constants.MEMCACHED_HOST_PATH, MEMCACHED_HOST_PATH,
timeout=1, timeout=1,
allow_unicode_keys=True, allow_unicode_keys=True,
encoding='utf-8' encoding='utf-8'

@ -1,5 +1,5 @@
from .landmark import Landmark from .landmark import Landmark
from utils.get_time_separation import get_time from ..utils.get_time_separation import get_time
class LinkedLandmarks: class LinkedLandmarks:
""" """

@ -0,0 +1,34 @@
from fastapi.testclient import TestClient
import pytest
from ..main import app
@pytest.fixture()
def client():
return TestClient(app)
def test_new_trip_invalid_prefs(client):
response = client.post(
"/trip/new",
json={
"preferences": {},
"start": [48.8566, 2.3522]
}
)
assert response.status_code == 422
def test_new_trip_single_prefs(client):
response = client.post(
"/trip/new",
json={
"preferences": {"sightseeing": {"type": "sightseeing", "score": 1}, "nature": {"type": "nature", "score": 1}, "shopping": {"type": "shopping", "score": 1}, "max_time_minute": 360, "detour_tolerance_minute": 0},
"start": [48.8566, 2.3522]
}
)
assert response.status_code == 200
def test_new_trip_matches_prefs(client):
# todo
pass

@ -1,9 +1,9 @@
import yaml import yaml
from geopy.distance import geodesic from geopy.distance import geodesic
import constants from ..constants import OPTIMIZER_PARAMETERS_PATH
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: with OPTIMIZER_PARAMETERS_PATH.open('r') as f:
parameters = yaml.safe_load(f) parameters = yaml.safe_load(f)
DETOUR_FACTOR = parameters['detour_factor'] DETOUR_FACTOR = parameters['detour_factor']
AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] AVERAGE_WALKING_SPEED = parameters['average_walking_speed']

@ -9,11 +9,10 @@ from pywikibot import config
config.put_throttle = 0 config.put_throttle = 0
config.maxlag = 0 config.maxlag = 0
from structs.preferences import Preferences, Preference from ..structs.preferences import Preferences, Preference
from structs.landmark import Landmark from ..structs.landmark import Landmark
from .take_most_important import take_most_important from .take_most_important import take_most_important
import constants from ..constants import AMENITY_SELECTORS_PATH, LANDMARK_PARAMETERS_PATH, OPTIMIZER_PARAMETERS_PATH, OSM_CACHE_DIR
@ -30,10 +29,10 @@ class LandmarkManager:
def __init__(self) -> None: def __init__(self) -> None:
with constants.AMENITY_SELECTORS_PATH.open('r') as f: with AMENITY_SELECTORS_PATH.open('r') as f:
self.amenity_selectors = yaml.safe_load(f) self.amenity_selectors = yaml.safe_load(f)
with constants.LANDMARK_PARAMETERS_PATH.open('r') as f: with LANDMARK_PARAMETERS_PATH.open('r') as f:
parameters = yaml.safe_load(f) parameters = yaml.safe_load(f)
self.max_bbox_side = parameters['city_bbox_side'] self.max_bbox_side = parameters['city_bbox_side']
self.radius_close_to = parameters['radius_close_to'] self.radius_close_to = parameters['radius_close_to']
@ -42,13 +41,13 @@ class LandmarkManager:
self.tag_coeff = parameters['tag_coeff'] self.tag_coeff = parameters['tag_coeff']
self.N_important = parameters['N_important'] self.N_important = parameters['N_important']
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: with OPTIMIZER_PARAMETERS_PATH.open('r') as f:
parameters = yaml.safe_load(f) parameters = yaml.safe_load(f)
self.walking_speed = parameters['average_walking_speed'] self.walking_speed = parameters['average_walking_speed']
self.detour_factor = parameters['detour_factor'] self.detour_factor = parameters['detour_factor']
self.overpass = Overpass() self.overpass = Overpass()
CachingStrategy.use(JSON, cacheDir=constants.OSM_CACHE_DIR) CachingStrategy.use(JSON, cacheDir=OSM_CACHE_DIR)
def generate_landmarks_list(self, center_coordinates: tuple[float, float], preferences: Preferences) -> tuple[list[Landmark], list[Landmark]]: def generate_landmarks_list(self, center_coordinates: tuple[float, float], preferences: Preferences) -> tuple[list[Landmark], list[Landmark]]:

@ -5,9 +5,9 @@ from scipy.optimize import linprog
from collections import defaultdict, deque from collections import defaultdict, deque
from geopy.distance import geodesic from geopy.distance import geodesic
from structs.landmark import Landmark from ..structs.landmark import Landmark
from .get_time_separation import get_time from .get_time_separation import get_time
import constants from ..constants import OPTIMIZER_PARAMETERS_PATH
@ -26,7 +26,7 @@ class Optimizer:
def __init__(self) : def __init__(self) :
# load parameters from file # load parameters from file
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: with OPTIMIZER_PARAMETERS_PATH.open('r') as f:
parameters = yaml.safe_load(f) parameters = yaml.safe_load(f)
self.detour_factor = parameters['detour_factor'] self.detour_factor = parameters['detour_factor']
self.average_walking_speed = parameters['average_walking_speed'] self.average_walking_speed = parameters['average_walking_speed']

@ -3,10 +3,10 @@ import yaml, logging
from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull from shapely import buffer, LineString, Point, Polygon, MultiPoint, concave_hull
from math import pi from math import pi
from structs.landmark import Landmark from ..structs.landmark import Landmark
from . import take_most_important, get_time_separation from . import take_most_important, get_time_separation
from .optimizer import Optimizer from .optimizer import Optimizer
import constants from ..constants import OPTIMIZER_PARAMETERS_PATH
@ -24,7 +24,7 @@ class Refiner :
self.optimizer = optimizer self.optimizer = optimizer
# load parameters from file # load parameters from file
with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: with OPTIMIZER_PARAMETERS_PATH.open('r') as f:
parameters = yaml.safe_load(f) parameters = yaml.safe_load(f)
self.detour_factor = parameters['detour_factor'] self.detour_factor = parameters['detour_factor']
self.detour_corridor_width = parameters['detour_corridor_width'] self.detour_corridor_width = parameters['detour_corridor_width']

@ -1,4 +1,4 @@
from structs.landmark import Landmark from ..structs.landmark import Landmark
def take_most_important(landmarks: list[Landmark], N_important) -> list[Landmark] : def take_most_important(landmarks: list[Landmark], N_important) -> list[Landmark] :
L = len(landmarks) L = len(landmarks)

@ -292,18 +292,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.4" version: "10.0.5"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.5"
leak_tracker_testing: leak_tracker_testing:
dependency: transitive dependency: transitive
description: description:
@ -332,18 +332,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.0" version: "0.11.1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.0" version: "1.15.0"
nested: nested:
dependency: transitive dependency: transitive
description: description:
@ -609,10 +609,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.2"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -641,10 +641,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.2.1" version: "14.2.4"
web: web:
dependency: transitive dependency: transitive
description: description: