Automatise les tests unitaires de l'API
This commit is contained in:
parent
ba5b5cdb6f
commit
f2ffd69fe6
@ -16,10 +16,10 @@ La version 9.0 s'efforce de reproduire presque à l'identique le fonctionnement
|
||||
de ScoDoc7, avec des composants logiciels différents (Debian 11, Python 3,
|
||||
Flask, SQLAlchemy, au lien de Python2/Zope dans les versions précédentes).
|
||||
|
||||
### État actuel (nov 22)
|
||||
### État actuel (dec 22)
|
||||
|
||||
- 9.3.x est en production
|
||||
- le prochain jalon est 9.4. Voir branches sur gitea.
|
||||
- 9.4.x est en production
|
||||
- le prochain jalon est 9.5. Voir branches sur gitea.
|
||||
|
||||
### Lignes de commandes
|
||||
|
||||
|
@ -48,6 +48,7 @@ from app.scodoc.sco_permissions import Permission
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoSuperAdmin)
|
||||
def api_get_glob_logos():
|
||||
"""Liste tous les logos"""
|
||||
logos = list_logos()[None]
|
||||
return jsonify(list(logos.keys()))
|
||||
|
||||
|
@ -1,28 +1,44 @@
|
||||
# Tests unitaires de l'API ScoDoc
|
||||
|
||||
Démarche générale:
|
||||
## Lancement des tests
|
||||
|
||||
La première fois, copier le fichier `tests/api/dotenv_exemple` vers
|
||||
`tests/api/.env`. Il est normalement inutile de modifier son contenu.
|
||||
|
||||
Dans un shell, lancer le script `start_api_server.py`, qui se charge
|
||||
d'initialiser une base SQL de test et de lancer le serveur ScoDoc approprié.
|
||||
|
||||
```bash
|
||||
tests/api/start_api_server.sh
|
||||
```
|
||||
|
||||
Dans un autre shell, lancer les tests:
|
||||
|
||||
```bash
|
||||
pytest tests/api
|
||||
```
|
||||
|
||||
## Notes sur la démarche
|
||||
|
||||
1. On génère une base SQL de test: voir
|
||||
`tools/fakedatabase/create_test_api_database.py`
|
||||
|
||||
1. modifier `/opt/scodoc/.env` pour indiquer
|
||||
|
||||
```bash
|
||||
FLASK_ENV=test_api
|
||||
FLASK_DEBUG=1
|
||||
```
|
||||
|
||||
2. En tant qu'utilisateur scodoc, lancer:
|
||||
1. En tant qu'utilisateur scodoc, lancer:
|
||||
|
||||
```bash
|
||||
# evite de modifier /opt/scodoc/.env
|
||||
export FLASK_ENV=test_api
|
||||
export FLASK_DEBUG=1
|
||||
tools/create_database.sh --drop SCODOC_TEST_API
|
||||
flask db upgrade
|
||||
flask sco-db-init --erase
|
||||
flask init-test-database
|
||||
```
|
||||
|
||||
en plus court: ```bash
|
||||
tools/create_database.sh --drop SCODOC_TEST_API && flask db upgrade &&flask sco-db-init --erase && flask init-test-database
|
||||
en plus court:
|
||||
|
||||
```bash
|
||||
export FLASK_ENV=test_api && tools/create_database.sh --drop SCODOC_TEST_API && flask db upgrade &&flask sco-db-init --erase && flask init-test-database
|
||||
```
|
||||
|
||||
2. On lance le serveur ScoDoc sur cette base
|
||||
|
@ -4,8 +4,11 @@
|
||||
# et à remplir.
|
||||
|
||||
# URL du serveur ScoDoc à interroger
|
||||
SCODOC_URL = "http://localhost:5000/"
|
||||
SCODOC_URL="http://localhost:5000/"
|
||||
|
||||
# Le client (python) doit-il vérifier le certificat SSL du serveur ?
|
||||
# ou True si serveur de production avec certif SSL valide
|
||||
CHECK_CERTIFICATE = False
|
||||
CHECK_CERTIFICATE=False
|
||||
|
||||
API_USER="lecteur_api"
|
||||
API_PASSWORD="azerty"
|
||||
|
25
tests/api/start_api_server.sh
Executable file
25
tests/api/start_api_server.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script recreating the TEST API database and starting the serveur
|
||||
|
||||
set -e
|
||||
|
||||
# Le répertoire de ce script:
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
# récupère API_USER et API_PASSWORD
|
||||
source "$SCRIPT_DIR"/.env
|
||||
|
||||
export FLASK_ENV=test_api
|
||||
export FLASK_DEBUG=1
|
||||
tools/create_database.sh --drop SCODOC_TEST_API
|
||||
flask db upgrade
|
||||
flask sco-db-init --erase
|
||||
flask init-test-database
|
||||
|
||||
flask user-create "$API_USER" LecteurAPI @all
|
||||
flask user-password --password "$API_PASSWORD" "$API_USER"
|
||||
flask edit-role LecteurAPI -a ScoView
|
||||
flask user-role "$API_USER" -a LecteurAPI
|
||||
|
||||
flask run --host 0.0.0.0
|
@ -76,7 +76,6 @@ def test_etudiants_courant(api_headers):
|
||||
|
||||
etud = etudiants[-1]
|
||||
assert verify_fields(etud, fields) is True
|
||||
assert etud["id"] == etud["etudid"]
|
||||
assert isinstance(etud["id"], int)
|
||||
assert isinstance(etud["code_nip"], str)
|
||||
assert isinstance(etud["nom"], str)
|
||||
|
@ -13,8 +13,13 @@ utilisation:
|
||||
# XXX TODO
|
||||
# Ce test a une logique très différente des autres : A UNIFIER
|
||||
|
||||
|
||||
from tests.api.setup_test_api import API_URL, api_admin_headers, api_headers
|
||||
import requests
|
||||
from tests.api.setup_test_api import (
|
||||
API_URL,
|
||||
api_admin_headers,
|
||||
api_headers,
|
||||
CHECK_CERTIFICATE,
|
||||
)
|
||||
|
||||
from scodoc import app
|
||||
from tests.unit.config_test_logos import (
|
||||
@ -30,147 +35,159 @@ def test_super_access(api_admin_headers):
|
||||
"""
|
||||
Route: /logos
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client(api_admin_headers) as client:
|
||||
response = client.get(API_URL + "/logos", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
|
||||
|
||||
def test_admin_access(api_headers):
|
||||
"""
|
||||
Route: /logos
|
||||
"""
|
||||
headers = api_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/logos", headers=headers)
|
||||
assert response.status_code == 401
|
||||
response = requests.get(
|
||||
API_URL + "/logos",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() is not None
|
||||
|
||||
|
||||
def test_lambda_access(api_headers):
|
||||
"""
|
||||
Route: /logos
|
||||
"""
|
||||
headers = api_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/logos", headers=headers)
|
||||
assert response.status_code == 401
|
||||
response = requests.get(
|
||||
API_URL + "/logos",
|
||||
headers=api_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
def test_global_logos(api_admin_headers):
|
||||
"""
|
||||
Route:
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/logos", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert "header" in response.json
|
||||
assert "footer" in response.json
|
||||
assert "B" in response.json
|
||||
assert "C" in response.json
|
||||
response = requests.get(
|
||||
API_URL + "/logos",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() is not None
|
||||
assert "header" in response.json()
|
||||
assert "footer" in response.json()
|
||||
assert "B" in response.json()
|
||||
assert "C" in response.json()
|
||||
|
||||
|
||||
def test_local_by_id_logos(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/id/1/logos
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/id/1/logos", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert "A" in response.json
|
||||
assert "D" in response.json
|
||||
response = requests.get(
|
||||
API_URL + "/departement/id/1/logos",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() is not None
|
||||
assert "A" in response.json()
|
||||
assert "D" in response.json()
|
||||
|
||||
|
||||
def test_local_by_name_logos(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/TAPI/logos
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/TAPI/logos", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.json is not None
|
||||
assert "A" in response.json
|
||||
assert "D" in response.json
|
||||
response = requests.get(
|
||||
API_URL + "/departement/TAPI/logos",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() is not None
|
||||
assert "A" in response.json()
|
||||
assert "D" in response.json()
|
||||
|
||||
|
||||
def test_local_png_by_id_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/id/1/logo/D
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/id/1/logo/D", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/departement/id/1/logo/D",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
||||
|
||||
|
||||
def test_global_png_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /logo/C
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/logo/C", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_C.png" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/logo/C",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_C.png" in response.headers["Content-Disposition"]
|
||||
|
||||
|
||||
def test_global_jpg_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /logo/B
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/logo/B", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_B.jpg" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/logo/B",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_B.jpg" in response.headers["Content-Disposition"]
|
||||
|
||||
|
||||
def test_local_png_by_name_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/TAPI/logo/A
|
||||
Route: /departement/TAPI/logo/D
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/TAPI/logo/D", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/departement/TAPI/logo/D",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/png"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
||||
|
||||
|
||||
def test_local_jpg_by_id_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/id/1/logo/D
|
||||
Route: /departement/id/1/logo/A
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/id/1/logo/A", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/departement/id/1/logo/A",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
||||
|
||||
|
||||
def test_local_jpg_by_name_logo(api_admin_headers):
|
||||
"""
|
||||
Route: /departement/TAPI/logo/A
|
||||
"""
|
||||
headers = api_admin_headers
|
||||
with app.test_client() as client:
|
||||
response = client.get(API_URL + "/departement/TAPI/logo/A", headers=headers)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
||||
response = requests.get(
|
||||
API_URL + "/departement/TAPI/logo/A",
|
||||
headers=api_admin_headers,
|
||||
verify=CHECK_CERTIFICATE,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.headers["Content-Type"] == "image/jpg"
|
||||
assert response.headers["Content-Disposition"].startswith("inline")
|
||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
||||
|
@ -15,7 +15,7 @@ if [ "$1" = "--drop" ]
|
||||
then
|
||||
db_name="$2"
|
||||
echo "Dropping database $db_name..."
|
||||
dropdb "$db_name"
|
||||
dropdb --if-exists "$db_name"
|
||||
else
|
||||
db_name="$1"
|
||||
fi
|
||||
|
Loading…
Reference in New Issue
Block a user