Tests semi-automatiques de tous les IDEs de la documentation#
À partir de la version 2.3.0, le thème propose de générer une page spécifique, depuis laquelle il est possible de tester automatiquement tous les IDEs créés dans la documentation, en exécutant leur section corr
en lieu et place de la section code
.
Mise en place#
Dans le cas d'une utilisation en local durant mkdocs serve
(voir plus bas pour une utilisation sur le site construit via un pipeline), il suffit d'ajouter le réglage ci-dessous à la configuration du plugin pyodide_macros
dans le fichier mkdocs.yml
:
plugins:
pyodide_macros:
testing:
include: serve
Ceci va automatiquement inclure à la racine de la documentation une page test_ides/
(ou bien test_ides.html
si le réglage use_directory_urls: false
est utilisé dans le fichier mkdocs.yml
).
Cette page contient un IDE vide, ainsi qu'une liste de tous les IDEs utilisés dans les autres pages de la documentation, et les informations et fonctionnalités associées aux tests :
Interface sous l'IDE#
Les boutons supérieurs :
Ces quatre boutons sont des filtres, permettant d'afficher ou non les éléments correspondant à l'état du bouton.
Noter que :
- Le filtre des succès contrôle les deux types de succès: et .
- S'il y a beaucoup de tests, l'affichage peut être long à se mettre à jour.
Sur la gauche :
-
Le bouton
en haut à gauche, permet de lancer tous les tests pour les IDEs actuellement sélectionnés (qu'ils aient déjà été testés ou non).
-
Le bouton
juste à côté permet de stopper les tests, une fois que le test en cours est terminé.
-
Suivent un certain nombre de compteurs :
IDEs found
: nombre d'IDEs trouvés dans toute la documentation.Skip
: nombre d'IDEs non testés (indiqués par dans l'interface. Voir aussi comment configurer le test d'un IDE plus bas dans la page).To do
: nombre d'IDEs sélectionnés mais non encore testés ().Success
: nombre d'IDEs ayant passé les tests sans erreur ( ou , voir la configuration de test d'un IDE).Error
: nombre d'IDEs ayant échoué les tests ().
-
Puis trois boutons:
- Les deux premiers pour sélectionner ou désélectionner tous les IDEs.
- Le troisième pour inverser la sélection de tous les IDE marqués comme nécessitant une "intervention humaine".
Zone centrale :
La zone centrale présente une liste de liens associés à chaque IDE de la documentation.
Les noms sont construits en indiquant la page contenant l'IDE, concaténée avec la chaîne utilisée pour l'argument py_name
, dans l'appel de macro IDE
, ainsi que l'argument ID
s'il a été utilisé.
Sur la droite :
La partie droite contient :
-
L'état de l'IDE en question vis-à-vis des tests :
État Signification Non testé À tester OK (pas d'erreur) OK (erreur voulue) Échec -
Un bouton
, permettant de charger l'intégralité de la configuration de l'IDE et les codes associés, dans celui en haut de la page de tests.
Noter que ce bouton peut être absent, selon les réglages utilisés pourtesting.include
ettesting.load_buttons
.Toutes les sections d'environnement, les restrictions, les tests de validations, ... sont utilisées comme dans l'IDE d'origine.
L'éditeur est par contre complété en y insérant :- le contenu de la section qui est testée (
corr
oucode
, selon comment l'argumentTEST
de l'IDE est défini) - toutes les autres sections non vides (
env
,env_term
,code
,post_term
,post
) sont ensuite insérées dans une chaîne multilignes, afin que l'intégralité des codes de l'IDE soient visibles.
- le contenu de la section qui est testée (
-
Un bouton
, qui permet de relancer le test de cet IDE uniquement.
-
Un ensemble de cases à cocher (désactivées) permettant de savoir quelles sections sont utilisées pour cet IDE. Les noms de sections sont affichés au survol de la souris. Un halo orange met en évidence la section qui sera lancée lors des tests (généralement, la section
corr
, mais cela peut être aussi la sectioncode
, selon la configuration du test).
La présence/absence de fichiersREM.md
ouVIS_REM.md
est également indiquée.
Fonctionnement des tests#
Déroulé#
Les tests sont exécutés dans l'ordre des IDEs affichés dans la zone centrale.
Pour chaque IDE testé, les opérations effectuées sont les suivantes :
- Chargement des données de l'IDE, et mise en place de sa configuration complète (toutes les données passées en argument à la macro: codes python,
SANS
,REC_LIMIT
, ...). - Effacement du contenu du terminal.
- Affiche le nom de l'IDE testé dans le terminal.
- Réinitialise l'environnement pyodide (en utilisant
clear_scope
), sauf si l'IDE est configuré pour ne pas le faire. - Met en place les outils spéciaux pour les tests.
- Lance une validation :
- Les sections d'environnement sont exécutées comme pour une validation normale.
- Utilise la section
corr
(même si elle n'a pas été définie) au lieu de la sectioncode
. Il peut être intéressant de configurer les IDEs n'ayant pas de sectioncorr
pour utiliser la sectioncode
à la place, ou encore pour que ces IDEs soient ignorés. L'option de configurationtesting.empty_section_fallback
peut également être mise à profit pour configurer ce type de comportement de manière plus globale. - Le décompte d'essais, et les affichages spéciaux liés à la révélation des corrections et remarques sont ignorés.
- Supprime les "outils spéciaux".
- Gère le résultat du test, en mettant à jour les compteurs et l'état de la case à cocher du test en cours.
Une fois tous les tests terminés, le contenu du terminal issu du dernier test reste affiché, et le temps total d'exécution est affiché en plus.
Les erreurs#
Lors des tests, le terminal de l'IDE en haut de la page affiche les messages comme le ferait l'IDE d'origine.
Si un test échoue, outre la mise à jour de l'état du test (case à cocher comme celles utilisées dans les QCMs), un message d'erreur détaillé est affiché en plus dans la console du navigateur (accessible via le raccourci F12 ), précédé par le lien vers l'IDE en question. Ceci permet d'analyser à posteriori les erreurs rencontrées.
Il est également possible de rejouer un test en particulier en cliquant sur le bouton qui lui est associé, pour pouvoir voir ce qui a est affiché dans le terminal durant les exécutions.
Outils spéciaux#
Un certain nombre de modifications sont apportées à l'environnement d'exécution, de manière à adapter au mieux certaines fonctionnalités qui pourraient être spécifiques à la page markdown d'origine contenant l'IDE testé.
Il n'est cependant pas possible de couvrir tous les cas, et certains IDEs ne pourront pas être testés avec succès. Dans ces cas là, utiliser l'argument TEST="skip"
dans l'appel de macros de l'IDE concerné permet de ne pas tester celui-ci.
Voici les fonctionnalités altérées pour les exécutions des tests :
Mermaid, Matplotlib
- La fonction
mermaid_figure
est toujours accessible dans la page de tests, quel que soit l'IDE testé actuellement. - Les autres fonctionnalités relatives à ces outils ne sont pas modifiées en elles-mêmes, mais elles peuvent être affectées par la modification du module
js
de pyodide (voir ci-dessous).
import
La fonction d'importation de modules est modifiée de manière à contrôler ce qui est effectivement importés durant les tests :
- Tout import du module
js
renverra un objetfake_js
(voir ci-dessous). - Tout import de
pyodide.http.pyfetch
renverra une fonction alternative permettant de gérer les redirections automatiques pour les requêtes utilisant des adresses relatives.
Le module js
de pyodide
Un objet fake_js
est renvoyé lors d'un import js
.
Cet objet se comporte comme le module d'origine excepté dans deux cas :
js.fetch
est remplacé par une fonction alternative permettant de gérer les redirections automatiques pour les requêtes avec des adresses relatives.js.document
renvoie un objet "siphon" équivalent à un Mock : tout accès de propriétés, appels de méthodes, ou modifications de propriétés sur ces objets (récursivement) n'auront plus aucun effet. Ceci permet d'éviter que les tentatives de modification du DOM sur des éléments inexistant ne fassent échouer les tests alors que c'est le reste du code que l'on veut tester.
Redirections automatiques de requêtes internes utilisant des adresses relatives
Comme évoqué dans les points précédents, les fonctions js.fetch
et pyodide.http.pyfetch
sont remplacées par des fonctions qui analysent l'adresse passée en argument avant de relayer la requête à la fonction d'origine : si l'adresse est identifiée comme étant une adresse relative, elle est modifiée automatiquement de manière à récupérer le fichier à son adresse réelle sur le serveur, depuis la page des tests.
Sont considérées comme relatives toutes les addresses qui ne commencent pas par l'un des préfixes suivants :
http://
https://
ftp://
ftps://
file://
www.
Fonction de téléchargement ou téléversement
Ces fonctions sont laissées intactes, ce qui veut dire que si les IDEs concernés sont testés :
- L'utilisateur devra rester devant son écran pour choisir les fichiers à téléverser.
- Après chaque sélection de fichier, il faudra cliquer dans l'interface, pour éviter le "bug" lié aux actions utilisateurs.
- Des fichiers seront créés sur le disque de l'utilisateur si le test engage la fonction de téléchargement.
Il peut être intéressant d'utiliser l'argument TEST="human"
pour ces IDEs.
Configurations...#
...de la page de tests#
Les réglages disponibles, avec leurs valeurs par défaut sont :
plugins:
- pyodide_macros:
testing:
empty_section_fallback: "skip"
include: "null"
load_buttons: null
page: "test_ides"
Les points notables sont les suivants :
-
Pour un travail en local, utiliser
include: serve
est suffisant :- Par défaut, le nom de la page générée est
test_ides
. - Elle apparaît à la fin du menu de navigation, dans la documentation.
- Toutes les fonctionnalités sont actives, comme décrites ci-dessus.
- Par défaut, le nom de la page générée est
-
Pour générer la page sur le site construit via un pipeline, utiliser
include: site
. La page est alors rendue moins facilement accessible et ne comporte pas toutes les fonctionnalités, du fait que le site est public :- Le nom de la page générée reste
test_ides
, par défaut. - Elle existe sur le site, mais n'est pas ajoutée au menu de navigation : il faut donc rentrer l'adresse à la main dans le navigateur pour y accéder.
- Les boutons de chargement des codes dans l'IDE de la page sont absents :
.
En effet, cela rendrait visible publiquement l'intégralité des codes de tous les IDEs pour toute personne ayant connaissance de l'existence de la page de tests.
Il est possible de modifier ce comportement si besoin (optiontesting.load_buttons: true
), mais il ne faut alors pas oublier de désactiver l'option par la suite.
- Le nom de la page générée reste
Les options présentes dans la sous-configuration testing
du plugin sont décrites ci-dessous.
page = C.Type(str, default='test_ides')
#
Nom de fichier markdown (avec ou sans l'extension .md
) utilisé pour générer une page contenant le nécessaire pour tester de manière semi-automatisée tous les IDEs de la documentation.
- La page n'est créée que si l'option
testing.include
n'est pas ànull
. - Une erreur est levée si un fichier du même nom existe déjà.
- Une erreur est levée si le fichier n'est pas à la racine de la documentation.
include = C.Choice(('null', 'serve', 'site'), default='null')
#
Définit si la page de tests des IDEs doit être générée et de quelle façon.
'null'
: la page de tests n'est pas générée.'serve'
: la page de tests est générée pendantmkdocs serve
, et est ajoutée automatiquement à la navigation.'site'
: la page de tests est ajoutée sur le site construit, mais n'apparaît pas dans la navigation.
load_buttons = C.Optional(C.Type(bool))
#
Définit si le bouton pour charger l'ensemble des codes associés à un IDE de la page des tests sera présent ou non.
Le comportement par défaut dépend de la valeur de l'option testing.include
:
- Pour
testing.include: serve
, le bouton est présent par défaut. - Pour
testing.include: site
, le bouton est absent par défaut.
empty_section_fallback = C.Choice(('', 'skip', 'fail', 'code', 'human', 'no_clear'), default='skip')
#
Lorsque la page des tests des IDEs est construite et que la section à tester pour un IDE donné ne contient pas de code et que empty_section_fallback
est définie, c'est cette "stratégie" qui sera utilisée à la place.
...du test d'un IDE#
Il est possible de modifier légèrement les comportements utilisés pour tester un IDE, en mettant à profit l'argument TEST
des macros IDE
et IDEv
.
Les valeurs utilisables pour cet argument sont un peu particulières :
-
La valeur à utiliser est une des chaînes de caractères suivantes, quand utilisée via les données de configuration (
mkdocs.yml
,.meta.pmt.yml
, ou les entêtes de pages markdown) :Valeur Effet ""
(Défaut) Le test est fait avec la configuration par défaut... "skip"
L'IDE ne sera pas testé. "fail"
Si une erreur est levée, l'IDE sera considéré comme passant le test.
(L'icône utilisée sera alors )."code"
C'est la section code
qui sera testée, et non la sectioncorr
."human"
Marque le test comme nécessitant une intervention humaine (typiquement, up-/download). Par défaut, ces tests sont désactivés, mais un bouton dans l'interface permet de basculer l'état de ces tests spécifiquement. "no_clear"
Dans ce cas, l'environnement pyodide n'est pas nettoyé au début du test.
(Ceci peut s'avérer utile pour des exercices où plusieurs IDEs partagent des fonctions, variables ou objets et sont sensés être exécutés dans l'ordre) -
Pour l'argument
TEST
des macrosIDE
etIDEv
, on peut utiliser :- Les chaînes décrites ci-dessus, ...
-
...mais il est également possible d'instancier des objets
Case
, qui vont permettre de combiner plusieurs paramètres (il est également possible d'ajouter une description au test) :Case( skip: bool = False, fail: bool = False, code: bool = False, human: bool = False, no_clear: bool = False, term_cmd: str="", description: str="", )
La classeCase
est disponible dans l'environnement des macros, ce qui permet de l'utiliser à l'intérieur même de l'appel à une macro :... {{ IDE("exo", TEST=Case(no_clear=True, code=True)) }}
Si l'argumentterm_cmd
est utilisé, le test est effectué en lançant la commande en question dans le terminal. Noter que dans ce cas :- Les différentes sections sont exécutées exactement de la même façon que lors des exécutions normales (notamment, les sections
env
etpost
peuvent être exécutées ou non, selon qu'elles l'ont déjà été auparavant ou pas). - Il est possible d'utiliser des commandes multilignes.
- Si l'objet
Case
utilisecode=True
, cet argument est ignoré et seule la commande indiquée avec l'argumentterm_cmd
est exécutée.
- Les différentes sections sont exécutées exactement de la même façon que lors des exécutions normales (notamment, les sections