post, j'avais déjà évoqué l'insuffisance de l'indicateur "couverture de test" à lui seul pour garantir la détection de régressions. Pour résumer, un autre indicateur permettant de répondre aux questions "mes tests me protègent-ils contre d'éventuelles régressions?" ou formuler autrement "Quel est le niveau de confiance que j'ai dans mes tests?" doit être trouvé.
Deux idées existent. La méthode plus simple consiste à compter le nombre d'assertions réalisées: efficace et simple à mettre en oeuvre puisque cette solution repose sur un simple grep (comme si grep était simple...).
L'autre méthode repose sur le principe suivant:
Le code de test "valide" le code métier. le code métier peut valider le code de test...
Alors concrètement comment faire?! comment l'implémenter? Comme j'avais envie de coder, voilà "l'histoire" d'un POC visant à valider les principes précédemment énoncés.
Le principe clé du POC est le suivant: modifions aléatoirement le code métier existant et assurons nous que les tests associés échouent. Formulé autrement, si pour un code métier donné le test est vert, alors en modifiant ce même code métier - et donc en introduisant des régressions - le test doit être rouge...
Ainsi, il suffit d'exécuter les tests unitaires existants N fois (N étant paramétrable) et pour chaque exécution:
On peut estimer que plus N (le nombre d'exécution des tests) est grand, plus l'éventail de régressions introduit sera riche et nous permettra de calculer un indice traduisant notre niveau de confiance dans les tests.
Concernant les principes techniques:
pointcut allBusinessCode() : execution( * *.*(..)) && !execution(*.(..))
&& within(com.mycompany.apb..*)
&& !within(com.mycompany.apb..*Test*);
public pointcut allTest(): within(*..*Test*)
&& execution(\* \*..test\*(..))
&& !within(com.agitator..\*);
after() throwing(junit.framework.AssertionFailedError afe):allTest()
{ ...
Alors quelles modifications introduire dans le code? A ce jour et à titre d'exemple les modifications type sont les suivantes:
Reste enfin à automatiser ces comportements: et là c'est Maven 2 et son mécanisme de plugin qui rentre en jeu..
Pour pouvoir réaliser les étapes citées précédemment, il est nécessaire:
target/agitator/classes
et target/agitator/test-classes
)le snippet suivant donne un exemple de la configuration du plugin
org.codehaus.mojo
maven-agitator-plugin
1.0-SNAPSHOT
testTheTests
test
instrument
< !\[CDATA\[within(com.mycompany.apb..\*) && !within(com.mycompany.apb..\*Test\*) && !within(com.mycompany.fwk.persistence.PersistentObject+)\]\]>
3
aspectj
aspectjrt
1.5.3
Ainsi au cours de l'exécution mvn site, l'ensemble des opérations de modification effectuées ainsi que leur impact sur le test sont stockés dans un fichier xml qui servira par la suite à la création du rapport Maven:
Cette première version du rapport indique un indicateur de confiance qui est le taux de tests dont le code a été modifié et qui sont en erreur (vous me suivez là? ). A ce jour et pour faire simple, si tous les tests ont échoués - c'est à dire que toutes les régressions introduites ont été modifiées -, cet indicateur est de 100 et est donc au vert. Le rapport indique ensuite pour chacun des tests modifiés et pour chacune des exécutions, la méthode métier modifiée ainsi qu'une description de la modification apportée.
Reste néanmoins qu'il s'agit là d'un POC et du travail reste nécessaire pour faire de ce plugin "quelque chose" de plus industriel et utilisable sereinement "dans la vraie vie" - avec notamment:
Reste également qu'aujourd'hui, à ma connaissance, aucun outil ne réalise vraiment ce genre de modification...