SlideShare una empresa de Scribd logo
1 de 18
7 astuces pour améliorer vos
tests unitaires
Pascal Laurin
Novembre 2015
@plaurin78
pascal.laurin@outlook.com
www.pascallaurin.com
http://fr.slideshare.net/PascalLaurin
https://bitbucket.org/pascallaurin
Microsoft .NET MVP
Développeur & Architect chez GSoft
1. Trouver les bons noms
2. Avoir des messages d’erreur clairs
3. Être facile à comprendre
4. Être rapide
5. Être indépendant
6. Tester une seule chose
7. Éviter les valeurs hard-coder
Agenda
Facile à comprendre
Facile à lire
On doit comprendre immédiatement ce qui se passe s’il échoue
Indépendant
Les tests doivent pouvoir s’exécuter dans n’importe quel ordre
Ne doit pas avoir de dépendances externes
Rapide
Exécution en moins de 0.01 secondes (ou 100 tests/seconde)
Doit tester une seule chose
Sinon il y a plusieurs raisons d’échouer et le problème va être plus
difficile à diagnostiquer
3
Principes des bons tests unitaires
Nom de la classe de test
Comprendre sur quoi le test s’applique
Recherche rapide
Nom de la méthode de test
Doit se lire comme le résumé du test
Surtout en cas d’échec du test
Dans le code du test
Nom de variables significatives
Utilisation du langage du domaine d’affaire
Objectif
Documentation du système
1. Trouver les bons noms
5
1. Trouver les bons noms
En cas d’échec le message doit être clair
Pour diagnostiquer le problème rapidement
Ajouter des traces au besoin
Toujours fournir une explication sur les Assert
Utiliser une libraires spécialiser (ie Fluent Assertions)
Comparaison entre objets attendus et objets actuels
En implémentant ToString() (et/ou Equals() et GetHashCode())
Sérialisation Json pour comparer et afficher l’état des objets
Objectif
Trouver la source du problème le plus rapidement possible
2. Avoir des messages d’erreur clairs
7
2. Avoir des messages d’erreur clairs
Code du test
Structure avec Arrange, Act et Assert
Utilisation de méthodes utilitaires
Méthodes de création, arrange et assert pour faciliter la lecture
Utilisation de classes utilitaires et classes de base pour la
réutilisation des méthodes utilitaires
Cacher ce qui n'est pas pertinent aux tests
Setup répétitif, plomberie d'architecture, les mocks, les valeurs
littérales qui ne sont pas importantes, etc...
Objectif
Garder le test pertinent longtemps (écrit une fois, lu plusieurs fois)
3. Être facile à comprendre
9
3. Être facile à comprendre
[Fact]
public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct()
{
const int OrderId = 12;
const int NumberOfLine = 2;
// Arrange
var existingOrder = CreateSomeOrder(OrderId, NumberOfLine);
this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder);
// Act
this.orderService.AddProductToOrder(OrderId, productId: 34, quantity: 56);
// Assert
this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1,
expectedNewProductId: 34, expectedNewQuantity: 56);
}
private static Order CreateSomeOrder(int orderId, int numberOfLine) {...}
private void ArrangeOrderRepositoryLoadOrderReturns(Order existingOrder) {...}
private void AssertOrderRepositorySaveOrderWith(int expectedCount,
int expectedNewProductId, int expectedNewQuantity) {...}
Aucun appel externe
Utilisation d’Interfaces pour fournir des « tests doubles » dans les
test unitaires
Utiliser le principe d’Inversion de Contrôle (IoC) et Injection de
Dépendances (DI)
Utiliser des Mocks (et mocking framework) pour se faciliter la vie
Objectif
Rouler les tests unitaires après chaque modification au système
4. Être rapide
11
4. Être rapide
public class OrderService
{
private readonly IOrderRepository orderRepository;
public OrderService(IOrderRepository orderRepository)
{
this.orderRepository = orderRepository;
}
public void AddProductToOrder(int orderId, int productId, int quantity)
{
var order = this.orderRepository.LoadOrder(orderId);
order.AddOrderLine(productId, quantity);
this.orderRepository.SaveOrder(order);
}
}
public OrderServiceTests()
{
this.fakeOrderRepository = A.Fake<IOrderRepository>();
this.orderService = new OrderService(this.fakeOrderRepository);
}
Ne pas être basé sur l'état des tests précédents
Chaque test est responsable de l’état initial du système sous test
Éviter les bases de données et les services web externes
Objectif
Pouvoir exécuter un test seul ou tous les tests sans manipulation
ou initialisation quelconque: éviter les faux positifs.
5. Être indépendant
13
5. Être indépendant
// Arrange
var existingOrder = CreateSomeOrder(OrderId, NumberOfLine);
...
private static Order CreateSomeOrder(int orderId, int numberOfLine)
{
var existingOrder = new Order { Id = orderId };
for (var i = 0; i < numberOfLine; i++)
{
existingOrder.AddOrderLine(productId: 123456 + i, quantity: 999);
}
return existingOrder;
}
Séparer les tests d'intégrations/systèmes
Tests unitaires pour le domaine d’affaire
Tests d’intégration pour les adaptateurs vers les systèmes
externes
Séparer les tests unitaires
Créer deux ou plusieurs tests à partir d’un test qui en fait trop
Extraire les tests d’intégrations
Objectif
En cas d’échec il n’y a qu’une seule cause: diagnostique rapide
6. Tester une seule chose
Utilisation de librairie de génération de valeurs aléatoire
i.e. AutoFixture
Ne garder que les valeurs pertinentes au test
Objectif
Identifier clairement les valeurs qui vont influencer le test : aide la
compréhension
7. Éviter les valeurs hard-coder
16
7. Éviter les valeurs hard-coder
[Fact]
public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct()
{
const int OrderId = 12;
const int NumberOfLine = 2;
// Arrange
var existingOrder = CreateSomeOrder(OrderId, NumberOfLine);
this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder);
// Act
this.orderService.AddProductToOrder(OrderId, productId: 34, quantity: 56);
// Assert
this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1,
expectedNewProductId: 34, expectedNewQuantity: 56);
}
17
7. Éviter les valeurs hard-coder
[Fact]
public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct()
{
var orderId = this.fixture.Create<int>();
var productId = this.fixture.Create<int>();
var quantity = this.fixture.Create<int>();
const int NumberOfLine = 2;
// Arrange
var existingOrder = this.CreateSomeOrder(orderId, NumberOfLine);
this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder);
// Act
this.orderService.AddProductToOrder(orderId, productId: productId,
quantity: quantity);
// Assert
this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1,
expectedNewProductId: productId, expectedNewQuantity: quantity);
}
Références
BitBucket pour le code
• http://bit.ly/1ITLwca
FakeItEasy
• http://fakeiteasy.github.io/
AutoFixture
• https://github.com/AutoFixture/AutoFixture
Questions?
@plaurin78
pascal.laurin@outlook.com
www.pascallaurin.com
http://fr.slideshare.net/PascalLaurin
https://bitbucket.org/pascallaurin

Más contenido relacionado

La actualidad más candente

[Agile Testing Day] Techniques avancées de tests
[Agile Testing Day] Techniques avancées de tests[Agile Testing Day] Techniques avancées de tests
[Agile Testing Day] Techniques avancées de testsCellenza
 
Automatisations des tests fonctionnels avec Robot Framework
Automatisations des tests fonctionnels avec Robot FrameworkAutomatisations des tests fonctionnels avec Robot Framework
Automatisations des tests fonctionnels avec Robot Frameworklaurent bristiel
 
Présentation de Robot framework
Présentation de Robot frameworkPrésentation de Robot framework
Présentation de Robot frameworkgilleslenfant
 
[Agile Testing Day] Test & Métiers
[Agile Testing Day] Test & Métiers[Agile Testing Day] Test & Métiers
[Agile Testing Day] Test & MétiersCellenza
 
Robot Framework Introduction
Robot Framework IntroductionRobot Framework Introduction
Robot Framework Introductionlaurent bristiel
 
Pourquoi vous ne pouvez pas tester votre code
Pourquoi vous ne pouvez pas tester votre codePourquoi vous ne pouvez pas tester votre code
Pourquoi vous ne pouvez pas tester votre codeRémi Lesieur
 
Outils et pratiques : tester une application web moderne
Outils et pratiques : tester une application web moderneOutils et pratiques : tester une application web moderne
Outils et pratiques : tester une application web modernehalleck45
 
[Agile Testing Day] Introduction
[Agile Testing Day] Introduction[Agile Testing Day] Introduction
[Agile Testing Day] IntroductionCellenza
 
TDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoringTDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoringneuros
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPhalleck45
 
Tdd en action - découverte
Tdd en action - découverteTdd en action - découverte
Tdd en action - découverteEric Mignot
 
Allons plus loin avec Selenium
Allons plus loin avec SeleniumAllons plus loin avec Selenium
Allons plus loin avec SeleniumSOAT
 
Paris Web 2015 - Atelier désendettement Javascript legacy
Paris Web 2015 - Atelier désendettement Javascript legacyParis Web 2015 - Atelier désendettement Javascript legacy
Paris Web 2015 - Atelier désendettement Javascript legacyFrançois Petitit
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...Cyrille Grandval
 
Common features in webapi aspnetcore
Common features in webapi aspnetcoreCommon features in webapi aspnetcore
Common features in webapi aspnetcoreMSDEVMTL
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application javaAntoine Rey
 
Commencer avec le tdd
Commencer avec le tddCommencer avec le tdd
Commencer avec le tddEric Hogue
 
Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Ippon
 

La actualidad más candente (20)

[Agile Testing Day] Techniques avancées de tests
[Agile Testing Day] Techniques avancées de tests[Agile Testing Day] Techniques avancées de tests
[Agile Testing Day] Techniques avancées de tests
 
Automatisations des tests fonctionnels avec Robot Framework
Automatisations des tests fonctionnels avec Robot FrameworkAutomatisations des tests fonctionnels avec Robot Framework
Automatisations des tests fonctionnels avec Robot Framework
 
Présentation de Robot framework
Présentation de Robot frameworkPrésentation de Robot framework
Présentation de Robot framework
 
[Agile Testing Day] Test & Métiers
[Agile Testing Day] Test & Métiers[Agile Testing Day] Test & Métiers
[Agile Testing Day] Test & Métiers
 
Robot Framework Introduction
Robot Framework IntroductionRobot Framework Introduction
Robot Framework Introduction
 
Pourquoi vous ne pouvez pas tester votre code
Pourquoi vous ne pouvez pas tester votre codePourquoi vous ne pouvez pas tester votre code
Pourquoi vous ne pouvez pas tester votre code
 
Outils et pratiques : tester une application web moderne
Outils et pratiques : tester une application web moderneOutils et pratiques : tester une application web moderne
Outils et pratiques : tester une application web moderne
 
[Agile Testing Day] Introduction
[Agile Testing Day] Introduction[Agile Testing Day] Introduction
[Agile Testing Day] Introduction
 
TDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoringTDD (Test Driven Developement) et refactoring
TDD (Test Driven Developement) et refactoring
 
Industrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHPIndustrialiser le contrat dans un projet PHP
Industrialiser le contrat dans un projet PHP
 
Tdd en action - découverte
Tdd en action - découverteTdd en action - découverte
Tdd en action - découverte
 
Allons plus loin avec Selenium
Allons plus loin avec SeleniumAllons plus loin avec Selenium
Allons plus loin avec Selenium
 
Paris Web 2015 - Atelier désendettement Javascript legacy
Paris Web 2015 - Atelier désendettement Javascript legacyParis Web 2015 - Atelier désendettement Javascript legacy
Paris Web 2015 - Atelier désendettement Javascript legacy
 
Bbl sur les tests
Bbl sur les testsBbl sur les tests
Bbl sur les tests
 
Flex Unit Testing
Flex Unit TestingFlex Unit Testing
Flex Unit Testing
 
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
PHPTour Lyon 2014 - Conférence - Tests unitaires Je veux mes 80% de couvertur...
 
Common features in webapi aspnetcore
Common features in webapi aspnetcoreCommon features in webapi aspnetcore
Common features in webapi aspnetcore
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
 
Commencer avec le tdd
Commencer avec le tddCommencer avec le tdd
Commencer avec le tdd
 
Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon Formation Gratuite Total Tests par les experts Java Ippon
Formation Gratuite Total Tests par les experts Java Ippon
 

Destacado

Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#Pascal Laurin
 
Behaviour Driven Development with SpecFlow
Behaviour Driven Development with SpecFlowBehaviour Driven Development with SpecFlow
Behaviour Driven Development with SpecFlowPascal Laurin
 
Cloud design patterns
Cloud design patternsCloud design patterns
Cloud design patternsPascal Laurin
 
Test Driven Development (C#)
Test Driven Development (C#)Test Driven Development (C#)
Test Driven Development (C#)Alan Dean
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Lars Thorup
 
Test Driven Development (TDD)
Test Driven Development (TDD)Test Driven Development (TDD)
Test Driven Development (TDD)David Ehringer
 
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLES
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLESTALLER 4 ESTRUCTURAS CICLICAS O DE BUCLES
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLESmelissa1andrea
 
les petites annonces
les petites annoncesles petites annonces
les petites annonceschalmel1
 
Tillie cole hades hangmen (1) it ain t me, babe
Tillie cole   hades hangmen (1) it ain t me, babeTillie cole   hades hangmen (1) it ain t me, babe
Tillie cole hades hangmen (1) it ain t me, babeMarcela June
 
Ils l'ont dit
Ils l'ont ditIls l'ont dit
Ils l'ont ditsandre07
 
C.v. mauricio zurita vaca
C.v. mauricio zurita vacaC.v. mauricio zurita vaca
C.v. mauricio zurita vacamauriciozurita
 
Redes sociales Sesión 4
Redes sociales Sesión 4Redes sociales Sesión 4
Redes sociales Sesión 4Alejandro Caro
 
Validación exposicion
Validación exposicionValidación exposicion
Validación exposicionMargarita1980
 

Destacado (20)

Implementing DDD with C#
Implementing DDD with C#Implementing DDD with C#
Implementing DDD with C#
 
C# 6
C# 6C# 6
C# 6
 
Behaviour Driven Development with SpecFlow
Behaviour Driven Development with SpecFlowBehaviour Driven Development with SpecFlow
Behaviour Driven Development with SpecFlow
 
Cloud design patterns
Cloud design patternsCloud design patterns
Cloud design patterns
 
Test Driven Development (C#)
Test Driven Development (C#)Test Driven Development (C#)
Test Driven Development (C#)
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
 
Test Driven Development (TDD)
Test Driven Development (TDD)Test Driven Development (TDD)
Test Driven Development (TDD)
 
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLES
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLESTALLER 4 ESTRUCTURAS CICLICAS O DE BUCLES
TALLER 4 ESTRUCTURAS CICLICAS O DE BUCLES
 
les petites annonces
les petites annoncesles petites annonces
les petites annonces
 
Fraude cb
Fraude cbFraude cb
Fraude cb
 
Ciberatleta
CiberatletaCiberatleta
Ciberatleta
 
GlobalZoo_1
GlobalZoo_1GlobalZoo_1
GlobalZoo_1
 
DERECHO FINANCIERO
DERECHO FINANCIERODERECHO FINANCIERO
DERECHO FINANCIERO
 
Tillie cole hades hangmen (1) it ain t me, babe
Tillie cole   hades hangmen (1) it ain t me, babeTillie cole   hades hangmen (1) it ain t me, babe
Tillie cole hades hangmen (1) it ain t me, babe
 
Ils l'ont dit
Ils l'ont ditIls l'ont dit
Ils l'ont dit
 
C.v. mauricio zurita vaca
C.v. mauricio zurita vacaC.v. mauricio zurita vaca
C.v. mauricio zurita vaca
 
Redes sociales Sesión 4
Redes sociales Sesión 4Redes sociales Sesión 4
Redes sociales Sesión 4
 
Validación exposicion
Validación exposicionValidación exposicion
Validación exposicion
 
1er avril 2012 renens
1er avril 2012  renens1er avril 2012  renens
1er avril 2012 renens
 
1er avril 2012 lausanne
1er avril 2012   lausanne1er avril 2012   lausanne
1er avril 2012 lausanne
 

Similar a 7 astuces pour améliorer vos tests unitaires

L'amélioration des tests unitaires par le refactoring
L'amélioration des tests unitaires par le refactoringL'amélioration des tests unitaires par le refactoring
L'amélioration des tests unitaires par le refactoringMSDEVMTL
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptxManalAg
 
Automatisation des tests - objectifs et concepts - partie 2
Automatisation des tests  - objectifs et concepts - partie 2Automatisation des tests  - objectifs et concepts - partie 2
Automatisation des tests - objectifs et concepts - partie 2Christophe Rochefolle
 
Automatisation des tests - objectifs et concepts - partie 1
Automatisation des tests  - objectifs et concepts - partie 1Automatisation des tests  - objectifs et concepts - partie 1
Automatisation des tests - objectifs et concepts - partie 1Christophe Rochefolle
 
Les cinq bonnes pratiques des Tests Unitaires dans un projet Agile
Les cinq bonnes pratiques des Tests Unitaires dans un projet AgileLes cinq bonnes pratiques des Tests Unitaires dans un projet Agile
Les cinq bonnes pratiques des Tests Unitaires dans un projet AgileDenis Voituron
 
Formation tests decembre2010
Formation tests decembre2010Formation tests decembre2010
Formation tests decembre2010Fou Cha
 
TDD avec ou sans mock
TDD avec ou sans mockTDD avec ou sans mock
TDD avec ou sans mockYannick Ameur
 
formation istqb.pdf
formation istqb.pdfformation istqb.pdf
formation istqb.pdfmido04
 
Cocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaHeads France
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?Fou Cha
 
13-Cours de Géniel Logiciel
13-Cours de Géniel Logiciel13-Cours de Géniel Logiciel
13-Cours de Géniel Logiciellauraty3204
 
Industrialisation des développements logiciels
Industrialisation des développements logicielsIndustrialisation des développements logiciels
Industrialisation des développements logicielsSylvain Leroy
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowMathias Kluba
 
Agilité, Tests Et Industrialisation
Agilité, Tests Et IndustrialisationAgilité, Tests Et Industrialisation
Agilité, Tests Et IndustrialisationPHPPRO
 
Le rôle du testeur et le Blackbox testing
Le rôle du testeur et le Blackbox testingLe rôle du testeur et le Blackbox testing
Le rôle du testeur et le Blackbox testingGeeks Anonymes
 

Similar a 7 astuces pour améliorer vos tests unitaires (20)

L'amélioration des tests unitaires par le refactoring
L'amélioration des tests unitaires par le refactoringL'amélioration des tests unitaires par le refactoring
L'amélioration des tests unitaires par le refactoring
 
testUnitaire (1).pptx
testUnitaire (1).pptxtestUnitaire (1).pptx
testUnitaire (1).pptx
 
Automatisation des tests - objectifs et concepts - partie 2
Automatisation des tests  - objectifs et concepts - partie 2Automatisation des tests  - objectifs et concepts - partie 2
Automatisation des tests - objectifs et concepts - partie 2
 
Automatisation des tests - objectifs et concepts - partie 1
Automatisation des tests  - objectifs et concepts - partie 1Automatisation des tests  - objectifs et concepts - partie 1
Automatisation des tests - objectifs et concepts - partie 1
 
Les cinq bonnes pratiques des Tests Unitaires dans un projet Agile
Les cinq bonnes pratiques des Tests Unitaires dans un projet AgileLes cinq bonnes pratiques des Tests Unitaires dans un projet Agile
Les cinq bonnes pratiques des Tests Unitaires dans un projet Agile
 
Formation tests decembre2010
Formation tests decembre2010Formation tests decembre2010
Formation tests decembre2010
 
TDD avec ou sans mock
TDD avec ou sans mockTDD avec ou sans mock
TDD avec ou sans mock
 
formation istqb.pdf
formation istqb.pdfformation istqb.pdf
formation istqb.pdf
 
Salesforce Tooling API
Salesforce Tooling APISalesforce Tooling API
Salesforce Tooling API
 
Cocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitairesCocoaheads Paris Nombembre Test unitaires
Cocoaheads Paris Nombembre Test unitaires
 
Valider par des tests - Blend
Valider par des tests - BlendValider par des tests - Blend
Valider par des tests - Blend
 
Test unitaire
Test unitaireTest unitaire
Test unitaire
 
Comment écrire du code testable ?
Comment écrire du code testable ?Comment écrire du code testable ?
Comment écrire du code testable ?
 
13-Cours de Géniel Logiciel
13-Cours de Géniel Logiciel13-Cours de Géniel Logiciel
13-Cours de Géniel Logiciel
 
Industrialisation des développements logiciels
Industrialisation des développements logicielsIndustrialisation des développements logiciels
Industrialisation des développements logiciels
 
J Unit
J UnitJ Unit
J Unit
 
ALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - SpecflowALT.Net Juin 2012 - Specflow
ALT.Net Juin 2012 - Specflow
 
Test unitaires
Test unitairesTest unitaires
Test unitaires
 
Agilité, Tests Et Industrialisation
Agilité, Tests Et IndustrialisationAgilité, Tests Et Industrialisation
Agilité, Tests Et Industrialisation
 
Le rôle du testeur et le Blackbox testing
Le rôle du testeur et le Blackbox testingLe rôle du testeur et le Blackbox testing
Le rôle du testeur et le Blackbox testing
 

7 astuces pour améliorer vos tests unitaires

  • 1. 7 astuces pour améliorer vos tests unitaires Pascal Laurin Novembre 2015 @plaurin78 pascal.laurin@outlook.com www.pascallaurin.com http://fr.slideshare.net/PascalLaurin https://bitbucket.org/pascallaurin Microsoft .NET MVP Développeur & Architect chez GSoft
  • 2. 1. Trouver les bons noms 2. Avoir des messages d’erreur clairs 3. Être facile à comprendre 4. Être rapide 5. Être indépendant 6. Tester une seule chose 7. Éviter les valeurs hard-coder Agenda
  • 3. Facile à comprendre Facile à lire On doit comprendre immédiatement ce qui se passe s’il échoue Indépendant Les tests doivent pouvoir s’exécuter dans n’importe quel ordre Ne doit pas avoir de dépendances externes Rapide Exécution en moins de 0.01 secondes (ou 100 tests/seconde) Doit tester une seule chose Sinon il y a plusieurs raisons d’échouer et le problème va être plus difficile à diagnostiquer 3 Principes des bons tests unitaires
  • 4. Nom de la classe de test Comprendre sur quoi le test s’applique Recherche rapide Nom de la méthode de test Doit se lire comme le résumé du test Surtout en cas d’échec du test Dans le code du test Nom de variables significatives Utilisation du langage du domaine d’affaire Objectif Documentation du système 1. Trouver les bons noms
  • 5. 5 1. Trouver les bons noms
  • 6. En cas d’échec le message doit être clair Pour diagnostiquer le problème rapidement Ajouter des traces au besoin Toujours fournir une explication sur les Assert Utiliser une libraires spécialiser (ie Fluent Assertions) Comparaison entre objets attendus et objets actuels En implémentant ToString() (et/ou Equals() et GetHashCode()) Sérialisation Json pour comparer et afficher l’état des objets Objectif Trouver la source du problème le plus rapidement possible 2. Avoir des messages d’erreur clairs
  • 7. 7 2. Avoir des messages d’erreur clairs
  • 8. Code du test Structure avec Arrange, Act et Assert Utilisation de méthodes utilitaires Méthodes de création, arrange et assert pour faciliter la lecture Utilisation de classes utilitaires et classes de base pour la réutilisation des méthodes utilitaires Cacher ce qui n'est pas pertinent aux tests Setup répétitif, plomberie d'architecture, les mocks, les valeurs littérales qui ne sont pas importantes, etc... Objectif Garder le test pertinent longtemps (écrit une fois, lu plusieurs fois) 3. Être facile à comprendre
  • 9. 9 3. Être facile à comprendre [Fact] public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct() { const int OrderId = 12; const int NumberOfLine = 2; // Arrange var existingOrder = CreateSomeOrder(OrderId, NumberOfLine); this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder); // Act this.orderService.AddProductToOrder(OrderId, productId: 34, quantity: 56); // Assert this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1, expectedNewProductId: 34, expectedNewQuantity: 56); } private static Order CreateSomeOrder(int orderId, int numberOfLine) {...} private void ArrangeOrderRepositoryLoadOrderReturns(Order existingOrder) {...} private void AssertOrderRepositorySaveOrderWith(int expectedCount, int expectedNewProductId, int expectedNewQuantity) {...}
  • 10. Aucun appel externe Utilisation d’Interfaces pour fournir des « tests doubles » dans les test unitaires Utiliser le principe d’Inversion de Contrôle (IoC) et Injection de Dépendances (DI) Utiliser des Mocks (et mocking framework) pour se faciliter la vie Objectif Rouler les tests unitaires après chaque modification au système 4. Être rapide
  • 11. 11 4. Être rapide public class OrderService { private readonly IOrderRepository orderRepository; public OrderService(IOrderRepository orderRepository) { this.orderRepository = orderRepository; } public void AddProductToOrder(int orderId, int productId, int quantity) { var order = this.orderRepository.LoadOrder(orderId); order.AddOrderLine(productId, quantity); this.orderRepository.SaveOrder(order); } } public OrderServiceTests() { this.fakeOrderRepository = A.Fake<IOrderRepository>(); this.orderService = new OrderService(this.fakeOrderRepository); }
  • 12. Ne pas être basé sur l'état des tests précédents Chaque test est responsable de l’état initial du système sous test Éviter les bases de données et les services web externes Objectif Pouvoir exécuter un test seul ou tous les tests sans manipulation ou initialisation quelconque: éviter les faux positifs. 5. Être indépendant
  • 13. 13 5. Être indépendant // Arrange var existingOrder = CreateSomeOrder(OrderId, NumberOfLine); ... private static Order CreateSomeOrder(int orderId, int numberOfLine) { var existingOrder = new Order { Id = orderId }; for (var i = 0; i < numberOfLine; i++) { existingOrder.AddOrderLine(productId: 123456 + i, quantity: 999); } return existingOrder; }
  • 14. Séparer les tests d'intégrations/systèmes Tests unitaires pour le domaine d’affaire Tests d’intégration pour les adaptateurs vers les systèmes externes Séparer les tests unitaires Créer deux ou plusieurs tests à partir d’un test qui en fait trop Extraire les tests d’intégrations Objectif En cas d’échec il n’y a qu’une seule cause: diagnostique rapide 6. Tester une seule chose
  • 15. Utilisation de librairie de génération de valeurs aléatoire i.e. AutoFixture Ne garder que les valeurs pertinentes au test Objectif Identifier clairement les valeurs qui vont influencer le test : aide la compréhension 7. Éviter les valeurs hard-coder
  • 16. 16 7. Éviter les valeurs hard-coder [Fact] public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct() { const int OrderId = 12; const int NumberOfLine = 2; // Arrange var existingOrder = CreateSomeOrder(OrderId, NumberOfLine); this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder); // Act this.orderService.AddProductToOrder(OrderId, productId: 34, quantity: 56); // Assert this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1, expectedNewProductId: 34, expectedNewQuantity: 56); }
  • 17. 17 7. Éviter les valeurs hard-coder [Fact] public void AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct() { var orderId = this.fixture.Create<int>(); var productId = this.fixture.Create<int>(); var quantity = this.fixture.Create<int>(); const int NumberOfLine = 2; // Arrange var existingOrder = this.CreateSomeOrder(orderId, NumberOfLine); this.ArrangeOrderRepositoryLoadOrderReturns(existingOrder); // Act this.orderService.AddProductToOrder(orderId, productId: productId, quantity: quantity); // Assert this.AssertOrderRepositorySaveOrderWith(expectedCount: NumberOfLine + 1, expectedNewProductId: productId, expectedNewQuantity: quantity); }
  • 18. Références BitBucket pour le code • http://bit.ly/1ITLwca FakeItEasy • http://fakeiteasy.github.io/ AutoFixture • https://github.com/AutoFixture/AutoFixture Questions? @plaurin78 pascal.laurin@outlook.com www.pascallaurin.com http://fr.slideshare.net/PascalLaurin https://bitbucket.org/pascallaurin

Notas del editor

  1. Démo: #region Rename tests AddOrderLineTest2 to OrderTestsFinal
  2. Démo: #region Compare state AssertEqualWithJsonOutput AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct
  3. Démo: #region Utility methods tests - AddProductToOrder_ForExistingOrder_ShouldSaveOrderWithTheNewProduct
  4. Démo: #region Utility methods tests OrderService OrderServiceTests.ctor
  5. Demo: #region Utility methods tests - OrderServiceTests
  6. Démo: #region Only pertinent literals tests OrderServiceTestsWithoutAutoFixture OrderServiceTestsWithAutoFixture