forked from ScoDoc/ScoDoc
API: modification format evaluations, et ajout route /evaluation.
This commit is contained in:
parent
fdeaafe622
commit
eb04984c2e
63
README.md
63
README.md
@ -1,5 +1,4 @@
|
|||||||
i
|
# ScoDoc - Gestion de la scolarité - Version ScoDoc 9
|
||||||
# ScoDoc - Gestion de la scolarité - Version ScoDoc 9
|
|
||||||
|
|
||||||
(c) Emmanuel Viennet 1999 - 2022 (voir LICENCE.txt).
|
(c) Emmanuel Viennet 1999 - 2022 (voir LICENCE.txt).
|
||||||
|
|
||||||
@ -9,39 +8,34 @@ Documentation utilisateur: <https://scodoc.org>
|
|||||||
|
|
||||||
## Version ScoDoc 9
|
## Version ScoDoc 9
|
||||||
|
|
||||||
La version ScoDoc 9 est parue en septembre 2021.
|
La version ScoDoc 9 est parue en septembre 2021. Elle représente une évolution
|
||||||
Elle représente une évolution majeure du projet, maintenant basé sur
|
majeure du projet, maintenant basé sur Flask (au lieu de Zope) et sur **python
|
||||||
Flask (au lieu de Zope) et sur **python 3.9+**.
|
3.9+**.
|
||||||
|
|
||||||
La version 9.0 s'efforce de reproduire presque à l'identique le fonctionnement
|
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)
|
||||||
|
|
||||||
|
- 9.3.x est en production
|
||||||
|
- le prochain jalon est 9.4. Voir branches sur gitea.
|
||||||
|
|
||||||
### État actuel (26 jan 22)
|
|
||||||
|
|
||||||
- 9.1.5x (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf:
|
|
||||||
- ancien module "Entreprises" (obsolète) et ajoute la gestion du BUT.
|
|
||||||
|
|
||||||
- 9.2 (branche dev92) est la version de développement.
|
|
||||||
|
|
||||||
|
|
||||||
### Lignes de commandes
|
### Lignes de commandes
|
||||||
|
|
||||||
Voir [https://scodoc.org/GuideConfig](le guide de configuration).
|
Voir [https://scodoc.org/GuideConfig](le guide de configuration).
|
||||||
|
|
||||||
|
|
||||||
## Organisation des fichiers
|
## Organisation des fichiers
|
||||||
|
|
||||||
L'installation comporte les fichiers de l'application, sous `/opt/scodoc/`, et
|
L'installation comporte les fichiers de l'application, sous `/opt/scodoc/`, et
|
||||||
les fichiers locaux (archives, photos, configurations, logs) sous
|
les fichiers locaux (archives, photos, configurations, logs) sous
|
||||||
`/opt/scodoc-data`. Par ailleurs, il y a évidemment les bases de données
|
`/opt/scodoc-data`. Par ailleurs, il y a évidemment les bases de données
|
||||||
postgresql et la configuration du système Linux.
|
postgresql et la configuration du système Linux.
|
||||||
|
|
||||||
### Fichiers locaux
|
### Fichiers locaux
|
||||||
Sous `/opt/scodoc-data`, fichiers et répertoires appartenant à l'utilisateur `scodoc`.
|
|
||||||
Ils ne doivent pas être modifiés à la main, sauf certains fichiers de configuration sous
|
Sous `/opt/scodoc-data`, fichiers et répertoires appartenant à l'utilisateur `scodoc`.
|
||||||
|
Ils ne doivent pas être modifiés à la main, sauf certains fichiers de configuration sous
|
||||||
`/opt/scodoc-data/config`.
|
`/opt/scodoc-data/config`.
|
||||||
|
|
||||||
Le répertoire `/opt/scodoc-data` doit être régulièrement sauvegardé.
|
Le répertoire `/opt/scodoc-data` doit être régulièrement sauvegardé.
|
||||||
@ -62,7 +56,7 @@ Principaux contenus:
|
|||||||
|
|
||||||
Installer ScoDoc 9 normalement ([voir la doc](https://scodoc.org/GuideInstallDebian11)).
|
Installer ScoDoc 9 normalement ([voir la doc](https://scodoc.org/GuideInstallDebian11)).
|
||||||
|
|
||||||
Puis remplacer `/opt/scodoc` par un clone du git.
|
Puis remplacer `/opt/scodoc` par un clone du git.
|
||||||
|
|
||||||
sudo su
|
sudo su
|
||||||
mv /opt/scodoc /opt/off-scodoc # ou ce que vous voulez
|
mv /opt/scodoc /opt/off-scodoc # ou ce que vous voulez
|
||||||
@ -76,7 +70,7 @@ Puis remplacer `/opt/scodoc` par un clone du git.
|
|||||||
|
|
||||||
# Et donner ce répertoire à l'utilisateur scodoc:
|
# Et donner ce répertoire à l'utilisateur scodoc:
|
||||||
chown -R scodoc.scodoc /opt/scodoc
|
chown -R scodoc.scodoc /opt/scodoc
|
||||||
|
|
||||||
Il faut ensuite installer l'environnement et le fichier de configuration:
|
Il faut ensuite installer l'environnement et le fichier de configuration:
|
||||||
|
|
||||||
# Le plus simple est de piquer le virtualenv configuré par l'installeur:
|
# Le plus simple est de piquer le virtualenv configuré par l'installeur:
|
||||||
@ -100,10 +94,10 @@ Avant le premier lancement, créer cette base ainsi:
|
|||||||
flask db upgrade
|
flask db upgrade
|
||||||
|
|
||||||
Cette commande n'est nécessaire que la première fois (le contenu de la base
|
Cette commande n'est nécessaire que la première fois (le contenu de la base
|
||||||
est effacé au début de chaque test, mais son schéma reste) et aussi si des
|
est effacé au début de chaque test, mais son schéma reste) et aussi si des
|
||||||
migrations (changements de schéma) ont eu lieu dans le code.
|
migrations (changements de schéma) ont eu lieu dans le code.
|
||||||
|
|
||||||
Certains tests ont besoin d'un département déjà créé, qui n'est pas créé par les
|
Certains tests ont besoin d'un département déjà créé, qui n'est pas créé par les
|
||||||
scripts de tests:
|
scripts de tests:
|
||||||
Lancer au préalable:
|
Lancer au préalable:
|
||||||
|
|
||||||
@ -117,24 +111,24 @@ Ou avec couverture (`pip install pytest-cov`)
|
|||||||
|
|
||||||
pytest --cov=app --cov-report=term-missing --cov-branch tests/unit/*
|
pytest --cov=app --cov-report=term-missing --cov-branch tests/unit/*
|
||||||
|
|
||||||
|
|
||||||
#### Utilisation des tests unitaires pour initialiser la base de dev
|
#### Utilisation des tests unitaires pour initialiser la base de dev
|
||||||
On peut aussi utiliser les tests unitaires pour mettre la base
|
|
||||||
de données de développement dans un état connu, par exemple pour éviter de
|
|
||||||
recréer à la main étudiants et semestres quand on développe.
|
|
||||||
|
|
||||||
Il suffit de positionner une variable d'environnement indiquant la BD
|
On peut aussi utiliser les tests unitaires pour mettre la base de données de
|
||||||
utilisée par les tests:
|
développement dans un état connu, par exemple pour éviter de recréer à la main
|
||||||
|
étudiants et semestres quand on développe.
|
||||||
|
|
||||||
|
Il suffit de positionner une variable d'environnement indiquant la BD utilisée
|
||||||
|
par les tests:
|
||||||
|
|
||||||
export SCODOC_TEST_DATABASE_URI=postgresql:///SCODOC_DEV
|
export SCODOC_TEST_DATABASE_URI=postgresql:///SCODOC_DEV
|
||||||
|
|
||||||
(si elle n'existe pas, voir plus loin pour la créer) puis de les lancer
|
(si elle n'existe pas, voir plus loin pour la créer) puis de les lancer
|
||||||
normalement, par exemple:
|
normalement, par exemple:
|
||||||
|
|
||||||
pytest tests/unit/test_sco_basic.py
|
pytest tests/unit/test_sco_basic.py
|
||||||
|
|
||||||
Il est en général nécessaire d'affecter ensuite un mot de passe à (au moins)
|
Il est en général nécessaire d'affecter ensuite un mot de passe à (au moins) un
|
||||||
un utilisateur:
|
utilisateur:
|
||||||
|
|
||||||
flask user-password admin
|
flask user-password admin
|
||||||
|
|
||||||
@ -178,12 +172,10 @@ Pour la visualisation, [snakeviz](https://jiffyclub.github.io/snakeviz/) est bie
|
|||||||
|
|
||||||
pip install snakeviz
|
pip install snakeviz
|
||||||
|
|
||||||
puis
|
puis
|
||||||
|
|
||||||
snakeviz -s --hostname 0.0.0.0 -p 5555 /opt/scodoc-data/GET.ScoDoc......prof
|
snakeviz -s --hostname 0.0.0.0 -p 5555 /opt/scodoc-data/GET.ScoDoc......prof
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Paquet Debian 11
|
# Paquet Debian 11
|
||||||
|
|
||||||
Les scripts associés au paquet Debian (.deb) sont dans `tools/debian`. Le plus
|
Les scripts associés au paquet Debian (.deb) sont dans `tools/debian`. Le plus
|
||||||
@ -191,5 +183,4 @@ important est `postinst`qui se charge de configurer le système (install ou
|
|||||||
upgrade de scodoc9).
|
upgrade de scodoc9).
|
||||||
|
|
||||||
La préparation d'une release se fait à l'aide du script
|
La préparation d'une release se fait à l'aide du script
|
||||||
`tools/build_release.sh`.
|
`tools/build_release.sh`.
|
||||||
|
|
||||||
|
@ -257,9 +257,9 @@ def dept_formsemestres_courants(acronym: str):
|
|||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
dept = Departement.query.filter_by(acronym=acronym).first_or_404()
|
||||||
faked_date = request.args.get("faked_date")
|
date_courante = request.args.get("date_courante")
|
||||||
if faked_date:
|
if date_courante:
|
||||||
test_date = datetime.fromisoformat(faked_date)
|
test_date = datetime.fromisoformat(date_courante)
|
||||||
else:
|
else:
|
||||||
test_date = app.db.func.now()
|
test_date = app.db.func.now()
|
||||||
# Les semestres en cours de ce département
|
# Les semestres en cours de ce département
|
||||||
@ -281,9 +281,9 @@ def dept_formsemestres_courants_by_id(dept_id: int):
|
|||||||
"""
|
"""
|
||||||
# Le département, spécifié par un id ou un acronyme
|
# Le département, spécifié par un id ou un acronyme
|
||||||
dept = Departement.query.get_or_404(dept_id)
|
dept = Departement.query.get_or_404(dept_id)
|
||||||
faked_date = request.args.get("faked_date")
|
date_courante = request.args.get("date_courante")
|
||||||
if faked_date:
|
if date_courante:
|
||||||
test_date = datetime.fromisoformat(faked_date)
|
test_date = datetime.fromisoformat(date_courante)
|
||||||
else:
|
else:
|
||||||
test_date = app.db.func.now()
|
test_date = app.db.func.now()
|
||||||
# Les semestres en cours de ce département
|
# Les semestres en cours de ce département
|
||||||
|
@ -76,9 +76,9 @@ def etudiants_courants(long=False):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
allowed_depts = current_user.get_depts_with_permission(Permission.ScoView)
|
allowed_depts = current_user.get_depts_with_permission(Permission.ScoView)
|
||||||
faked_date = request.args.get("faked_date")
|
date_courante = request.args.get("date_courante")
|
||||||
if faked_date:
|
if date_courante:
|
||||||
test_date = datetime.fromisoformat(faked_date)
|
test_date = datetime.fromisoformat(date_courante)
|
||||||
else:
|
else:
|
||||||
test_date = app.db.func.now()
|
test_date = app.db.func.now()
|
||||||
etuds = Identite.query.filter(
|
etuds = Identite.query.filter(
|
||||||
|
@ -22,6 +22,44 @@ from app.scodoc.sco_permissions import Permission
|
|||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/evaluation/<int:evaluation_id>")
|
||||||
|
@api_web_bp.route("/evaluation/<int:evaluation_id>")
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def evaluation(evaluation_id: int):
|
||||||
|
"""Description d'une évaluation.
|
||||||
|
|
||||||
|
{
|
||||||
|
'coefficient': 1.0,
|
||||||
|
'date_debut': '2016-01-04T08:30:00',
|
||||||
|
'date_fin': '2016-01-04T12:30:00',
|
||||||
|
'description': 'TP NI9219 Température',
|
||||||
|
'evaluation_type': 0,
|
||||||
|
'id': 15797,
|
||||||
|
'moduleimpl_id': 1234,
|
||||||
|
'note_max': 20.0,
|
||||||
|
'numero': 3,
|
||||||
|
'poids': {
|
||||||
|
'UE1.1': 1.0,
|
||||||
|
'UE1.2': 1.0,
|
||||||
|
'UE1.3': 1.0
|
||||||
|
},
|
||||||
|
'publish_incomplete': False,
|
||||||
|
'visi_bulletin': True
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
query = Evaluation.query.filter_by(id=evaluation_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = (
|
||||||
|
query.join(ModuleImpl)
|
||||||
|
.join(FormSemestre)
|
||||||
|
.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
)
|
||||||
|
e = query.first_or_404()
|
||||||
|
return jsonify(e.to_dict_api())
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/moduleimpl/<int:moduleimpl_id>/evaluations")
|
@bp.route("/moduleimpl/<int:moduleimpl_id>/evaluations")
|
||||||
@api_web_bp.route("/moduleimpl/<int:moduleimpl_id>/evaluations")
|
@api_web_bp.route("/moduleimpl/<int:moduleimpl_id>/evaluations")
|
||||||
@login_required
|
@login_required
|
||||||
@ -33,39 +71,16 @@ def evaluations(moduleimpl_id: int):
|
|||||||
|
|
||||||
moduleimpl_id : l'id d'un moduleimpl
|
moduleimpl_id : l'id d'un moduleimpl
|
||||||
|
|
||||||
Exemple de résultat :
|
Exemple de résultat : voir /evaluation
|
||||||
[
|
|
||||||
{
|
|
||||||
"moduleimpl_id": 1,
|
|
||||||
"jour": "20/04/2022",
|
|
||||||
"heure_debut": "08h00",
|
|
||||||
"description": "eval1",
|
|
||||||
"coefficient": 1.0,
|
|
||||||
"publish_incomplete": false,
|
|
||||||
"numero": 0,
|
|
||||||
"id": 1,
|
|
||||||
"heure_fin": "09h00",
|
|
||||||
"note_max": 20.0,
|
|
||||||
"visibulletin": true,
|
|
||||||
"evaluation_type": 0,
|
|
||||||
"evaluation_id": 1,
|
|
||||||
"jouriso": "2022-04-20",
|
|
||||||
"duree": "1h",
|
|
||||||
"descrheure": " de 08h00 à 09h00",
|
|
||||||
"matin": 1,
|
|
||||||
"apresmidi": 0
|
|
||||||
},
|
|
||||||
...
|
|
||||||
]
|
|
||||||
"""
|
"""
|
||||||
query = Evaluation.query.filter_by(id=moduleimpl_id)
|
query = Evaluation.query.filter_by(moduleimpl_id=moduleimpl_id)
|
||||||
if g.scodoc_dept:
|
if g.scodoc_dept:
|
||||||
query = (
|
query = (
|
||||||
query.join(ModuleImpl)
|
query.join(ModuleImpl)
|
||||||
.join(FormSemestre)
|
.join(FormSemestre)
|
||||||
.filter_by(dept_id=g.scodoc_dept_id)
|
.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
)
|
)
|
||||||
return jsonify([d.to_dict() for d in query])
|
return jsonify([e.to_dict_api() for e in query])
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/evaluation/<int:evaluation_id>/notes")
|
@bp.route("/evaluation/<int:evaluation_id>/notes")
|
||||||
|
@ -398,7 +398,7 @@ def etat_evals(formsemestre_id: int):
|
|||||||
for evaluation_id in modimpl_results.evaluations_etat:
|
for evaluation_id in modimpl_results.evaluations_etat:
|
||||||
eval_etat = modimpl_results.evaluations_etat[evaluation_id]
|
eval_etat = modimpl_results.evaluations_etat[evaluation_id]
|
||||||
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
evaluation = Evaluation.query.get_or_404(evaluation_id)
|
||||||
eval_dict = evaluation.to_dict()
|
eval_dict = evaluation.to_dict_api()
|
||||||
eval_dict["etat"] = eval_etat.to_dict()
|
eval_dict["etat"] = eval_etat.to_dict()
|
||||||
|
|
||||||
eval_dict["nb_inscrits"] = modimpl_results.nb_inscrits_module
|
eval_dict["nb_inscrits"] = modimpl_results.nb_inscrits_module
|
||||||
|
@ -51,7 +51,7 @@ class Evaluation(db.Model):
|
|||||||
self.description[:16] if self.description else ''}">"""
|
self.description[:16] if self.description else ''}">"""
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
"Représentation dict, pour json"
|
"Représentation dict (riche, compat ScoDoc 7)"
|
||||||
e = dict(self.__dict__)
|
e = dict(self.__dict__)
|
||||||
e.pop("_sa_instance_state", None)
|
e.pop("_sa_instance_state", None)
|
||||||
# ScoDoc7 output_formators
|
# ScoDoc7 output_formators
|
||||||
@ -71,6 +71,34 @@ class Evaluation(db.Model):
|
|||||||
e["poids"] = self.get_ue_poids_dict() # { ue_id : poids }
|
e["poids"] = self.get_ue_poids_dict() # { ue_id : poids }
|
||||||
return evaluation_enrich_dict(e)
|
return evaluation_enrich_dict(e)
|
||||||
|
|
||||||
|
def to_dict_api(self) -> dict:
|
||||||
|
"Représentation dict pour API JSON"
|
||||||
|
if self.jour is None:
|
||||||
|
date_debut = None
|
||||||
|
date_fin = None
|
||||||
|
else:
|
||||||
|
date_debut = datetime.datetime.combine(
|
||||||
|
self.jour, self.heure_debut or datetime.time(0, 0)
|
||||||
|
).isoformat()
|
||||||
|
date_fin = datetime.datetime.combine(
|
||||||
|
self.jour, self.heure_fin or datetime.time(0, 0)
|
||||||
|
).isoformat()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"coefficient": self.coefficient,
|
||||||
|
"date_debut": date_debut,
|
||||||
|
"date_fin": date_fin,
|
||||||
|
"description": self.description,
|
||||||
|
"evaluation_type": self.evaluation_type,
|
||||||
|
"id": self.id,
|
||||||
|
"moduleimpl_id": self.moduleimpl_id,
|
||||||
|
"note_max": self.note_max,
|
||||||
|
"numero": self.numero,
|
||||||
|
"poids": self.get_ue_poids_dict(),
|
||||||
|
"publish_incomplete": self.publish_incomplete,
|
||||||
|
"visi_bulletin": self.visibulletin,
|
||||||
|
}
|
||||||
|
|
||||||
def from_dict(self, data):
|
def from_dict(self, data):
|
||||||
"""Set evaluation attributes from given dict values."""
|
"""Set evaluation attributes from given dict values."""
|
||||||
check_evaluation_args(data)
|
check_evaluation_args(data)
|
||||||
@ -227,7 +255,7 @@ def evaluation_enrich_dict(e: dict):
|
|||||||
heure_fin_dt = e["heure_fin"] or datetime.time(8, 00)
|
heure_fin_dt = e["heure_fin"] or datetime.time(8, 00)
|
||||||
e["heure_debut"] = ndb.TimefromISO8601(e["heure_debut"])
|
e["heure_debut"] = ndb.TimefromISO8601(e["heure_debut"])
|
||||||
e["heure_fin"] = ndb.TimefromISO8601(e["heure_fin"])
|
e["heure_fin"] = ndb.TimefromISO8601(e["heure_fin"])
|
||||||
e["jouriso"] = ndb.DateDMYtoISO(e["jour"])
|
e["jour_iso"] = ndb.DateDMYtoISO(e["jour"])
|
||||||
heure_debut, heure_fin = e["heure_debut"], e["heure_fin"]
|
heure_debut, heure_fin = e["heure_debut"], e["heure_fin"]
|
||||||
d = ndb.TimeDuration(heure_debut, heure_fin)
|
d = ndb.TimeDuration(heure_debut, heure_fin)
|
||||||
if d is not None:
|
if d is not None:
|
||||||
|
@ -93,7 +93,7 @@ def do_evaluation_list(args, sortkey=None):
|
|||||||
# Attention: transformation fonction ScoDoc7 en SQLAlchemy
|
# Attention: transformation fonction ScoDoc7 en SQLAlchemy
|
||||||
cnx = ndb.GetDBConnexion()
|
cnx = ndb.GetDBConnexion()
|
||||||
evals = _evaluationEditor.list(cnx, args, sortkey=sortkey)
|
evals = _evaluationEditor.list(cnx, args, sortkey=sortkey)
|
||||||
# calcule duree (chaine de car.) de chaque evaluation et ajoute jouriso, matin, apresmidi
|
# calcule duree (chaine de car.) de chaque evaluation et ajoute jour_iso, matin, apresmidi
|
||||||
for e in evals:
|
for e in evals:
|
||||||
evaluation_enrich_dict(e)
|
evaluation_enrich_dict(e)
|
||||||
|
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
# Tests unitaires de l'API ScoDoc
|
# Tests unitaires de l'API ScoDoc
|
||||||
|
|
||||||
Démarche générale:
|
Démarche générale:
|
||||||
|
|
||||||
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. modifier /opt/scodoc/.env pour indiquer
|
|
||||||
```
|
```
|
||||||
FLASK_ENV=test_api
|
FLASK_ENV=test_api
|
||||||
FLASK_DEBUG=1
|
FLASK_DEBUG=1
|
||||||
```
|
```
|
||||||
|
|
||||||
2. En tant qu'utilisateur scodoc, lancer:
|
2. En tant qu'utilisateur scodoc, lancer:
|
||||||
|
|
||||||
```
|
```
|
||||||
tools/create_database.sh --drop SCODOC_TEST_API
|
tools/create_database.sh --drop SCODOC_TEST_API
|
||||||
flask db upgrade
|
flask db upgrade
|
||||||
@ -25,17 +26,20 @@ Démarche générale:
|
|||||||
```
|
```
|
||||||
|
|
||||||
2. On lance le serveur ScoDoc sur cette base
|
2. On lance le serveur ScoDoc sur cette base
|
||||||
|
|
||||||
```
|
```
|
||||||
flask run --host 0.0.0.0
|
flask run --host 0.0.0.0
|
||||||
```
|
```
|
||||||
|
|
||||||
3. On lance les tests unitaires API
|
3. On lance les tests unitaires API
|
||||||
|
|
||||||
```
|
```
|
||||||
pytest tests/api/test_api_departements.py
|
pytest tests/api/test_api_departements.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Rappel: pour interroger l'API, il fait avoir un utilisateur avec (au moins) la permission
|
Rappel: pour interroger l'API, il fait avoir un utilisateur avec (au moins) la permission
|
||||||
ScoView dans tous les départements. Pour en créer un:
|
ScoView dans tous les départements. Pour en créer un:
|
||||||
|
|
||||||
```
|
```
|
||||||
flask user-create lecteur_api LecteurAPI @all
|
flask user-create lecteur_api LecteurAPI @all
|
||||||
flask user-password lecteur_api
|
flask user-password lecteur_api
|
||||||
|
@ -115,7 +115,7 @@ class Sample:
|
|||||||
pp(self.result, indent=4)
|
pp(self.result, indent=4)
|
||||||
|
|
||||||
def dump(self, file):
|
def dump(self, file):
|
||||||
self.url = self.url.replace("?faked_date=2022-07-20", "")
|
self.url = self.url.replace("?date_courante=2022-07-20", "")
|
||||||
|
|
||||||
file.write(f"#### {self.method} {self.url}\n")
|
file.write(f"#### {self.method} {self.url}\n")
|
||||||
if len(self.content) > 0:
|
if len(self.content) > 0:
|
||||||
|
@ -46,26 +46,17 @@ def test_evaluations(api_headers):
|
|||||||
for eval in list_eval:
|
for eval in list_eval:
|
||||||
assert verify_fields(eval, EVALUATIONS_FIELDS) is True
|
assert verify_fields(eval, EVALUATIONS_FIELDS) is True
|
||||||
assert isinstance(eval["id"], int)
|
assert isinstance(eval["id"], int)
|
||||||
assert isinstance(eval["jour"], str)
|
|
||||||
assert isinstance(eval["heure_fin"], str)
|
|
||||||
assert isinstance(eval["note_max"], float)
|
assert isinstance(eval["note_max"], float)
|
||||||
assert isinstance(eval["visibulletin"], bool)
|
assert isinstance(eval["visi_bulletin"], bool)
|
||||||
assert isinstance(eval["evaluation_type"], int)
|
assert isinstance(eval["evaluation_type"], int)
|
||||||
assert isinstance(eval["moduleimpl_id"], int)
|
assert isinstance(eval["moduleimpl_id"], int)
|
||||||
assert isinstance(eval["heure_debut"], str)
|
|
||||||
assert eval["description"] is None or isinstance(eval["description"], str)
|
assert eval["description"] is None or isinstance(eval["description"], str)
|
||||||
assert isinstance(eval["coefficient"], float)
|
assert isinstance(eval["coefficient"], float)
|
||||||
assert isinstance(eval["publish_incomplete"], bool)
|
assert isinstance(eval["publish_incomplete"], bool)
|
||||||
assert isinstance(eval["numero"], int)
|
assert isinstance(eval["numero"], int)
|
||||||
assert isinstance(eval["evaluation_id"], int)
|
|
||||||
assert eval["date_debut"] is None or isinstance(eval["date_debut"], str)
|
assert eval["date_debut"] is None or isinstance(eval["date_debut"], str)
|
||||||
assert eval["date_fin"] is None or isinstance(eval["date_fin"], str)
|
assert eval["date_fin"] is None or isinstance(eval["date_fin"], str)
|
||||||
assert isinstance(eval["poids"], dict)
|
assert isinstance(eval["poids"], dict)
|
||||||
assert eval["jouriso"] is None or isinstance(eval["jouriso"], str)
|
|
||||||
assert isinstance(eval["duree"], str)
|
|
||||||
assert isinstance(eval["descrheure"], str)
|
|
||||||
assert isinstance(eval["matin"], int)
|
|
||||||
assert isinstance(eval["apresmidi"], int)
|
|
||||||
|
|
||||||
assert eval["moduleimpl_id"] == moduleimpl_id
|
assert eval["moduleimpl_id"] == moduleimpl_id
|
||||||
|
|
||||||
|
@ -545,27 +545,17 @@ FORMSEMESTRE_ETUS_GROUPS_FIELDS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EVALUATIONS_FIELDS = {
|
EVALUATIONS_FIELDS = {
|
||||||
"id",
|
|
||||||
"jour",
|
|
||||||
"heure_fin",
|
|
||||||
"note_max",
|
|
||||||
"visibulletin",
|
|
||||||
"evaluation_type",
|
|
||||||
"moduleimpl_id",
|
|
||||||
"heure_debut",
|
|
||||||
"description",
|
|
||||||
"coefficient",
|
"coefficient",
|
||||||
"publish_incomplete",
|
|
||||||
"numero",
|
|
||||||
"evaluation_id",
|
|
||||||
"date_debut",
|
"date_debut",
|
||||||
"date_fin",
|
"date_fin",
|
||||||
|
"description",
|
||||||
|
"evaluation_type",
|
||||||
|
"id",
|
||||||
|
"note_max",
|
||||||
|
"numero",
|
||||||
"poids",
|
"poids",
|
||||||
"jouriso",
|
"publish_incomplete",
|
||||||
"duree",
|
"visi_bulletin",
|
||||||
"descrheure",
|
|
||||||
"matin",
|
|
||||||
"apresmidi",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EVALUATION_FIELDS = {
|
EVALUATION_FIELDS = {
|
||||||
|
Loading…
Reference in New Issue
Block a user