SlideShare une entreprise Scribd logo
Living Documentation
Comment coder et
transmettre
ou
@guillaume_agile
Documenter? Pourquoi?
Qui est le public visé?
Qui va relire?
Que voulons nous dire?
Que voulons nous laisser comme trace?
Documenter? A quel prix?
It is more important to
communicate to humans with
your code
than to communicate with a
machine.
Bob C. Martin
Quels écueils ?
➔ Avoir de la documentation non alignée et pas à jour
◆ dès qu’une ligne de code change, le comportement
change et la documentation est obsolète
◆ dès qu’une ligne de spécification change, aussi
◆ on sent le besoin d’un lien entre les deux !!!
➔ Documentation qui n’a pas public
➔ Documentation illisible pour son public
➔ De la documentation inutile
◆ données que l’on a déjà ou qui se trouvent ailleurs
(redondance)
◆ Informations inutiles (OSF)
“La vérité est dans
le code”
Est ce bien le code qu’il faut documenter?
Le code, s’il est bien écrit peut être très expressif:
➔ les noms sont importants:
◆ variables
◆ fonctions
◆ classes
➔ Sujets, verbes et compléments forment des phrases
➔ Les fonctions font !
➔ Les fonctions sont fonctionnelles
➔ A l’intérieur du code, qui lit? qui va comprendre? qu’est
ce qu’il y a comprendre?
➔ Essayez: fluent programming
➔ Essayez: functionnal programming
➔ Pensez à HATHEOAS
DRY !!!
➔ Uniquement des informations pertinentes
➔ Aucune redondance
➔ De l’information utile
➔ Qui donne du sens
➔ Qui soit compréhensible
Le code c’est “COMMENT”
Ce serait bien de documenter le POURQUOI ? !!!
Relisez 3 fois le code pour savoir ce qu’il contient déjà...
et ré-écrivez le!
Redondant ?
//ceci est une calculateur qui calcule
public class Calculateur
{
//renvoit le résultat de a additioné à b
public double Additionne (double a, double b )
{
}
Redondant ?
//ceci est une calculateur qui calcule
public class Calculateur
{
//renvoit le résultat de a additioné à b
public double Additionne (double a, double b )
{
return a - b;
}
// mais c’est pas grave ;)
Compliqué ? Laid ?
static void Main()
{
try
{
// Iterate through all plug-ins.
foreach (var filePath in Directory.GetFiles(Constants.PluginPath, Constants.PluginSearchPattern))
{
// Create the plug-in AppDomain setup.
var pluginAppDomainSetup = new AppDomainSetup();
pluginAppDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
// Create the plug-in AppDomain with the setup.
var plugInAppDomain = AppDomain.CreateDomain(filePath, null, pluginAppDomainSetup);
// Pass the plug-in file path to the AppDomain
var pluginContext = new PluginContext { FilePath = filePath };
plugInAppDomain.SetData(Constants.PluginContextKey, pluginContext);
// Execute the loader in the plug-in AppDomain's context.
// This will also execute the plug-in.
plugInAppDomain.DoCallBack(PluginCallback);
// Retrieve the flag if the plug-in has executed and can be deleted.
pluginContext = plugInAppDomain.GetData(Constants.PluginContextKey) as PluginContext;
// Unload the plug-in AppDomain.
AppDomain.Unload(plugInAppDomain);
// Delete the plug-in if applicable.
if (pluginContext != null && pluginContext.CanDeletePlugin)
{
File.Delete(filePath);
}
}
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
}
public class JeFaisDesTrucsSuper {
public int JeLeFaisAvecUnUtilisateur() {
//je regarde si je connais l'utilisateur
if (e.AddedItems.Count > 0)
{ details.InitializeWith(e.AddedItems[0] as Model.Definition.AppointmentOrTask);
MainGrid.ColumnDefinitions.Add(DetailsAreVisible); }
else MainGrid.ColumnDefinitions.Add(DetailsAreInvisible);
//je vais lui demander son année de naissance
if (Sort == null) return false;
Sort.IsAcsending = Sort.IsAcsending.HasValue && !Sort.IsAcsending.Value;
var items = List.ItemsSource.Cast<object>();
List.ItemsSource = Sort.IsAcsending.Value
? items.OrderBy(o => SortBy.GetValue(o, null))
: items.OrderByDescending(o => SortBy.GetValue(o, null));
//je vais mémoriser son choix
//je vais générer une chiffre au hasard
//je vais demander l'age du captain
//je vais additionner tout cela
//et dire à l'utilisateur que j'ai trouvé son chiffre porte bonheur
//je vais le mémoriser aussi
using (var dbCommand = Sqlbase.CreateCommand (connection,
defautCommandTimeOutForSelectStatement, selectCommand, CommandType.Text, spParams))
{
Log.Write (LogLevel.Verbose, "Sql.Select: {0} with params: {1}", selectCommand.Replace
("rn", " "), DisplayParamsDetails (spParams));
IDbTransaction transaction = null;
if (isolation != IsolationLevel.Unspecified) {
transaction = connection.BeginTransaction (isolation);
dbCommand.Transaction = transaction;
}
}
//et je renvoie, on ne sait jamais
return x;
}
}
//fin de ma fonction
Refactoring
Single Responsability
Nommage intelligible et intelligent
Qu’est ce qui est isolable et testable?
public class JeFaisDesTrucsSuperMaisEnMieux
{
public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui,
IStockeDesTrucs stockage)
{
//je regarde si je connais l'utilisateur
var esTuConnu = ui.Utilisateur.DemandeIdentite();
if (esTuConnu)
return -1;
//je vais lui demander son année de naissance
var anneeNaissance = ui.QuelEstTonAnneeDeNaissance();
//je vais mémoriser son choix
var resultatStockage = stockage.Sauvegarde( anneeNaissance,
ui.Utilisateur.IdentifiantUniversel );
public class JeFaisDesTrucsSuperMaisEnMieux
{
public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui,
IStockeDesTrucs stockage)
{
var esTuConnu = ui.Utilisateur.DemandeIdentite();
if (esTuConnu)
return -1;
var anneeNaissance = ui.QuelEstTonAnneeDeNaissance();
var resultatStockage = stockage.Sauvegarde( anneeNaissance,
ui.Utilisateur.IdentifiantUniversel );
Et quand on en a marre de lire le code..
Quelle serait la place pour une documentation efficace?
Un document électronique qui n’est pas le code mais “entre” le code et les
spécifications...
Mais bon sang, c’est bien sûr....
NOS AMIS LES TESTS
public class JeFaisDesTrucsSuperMaisEnMieux
{
public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui,
IStockeDesTrucs stockage)
{
var esTuConnu = ui.Utilisateur.DemandeIdentite();
if (esTuConnu)
return -1;
var anneeNaissance = ui.QuelEstTonAnneeDeNaissance();
var resultatStockage = stockage.Sauvegarde( anneeNaissance,
ui.Utilisateur.IdentifiantUniversel );
[TestFixture ()]
public class TesteLeStockage
{
[Test ()]
public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur ()
{ //arrange
int valeurAStocker = 101;
int IdUser = 1;
IJeStocke sut = depencyInjection.Get<IJeStocke> ();
//act
var resultatStockage = sut.Stocke (valeurAStocker, IdUser);
sut.ResetConnection();
int verificationValeur = 0;
var resultatLecture = sut.Lecture (out verificationValeur, IdUser);
//assert
Assert.That(verificationValeur , Is.EqualTo(valeurAStocker));
}
}
Les Tests Unitaires
• Ils décrivent ce qui est attendu
• Ils “déclenchent” le code
• Ils sont organisés avec le code
• Si le comportement du code change, au
moins un de mes tests passe au rouge
(sinon j’ai un souci...)
• Donc ils vivent avec le code
• Et si mes tests pouvaient être écrits dans un
langage compréhensible par tous...
IT’S ABOUT TELLING A STORY
[TestFixture ()]
public class TesteLeStockage
{
[Test ()]
public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur ()
{
int valeurAStocker = 101;
int IdUser = 1;
IJeStocke sut = depencyInjection.Get<IJeStocke> ();
var resultatStockage = sut.Stocke (valeurAStocker, IdUser);
sut.ResetConnection();
int verificationValeur = 0;
var resultatLecture = sut.Lecture (out verificationValeur, IdUser);
Assert.That(verificationValeur , Is.EqualTo(valeurAStocker));
}
}
Behaviors Driven Tests
Une syntaxe simple et légère
• Given
• When
• Then
Des utilitaires pour faire tourner les tests basés sur *Unit
* au choix: J/N/JS/x/....
Pas la peine d’en faire plus!
Scenario: Le Stockage Doit Memoriser Une Valeur Pour
Un Utilisateur
Given j’initialise correctement mon test
And j’ai un utilisateur ‘1’ connecté
When je sauve la valeur ‘101’
And je réinitialise le système
And je lis la valeur stockée
Alors le résultat de lecture est ‘101’
IT’S ABOUT BEING FORMAL
Scenario: Le Stockage Doit Memoriser Une Valeur Pour
Un Autre Utilisateur
Given j’initialise correctement mon test
And j’ai un utilisateur ‘222’ connecté
When je sauve la valeur ‘33333’
And je réinitialise le système
And je lis la valeur stockée
Alors le résultat de lecture est ‘3333’
IT’S ABOUT BEING MACHINE
READABLE
Executable Steps
[Given(@"j’initialise correctement mon test")]
public void GivenTestInit()
{
IJeStocke sut = depencyInjection.Get<IJeStocke> ();
}
Executable Steps (2)
[Given(@"j’ai un utilisateur ‘(.*)’ connecté")]
public void GivenTestInit(string x)
{
int IdUser = int.Parse( x );
}
Regular expressions
Pour l’instant la seule manière de passer du
langage naturel à une expression comprise
par la machine...
Des idées pour le futur ?
Executable Steps (2)
[Given(@"j’ai un utilisateur ‘[([0-9]+)]’ connecté")]
public void GivenTestInit(int x)
{
int IdUser = x ;
}
Step to Step
[Given(@"j’ai un utilisateur ‘[([0-9]+)]’ connecté")]
public void GivenTestInit(int x)
{
int IdUser = x ;
ScenarioContext.Current.Set(IdUser, “IdUser”);
}
Step to Step
[When(@" je sauve la valeur ‘‘[([0-9]+)]’’")]
public void WhenValueIsSaved(int valeurAStocker)
{
var IdUser = ScenarioContext.Current.Get<int>(
“IdUser”);
var resultatStockage = sut.Stocke (valeurAStocker,
IdUser);
Assert.That (resultatStockage, Is.True);
}
IT’S ABOUT OBJECTS
Talking to objects
Objects = instance de classe
Class = abstraction, concept
Interface = contrat, capacité de comportement
Inter-active Steps
[When(@" je sauve la valeur ‘‘[([0-9]+)]’’")]
public void WhenValueIsSaved(int valeurAStocker)
{
var IdUser = ScenarioContext.Current.Get<int>( “IdUser”);
var sut = ScenarioContext.Current.Get<IJeStocke>
( “CurrentTestStorage”);
var resultatStockage = sut.Stocke (valeurAStocker, IdUser);
Assert.That (resultatStockage, Is.True);
}
public interface IJeStocke
{
int Stocke (int valeur, int identifiantUniversel);
int Lecture (out int valeur, int
identifiantUniversel);
}
IT’S ABOUT BEING HUMAN
[TestFixture ()]
public class TesteLeStockage
{
[Test ()]
public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur ()
{
int valeurAStocker = 101;
int IdUser = 1;
IJeStocke sut = depencyInjection.Get<IJeStocke> ();
var resultatStockage = sut.Stocke (valeurAStocker, IdUser);
sut.ResetConnection();
int verificationValeur = 0;
var resultatLecture = sut.Lecture (out verificationValeur, IdUser);
Assert.That(verificationValeur , Is.EqualTo(valeurAStocker));
}
}
Scenario:
LeStockageDoitMemoriserUneValeurPourUnUtilisateur
Given j’initialise correctement mon test
And j’ai un utilisateur ‘222’ connecté
When je sauve la valeur ‘33333’
And je réinitialise le système
And je lis la valeur stockée
Alors le résultat de lecture est ‘3333’
Interfaces : the human side of objects
La documentation à travers les spécifications
exécutables est le reflet des interfaces objets
dans le monde des humains.
public interface IJeStocke
{
int JeSauve (int valeur, int identifiantUniversel);
int JeLis (out int valeur, int identifiantUniversel);
}
public interface IEntrepot
{
int JeSauve (int valeur, int identifiantUniversel);
int JeLis (out int valeur, int identifiantUniversel);
}
public class NoSqlQuiPoutre : IEntrepot
{
public int JeSauve (int valeur, int identifiantUniversel)
{ ............;}
public int JeLis (out int valeur, int identifiantUniversel)
{ ............;}
}
AI JE BESOIN DE COMMENTAIRES ???
[TestFixture ()]
public class TesteLeStockage
{
[Test ()]
public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur ()
{
int valeurAStocker = 101;
int IdUser = 1;
IJeStocke sut = depencyInjection.Get<IJeStocke> ();
var resultatStockage = sut.JeSauve (valeurAStocker, IdUser);
sut.ResetConnection();
int verificationValeur = 0;
var resultatLecture = sut.JeLis (out verificationValeur, IdUser);
} }
Change the way you code
What are interfaces (really) ?
Du rôle des interfaces
Ainsi « l’interface devient le produit et l’objet du service ». Elle n’est
plus un espace de commande utilisable, elle est la représentation
du service, son usage et sa finalité symbolique, cognitive et
esthétique.
http://www.nodesign.net/blog/vers-un-confort-numerique-moderne/
Les Interfaces doivent être ergonomiques
https://goo.gl/WUEh48
BDD: It's about Behaviour
BACKGROUND + GIVEN : Environnement + Setup
WHEN: ACTION
• Sujet
• Verbe
• Complement
THEN: RESULTAT ATTENDU
• Sujet
• Etat
END : Environnement rétalbi
IT’S ABOUT BEING MORE HUMAN
READABLE
Scenario:
LeStockageDoitMemoriserUneValeurPourUnUtilisateur
Given j’initialise correctement mon test
And j’ai un utilisateur ‘1’ connecté
When je sauve la valeur ‘101’
And je réinitialise le système
And je lis la valeur stockée
Alors le résultat de lecture est ‘101’
Scenario:
LeStockageDoitMemoriserUneValeurPourUnUtilisateur
Given j’initialise correctement le système de stockage
And j’ai un utilisateur ‘1’ connecté
When je sauve la valeur ‘101’ pour cet utilisateur
And je réinitialise le système de stockage
And je lis la valeur stockée pour l’utilisateur connecté
Alors le résultat de lecture est ‘1’
Inter-active Steps
[When(@" je sauve la valeur ‘‘[([0-9]+)]’’")]
public void WhenValueIsSaved(int valeurAStocker)
{
var IdUser = ScenarioContext.Current.Get<IUtilisateur>(
“User”);
var sut = ScenarioContext.Current.Get<IJeStocke>
( “CurrentTestStorage”);
var resultatStockage = sut.Stocke (valeurAStocker, IdUser);
Assert.That (resultatStockage, Is.True);
}
IT’S ABOUT CODE BEING MORE
HUMAN READABLE
public interface IEntrepot
{
int JeSauve (int valeur, IUtilisateur utilisateur);
int JeLis (out int valeur, IUtilisateur utilisateur);
}
public interface IUtilisateur
{
bool DemandeIdentite (ICredential credits);
int DonneAnneeNaissance ();
}
IT’S ABOUT TDD
Writing Test First
Feature: identification avec des jetons
Scenario: Un utilisateur est identifié
Given j’initialise correctement mon test
And j’ai un jeton égal à x10103
When je demande à identifier l’utilisateur avec ce jeton
Alors le résultat est ok
public class UtilisateurAJetons : IUtilisateur
{
#region IUtilisateur implementation
bool IUtilisateur.DemandeIdentite (Icredential credits)
{
throw new NotImplementedException ();
}
int IUtilisateur.DonneAnneeNaissance ()
{
throw new NotImplementedException ();
}
#endregion
}
Reusing Tests
Feature: identification avec Facebook
Scenario: Un utilisateur est identifié
Given j’initialise correctement mon test
And j’ai un jeton égal à FB44103
When je demande à identifier l’utilisateur avec ce jeton
Alors le résultat est ok
public class UtilisateurFacebook : IUtilisateur
{
#region IUtilisateur implementation
bool IUtilisateur.DemandeIdentite (Icredential credits)
{
throw new NotImplementedException ();
}
int IUtilisateur.DonneAnneeNaissance ()
{
throw new NotImplementedException ();
}
#endregion
}
IT’S ABOUT REFACTORING
Est ce que mon test est lisible ?
⇥
Est ce que j’ai bien ré-utilisé mes steps ?
⇥
Est ce que j’ai généralisé les bons concepts ?
⇥
Design des interfaces et des objets
IT’S ABOUT REUSING
Scenario:
LeStockageDoitMemoriserUneValeurPourUnUtilisateur
Given j’initialise correctement le système de stockage
And j’ai un utilisateur ‘1’ connecté
When je sauve la valeur ‘101’ pour cet utilisateur
And je réinitialise le système de stockage
And je lis la valeur stockée pour l’utilisateur connecté
Alors le résultat de lecture est ‘1’
Scenario: L’ Utilisateur doit pouvoir saisir une année de
naissance
Given j’initialise correctement le système graphique
And j’ai un utilisateur ‘1’ connecté
When l’ utilisateur saisi la valeur ‘1970’
Alors le résultat de Utilisateur[1].AnnéeDeNaissance est
‘1970’
Scenario: L’ Utilisateur doit pouvoir saisir une année de
naissance
Given j’initialise correctement le système graphique
And j’ai un utilisateur ‘1’ connecté
When l’ utilisateur saisi la valeur ‘1970’
Alors le résultat de Utilisateur[1].AnnéeDeNaissance est
‘1970’
Action/Verbe (step ré-utilisable)
Concept (ré-utilisable) ⇒ interface
IT’S ABOUT TDD (again)
A test written in Specflow can be re-
written in Nunit (or any test
framework)
A test written in Specflow form has the
same value than a Unit Test
Consider your Specflow tests as Unit
Tests
• It it executable
• It’s UNITaire
• It’s fast to execute
What are Tests ?
http://fr.slideshare.net/confiz/software-testing-methods-levels-and-types
Pourquoi les opposer?
Les tests dépendent de la vision du
logiciel que l’on a
et comment on le construit
Développeur = Testeur
Integration testing: Testing continuously evolving modules (with
defined expected actual outcome)
User acceptance testing: User representative testing (with defined
expected actual outcome)
Sanity testing: Testing after multiple builds (with defined expected
actual outcome)
Smoke testing: Testing after every build (with defined expected
actual outcome)
Exploratory testing: Unplanned and unscripted testing (no defined
expected actual outcome)
Regression testing: End-to-end testing done to ensure that
nothing is broken in the integrating modules -
https://www.scrumalliance.org/community/articles/2013/march/agile-methodology-is-not-all-about-
exploratory-tes#sthash.QEmYsyLg.dpuf
Yes, TDD has a cost!
• In 2008 Microsoft Research study and results published
in a paper Realizing quality improvement through test
driven development: results and experiences of four
industrial teams, by Nachi Nagappan and research
colleagues E. Michael Maximilien of IBM
• What the research team found was that the TDD teams
produced code that was 60 to 90 percent better in
terms of defect density than non-TDD teams.
• They also discovered that TDD teams took longer to
complete their projects—15 to 35 percent longer.
IT’S ABOUT DOCUMENTATION and
QUALITY
Gherkin / Cucumber / Specflow
fichiers textuels (.feature)
⇥ convertisseur html/pdf
⇥ liaison avec le repository de code (changes)
⇥ liaison avec le Product Backlog (UC / WI)
⇥ production de la documentation concernant
le release
⇥ mise au format du RQ/QA
⇥ signature.
REX
Documentation de 2000+ pages générée à la demande.
Générées automatiquement sans aucun effort ( ...
maintenant que les automatismes sont en place)
Personne de l’assurance qualité ne les lit, mais ils les
signent !
Les tests verts n’ont jamais tort!
Un bug = un test manque pour couvrir le cas rencontré.
Des développeurs essayent de se
rapprocher du fonctionnel
Et l’inverse ?
Specification by Exemple...
https://leanpub.com/livingdocumentation

Contenu connexe

Similaire à Living Documentation (TDD, BDD).pptx

Formation tests decembre2010
Formation tests decembre2010Formation tests decembre2010
Formation tests decembre2010
Fou Cha
 
Les tests en PHP
Les tests en PHPLes tests en PHP
Les tests en PHP
Jean-Philippe Chateau
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
Microsoft
 
Des tests modernes pour Drupal
Des tests modernes pour DrupalDes tests modernes pour Drupal
Des tests modernes pour Drupal
Christophe Villeneuve
 
Persona: un système d'identité pour le Web
Persona: un système d'identité pour le WebPersona: un système d'identité pour le Web
Persona: un système d'identité pour le Web
Francois Marier
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web
5pidou
 
Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend Framework
Mickael Perraud
 
jQuery
jQueryjQuery
jQuery
Franck SIMON
 
Fondamentaux portée - contexte - function ms tech days
Fondamentaux   portée - contexte - function ms tech daysFondamentaux   portée - contexte - function ms tech days
Fondamentaux portée - contexte - function ms tech days
Jean-Pierre Vincent
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
Antoine Rey
 
POO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfPOO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdf
LarbaSAWADOGO2
 
Javascript : fondamentaux et OOP
Javascript : fondamentaux et OOPJavascript : fondamentaux et OOP
Javascript : fondamentaux et OOP
Jean-Pierre Vincent
 
Javascript Json artchitecture
Javascript  Json artchitecture Javascript  Json artchitecture
Javascript Json artchitecture
zaghir
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - Specflow
Mathias Kluba
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
guest6e3bed
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
JS Bournival
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013
Guillaume Laforge
 
Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'ts
Julien Wittouck
 
Draft - Developper Sur Elgg
Draft - Developper Sur ElggDraft - Developper Sur Elgg
Draft - Developper Sur Elgg
Brice Gaillard
 

Similaire à Living Documentation (TDD, BDD).pptx (20)

Formation tests decembre2010
Formation tests decembre2010Formation tests decembre2010
Formation tests decembre2010
 
Les tests en PHP
Les tests en PHPLes tests en PHP
Les tests en PHP
 
Introduction à JavaScript
Introduction à JavaScriptIntroduction à JavaScript
Introduction à JavaScript
 
Des tests modernes pour Drupal
Des tests modernes pour DrupalDes tests modernes pour Drupal
Des tests modernes pour Drupal
 
Persona: un système d'identité pour le Web
Persona: un système d'identité pour le WebPersona: un système d'identité pour le Web
Persona: un système d'identité pour le Web
 
Quelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application webQuelle place pour le framework Rails dans le développement d'application web
Quelle place pour le framework Rails dans le développement d'application web
 
Tester les applications Zend Framework
Tester les applications Zend FrameworkTester les applications Zend Framework
Tester les applications Zend Framework
 
jQuery
jQueryjQuery
jQuery
 
Fondamentaux portée - contexte - function ms tech days
Fondamentaux   portée - contexte - function ms tech daysFondamentaux   portée - contexte - function ms tech days
Fondamentaux portée - contexte - function ms tech days
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
 
POO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdfPOO_Java_BasesLangage.pdf
POO_Java_BasesLangage.pdf
 
Javascript : fondamentaux et OOP
Javascript : fondamentaux et OOPJavascript : fondamentaux et OOP
Javascript : fondamentaux et OOP
 
iTunes Stats
iTunes StatsiTunes Stats
iTunes Stats
 
Javascript Json artchitecture
Javascript  Json artchitecture Javascript  Json artchitecture
Javascript Json artchitecture
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - Specflow
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Présentation Groovy
Présentation GroovyPrésentation Groovy
Présentation Groovy
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013
 
Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'ts
 
Draft - Developper Sur Elgg
Draft - Developper Sur ElggDraft - Developper Sur Elgg
Draft - Developper Sur Elgg
 

Plus de Guillaume Saint Etienne

Ecologie du Logiciel (Craft Luxembourg 2022).pdf
Ecologie du Logiciel (Craft Luxembourg 2022).pdfEcologie du Logiciel (Craft Luxembourg 2022).pdf
Ecologie du Logiciel (Craft Luxembourg 2022).pdf
Guillaume Saint Etienne
 
musique electronique au cinéma.pptx
musique electronique au cinéma.pptxmusique electronique au cinéma.pptx
musique electronique au cinéma.pptx
Guillaume Saint Etienne
 
DDD FOR POs.pdf
DDD FOR POs.pdfDDD FOR POs.pdf
DDD FOR POs.pdf
Guillaume Saint Etienne
 
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Guillaume Saint Etienne
 
des algoritmes et des hommes (ethique et code).pdf
des algoritmes et des hommes (ethique et code).pdfdes algoritmes et des hommes (ethique et code).pdf
des algoritmes et des hommes (ethique et code).pdf
Guillaume Saint Etienne
 
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdfLa crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
Guillaume Saint Etienne
 
How we can BUILD.pdf
How we can BUILD.pdfHow we can BUILD.pdf
How we can BUILD.pdf
Guillaume Saint Etienne
 
des mutants dans le code.pdf
des mutants dans le code.pdfdes mutants dans le code.pdf
des mutants dans le code.pdf
Guillaume Saint Etienne
 
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
Guillaume Saint Etienne
 
Il n’y a pas de bons développeurs.pptx
Il n’y a pas de bons développeurs.pptxIl n’y a pas de bons développeurs.pptx
Il n’y a pas de bons développeurs.pptx
Guillaume Saint Etienne
 
Agile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptxAgile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptx
Guillaume Saint Etienne
 
10 ans de Code (Agile Bordeaux 2019).pptx
10 ans de Code (Agile Bordeaux 2019).pptx10 ans de Code (Agile Bordeaux 2019).pptx
10 ans de Code (Agile Bordeaux 2019).pptx
Guillaume Saint Etienne
 
Vendredi Tech_ la programmation fonctionnelle.pptx
Vendredi Tech_ la programmation fonctionnelle.pptxVendredi Tech_ la programmation fonctionnelle.pptx
Vendredi Tech_ la programmation fonctionnelle.pptx
Guillaume Saint Etienne
 
Feedback on DDD Europe - short -event storming.pptx
Feedback on DDD Europe - short -event storming.pptxFeedback on DDD Europe - short -event storming.pptx
Feedback on DDD Europe - short -event storming.pptx
Guillaume Saint Etienne
 
Crise agile chez les développeurs (frug agile 2020)
Crise agile chez les développeurs (frug agile 2020)Crise agile chez les développeurs (frug agile 2020)
Crise agile chez les développeurs (frug agile 2020)
Guillaume Saint Etienne
 
My feedback on ddd europe
My feedback on ddd europeMy feedback on ddd europe
My feedback on ddd europe
Guillaume Saint Etienne
 
Electronic Music and Software Craftsmanship: analogue patterns.
Electronic Music and Software Craftsmanship: analogue patterns.Electronic Music and Software Craftsmanship: analogue patterns.
Electronic Music and Software Craftsmanship: analogue patterns.
Guillaume Saint Etienne
 
Tdd vs SQL
Tdd vs SQLTdd vs SQL
Services & Contrats Agiles
Services & Contrats AgilesServices & Contrats Agiles
Services & Contrats Agiles
Guillaume Saint Etienne
 

Plus de Guillaume Saint Etienne (20)

Ecologie du Logiciel (Craft Luxembourg 2022).pdf
Ecologie du Logiciel (Craft Luxembourg 2022).pdfEcologie du Logiciel (Craft Luxembourg 2022).pdf
Ecologie du Logiciel (Craft Luxembourg 2022).pdf
 
musique electronique au cinéma.pptx
musique electronique au cinéma.pptxmusique electronique au cinéma.pptx
musique electronique au cinéma.pptx
 
DDD FOR POs.pdf
DDD FOR POs.pdfDDD FOR POs.pdf
DDD FOR POs.pdf
 
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
Tout ce que vous avez voulu savoir sur les Doublures sans jamais oser le dema...
 
des algoritmes et des hommes (ethique et code).pdf
des algoritmes et des hommes (ethique et code).pdfdes algoritmes et des hommes (ethique et code).pdf
des algoritmes et des hommes (ethique et code).pdf
 
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdfLa crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
La crise Agile chez les Developpeurs (AGrenoble2019) (1).pdf
 
How we can BUILD.pdf
How we can BUILD.pdfHow we can BUILD.pdf
How we can BUILD.pdf
 
des mutants dans le code.pdf
des mutants dans le code.pdfdes mutants dans le code.pdf
des mutants dans le code.pdf
 
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
_(V3.0) Aux sources de la simplicité Bordeaux 2022.pptx
 
Il n’y a pas de bons développeurs.pptx
Il n’y a pas de bons développeurs.pptxIl n’y a pas de bons développeurs.pptx
Il n’y a pas de bons développeurs.pptx
 
Agile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptxAgile pour l'echafaud ATT2020.pptx
Agile pour l'echafaud ATT2020.pptx
 
10 ans de Code (Agile Bordeaux 2019).pptx
10 ans de Code (Agile Bordeaux 2019).pptx10 ans de Code (Agile Bordeaux 2019).pptx
10 ans de Code (Agile Bordeaux 2019).pptx
 
Vendredi Tech_ la programmation fonctionnelle.pptx
Vendredi Tech_ la programmation fonctionnelle.pptxVendredi Tech_ la programmation fonctionnelle.pptx
Vendredi Tech_ la programmation fonctionnelle.pptx
 
Feedback on DDD Europe - short -event storming.pptx
Feedback on DDD Europe - short -event storming.pptxFeedback on DDD Europe - short -event storming.pptx
Feedback on DDD Europe - short -event storming.pptx
 
Crise agile chez les développeurs (frug agile 2020)
Crise agile chez les développeurs (frug agile 2020)Crise agile chez les développeurs (frug agile 2020)
Crise agile chez les développeurs (frug agile 2020)
 
My feedback on ddd europe
My feedback on ddd europeMy feedback on ddd europe
My feedback on ddd europe
 
Electronic Music and Software Craftsmanship: analogue patterns.
Electronic Music and Software Craftsmanship: analogue patterns.Electronic Music and Software Craftsmanship: analogue patterns.
Electronic Music and Software Craftsmanship: analogue patterns.
 
Tdd vs SQL
Tdd vs SQLTdd vs SQL
Tdd vs SQL
 
Clean architectures
Clean architecturesClean architectures
Clean architectures
 
Services & Contrats Agiles
Services & Contrats AgilesServices & Contrats Agiles
Services & Contrats Agiles
 

Living Documentation (TDD, BDD).pptx

  • 1. Living Documentation Comment coder et transmettre ou @guillaume_agile
  • 2. Documenter? Pourquoi? Qui est le public visé? Qui va relire? Que voulons nous dire? Que voulons nous laisser comme trace?
  • 4. It is more important to communicate to humans with your code than to communicate with a machine. Bob C. Martin
  • 5. Quels écueils ? ➔ Avoir de la documentation non alignée et pas à jour ◆ dès qu’une ligne de code change, le comportement change et la documentation est obsolète ◆ dès qu’une ligne de spécification change, aussi ◆ on sent le besoin d’un lien entre les deux !!! ➔ Documentation qui n’a pas public ➔ Documentation illisible pour son public ➔ De la documentation inutile ◆ données que l’on a déjà ou qui se trouvent ailleurs (redondance) ◆ Informations inutiles (OSF)
  • 6. “La vérité est dans le code”
  • 7. Est ce bien le code qu’il faut documenter? Le code, s’il est bien écrit peut être très expressif: ➔ les noms sont importants: ◆ variables ◆ fonctions ◆ classes ➔ Sujets, verbes et compléments forment des phrases ➔ Les fonctions font ! ➔ Les fonctions sont fonctionnelles ➔ A l’intérieur du code, qui lit? qui va comprendre? qu’est ce qu’il y a comprendre? ➔ Essayez: fluent programming ➔ Essayez: functionnal programming ➔ Pensez à HATHEOAS
  • 8. DRY !!! ➔ Uniquement des informations pertinentes ➔ Aucune redondance ➔ De l’information utile ➔ Qui donne du sens ➔ Qui soit compréhensible Le code c’est “COMMENT” Ce serait bien de documenter le POURQUOI ? !!! Relisez 3 fois le code pour savoir ce qu’il contient déjà... et ré-écrivez le!
  • 9. Redondant ? //ceci est une calculateur qui calcule public class Calculateur { //renvoit le résultat de a additioné à b public double Additionne (double a, double b ) { }
  • 10. Redondant ? //ceci est une calculateur qui calcule public class Calculateur { //renvoit le résultat de a additioné à b public double Additionne (double a, double b ) { return a - b; } // mais c’est pas grave ;)
  • 11. Compliqué ? Laid ? static void Main() { try { // Iterate through all plug-ins. foreach (var filePath in Directory.GetFiles(Constants.PluginPath, Constants.PluginSearchPattern)) { // Create the plug-in AppDomain setup. var pluginAppDomainSetup = new AppDomainSetup(); pluginAppDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; // Create the plug-in AppDomain with the setup. var plugInAppDomain = AppDomain.CreateDomain(filePath, null, pluginAppDomainSetup); // Pass the plug-in file path to the AppDomain var pluginContext = new PluginContext { FilePath = filePath }; plugInAppDomain.SetData(Constants.PluginContextKey, pluginContext); // Execute the loader in the plug-in AppDomain's context. // This will also execute the plug-in. plugInAppDomain.DoCallBack(PluginCallback); // Retrieve the flag if the plug-in has executed and can be deleted. pluginContext = plugInAppDomain.GetData(Constants.PluginContextKey) as PluginContext; // Unload the plug-in AppDomain. AppDomain.Unload(plugInAppDomain); // Delete the plug-in if applicable. if (pluginContext != null && pluginContext.CanDeletePlugin) { File.Delete(filePath); } } } catch (Exception exception) { Console.WriteLine(exception); } }
  • 12. public class JeFaisDesTrucsSuper { public int JeLeFaisAvecUnUtilisateur() { //je regarde si je connais l'utilisateur if (e.AddedItems.Count > 0) { details.InitializeWith(e.AddedItems[0] as Model.Definition.AppointmentOrTask); MainGrid.ColumnDefinitions.Add(DetailsAreVisible); } else MainGrid.ColumnDefinitions.Add(DetailsAreInvisible); //je vais lui demander son année de naissance if (Sort == null) return false; Sort.IsAcsending = Sort.IsAcsending.HasValue && !Sort.IsAcsending.Value; var items = List.ItemsSource.Cast<object>(); List.ItemsSource = Sort.IsAcsending.Value ? items.OrderBy(o => SortBy.GetValue(o, null)) : items.OrderByDescending(o => SortBy.GetValue(o, null)); //je vais mémoriser son choix //je vais générer une chiffre au hasard //je vais demander l'age du captain //je vais additionner tout cela //et dire à l'utilisateur que j'ai trouvé son chiffre porte bonheur
  • 13. //je vais le mémoriser aussi using (var dbCommand = Sqlbase.CreateCommand (connection, defautCommandTimeOutForSelectStatement, selectCommand, CommandType.Text, spParams)) { Log.Write (LogLevel.Verbose, "Sql.Select: {0} with params: {1}", selectCommand.Replace ("rn", " "), DisplayParamsDetails (spParams)); IDbTransaction transaction = null; if (isolation != IsolationLevel.Unspecified) { transaction = connection.BeginTransaction (isolation); dbCommand.Transaction = transaction; } } //et je renvoie, on ne sait jamais return x; } } //fin de ma fonction
  • 14. Refactoring Single Responsability Nommage intelligible et intelligent Qu’est ce qui est isolable et testable?
  • 15. public class JeFaisDesTrucsSuperMaisEnMieux { public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui, IStockeDesTrucs stockage) { //je regarde si je connais l'utilisateur var esTuConnu = ui.Utilisateur.DemandeIdentite(); if (esTuConnu) return -1; //je vais lui demander son année de naissance var anneeNaissance = ui.QuelEstTonAnneeDeNaissance(); //je vais mémoriser son choix var resultatStockage = stockage.Sauvegarde( anneeNaissance, ui.Utilisateur.IdentifiantUniversel );
  • 16. public class JeFaisDesTrucsSuperMaisEnMieux { public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui, IStockeDesTrucs stockage) { var esTuConnu = ui.Utilisateur.DemandeIdentite(); if (esTuConnu) return -1; var anneeNaissance = ui.QuelEstTonAnneeDeNaissance(); var resultatStockage = stockage.Sauvegarde( anneeNaissance, ui.Utilisateur.IdentifiantUniversel );
  • 17. Et quand on en a marre de lire le code.. Quelle serait la place pour une documentation efficace? Un document électronique qui n’est pas le code mais “entre” le code et les spécifications... Mais bon sang, c’est bien sûr....
  • 18. NOS AMIS LES TESTS
  • 19. public class JeFaisDesTrucsSuperMaisEnMieux { public int JeLeFaisAvecUnUtilisateur(IParleALUtilisateur ui, IStockeDesTrucs stockage) { var esTuConnu = ui.Utilisateur.DemandeIdentite(); if (esTuConnu) return -1; var anneeNaissance = ui.QuelEstTonAnneeDeNaissance(); var resultatStockage = stockage.Sauvegarde( anneeNaissance, ui.Utilisateur.IdentifiantUniversel );
  • 20. [TestFixture ()] public class TesteLeStockage { [Test ()] public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur () { //arrange int valeurAStocker = 101; int IdUser = 1; IJeStocke sut = depencyInjection.Get<IJeStocke> (); //act var resultatStockage = sut.Stocke (valeurAStocker, IdUser); sut.ResetConnection(); int verificationValeur = 0; var resultatLecture = sut.Lecture (out verificationValeur, IdUser); //assert Assert.That(verificationValeur , Is.EqualTo(valeurAStocker)); } }
  • 21. Les Tests Unitaires • Ils décrivent ce qui est attendu • Ils “déclenchent” le code • Ils sont organisés avec le code • Si le comportement du code change, au moins un de mes tests passe au rouge (sinon j’ai un souci...) • Donc ils vivent avec le code • Et si mes tests pouvaient être écrits dans un langage compréhensible par tous...
  • 23. [TestFixture ()] public class TesteLeStockage { [Test ()] public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur () { int valeurAStocker = 101; int IdUser = 1; IJeStocke sut = depencyInjection.Get<IJeStocke> (); var resultatStockage = sut.Stocke (valeurAStocker, IdUser); sut.ResetConnection(); int verificationValeur = 0; var resultatLecture = sut.Lecture (out verificationValeur, IdUser); Assert.That(verificationValeur , Is.EqualTo(valeurAStocker)); } }
  • 24. Behaviors Driven Tests Une syntaxe simple et légère • Given • When • Then Des utilitaires pour faire tourner les tests basés sur *Unit * au choix: J/N/JS/x/.... Pas la peine d’en faire plus!
  • 25. Scenario: Le Stockage Doit Memoriser Une Valeur Pour Un Utilisateur Given j’initialise correctement mon test And j’ai un utilisateur ‘1’ connecté When je sauve la valeur ‘101’ And je réinitialise le système And je lis la valeur stockée Alors le résultat de lecture est ‘101’
  • 27. Scenario: Le Stockage Doit Memoriser Une Valeur Pour Un Autre Utilisateur Given j’initialise correctement mon test And j’ai un utilisateur ‘222’ connecté When je sauve la valeur ‘33333’ And je réinitialise le système And je lis la valeur stockée Alors le résultat de lecture est ‘3333’
  • 28. IT’S ABOUT BEING MACHINE READABLE
  • 29. Executable Steps [Given(@"j’initialise correctement mon test")] public void GivenTestInit() { IJeStocke sut = depencyInjection.Get<IJeStocke> (); }
  • 30. Executable Steps (2) [Given(@"j’ai un utilisateur ‘(.*)’ connecté")] public void GivenTestInit(string x) { int IdUser = int.Parse( x ); }
  • 31. Regular expressions Pour l’instant la seule manière de passer du langage naturel à une expression comprise par la machine... Des idées pour le futur ?
  • 32. Executable Steps (2) [Given(@"j’ai un utilisateur ‘[([0-9]+)]’ connecté")] public void GivenTestInit(int x) { int IdUser = x ; }
  • 33. Step to Step [Given(@"j’ai un utilisateur ‘[([0-9]+)]’ connecté")] public void GivenTestInit(int x) { int IdUser = x ; ScenarioContext.Current.Set(IdUser, “IdUser”); }
  • 34. Step to Step [When(@" je sauve la valeur ‘‘[([0-9]+)]’’")] public void WhenValueIsSaved(int valeurAStocker) { var IdUser = ScenarioContext.Current.Get<int>( “IdUser”); var resultatStockage = sut.Stocke (valeurAStocker, IdUser); Assert.That (resultatStockage, Is.True); }
  • 36. Talking to objects Objects = instance de classe Class = abstraction, concept Interface = contrat, capacité de comportement
  • 37. Inter-active Steps [When(@" je sauve la valeur ‘‘[([0-9]+)]’’")] public void WhenValueIsSaved(int valeurAStocker) { var IdUser = ScenarioContext.Current.Get<int>( “IdUser”); var sut = ScenarioContext.Current.Get<IJeStocke> ( “CurrentTestStorage”); var resultatStockage = sut.Stocke (valeurAStocker, IdUser); Assert.That (resultatStockage, Is.True); }
  • 38. public interface IJeStocke { int Stocke (int valeur, int identifiantUniversel); int Lecture (out int valeur, int identifiantUniversel); }
  • 40. [TestFixture ()] public class TesteLeStockage { [Test ()] public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur () { int valeurAStocker = 101; int IdUser = 1; IJeStocke sut = depencyInjection.Get<IJeStocke> (); var resultatStockage = sut.Stocke (valeurAStocker, IdUser); sut.ResetConnection(); int verificationValeur = 0; var resultatLecture = sut.Lecture (out verificationValeur, IdUser); Assert.That(verificationValeur , Is.EqualTo(valeurAStocker)); } }
  • 41. Scenario: LeStockageDoitMemoriserUneValeurPourUnUtilisateur Given j’initialise correctement mon test And j’ai un utilisateur ‘222’ connecté When je sauve la valeur ‘33333’ And je réinitialise le système And je lis la valeur stockée Alors le résultat de lecture est ‘3333’
  • 42. Interfaces : the human side of objects La documentation à travers les spécifications exécutables est le reflet des interfaces objets dans le monde des humains.
  • 43. public interface IJeStocke { int JeSauve (int valeur, int identifiantUniversel); int JeLis (out int valeur, int identifiantUniversel); }
  • 44. public interface IEntrepot { int JeSauve (int valeur, int identifiantUniversel); int JeLis (out int valeur, int identifiantUniversel); }
  • 45. public class NoSqlQuiPoutre : IEntrepot { public int JeSauve (int valeur, int identifiantUniversel) { ............;} public int JeLis (out int valeur, int identifiantUniversel) { ............;} } AI JE BESOIN DE COMMENTAIRES ???
  • 46. [TestFixture ()] public class TesteLeStockage { [Test ()] public void LeStockageDoitMemoriserUneValeurPourUnUtilisateur () { int valeurAStocker = 101; int IdUser = 1; IJeStocke sut = depencyInjection.Get<IJeStocke> (); var resultatStockage = sut.JeSauve (valeurAStocker, IdUser); sut.ResetConnection(); int verificationValeur = 0; var resultatLecture = sut.JeLis (out verificationValeur, IdUser); } } Change the way you code
  • 47. What are interfaces (really) ? Du rôle des interfaces Ainsi « l’interface devient le produit et l’objet du service ». Elle n’est plus un espace de commande utilisable, elle est la représentation du service, son usage et sa finalité symbolique, cognitive et esthétique. http://www.nodesign.net/blog/vers-un-confort-numerique-moderne/ Les Interfaces doivent être ergonomiques https://goo.gl/WUEh48
  • 48. BDD: It's about Behaviour BACKGROUND + GIVEN : Environnement + Setup WHEN: ACTION • Sujet • Verbe • Complement THEN: RESULTAT ATTENDU • Sujet • Etat END : Environnement rétalbi
  • 49. IT’S ABOUT BEING MORE HUMAN READABLE
  • 50. Scenario: LeStockageDoitMemoriserUneValeurPourUnUtilisateur Given j’initialise correctement mon test And j’ai un utilisateur ‘1’ connecté When je sauve la valeur ‘101’ And je réinitialise le système And je lis la valeur stockée Alors le résultat de lecture est ‘101’
  • 51. Scenario: LeStockageDoitMemoriserUneValeurPourUnUtilisateur Given j’initialise correctement le système de stockage And j’ai un utilisateur ‘1’ connecté When je sauve la valeur ‘101’ pour cet utilisateur And je réinitialise le système de stockage And je lis la valeur stockée pour l’utilisateur connecté Alors le résultat de lecture est ‘1’
  • 52. Inter-active Steps [When(@" je sauve la valeur ‘‘[([0-9]+)]’’")] public void WhenValueIsSaved(int valeurAStocker) { var IdUser = ScenarioContext.Current.Get<IUtilisateur>( “User”); var sut = ScenarioContext.Current.Get<IJeStocke> ( “CurrentTestStorage”); var resultatStockage = sut.Stocke (valeurAStocker, IdUser); Assert.That (resultatStockage, Is.True); }
  • 53. IT’S ABOUT CODE BEING MORE HUMAN READABLE
  • 54. public interface IEntrepot { int JeSauve (int valeur, IUtilisateur utilisateur); int JeLis (out int valeur, IUtilisateur utilisateur); }
  • 55. public interface IUtilisateur { bool DemandeIdentite (ICredential credits); int DonneAnneeNaissance (); }
  • 57. Writing Test First Feature: identification avec des jetons Scenario: Un utilisateur est identifié Given j’initialise correctement mon test And j’ai un jeton égal à x10103 When je demande à identifier l’utilisateur avec ce jeton Alors le résultat est ok
  • 58. public class UtilisateurAJetons : IUtilisateur { #region IUtilisateur implementation bool IUtilisateur.DemandeIdentite (Icredential credits) { throw new NotImplementedException (); } int IUtilisateur.DonneAnneeNaissance () { throw new NotImplementedException (); } #endregion }
  • 59. Reusing Tests Feature: identification avec Facebook Scenario: Un utilisateur est identifié Given j’initialise correctement mon test And j’ai un jeton égal à FB44103 When je demande à identifier l’utilisateur avec ce jeton Alors le résultat est ok
  • 60. public class UtilisateurFacebook : IUtilisateur { #region IUtilisateur implementation bool IUtilisateur.DemandeIdentite (Icredential credits) { throw new NotImplementedException (); } int IUtilisateur.DonneAnneeNaissance () { throw new NotImplementedException (); } #endregion }
  • 62. Est ce que mon test est lisible ? ⇥ Est ce que j’ai bien ré-utilisé mes steps ? ⇥ Est ce que j’ai généralisé les bons concepts ? ⇥ Design des interfaces et des objets
  • 64. Scenario: LeStockageDoitMemoriserUneValeurPourUnUtilisateur Given j’initialise correctement le système de stockage And j’ai un utilisateur ‘1’ connecté When je sauve la valeur ‘101’ pour cet utilisateur And je réinitialise le système de stockage And je lis la valeur stockée pour l’utilisateur connecté Alors le résultat de lecture est ‘1’
  • 65. Scenario: L’ Utilisateur doit pouvoir saisir une année de naissance Given j’initialise correctement le système graphique And j’ai un utilisateur ‘1’ connecté When l’ utilisateur saisi la valeur ‘1970’ Alors le résultat de Utilisateur[1].AnnéeDeNaissance est ‘1970’
  • 66. Scenario: L’ Utilisateur doit pouvoir saisir une année de naissance Given j’initialise correctement le système graphique And j’ai un utilisateur ‘1’ connecté When l’ utilisateur saisi la valeur ‘1970’ Alors le résultat de Utilisateur[1].AnnéeDeNaissance est ‘1970’ Action/Verbe (step ré-utilisable) Concept (ré-utilisable) ⇒ interface
  • 67. IT’S ABOUT TDD (again)
  • 68. A test written in Specflow can be re- written in Nunit (or any test framework)
  • 69. A test written in Specflow form has the same value than a Unit Test
  • 70. Consider your Specflow tests as Unit Tests • It it executable • It’s UNITaire • It’s fast to execute
  • 71. What are Tests ? http://fr.slideshare.net/confiz/software-testing-methods-levels-and-types
  • 73. Les tests dépendent de la vision du logiciel que l’on a et comment on le construit
  • 74. Développeur = Testeur Integration testing: Testing continuously evolving modules (with defined expected actual outcome) User acceptance testing: User representative testing (with defined expected actual outcome) Sanity testing: Testing after multiple builds (with defined expected actual outcome) Smoke testing: Testing after every build (with defined expected actual outcome) Exploratory testing: Unplanned and unscripted testing (no defined expected actual outcome) Regression testing: End-to-end testing done to ensure that nothing is broken in the integrating modules - https://www.scrumalliance.org/community/articles/2013/march/agile-methodology-is-not-all-about- exploratory-tes#sthash.QEmYsyLg.dpuf
  • 75. Yes, TDD has a cost! • In 2008 Microsoft Research study and results published in a paper Realizing quality improvement through test driven development: results and experiences of four industrial teams, by Nachi Nagappan and research colleagues E. Michael Maximilien of IBM • What the research team found was that the TDD teams produced code that was 60 to 90 percent better in terms of defect density than non-TDD teams. • They also discovered that TDD teams took longer to complete their projects—15 to 35 percent longer.
  • 77. Gherkin / Cucumber / Specflow fichiers textuels (.feature) ⇥ convertisseur html/pdf ⇥ liaison avec le repository de code (changes) ⇥ liaison avec le Product Backlog (UC / WI) ⇥ production de la documentation concernant le release ⇥ mise au format du RQ/QA ⇥ signature.
  • 78. REX Documentation de 2000+ pages générée à la demande. Générées automatiquement sans aucun effort ( ... maintenant que les automatismes sont en place) Personne de l’assurance qualité ne les lit, mais ils les signent ! Les tests verts n’ont jamais tort! Un bug = un test manque pour couvrir le cas rencontré.
  • 79. Des développeurs essayent de se rapprocher du fonctionnel Et l’inverse ? Specification by Exemple...