Coach Technique
Développeur Généraliste
A11Y
Marc Bouvier • u.baldir.fr/me
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 ? |
Outil qui simplifie les assertions de documents et modèles d’objets complexes
On Ă©crit un test avec une assertion de Approvals
Jouer le test la première fois génère
un fichier "approuvé" vide
un fichier "reçu" avec le résultat du test
Rejouer le test compare les 2 fichiers
Approuver le résultat si il nous convient
Si les 2 fichiers sont identiques le test passe
En gros c’est ça !
Coach Technique
Développeur Généraliste
A11Y
Caractérisation de code existant
Verrouiller pour Refactor du Code Legacy
Test Driven Development
Acceptance Test Driven Development
REST API
IHM
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é
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
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.
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 |
|
IdĂ©alement pouvoir maitriser l’Ă©tat de dĂ©part et d’arrivĂ©e |
Se concentrer sur la sémantique plutôt que les détails. Pas toujours le plus adapté |
|
|
DĂ©mo
DĂ©mo
Attention Ă l’explosion combinatoire! |
DĂ©mo
<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>
@Test
void truc_approved_basic() {
Approvals.verify("""
Foo : bar
Bar : baz
Baldir.fr""");
}
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
@Test
void fizzbuzz_acceptance() {
Approvals.verifyAll(
range(1, 101).boxed().toList(),
n -> n + " => " + fizzBuzz(n)
);
}
@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");
}
Quand tous les tests de la boucle interne passent et que la boucle externe passe.
La fonctionalité est terminée.
DĂ©mo
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
30 mai
6 juin