# Architecture de test Chaque étape du compilateur (lexing, analyse, vérification et génération de code) peut être testée individuellement - en tenant compte de leurs dépendances en cascade - en utilisant le script de lancement désigné trouvé dans `src/test/script/launchers/` (respectivement `test_lex`, `test_synt`,` test_context`, `test_codegen`). Cependant, tous les tests automatiques sont appelés à partir d'un script de test principal, `src/test/script/run-all-tests.sh`. Ce script est également lancé lors de l'exécution de la commande `mvn verify`. Il vérifie d'abord que ANTLR se comporte correctement (c'est-à-dire qu'il ne plante pas dans la génération du code Java). Ce script utilise son premier argument ou lit un fichier `conf` à la racine du répertoire du projet pour définir la phase du projet (sous-langages Déca) que nous développons et testons actuellement: * `hello_world`: options de `decac`, commentaires, chaînes, `#include`s et `println("...");` dans main. * `sans_objet`: tout ce que l'on peut écrire dans la routine principale de deca et qui n'était pas dans hello_world (pour le moment pas de classes, d'attributs ou de méthodes). * `essentiel`: la partie objet qui manquait à la phase précédente. * `complet`: langage essentiel plus `cast` et `instanceof`. * `extension`: l'extension des lambdas-fonctions. Il convient de noter qu'une phase de projet ultérieure exécute les tests de tous les précédentes phases. ## Tests au niveau de code source deca Le pilote de test principal utilise un script auxiliaire, `src/test/script/test-specific.sh`, pour exécuter les tests de manière compartimentée. Il le fait en prenant comme arguments la phase du compilateur à tester ('lex' et 'parse' correspondant aux tests du dossier `src/test/deca/syntax`, 'context' à `src/test/deca/context` , et 'codegen' à `src/test/deca/codegen`) et un sous-dossier pour les tests spécifiques à la phase actuelle du projet (comme 'hello_world', voir ci-dessus). Ce script vérifie que les tests invalides échouent et que les tests valides réussissent, puis il vérifie si la sortie correspond à ce qui est attendu. Il prend comme argument une ou plusieurs tags, qui sont utilisées pour extraire la sortie attendue d'un test de son propre fichier source (ceci est fait par un programme python à `src/test/script/expect.py`). A titre d'exemple, nous pouvons spécifier le tag `"<IMA_OUTPUT>"` pour nous assurer que le programme deca suivant donne la sortie attendue. ```java /*<IMA_OUTPUT> Hello world !+ <IMA_OUTPUT>*/ { println("Hello world !!!!!"); } ``` De manière analogue, on pourra utiliser les balises `<PARSE_OUTPUT>, <LEX_OUTPUT>` ou `<CTX_OUTPUT>` pour les différentes phases concernées. Notez que nous utilisons des expressions régulières pour designer la sortie attendue, alors il faut faire attention aux caractères spéciaux regex: `[\^$.|?*+(){}`. L'idée est d'utiliser ces expressions régulières pour éviter le codage en dur dans les tests des numéros de colonnes et des lignes, par exemple, lors d'un test de la sortie du lexer. ## Tests des options de la commande Decac Le script principal appelle `src/test/script/test-decac-options.sh` pour tester les différentes options de ligne de commande du compilateur `decac`. De plus, il est possible, en ajoutant des commentaires avec la balise `<DECAC_OPTIONS>`, de lancer decac avec une option particulière. Les tests doivent alors être placé dans les dossiers `custom-valid` et `custom-invalid`. Cela nous a en particulier permis de tester l'option -n, qui neutralise certaines vérifications à l'exécution. ## Tests interactifs Pour tester les fonctions qui lisent des entrées, nous avons développé des tests qui permettent de les utiliser en utilisant la balise `<DECA_INPUT>`. Ces tests doivent être placé dans le dossier `interactive` pour ouvoir être traité par le script général. Ces tests peuvent être lancé seuls à l'aide du script `test-interactive.sh` situé dans le répertoire de scripts. ## Tests de performance Il est également possible, en plaçant les tests dans le dossier `perf`, de compter le nombre de cycles nécessaires à l'exécution de ceux-ci. Le résultat est visible à l'issue d'une exécution de `mvn verify`, ou alors en lançant le script `test-perf.sh` dans le répertoire de scripts. ## Pipeline Sur le dépôt Gitlab, nous avons mis en place un système de pipeline afin de tester en continu le projet au cours de son développement. Le fichier `.gitlab-ci.yml` situé à la raçine du projet permet de gérer ses options. ## Résultats des tests de couverture Nous avons utilisé l'outil Jacoco pour estimer la proportion de couverture de nos tests. A l'issue du développement, nous avons atteint une couverture de 81 % en terme d'instructions. Les instructions ratées sont en grande partie localisées dans le fichier généré `DecaParser.java`. On peut également remaquer qu'on atteint une couverture de branche de 65%. Cela signifie que les branches ratées sont des branches contenant peu d'instructions et donc vraisemblablement dédiées à la programmation défensive (par exemple vérifier qu'un argument n'est pas nul). Nous sommes satisfaits de cette couverture.