Journal Documenter ou tester, il faut trancher (j'ai pas trouvé de rime avec choisir...)

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
12
6
fév.
2025

Sommaire

La dernière fois que j'ai écris sur LinuxFR, j'ai eu une tonne de commentaires utiles, des idées, des critiques, pleins de références comparables à ce que je proposais. C'était exactement ce que je demandais.

Il se trouve que c'est aussi exactement ce dont j'ai besoin aujourd'hui, donc… ben je reviens!

J'ai créé un outil de test, qui me paraît présenter un rapport efficacité / courbe d'apprentissage / utilité très intéressant.
(Oui, je sais, quand on a plus d'un '/' dans la phrase, on ne sait plus bien de quel rapport on parle, mais tu vois l'idée!)
Cette fois-ci, j'ai bien cherché s'il avait de l'existant avant de me lancer, parce que le domaine du test est exploré depuis la nuit des temps informatiques, qu'il y a des dizaines d'outils existant, et donc j'étais sûr de trouver quelque chose.

Mais non. Et donc je pense que j'ai fait quelque chose de nouveau, n'ayons pas peur des mots.

Oui, mais tu cherchais quoi?

Mes deux derniers projets sont des applis en ligne de commande. Elles prennent des choses en entrée, et recrache des choses en sortie.
Les traitements étant rapide, je me suis retrouvé avec 95% de tests end-to-end, comme on dit dans la langue de Donald Molière, et malgré tout une suite de tests qui s'exécute en moins de deux minutes.

J'avais tout naturellement commencé par un petit Makefile, qui lançait l'appli avec les bonnes options, puis un diff de la sortie obtenue avec la sortie attendue.
La suite de tests prenant des stéroïdes, je me suis retrouvé avec une hiérarchie de répertoire de test et de Makefile.
En parallèle, comme je suis un bon gars à l'écoute des "bonnes pratiques", j'ai ajouté dans mes Makefile la génération de la description des tests, et des résultats, qui se retrouvaient à la fin du process dans des fichiers Markdown ou html.
Au début j'avais le sourire, c'était beau à voir tourner.
Puis, à force d'ajouter des tests, j'ai fini par avoir des Makefile d'une longueur énorme, avec une partie documentation pas facile à mettre à jour.

Et ça m'a gonflé.
En informatique, il y a beaucoup de bonnes idées qui ont commencées par un gros soupir de lassitude.

La lettre au père noël

Tant qu'à viser la lune, ça ne me fait pas peur d'en demander beaucoup.
(Oui, il y a de vrais références culturelles dans ce journal)

Première chose, générer la doc. Hashtag #docascode, tout ça.
OK, mais si on prenait la chose au premier degré, et qu'on générait les tests à partir de la doc, et pas le contraire?
Idée vieille comme le monde info… (ah non je l'ai déjà faite, celle là).
Pas question ici néanmoins de sortir les grands moyens, AGL, méthodes formelles, etc. : je développe sur mon temps libre des applis pour m'amuser, pas pour me faire certifier SIL 13 ou DO 178 Z. Il faut que ça reste simple, le but étant de gagner du temps pour un dev "classique".

Pour que ce soit vraiment cool, il faudrait que la doc utilisateur et le script de test ne fasse qu'un. Et que ce soit en anglais, pas dans un langage de programmation ou de script.
L'air de ne pas y toucher, avec cette dernière exigence, je viens de faire sauter 99% de l'offre disponible. En effet, à ma grande surprise, je n'ai pas trouvé d'outil simple qui permette une exécution directe de la doc décrivant le comportement souhaité de l'appli en anglais "normal".

L'utilisation du langage naturel est un vieux dada pour moi. Aussi me suis-je demandé dans quelles conditions, forcément restrictives, je pourrais l'utiliser.
Le premier tour de piste a montré que l'essentiel de mes tests :
1. créaient des fichiers de donnée
2. lancaient mon appli avec les bonnes options
3. vérifiaient les sorties

En utilisant un formalisme Gherkin, ca donne quelque chose comme :
Given the input file machin containing mes datas
When I run mon_app --input=machin
Then I get résultat_attendu

On a pas besoin d'une grammaire sophistiquée. En réalité, je n'ai même pas besoin d'une grammaire complète, au sens où nous l'entendons pour les langages de programmation. (Après avoir codé mon proto, j'ai trouvé des références (rares) sur le net qualifiant ce que j'avais fait de partial parsing, et ça existe depuis 60 ans)

Ca va être moche?

Pour rappel, le but c'est de faire uniquement une documentation "utilisateur".
Dans mes projets, j'utilise MarkDown. (Pour les exigeants, je précise que asciidoc ou autre sont dans la roadmap, en attente d'une demande sérieuse!)
Le principe général "ce dont tu as besoin existe déjà quelque part" n'a pas fonctionné avec l'outil, mais ça a fonctionné avec le format: les gens de Gherkin ont déjà défini une déclinaison Markdown du format Gherkin initial, MDG, que j'ai trouvé très bien, et immédiatement adopté.

Un scenario minimal, ce sera par exemple :

# Scenario: gcc illegal option

(Je prends gcc comme exemple, tout le monde connaît)

- When I run `gcc -tr`
- Then I get an error
- And the output contains `error: unrecognized command-line option`

Et la beauté de la chose, c'est que grosso modo tout ce qui n'est pas dans une ligne Given / When / Then n'est pas interprété par l'outil. Donc on peut vraiment faire une doc à sa guise, avec le plan que l'on veut, en insérant des graphiques, des tableaux, etc.

Sur la forme, c'est du markdown, le rendu n'est pas moche, c'est même beau.

Sur le fond, quand on regarde les fichiers d'entrées qui sont acceptés par l'outils, il est difficile de distinguer la partie qui est du commentaire de la partie qui est exécutée, qui est également écrite dans un anglais presque fluide, non informatique en tout cas.
On peut dire que le but de lisibilité et ouverture à une population de non programmeur est atteint.

Silence, ça tourne

L'outil s'appelle bbt, ce qui veut simplement dire black box tester.
Le proto a rapidement produit un résultat correct, validant le concept.
Je peux même dire à ma grande surprise.

Mon test case est l'un de mes deux projets évoqués ci-dessus, et j'ai donc commencé à migrer mes gros Makefile vers la nouvelle solution. Puis j'ai fait une annonce limitée dans le monde Ada pour avoir les premiers retours utilisateurs.
L'outil est écrit en Ada, c'est mon choix. (j'ai prévenu, gros contenu culturel dans ce texte)
Mais en fait ça n'a aucune importance pour l'utilisateur, on utilise un exe, il n'y a par principe rien à coder ni rien a stubber ou linker avec l'appli.

Pas de chance, mon premier utilisateur enthousiaste était sous Windows. J'avais packagé mon logiciel sous Alire (le cargo d'Ada), et le process de soumission du crate vérifie que ça compile sous Windows et MacOS, mais je n'avais jamais lancé l'appli et encore moins exécuté la suite de test en dehors de Linux.

Incroyable mais vrai, ça marche, et il réussi à l'utiliser. (C'est quand même bien Ada!)
Heureusement d'ailleurs, parce que je voulais des retours sur les fonctionnalités, mais pas perdre mon temps avec de la portabilité. Et bien re-incroyable mais vrai, si le deuxième qui l'a utilisé était bien sous Linux, le troisième était sous Darwin!
La totale, j'aurai du faire appel à linuxFR en premier…

Quoi qu'il en soit, ils m'ont fait des remarques pertinentes, que j'ai prise en compte.
Ils ont utilisé l'outil tout à fait dans l'esprit : globalement, ils ont un fichier markdown qui décrit leur acceptance tests, l'ensemble étant exécuté avec une ligne dans un Makefile.
On ne peut pas faire plus simple et rapide.

Au mois de décembre, j'essaie l'outil en participant (une seule journée) aux défis de codage The Advent of Code.
Le résultat est là : les tests sont tellement rapides à écrire que je passe bien 95% de mon temps sur le code, ce qui est l'objectif.
(Le code est disponible ici, le scenario de test est dans le fichier .md).

Je prévoyais de faire mûrir l'outil encore un peu dans la discrétion, mais au mois de janvier, surprise, AdaCore, que je remercie une fois encore, attribue le prix "Ada crate of the year 2024" à bbt!

Donc je sors du bois.

Mais alors, c'est un outil de doc ou un outil de test? BDD ou test unitaire?

Bonnes questions.
Ce qui est sur, c'est que si tu écris la doc avec bbt, tu n'as pas de tests à écrire.
(hashtag #runthedoc)
Et si tu écris des tests avec bbt, ces tests seront documentés.

Mais tu n'as qu'un seul des deux à faire.

Sur l'esprit : si tu es dans une logique très Gherkin, tu va respecter certaines règles, officielles ou officieuses. Par exemple, mettre un seul "Then" par scenario,
(bbt dispose même d'une option --strict pour vérifier celà), ou respecter un plan de présentation identique pour chaque Feature, suivant tes habitudes ATDD, BDD, etc.

Mais si tu es dans une démarche de test, tu peux faire au plus simple.
L'exemple ci-avant qui teste la réaction de gcc à une mauvaise option sur la ligne de commande contient seulement un scenario, pas de Feature, ce qui est illégal en Gherkin.
De même, pour un test de non régression qui reproduit un bug utilisateur, on a envie de mettre toute les actions qui amènent au bug à la suite: on va avoir plusieurs "When", entrelacés avec des "Then", et peut être même des "Given" après le premier "When".

Ces deux points ne posent pas de problème à bbt : bbtest là pour aider, pas pour juger.

(mon service marketing a insisté pour que je mette cette formulation ici)

Et maintenant?

J'ai le sentiment que tout le monde a, à un moment ou un autre, quelques tests à faire rapidement sur un exe, et que bbt est tellement rapide à mettre en oeuvre qu'il peut être utile pour un très grand nombre de développeur.
Mais en fait je n'en sais rien, je me suis trop souvent enthousiasmé pour des idées qui au final n'intéressaient que moi.

C'est pourquoi je suis très curieux de l'accueil que vous ferez à l'idée d'avoir des tests exécutés à partir d'un document de spécification, et vous remercie par avance pour tout retour sur le concept, l'usage, la doc… sur tout en fait.

Le projet est très jeune (version 0.0.7, c'est tout dire). Il a déjà des cool-features, que je n'ai pas abordées ici. Mais si vous avez des idées nouvelles, je suis à l'écoute, dite moi!

Références

  • # Documentation exécutable, expect, tests unitaires

    Posté par  . Évalué à 4 (+2/-0). Dernière modification le 06 février 2025 à 06:05.

    La doc exécutable, je trouve ça très malin. Ça peut encourager à écrire de la doc quand on écrit des tests, et vice versa. D'une pierre deux coups, on améliore la qualité et la maintenabilité d'un logiciel. Avec une garantie que la doc est correcte et à jour, voire complète si on vérifie la couverture du code. Et des tests lisibles, compréhensibles et qui ont du sens. Ça me donne envie de m'y mettre.

    Ça fait beaucoup penser à l'outil unix expect, qui peut lancer des programmes, écrire dans l'entrée standard, tester la sortie… C'est très complet, et de façon amusante, dans le basique de chez basique, ça ressemble un peu à la grammaire de ton outil : les commandes commencent par un verbe en anglais.

    Par contre, ce n'est pas du tout orienté doc ; tu écrits un script expect quoi.

    Du coup, en partant de la supposition qu'il y aura fatalement des cas demander une telle complexité, ton outil propose-t-il des fonctionnalités du même genre qu'expect, ou est-ce prévu ?

    J'ai l'impression que quelqu'un pourrait implémenter ton idée en faisant un préprocesseur pour expect, qui mange du markdown ou autre en ne gardant que les lignes à destination de l'outil, et qui sort des scripts expect. Est-ce une piste que tu avais envisagé ?

    Y a-t-il des plans pour sortir du modèle "appeler un binaire" et permettre l'exécution des tests dans un code de test ? Ça donne envie de pouvoir documenter et tester des appels de fonctions / méthodes comme ça, où les exemples dans la doc seraient en fait des cas de tests. (Pour le coup, j'ai la vague impression qu'une implémentation en mode préprocesseur pour expect serait un poil incompatible) (et je comprends bien que ça sort probablement très largement du scope de ton implémentation et qu'un outil pour faire une chose bien, c'est pas mal aussi)

    Je suppose que ça demanderait de fournir une bibliothèque et des bindings dans chaque langage de programmation, où le fonctionnement actuel serait juste l'utilisation du binding pour le shell unix.

    En tout cas merci pour l'idée et le partage, et l'outil en libre. Que je me mette à utiliser ton implémentation ou non, c'est inspirant.

  • # Très intéressant commme approche

    Posté par  . Évalué à 0 (+0/-0). Dernière modification le 06 février 2025 à 06:10.

    Très intéressant comme approche. Après question outillage cela dépend beaucoup du langage de programmation utilisé : pour ma part j'aime beaucoup l'approche d'une doc rédigée directement dans le code, avec des exemples qui sont testés pour 1) rester à jour avec le code 2) vérifier les propriétés attendues. La doc est ensuite générée pour avoir un manuel approprié et on peut tester la couverture du code testé et documenté.

    Pour Haskell, il y ainsi doctest, très pratique.

  • # Et l’approche inverse ?

    Posté par  . Évalué à 0 (+0/-0).

    Je viens de réaliser que ce serait peut-être plus simple de générer la doc à partir du code de test plutôt que l’inverse. C’est-à-dire utiliser l’approche programmation lettrée, où on mêlerait pure texte avec le langage de test plus formel, ce dernier étant ensuite remplacé par du texte à la génération de la doc ou exécuté quand on lance les tests. La différence avec l’approche présentée dans le billet est juste que le langage de test est clairement séparé et plus formel.

    Dans un autre domaine, je me souviens de Catala pour les textes législatifs, vous connaissez ?

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.