Monkey testing et Property-based testing : une exploration

Monkey testing et Property-based testing : une exploration

Ouvrez l'application que vous développez avec amour depuis des mois et placez un singe devant l'ordinateur. Aussitôt, le primate se saisit du clavier et clique, clique, clique et clique encore, avec un enthousiasme insoupçonné faisant plaisir à voir.

Ce qui, en revanche, fait moins plaisir à voir, c'est l'état de votre application à l'issue de cette petite expérience. Si votre application était bien ficelée, elle aurait résisté à ce stress et se trouverait dans un état cohérent une fois Cheeta retournée à une activité plus normale.

Voilà : le monkey testing, c'est à peu près ça.

Évidemment, c'est prêter bien peu de qualités à nos amis amateurs de bananes, puisque le présupposé est qu'ils ne savent pas faire mieux que taper aléatoirement sur le clavier. Passons outre.

Sachez d'ailleurs que cela fonctionne avec d'autres mammifères. Pour ma part, n'ayant pas de singe sous la main, je laisse mon chat se balader sur le clavier et, croyez moi, elle (c'est une femelle) est très forte pour produire des choses improbables à l'écran.

Bref, assez palabré.

Des outils existent qui permettent de simuler une saisie utilisateur aléatoire au travers de l'IHM. Le monkey testing consiste alors à vérifier que l'application ne casse pas, et c'est déjà beaucoup.

Pour ma part, étant en pleine exploration du Property-based testing (PBT), je me suis demandé si cette façon de tester (déjà évoquée dans un précédent billet) ne pourrait pas nous être de quelques secours.

Voici l'approche, justement :

  • Une architecture functional core / imperative shell afin d'isoler le domaine. L'architecture hexagonale fonctionne sur le papier mais reste peu actionnable dans les faits à cause des dépendances : il faut les mocker, ou bien mettre en place un environnement de test dédié, réinitialisé à chaque fois.

  • L'état applicatif (state) évolue grâce à des fonctions appelées "reducers" : state -> state ou data -> state -> state. Ces fonctions sont appelées par l'API, constitutive de l'imperative shell. Ces reducers sont faciles à composer car les types d'entrée et de sortie sont identiques (state).

  • Le test : un état initial cohérent, que l'on fait évoluer en le passant au travers de reducers choisis aléatoirement. L'état qui en résulte doit être cohérent quoi qu'il arrive, ce qui revient à dire qu'il y a un invariant / une propriété que l'on peut vérifier, d'où le PBT.

Ce qui donne : https://gist.github.com/mathieueveillard/adb3c39ad0cef9861ee70d01695779a9

Voilà, au final c'est plutôt simple. Certes, ça ne teste pas la même "épaisseur" de code que si l'on interagissait au travers de l'IHM, mais personnellement cela me donne déjà un vrai sentiment de sécurité : un état final cohérent après 100 actions aléatoires, c'est déjà bien.

Et pour tout dire, cela m'a permis de déceler un bug bien tordu, donc à mes yeux cette approche était vraiment fructueuse.

Subscribe to Mathieu Eveillard

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe