Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tests de caractérisation : à l’assaut de votre ...

Tests de caractérisation : à l’assaut de votre code "Legacy" patrimonial [FR]

Beaucoup d’entreprises sont aux prises avec une importante base de code patrimoniale (legacy). Elles savent qu’il faut s’y attaquer, mais elles ne savent pas par où commencer et abandonnent par découragement

Pas de tests → Difficulté à réusiner → Architecture mal adaptée
→ Difficulté à écrire des tests → “Patch” laide → Retour à la case départ → ... → Refonte obligatoire :(

Comment éviter le piège coûteux et extrêmement risqué de la refonte ? Pour briser ce cercle vicieux, il existe une forme de tests appelés “tests de caractérisation”. Voici une technique de “consolidation de dettes” techniques !

Dans cette présentation Félix-Antoine Bourbonnais et Pascal Roy d’Elapse Technologies vous présenteront pourquoi, comment, quand écrire et ne pas écrire ce type de tests.

Une démonstration dynamique avec du code typique qui vous permettra de voir en action l’écriture de tests de caractérisation, puis le réusinage (refactoring).

Voir:
http://conferences.elapsetech.com/legacy-tests-caracterisation/

More Decks by Félix-Antoine Bourbonnais

Other Decks in Technology

Transcript

  1. & FÉLIX-ANTOINE BOURBONNAIS B.ING., M.SC, PSM Version: Mai 2017 (DEV)

    Tests de caractérisation : à l’assaut de votre code « Legacy » patrimonial PASCAL ROY ING., CSM, PSM, PMP
  2. Imaginez du code patrimonial (Legacy)… Imaginez un outil qui permettrait

    à la fois d’explorer ce que le code fait réellement et de réusiner ce vieux code…
  3. 4 Qui sommes-nous ? Pascal Roy Ing., PSM, CSM, PMP

    Félix-Antoine Bourbonnais B.ing., PSM, M.Sc.
  4. Conférenciers Formateurs Mentors Tech. Équipe & Affaires Gestion TDD Architecture

    évolutive Essais automatisés DDD … Scrum QA Agile Gestion de projets Agilité BDD > Nous sommes Conseils stratégiques > Spécialités
  5. C’est du code difficile à faire évoluer. Peu importe son

    âge ou la raison. Qu’est-ce que du Legacy Code ?
  6. • Du code écrit par d’autres • Du code que

    plus personne ne veut toucher • Du code qui n’est plus supporté par ceux qui l’ont écrit • Du code qui pourrait être réécrit en utilisant de meilleures pratiques de code, d’outils ou de langages • ... Quelques autres définitions possibles…
  7. C’est un briseur de PEUR ! Pour… Comprendre et documenter

    ce que fait le code Empêcher la régression lors du réusinage +
  8. 1. Identifier et isoler un bout de code à modifier

    ou à analyser 2. Écrire un test qui passe par le bout de code avec une assertion qui échouera 3. Exécuter le test et le laisser vous dire quel est le comportement actuel 4. Changer votre assertion et le nom du test pour tenir compte du comportement actuel 5. Répéter… La mécanique d’écriture d’un test de caractérisation
  9. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; public double calculate(double tSales) { if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1 + (tSales - BQ * 2) * BCR * OQM2; } } } http://s3.amazonaws.com/giles/demons_010609/wtfm.jpg Un exemple simple de code patrimonial? WTF? WTF? WTF?
  10. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; public double calculate(double tSales){ if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1 + (tSales - BQ * 2) * BCR * OQM2; } } } @Test public void test… { assert(...) } Étape 1: identifier un bout de code 1 ? 2 ? ? 1 2
  11. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; double calculate(double tSales) { if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1+ (tSales - BQ*2)*BCR * OQM2; } } } @Test public void testCalculate() { assertEquals( 0.0, SalesUtil.calculate(1000.0) ); } Étape 2: écrire une assertion qui ne passe pas 1 ? 2 ? ? 1 2
  12. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; double calculate(double tSales) { if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1 + (tSales - BQ * 2) * BCR * OQM2; } } } @Test public void testCalculate() { assertEquals( 0.0, SalesUtil.calculate(1000.0) ); } Étape 3: exécuter le test + trouver le comportement actuel > junit.framework.AssertionFailedError: expected:<0.0> but was:<200.0> 1 ? 2 ? ?
  13. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; double calculate(double tSales) { if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1+ (tSales – BQ*2)*BCR * OQM2; } } } @Test public void lessThanBaseQuota_useBaseCommissionRate() { assertEquals( 200.0, SalesUtil.calculate(1000.0) ); } Étape 4: Remplacer par le comportement découvert 1 2 1 200 2 ? ?
  14. public class SalesUtil { double BQ = 1000.0; double BCR

    = 0.20; double OQM1 = 1.5; double OQM2 = OQM1 * 2; double calculate(double tSales) { if (tSales <= BQ) { return tSales * BCR; } else if (tSales <= BQ * 2) { return (BQ) * BCR + (tSales - BQ) * BCR * OQM1; } else { return (BQ) * BCR + (tSales - BQ) * BCR*OQM1+ (tSales – BQ*2) * BCR*OQM2; } } } … @Test public void testCalculate() { assertEquals( 0.0, SalesUtil.calculate(2000.0) ); } Étape 5: Répéter 1 2 1 200 2 ? ?
  15. Attention aux « tant qu’à y être » ! Ciblez

    uniquement ce que vous voulez modifier.
  16. Combien de temps ça prend pour comprendre un bout de

    code Legacy avant de le modifier?
  17. • Spécification du comportement requis • Comportement connu et nouveau

    code • Permanent • Spécification du comportement actuel • Code patrimonial, comportement flou ou perdu • Temporaire Test unitaire Caractérisation How is a CT different?
  18. Une dépense Big Bang Risque très élevé Pas de nouvelle

    valeur Paiements réguliers (dette) Étape par étape Risque moindre Produit de la valeur Refaire Rénover / Revitaliser Refonte ou réusinage ?!?
  19. La stratégie > on veut limiter les dommages et focaliser

    sur l’objectif le plus pressant Comme la prise en charge d’un patient dans une urgence…
  20. Cette présentation montre à comprendre et sécuriser votre patrimoine… Maintenant,

    vous pouvez apprendre à rénover votre patrimoine: • Sprout Methods/Classes • Instance Delegator • Extract to Method • … Maintenant… comment réusiner ?
  21. Although our first joy of programming may have been intense,

    the misery of dealing with legacy code is often sufficient to extinguish that flame. Michael Feathers, Working Effectively with Legacy Code Le code patrimonial tue la flamme!
  22. Site elapsetech.com Twitter @fbourbonnais Courriel [email protected] [email protected] LinkedIn linkedin.com/in/fbourbonnais/fr ca.linkedin.com/in/roypa

    conferences.elapsetech.com Toutes nos présentations conferences.elapsetech.com /legacy-tests-caracterisation Diapositives et références Félix-Antoine Bourbonnais Pascal Roy