:: Enseignements :: Master :: M1 :: 2018-2019 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
Projet de Java Avancé MASTER 1 2018
|
Exercice 1 - CodeCoverage
Le but du projet
CodeCoverage est d'implanter un outil permettant de mesurer
la couverture de code (Code Coverage) de test unitaires.
Et pour rendre les choses un peu plus compliquées, vous devez vous intégrer à un outil de build,
pro,
développé en interne à la fac (parce que Gradle ou Maven, c'est trop simple à utiliser, ils sont documentés).
L’application CodeCoverage (techniquement, c'est pas une vrai application cf plus tard) doit:
-
permettre de mesurer la couverture de code par ligne de code, par instruction Java, par branches
(de if, while, try/catch, etc);
-
s'intégrer au logiciel Pro et plus particulièrement à son plugin tester;
-
insérer le code de mesure de la couverture des tests en utilisant, trois techniques différentes, la ré-écriture de bytecode offline,
un système d'agent Java permettant la ré-écriture de bytecode à l'exécution et un processeur d'annotation lié au compilateur Java.
-
générer un fichier code-coverage.xml au format XML indiquant la couverture de code.
-
proposer une interface JavaScript permettant de visualiser la couverture des tests en prenant en entrée des répertoires contenant
les fichiers sources (les .java) et un fichier code-coverage.xml.
-
avoir une suite de tests unitaires couvrant le code de CodeCoverage ayant une couverture de tests de 100%.
La partie JavaScript doit pouvoir marcher sans utiliser de serveur Web particulier, il s'agit d'une page statique
et d'un ensemble de scripts utilisant la librairie reactjs.
Pour permettre l’interopérabilité du fichier
code-coverage.xml, vous utiliserez le format XML
défini par la
DTD de JaCoCo.
Attention, sachant que nous allons tester votre programme de façon automatique, il est vital que ce format soit respecté.
Note: cela rend aussi le visualiseur JavaScript indépendant de la partie qui calcule la couverture de code,
donc il doit être possible d'utiliser l'outil de visualisation d'un groupe avec le fichier
code-coverage.xml
généré par un autre groupe.
Le code source de l'outil de build pro va changer lors de votre développement, vous devez faire en sorte de suivre son évolution pendant la durée de votre développement (pour cela git est votre ami).
Instrumentation du code
Pour savoir si un morceau de code a été exécuté ou non, l'idée est d'ajouter au fichier .class un ensemble d'instructions
dans chaque méthode aux endroits intéressants. L'ensemble d'instructions, appelé communément
probe consiste souvent en un appel
de méthode qui va indiquer "je suis passé à tel endroit". Les probes font donc appel à une méthode qui enregistre les endroits
qui ont été appelé dans le code et à partir de là on peut calculer la couverture des tests.
On vous demande d'implanter au moins 2 types de
probes: celle, classique, qui utilise un appel de méthode et
celle, plus moderne, qui utilise un appel de méthode utilisant
invokedynamic. L'intérêt d'avoir une probe utilisant
invokedynamic est que
invokedynamic permet de capturer le premier appel et de faire en sorte que les appels
suivants ne fassent rien, donc cela trouble moins les performances qu'un appel de méthode classique. Le problème de
invokedynamic
est que l'instruction a été ajoutée à Java 7, elle n'existe pas pour les versions de classe antérieure, donc il n'est pas
possible d'utiliser ce probe si le code a été généré en demandant une version inférieure à la version 7 de Java.
Bien sûr, le code d'une
probe doit être le plus petit possible, et ne pas ajouter des champs ou méthodes dans les classes
pour éviter de troubler trop les performances du code qui s'exécute.
L'autre question est de savoir où mettre les probes et la réponse dépend de ce que l'on veut mesurer,
une ligne, une instruction ou les branches. Vous devez donc avoir des stratégies de placement des probes différentes
en fonction de ce que l'on veut mesurer.
Il vous faut donc être capable de lire un .class et de pouvoir le modifier, vous utiliserez pour cela la librarie
ASM 7 qui est capable de lire et d'écrire du bytecode.
Le bytecode étant un petit peu compliqué je vous encourage vivement à lire les ressources et regarder les vidéos suivantes:
Pour savoir comment utiliser un agent Java et un processeur d'annotations lié au compilateur Java, je vous laisse faire les recherches par vous même.
Calendrier des rendus:
12 octobre: Démarrage + parsing du bytecode
Création d'un module spécifique com.github.forax.pro.coverage contenant l'application
Modification du plugin tester pour appeler le code coverage s'il est activé (activé par défaut).
Ajout des diverses propriétés nécessaires dans les paramètres du tester.
Utilisation d'ASM pour trouver toutes les lignes de toutes les méthodes de toutes les classes.
26 octobre: Premier prototype: Probe simple pour les lignes + génération fichier XML
Création d'une probe simple permettant d'enregistrer les lignes exécutées lorsque les tests sont exécutés.
Les jars du code dans src/main sont ré-écrits en utilisant ASM pour insérer les probes.
Génération du fichier code-coverage.xml une fois que tous les tests on été exécutés.
Ajout des tests unitaires testant le module com.github.forax.pro.coverage (votre propre code),
comme cela vous pouvez tester votre outil de coverage sur votre propre code.
Attention: les tests sont exécutés par défaut en parallèle par plusieurs threads.
9 novembre: invokedynamic, stratégies d'instrumentation, interface graphique.
Développement de la probe utilisant
invokedynamic.
Implantation des stratégies d'instrumentation des lignes, des instructions ou des branches.
Développement de l'interface graphique en JavaScript pure en utilisant les principes du
responsive web design.
24 novembre: ajout des différentes façons d'instrumenter le code
Ajouter un nouveau type de probe (appel classique + invokedynamic) qui ne stocke rien sur la pile
mais qui peut être plus lent.
Ajout de la possibilité d'instrumenter le code à chaud en utilisant un agent Java (option par défaut).
Ajout de la possibilité de modifier le code en utilisant un parseur d'annotations liés au compilateur.
15 décembre: version bêta.
Écrire la doc utilisateur.
Mettre à jour la doc de développement et la javadoc.
La bêta peut avoir des bugs mais doit contenir toutes les fonctionnalités.
31 décembre: version finale.
Corriger les bugs restants.
Se préparer pour la soutenance.
Pour vous aider, si vous ne respectez pas les indications de "sudden death" suivantes,
votre projet ne sera pas noté.
Pour la partie Java, le programme doit être écrit en utilisant correctement les différents concepts
vus lors du cours de Java Avancé (sous-typage, polymorphisme, lambda, classes internes,
exceptions, types paramétrés, collections, entrées/sorties et réflexion).
-
Il ne doit pas y avoir de warnings lorsque l'on charge le code dans Eclipse avec tous les warnings activés !
-
Il ne doit pas y avoir de warnings lorsque l'on compile avec javac -Xlint:all.
-
Dans un module, les packages d'implantation ne doivent pas être exportés et
requires transitive doit être utilisé là où c'est nécessaire.
-
Il ne doit pas y avoir de raw types, de @SuppressWarning non justifié, de cast non justifié.
-
Il ne doit pas y avoir de champs ou méthodes protected.
-
Il ne doit pas y avoir d'instanceof/switch/if...else sur des types là où il est possible
d'utiliser le polymorphisme.
-
Chaque interface devra être nécessaire.
-
Aucune classe abstraite ne doit être publique ou utilisée comme un type.
-
Chaque méthode devra être appelée (pas de code mort).
-
Aucune méthode ne doit pas faire plus de 10 lignes sans une vraie justification.
-
Il est interdit d'utiliser des champs static typés par un objet (pas de globale),
seule les constantes (static final) de type primitif sont autorisées.
Pour la partie JavaScript, les bonnes pratiques vu dans le cours de
Programmation Web de L1 devront être respecté.
-
Le programme devra utiliser la notion de classe et de arrow function.
-
L'utilisation de 'var' est interdite.
-
Le design de la page devra être responsive, pour smartphone, tablette et desktop.
© Université de Marne-la-Vallée