Résumé : Au bout de 3 ans de pratique intensive du BDD avec Specflow en C#, je vous propose de passer en revue les avantages et les écueils de cette pratique, mais également partager "trucs et astuces" et surtout les questionnements qui restent en suspend.
Bénéfices pour les participants : Apprendre et progresser sur le BDD et l'écriture de logiciel pilotée par les tests comportementalistes.
Guillaume, Saint Etienne : Développeur depuis mon premier micro: un ZX81, j’ai endossé également différents rôles, principalement chez des éditeurs logiciels: chef de projet, architecte logiciel, scrum master , et encore maintenant « Senior Software Programmer ».
13. goOgle est mon ennemi
• Le TOP 50 des résultats pour « BDD » (en
français)
– Exemples simplistes et enfantins
– Pas représentatifs d’un vrai projet logiciel
– Pas de vrai retour d’expérience
– Articles sur BDD = ATDD (Acceptance testing /
test d’IHM)
14.
15. Exception!
• Il faut rendre à César ce qui est à Pierre Irrmann
• http://www.arolla.fr/blog/2012/09/bdd-et-
specflow-pour-des-tests-plus-lisibles/
• « Gherkin pour écrire des tests en langage
naturel ».
• « Lorsqu’on développe en BDD, les tests sont
écrits pour tester des fonctionnalités et des
exemples précis de comportements. »
23. La puce à l’oreille
• La section « Feature » dans Gherkin
– In order to
– As a
– I want to
…ne sert à rien!!!!
Elle n’est pas compilée et donc pas « exécutée »
25. Tester c’est comprendre
• du latin « comprehensio »1, de « cum », avec,
et « prehendere », prendre: action de saisir
ensemble ou de prendre avec soi
29. Idées reçues sur le BDD
• You want to do acceptance testing rather than
unit testing.
• You want to use it as a communication tool
with the stake holder.
• You want to do large scale tests rather than
granular tests.
• You want non-technical people to write the
tests.
http://gojko.net/2012/06/18/bdd-busting-the-myths/ [Gojko Adzic]
http://stackoverflow.com/questions/2238176/using-fitnesse-rather-than-nunit
30. You want to do acceptance testing rather
than unit testing.
31. You want to do acceptance testing rather
than unit testing.
32. You want to do acceptance testing rather
than unit testing.
•TDD is excellent
33. You want to do acceptance testing rather
than unit testing.
•TDD is the only way to be agile
•BDD is no more than TDD
34. You want to do acceptance testing rather
than unit testing.
•TDD is the only way to be agile
•BDD is no more than TDD
•BDD is first doing « unit » testing
35. You want to do acceptance testing rather
than unit testing.
•TDD is the only way to be agile
•BDD is no more than TDD
•BDD is first doing « unit » testing
•A «non-unit » test is a scam!
– Test only one thing at a time
36. You want to use it as a communication tool with
the stake holder.
37. You want to use it as a communication tool with
the stake holder.
First, use it as a communication with yourself
38. You want to use it as a communication tool with
the stake holder.
First, use it as a communication with yourself
…
then your team
39. You want to use it as a communication tool with
the stake holder.
First, use it as a communication with yourself
…
then your team
…
then (maybe) the stakeholder or the users.
40. You want to do large scale tests rather than
granular tests.
41. You want to do large scale tests rather than
granular tests.
42. You want to do large scale tests rather than
granular tests.
http://www.jbrains.ca/permalink/integrated-
tests-are-a-scam-part-1
43. Why integrated tests are a scam!
• I use the term integrated
test to mean any test
whose result (pass or
fail) depends on the
correctness of the
implementation of more
than one piece of non-
trivial behavior.
– J. B. Rainsberger
48. You want non-technical people to write the
tests.
•I wish I could …
•Be pragmatic!
•Maybe in the future …
49. Bref, j’ai fait du BDD
• Je passe à une description textuelle
• Exemple!
50. Bref, j’ai fait du BDD
Given I initialize the reader
And jouvre le dossier patient '1'
When je veux lire 'nom'
Then I dont have error
And jobtient une valeur 'Nom 1'
52. DRY
• Mes tests aussi !
• Refactoring
• Les Steps Given/When/Then sont une façon
de « DRY »
• Puissance (et pièges) des expressions
régulières.
• Exemple…
53. Given I initialize the reader
And jouvre le dossier patient '1'
When je veux lire 'nom'
Then I dont have error
And jobtient une valeur 'Nom 1‘
Given I initialize the reader
And jouvre le dossier patient '1'
When je veux lire 'nais'
Then I dont have error
And jobtient une valeur '2/1/1973'
55. Given I initialize the reader
And jouvre le dossier patient '1'
When je veux lire 'nom'
Then I dont have error
And jobtient une valeur 'Nom 1‘
Given I initialize the reader
And jouvre le dossier patient '1'
When je veux lire 'nais'
Then I dont have error
And jobtient une valeur '2/1/1973'
Given I initialize the reader
And jouvre le dossier patient 'F2'
And the log system is initialized with the LogWatch configur
ation
When I read ‘droits' as a Numeric
Then I have an error
And the previous log messages contains: The field 'droits' co
uldn't be read as a Decimal
56. Exemple de refactoring
• On fini par gagner énormément de temps
• Fini le copier/coller… dans le code !
• Donc fini les erreurs…. sur le code (technique)
des tests!
• Exemple!
62. Refactoring en BDD
• Nécessité de créer des Steps efficaces
• Ils sont exécutables, donc il y a du code
derrière.
• Même qualité du code des steps que du reste
du code.
• Ré-utilisables
– Then I dont have error
63. Les outils incontournables
– Dummies
– Fake
– Mocks
– Stub
– Espions / Spies
– Inversion de contrôle / Injection de dépendance
– Helpers
– … comme dans le TDD après tout!
64. Fake / Substituts
• De faux objets ayant un comportement
similaire à l’objet réel, mais d’une façon
simplifiée.
• Il n’agit pas comme un point de contrôle, mais
permet d’accélérer l’exécution des tests.
• Par exemple en remplaçant l’accès à la base
de données par des données dans un fichier
ou en mémoire.
65. Fake
• « Doublure » qui fait comme l’original
DB
ORM 4
Test
Db 4
File Object
66.
67. Mocks
• Une « leurre » mais pas besoin d’écrire son
code « interne »
• Juste décrire ce que l’on attend de lui
68. Mock
• Le Mock se contente de bien se « comporter ».
• Simulation (Setup)
• Vérification du comportement attendu
(optionnelle).
70. Stubs
• Similaires aux MOCKs
• La différence principale vient du fait qu’avec
le Stub on vérifie l’état de l’objet alors
qu’avec le Mock on en vérifie le
comportement (les interactions).
• http://bruno-orsier.developpez.com/mocks-
arent-stubs
71. Refactoring steps with helpers
• Une syntaxe pour accéder aux objets (C# 3.5)
• Sans:
– When je lis le champs ‘City’ dans la 1e adresse du patient en cours
And je lis le champs ‘Type’ dans la 1e adresse du patient en cours
And je lis le champs ‘Type’ dans la 2e adresse du patient en cours
And je lis le champs ‘Type’ dans la 3e adresse du patient en cours
• Avec:
72. Au final, qu’est ce que je teste?
• SUT / SCT : System Under Test / Système en
Cours de Test
• L’Isolation des tests est indispensable (1
problème à la fois)
• Impossible de se passer des doublures.
• Un exemple avec les Spies / Espions
74. Chainage des vérifications
• Pas besoin de tests automatisé intégrés.
• Si tous les mécanismes vu précédemment
sont en place.
• Néanmoins, comment en être sûr?
75. S.O.L.I.D.
• Single responsibility principle
– the notion that an object should have only a single
responsibility.
• Liskov substitution principle
– the notion that “objects in a program should be
replaceable with instances of their subtypes
without altering the correctness of that program”
• Interface segregation principle
– the notion that “many client specific interfaces
are better than one general purpose interface
76. Si mon code est SOLID
• Alors mes tests doivent l’être aussi
79. Vérification automatique
• => Outil de couverture de code.
• Néanmoins difficile d’avoir 100% (erreurs de
l’outil, code inatteignable)
• Donne une très bonne mesure de
l’amélioration de la couverture par les tests.
80. Autres vérifications à faire
• Complétude des tests
• Les « fakes » doivent être testés à leur tour.
• Parcours et vérifications auto. des interfaces:
– Si une doublure (spy/mock/stub) se fait passer
pour une interface, et qu’on n’en trouve pas une
implémentation qui ne soit pas couverte à 100%
par d’autres tests (eux même en parfaite
isolation), alors c’est un échec!
– À inventer!
93. Charge de travail effective
• Nombre de bugs déclarés en exploration et
après livraison:
– 1ere année: 51
– 2ème année: 27
• Nombre de WorkItems (User Needs, Design
Quality)
– 1ere année: 98
– 2ème année: 100
94. Les tests peuvent être lus
• Ce n’est (presque) plus du code, c’est du
texte!!
• On change de perspective (passer de
l’impératif au descriptif).
• Je peux échanger avec mon équipe plus vite.
• Quelqu’un de non technique pourrait-il les
comprendre? Les écrire ?
95. Mais on est encore très loin du
langage naturel
• P.O et skateholders ne comprennent (pour
l’instant) pas tout.
96. PAG
GAP
https://docs.google.com/viewer?url=http%3A%2F%2Fwww.scrumalliance.org%2Fsystem%2Fslides%2F118%2Foriginal
%2FChristianHossa_SpecificationByExampleWithGherkin.pdf%3F1349824954
97. Qu'est ce que mon test raconte?
• Un scénario.
• Même s’il revêt une réalité technique, le
comportement devrait pouvoir être compris
et approuvé par quelqu’un de logique.
• Il ne doit cibler qu’une chose à la fois
(isolation).
98. MIEUX RACONTER
• Etre rigoureux à l’écriture des Steps
• Se conformer au Domaine (Domain Language)
• Faire du Domain Driven Design précisément
• Tests qui resteront techniques et ceux qui
seront plus proches du fonctionnel
• Masquer la technique tout en permettant une
bonne réutilisation des steps (!)
100. Souvent!
• Si c’est bien raconté, oui pour spécifications.
• Doc Technique = OUI ! SI! YES ! JA ! DA!
• Pèsera autant qu’un lourd cahier de tests.
• On a gagné des semaines (voir des mois)
hommes de travail de rédaction et de
vérifications.
• Export automatique des fichiers Specflow ->
Html, Word, Pdf.
116. • the system can’t neatly be tested with automated test
suites because part of the logic is dependent on
often-changing visual details
• http://alistair.cockburn.us/Hexagonal+architecture
124. Polyglot Data
• Le meilleur moyen d’être Data Storage
Agnostic
• Ce n’est plus le DBA qui commande
• SQL / NoSQL ?
• La persistance est un plus, voila tout.
• Exemple: le FakeStorer dans les tests
125. Incidences sur le code
1. Ecrire des Interfaces qui décrivent (abstraire)
ce que les tests vont spécifier dans des
scénarios mettant en évidence la valeur
ajoutée du comportement choisi.
2. Ecrire l’implémentation ensuite.
3. L’intégration continue vérifie tout
automatiquement => non régression.
126. Responsabiliser le code
• Isolation = Une seule responsabilité
Tester c’est apprivoiser.
• « Tu deviens responsable pour toujours de ce
que tu as testé »
Antoine de Saint-Test
127. Toujours plus fluide
• Le style change
• On devient plus « fluent »
• Le code se lit (presque) comme une phrase en
langage naturel
• On se rapproche de la programmation
fonctionnelle (sans changer de langage)
• Fluent API + lambda expressions = le chainon
manquant?
128. En Pratique
• des DOJOS pour montrer que bien tester en
1er, et tester par le comportement induit un
changement de vision dans le design du
logiciel
• Une mise en œuvre des tests et du code par la
simplicité, la rigueur et l’efficacité
• des exemples bientôt sur mon site
http://www.dotnetguru2.org/gse/
130. Comment on a tuer l’intégration
• Créez (ou utilisez) un mécanisme d’intégration
automatique
• Testez le!
• => plus besoin de tester en intégration
• Ajoutez tous les tests qu’il faut pour renforcer
l’intégrité du tout.
• Est-ce une bonne chose?
139. Les pièges à éviter
• Dire « comment » au lieu de « quoi »
• Ne pas laisser transparaitre le « software
design »
• Le « software design » devrait se fondre dans
les spécifications et devenir naturel
• Ne pas se laisser enfermer dans les détails
• Ne pas tout tester en même temps (bis
répetita)
140. Pièges (Suite)
• Garder les tests parlants… (pour qui?)
• Ne pas sur-spécifier (YAGNI sur les tests)
• La partie setup/Given devrait rester simple
• Utiliser un « ubiquitous languange »
• Ne retardez pas l’usage des doublures,
injection de dépendance et autres assistants
• Ne pas sous-estimez votre code « assistant »
(testez les aussi bien)
• Introduire une part de travail manuel
141. (suite)
• Se baser sur des données pré-existantes(!!)
• Ne pas être certain que chaque test soit
idempotent.
• Perdre du sens par soucis de concision
(masquer la réaliter au lieu de la simplifier)
• L’endettement (on fini toujours par payer, et
les taux augmentent avec le temps)
142. Trucs
• Commencer petit
• Progresser à son rythme
• Refactorer régulièrement
• Le temps est votre allié
DRY! KISS! YAGNI! SOLID!