Automatise les tests unitaires de l'API

This commit is contained in:
Emmanuel Viennet 2022-12-07 13:22:11 +01:00 committed by iziram
parent ba5b5cdb6f
commit f2ffd69fe6
8 changed files with 167 additions and 106 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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