forked from ScoDoc/ScoDoc
Automatise les tests unitaires de l'API
This commit is contained in:
parent
d36004abfe
commit
1ea782102b
@ -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,
|
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).
|
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
|
- 9.4.x est en production
|
||||||
- le prochain jalon est 9.4. Voir branches sur gitea.
|
- le prochain jalon est 9.5. Voir branches sur gitea.
|
||||||
|
|
||||||
### Lignes de commandes
|
### Lignes de commandes
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ from app.scodoc.sco_permissions import Permission
|
|||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoSuperAdmin)
|
@permission_required(Permission.ScoSuperAdmin)
|
||||||
def api_get_glob_logos():
|
def api_get_glob_logos():
|
||||||
|
"""Liste tous les logos"""
|
||||||
logos = list_logos()[None]
|
logos = list_logos()[None]
|
||||||
return jsonify(list(logos.keys()))
|
return jsonify(list(logos.keys()))
|
||||||
|
|
||||||
|
@ -1,28 +1,44 @@
|
|||||||
# Tests unitaires de l'API ScoDoc
|
# 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
|
1. On génère une base SQL de test: voir
|
||||||
`tools/fakedatabase/create_test_api_database.py`
|
`tools/fakedatabase/create_test_api_database.py`
|
||||||
|
|
||||||
1. modifier `/opt/scodoc/.env` pour indiquer
|
1. En tant qu'utilisateur scodoc, lancer:
|
||||||
|
|
||||||
```bash
|
|
||||||
FLASK_ENV=test_api
|
|
||||||
FLASK_DEBUG=1
|
|
||||||
```
|
|
||||||
|
|
||||||
2. En tant qu'utilisateur scodoc, lancer:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# evite de modifier /opt/scodoc/.env
|
||||||
|
export FLASK_ENV=test_api
|
||||||
|
export FLASK_DEBUG=1
|
||||||
tools/create_database.sh --drop SCODOC_TEST_API
|
tools/create_database.sh --drop SCODOC_TEST_API
|
||||||
flask db upgrade
|
flask db upgrade
|
||||||
flask sco-db-init --erase
|
flask sco-db-init --erase
|
||||||
flask init-test-database
|
flask init-test-database
|
||||||
```
|
```
|
||||||
|
|
||||||
en plus court: ```bash
|
en plus court:
|
||||||
tools/create_database.sh --drop SCODOC_TEST_API && flask db upgrade &&flask sco-db-init --erase && flask init-test-database
|
|
||||||
|
```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
|
2. On lance le serveur ScoDoc sur cette base
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
# et à remplir.
|
# et à remplir.
|
||||||
|
|
||||||
# URL du serveur ScoDoc à interroger
|
# 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 ?
|
# Le client (python) doit-il vérifier le certificat SSL du serveur ?
|
||||||
# ou True si serveur de production avec certif SSL valide
|
# 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]
|
etud = etudiants[-1]
|
||||||
assert verify_fields(etud, fields) is True
|
assert verify_fields(etud, fields) is True
|
||||||
assert etud["id"] == etud["etudid"]
|
|
||||||
assert isinstance(etud["id"], int)
|
assert isinstance(etud["id"], int)
|
||||||
assert isinstance(etud["code_nip"], str)
|
assert isinstance(etud["code_nip"], str)
|
||||||
assert isinstance(etud["nom"], str)
|
assert isinstance(etud["nom"], str)
|
||||||
|
@ -13,8 +13,13 @@ utilisation:
|
|||||||
# XXX TODO
|
# XXX TODO
|
||||||
# Ce test a une logique très différente des autres : A UNIFIER
|
# Ce test a une logique très différente des autres : A UNIFIER
|
||||||
|
|
||||||
|
import requests
|
||||||
from tests.api.setup_test_api import API_URL, api_admin_headers, api_headers
|
from tests.api.setup_test_api import (
|
||||||
|
API_URL,
|
||||||
|
api_admin_headers,
|
||||||
|
api_headers,
|
||||||
|
CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
|
||||||
from scodoc import app
|
from scodoc import app
|
||||||
from tests.unit.config_test_logos import (
|
from tests.unit.config_test_logos import (
|
||||||
@ -30,147 +35,159 @@ def test_super_access(api_admin_headers):
|
|||||||
"""
|
"""
|
||||||
Route: /logos
|
Route: /logos
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client(api_admin_headers) as client:
|
API_URL + "/logos",
|
||||||
response = client.get(API_URL + "/logos", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.json is not None
|
)
|
||||||
|
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
|
|
||||||
|
|
||||||
|
|
||||||
def test_lambda_access(api_headers):
|
def test_lambda_access(api_headers):
|
||||||
"""
|
"""
|
||||||
Route: /logos
|
Route: /logos
|
||||||
"""
|
"""
|
||||||
headers = api_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/logos",
|
||||||
response = client.get(API_URL + "/logos", headers=headers)
|
headers=api_headers,
|
||||||
assert response.status_code == 401
|
verify=CHECK_CERTIFICATE,
|
||||||
|
)
|
||||||
|
assert response.status_code == 401
|
||||||
|
|
||||||
|
|
||||||
def test_global_logos(api_admin_headers):
|
def test_global_logos(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route:
|
Route:
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/logos",
|
||||||
response = client.get(API_URL + "/logos", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.json is not None
|
)
|
||||||
assert "header" in response.json
|
assert response.status_code == 200
|
||||||
assert "footer" in response.json
|
assert response.json() is not None
|
||||||
assert "B" in response.json
|
assert "header" in response.json()
|
||||||
assert "C" 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):
|
def test_local_by_id_logos(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /departement/id/1/logos
|
Route: /departement/id/1/logos
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/id/1/logos",
|
||||||
response = client.get(API_URL + "/departement/id/1/logos", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.json is not None
|
)
|
||||||
assert "A" in response.json
|
assert response.status_code == 200
|
||||||
assert "D" in response.json
|
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):
|
def test_local_by_name_logos(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /departement/TAPI/logos
|
Route: /departement/TAPI/logos
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/TAPI/logos",
|
||||||
response = client.get(API_URL + "/departement/TAPI/logos", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.json is not None
|
)
|
||||||
assert "A" in response.json
|
assert response.status_code == 200
|
||||||
assert "D" in response.json
|
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):
|
def test_local_png_by_id_logo(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /departement/id/1/logo/D
|
Route: /departement/id/1/logo/D
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/id/1/logo/D",
|
||||||
response = client.get(API_URL + "/departement/id/1/logo/D", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/png"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
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):
|
def test_global_png_logo(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /logo/C
|
Route: /logo/C
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/logo/C",
|
||||||
response = client.get(API_URL + "/logo/C", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/png"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_C.png" in response.headers["Content-Disposition"]
|
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):
|
def test_global_jpg_logo(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /logo/B
|
Route: /logo/B
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/logo/B",
|
||||||
response = client.get(API_URL + "/logo/B", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/jpg"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_B.jpg" in response.headers["Content-Disposition"]
|
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):
|
def test_local_png_by_name_logo(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /departement/TAPI/logo/A
|
Route: /departement/TAPI/logo/D
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/TAPI/logo/D",
|
||||||
response = client.get(API_URL + "/departement/TAPI/logo/D", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/png"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_D.png" in response.headers["Content-Disposition"]
|
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):
|
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
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/id/1/logo/A",
|
||||||
response = client.get(API_URL + "/departement/id/1/logo/A", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/jpg"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
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):
|
def test_local_jpg_by_name_logo(api_admin_headers):
|
||||||
"""
|
"""
|
||||||
Route: /departement/TAPI/logo/A
|
Route: /departement/TAPI/logo/A
|
||||||
"""
|
"""
|
||||||
headers = api_admin_headers
|
response = requests.get(
|
||||||
with app.test_client() as client:
|
API_URL + "/departement/TAPI/logo/A",
|
||||||
response = client.get(API_URL + "/departement/TAPI/logo/A", headers=headers)
|
headers=api_admin_headers,
|
||||||
assert response.status_code == 200
|
verify=CHECK_CERTIFICATE,
|
||||||
assert response.headers["Content-Type"] == "image/jpg"
|
)
|
||||||
assert response.headers["Content-Disposition"].startswith("inline")
|
assert response.status_code == 200
|
||||||
assert "logo_A.jpg" in response.headers["Content-Disposition"]
|
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
|
then
|
||||||
db_name="$2"
|
db_name="$2"
|
||||||
echo "Dropping database $db_name..."
|
echo "Dropping database $db_name..."
|
||||||
dropdb "$db_name"
|
dropdb --if-exists "$db_name"
|
||||||
else
|
else
|
||||||
db_name="$1"
|
db_name="$1"
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user