implement basic testing fixtures and linting
Some checks failed
Build and push docker image / Build (pull_request) Successful in 1m40s
Run linting on the backend code / Build (pull_request) Failing after 10s
Build and release APK / Build APK (pull_request) Has been cancelled

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

View File

@ -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

View File

@ -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
View File

@ -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
View File

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

View File

@ -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
View File

View 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__)

View File

@ -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'

View File

@ -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:
""" """

View File

View File

@ -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

View File

@ -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']

View File

@ -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]]:

View File

@ -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']

View File

@ -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']

View File

@ -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)

View File

@ -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: