Approval Testing + Asciidoctor = BDD + đź’•

🔥 Ce talk contient des démos

Avez-vous déjà ?

Rencontré une base de code sans tests ?

Trouvé du code difficile à refactorer ?

Des assertions difficiles à faire sur des documents ou modèles de données complexes ?

Eu des difficultés à communiquer avec le métier sur le comportement du code ?

Approval testing Assertions

Outil qui simplifie les assertions de documents et modèles d’objets complexes

  1. On Ă©crit un test avec une assertion de Approvals

  2. Jouer le test la première fois génère

    • un fichier "approuvĂ©" vide

    • un fichier "reçu" avec le rĂ©sultat du test

  3. Rejouer le test compare les 2 fichiers

  4. Approuver le résultat si il nous convient

  5. Si les 2 fichiers sont identiques le test passe

En gros c’est ça !

Marc Bouvier

Cas d’utilisation

  • CaractĂ©risation de code existant

  • Verrouiller pour Refactor du Code Legacy

  • Test Driven Development

  • Acceptance Test Driven Development

  • REST API

  • IHM

Caractérisation de code existant

Peut être pertinent quand la connaissance métier a été diluée ou oubliée.

Les règles métier sont dans le code. Rendons les explicites

  • Isoler un bout de code dans un filet de test

  • Ecrire une assertion qui Ă©choue

  • Executer le test

  • Changer le test pour qu’il corresponde au rĂ©sultat

  • RĂ©pter jusqu’à ĂŞtre relativement sĂ»r·e que tous les degrĂ©s de libertĂ©s sont identifiĂ©s et testĂ©

  • Nommer le test selon le comportement caractĂ©risĂ©

Verrouiller pour Refactor du Code Legacy

Peut ĂŞtre pertinent quand un code n’est pas du tout testĂ© et qu’on veut le refactorer.

Et on ne sait pas par oĂą commencer.

De façon similaire à la caractérisation

  • Isoler un bout de code dans un filet de test

  • Ecrire des tests pour couvrir un maximum de branches

  • Refactorer

  • Au fur et Ă  mesure du refactoring on peut ajouter des tests plus petits

  • (bonus) lancer des tests de mutation peut permettre de dĂ©tecter du code mort ou des assertions manquantes

  • Jeter les tests de verrouillage

Test Driven Development

Les assertions "Approval" peuvent être utilisées dans un flow TDD [1]

C’est Ă  dire qu’on Ă©crit d’abord un test qui Ă©choue et on Ă©crit le code de production pour qu’il passe.

1. Test Driven Development
Tableau blanc illustrant le comportement attendu
Fichier de test et fichier de code vide
Ajout d’un test. Le code de production n’existe pas. Un fichier texte vide avec le suffixe .approved et un fichier avec le prĂ©fixe .received sont visibles. Le test Ă©choue.
Le fichier .approved est rempli Ă  l’avance avec les 2 lignes attendues
Le code de production est ajouté poure faire passer le test. Le fichier .approved est identique au fichier .received
Le test passe. Le fichier .received est supprimé.
Refactoring du code de production. Les tests restent vert

Approval Testing et Refactoring

Approval Testing nous impose de crĂ©er un rendu texte de l’Ă©tat attendu.

En quoi c’est intĂ©ressant pour nos tests ?

On crée un découplage entre le code et le résultat attendu.

Ces tests sont plus résistants aux refactorings

Les tests sont peu couplés au langage : on peut ainsi écrire en français

approval tdd 08 new feature approved red
approval tdd 09 new interaction red
approval tdd 10 production code green delete received
approval tdd 11 final green

Acceptance Test Driven Development

image 2024 05 24 10 32 27 341
approval attd 01
approval attd 02
approval attd 03
approval attd 04
approval attd 05
approval attd 06
approval attd 07
approval attd 08

Intérêt

  • On peut laisser le travail en plan

    • Les tests nous indiquent ce qu’il reste Ă  faire

    • On peut s’appuyer sur notre brouillon

    • On peut tester les règles plus fines une Ă  la fois

REST API

IdĂ©alement pouvoir maitriser l’Ă©tat de dĂ©part et d’arrivĂ©e

IHM

Se concentrer sur la sémantique plutôt que les détails.

Pas toujours le plus adapté

Propriétés

  • FacilitĂ© de mise en place

  • Très couvrant

  • Très refactoring friendly

  • Outils de diff pour mettre Ă  jour les changements

  • On sait facilement oĂą on en est : on peut comparer Ă  notre brouillon sur papier ou tableau blanc

  • Aide Ă  Ă©viter des abstractions prĂ©maturĂ©es

  • Binomer avec les gens du mĂ©tier

  • Eviter des dĂ©velopper des IHM trop tĂ´t

Inconvénients

  • Les fichiers sont gĂ©nĂ©rĂ©s Ă  partir des noms de fichier et de fonctions, il vaut mieux anticiper les noms de ces test.

Possibilités

Tests paramétrés

DĂ©mo

Scrubbers

DĂ©mo

Combinaisons

Attention Ă  l’explosion combinatoire!

DĂ©mo

Exemples En Java

TDD avec Approvals en Java

pom.xml
<dependencies>
    <dependency>
        <groupId>com.approvaltests</groupId>
        <artifactId>approvaltests</artifactId>
        <version>23.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Dessiner sur un papier ou tableau blanc

approval tdd demo sketch

Un test avec une assertion Approval

TrucTest.java
@Test
void truc_approved_basic() {
    Approvals.verify("""
            Foo : bar
            Bar : baz
            Baldir.fr""");
}

Diff tool et fichiers .approved / .received

java approvals 01 diff tool and approved received after running test first time

ATTD avec Approvals en Java

Écrire les cas qu’on imagine

FizzBuzzAttdTest.OuterLoop.fizzbuzz_acceptance.approved.txt
1 => 1
2 => 2
3 => Fizz
4 => 4
5 => Buzz
6 => Fizz
7 => 7
8 => 8
9 => Fizz
10 => Buzz
11 => 11
12 => Fizz
13 => 13
14 => 14
15 => FizzBuzz
16 => 16
17 => 17
18 => Fizz
19 => 19
20 => Buzz
21 => Fizz
22 => 22
23 => 23
24 => Fizz
25 => Buzz
26 => 26
27 => Fizz
28 => 28
29 => 29
30 => FizzBuzz
31 => 31
32 => 32
33 => Fizz
34 => 34
35 => Buzz
36 => Fizz
37 => 37
38 => 38
39 => Fizz
40 => Buzz
41 => 41
42 => Fizz
43 => 43
44 => 44
45 => FizzBuzz
46 => 46
47 => 47
48 => Fizz
49 => 49
50 => Buzz
51 => Fizz
52 => 52
53 => 53
54 => Fizz
55 => Buzz
56 => 56
57 => Fizz
58 => 58
59 => 59
60 => FizzBuzz
61 => 61
62 => 62
63 => Fizz
64 => 64
65 => Buzz
66 => Fizz
67 => 67
68 => 68
69 => Fizz
70 => Buzz
71 => 71
72 => Fizz
73 => 73
74 => 74
75 => FizzBuzz
76 => 76
77 => 77
78 => Fizz
79 => 79
80 => Buzz
81 => Fizz
82 => 82
83 => 83
84 => Fizz
85 => Buzz
86 => 86
87 => Fizz
88 => 88
89 => 89
90 => FizzBuzz
91 => 91
92 => 92
93 => Fizz
94 => 94
95 => Buzz
96 => Fizz
97 => 97
98 => 98
99 => Fizz
100 => Buzz

Écrire un test d’acceptation avec une assertion Approvals

FizzBuzzAttdTest.java
        @Test
        void fizzbuzz_acceptance() {
            Approvals.verifyAll(
                    range(1, 101).boxed().toList(),
                    n -> n + " => " + fizzBuzz(n)
            );
        }
approvals attd java 01 blank diff

Boucle interne TDD

        @Test
        void the_number_provided() {
            assertThat(fizzBuzz(1)).isEqualTo("1");
            assertThat(fizzBuzz(2)).isEqualTo("2");
            assertThat(fizzBuzz(4)).isEqualTo("4");
        }
        @Test
        void fizzes() {
            assertThat(fizzBuzz(3)).isEqualTo("Fizz");
            assertThat(fizzBuzz(6)).isEqualTo("Fizz");
            assertThat(fizzBuzz(99)).isEqualTo("Fizz");
        }
        @Test
        void buzzes() {
            assertThat(fizzBuzz(5)).isEqualTo("Buzz");
            assertThat(fizzBuzz(10)).isEqualTo("Buzz");
            assertThat(fizzBuzz(100)).isEqualTo("Buzz");
        }
        @Test
        void fizzBuzzes() {
            assertThat(fizzBuzz(15)).isEqualTo("FizzBuzz");
            assertThat(fizzBuzz(30)).isEqualTo("FizzBuzz");
            assertThat(fizzBuzz(60)).isEqualTo("FizzBuzz");
        }

Vert

Quand tous les tests de la boucle interne passent et que la boucle externe passe.

La fonctionalité est terminée.

Approvals + Asciidoctor

DĂ©mo

Et BDD dans tout ça?

  • BinĂ´mer avec le mĂ©tier

    • RĂ©flĂ©chir sur brouillons et tableau blanc

    • A l’aide de rĂ©sultats de scĂ©narios lisibles par des humains

  • ItĂ©rer rapidement

    • Avec un rendu "sexy"

    • Permet de discuter mĂ©tier sans IHM ou maquettes

binomer metier

Questions ?

Software Craft Strasbourg

qrcode swcraft

30 mai

image 2024 05 24 10 17 11 591

6 juin

image 2024 05 24 10 17 31 287
Logo Agile Tour Strasbourg