Tests
&
Recettes

Mis à jour le 22/04/2025

Cédric BRASSEUR

Cédric BRASSEUR

  • Ancien étudiant de l'Exia.cesi
  • 4 ans consultant chez Amaris, placé chez Euro Information Dev
  • Auto-entrepreneur depuis début 2020 (Création de sites web, applications mobiles & formateur)

Et vous ?

  • Nom, prénom
  • Etudes réalisées 
  • Tests en entreprises ?
  • Autres infos appréciées

Plan du cours

  • Introduction : Importances des tests en entreprise
     

  • Fonctionnement et cible des tests
     

  • Les différents types de tests
     

  • Méthodologies de tests
     

  • Contenu et rédaction d'un cahier de recettes

T&R

Objectifs de la journée

  • Appréhender les techniques de recette dans un projet informatique
     
  • Utiliser une méthodologie de recettage
     
  • Construire des scenarii de tests
     
  • Produire des documents de recette

Introduction

Importance des tests et enjeux pour l'entreprise

Test

Recette

Tests & Recettes : Définitions

Un test est un morceau de code écrit afin de tester un élément ou un ensemble d'éléments de votre code projet.

Ces derniers ont pour vocations d'êtres automatisés !

La recette est l'ensemble comprenant : La définition du test, les étapes à réaliser, le résultat attendu et la validation par un recetteur.

Une recette peut également être automatisée.

  • Tester atomiquement ses développements
  • Tester les fonctionnalités attendues
  • Tester la robustesse de l'application
  • Tester automatiquement ce qui était fait manuellement auparavant
  • ...

Pourquoi tester ?

Tester, c'est s'assurer que l'on n'a pas raté quelque chose, mais c'est surtout s'assurer que tout fonctionne comme prévu pour l'intégralité de votre projet.

Primordial !

En plus, vous le faites
pour chaque projet, même manuellement

Importance des tests

L'objectif premier de réaliser des tests sur son application est de limité d'envoyer des erreurs en production.

On va donc tester les développements réalisés à chaque changement et surtout avant chaque mise en production, ce qui rend l'application plus robuste mais ne la rend pas infaillible.

  • L'utilisation d'une CI/CD force la réalisation de tests et surtout de s'assurer qu'ils passent,
  • L'identification des problèmes est donc réalisée bien plus tôt et plus simplement car tout est cloisonné,
  • Plus de productivité (si industrialisé) et rendement.
  • Si vous maîtrisez l'outil de débogue comme personne, vous pouvez tout oublier !
     
  • Tout ce que vous pouvez faire en débogage (pas à pas détaillé, espions sur les variables,...) est faisable depuis un test !
     
  • Le test reste dans le temps et il a son importance, si vous avez dû déboguer pour que ça marche un jour, autant avoir le test pour vérifier si ça marche toujours !

Evitez le débogage

Déboguer, c'est réaliser des tests manuellement qui ne pourront plus êtres réexécutés à l'avenir... Quelle dommage !

D E B U G

Pyramide des tests

Attention aux coûts de ces différents tests !

 

La pyramide des tests, définie par Martin Flower, explique le rapport en coûts et rapidité de développement selon la couverture des tests mis en place.

Peu de mise en place
nécessaire et tout développeur sait réaliser ce genre de tests

Peu de mise en place
nécessaire et tout développeur sait réaliser ce genre de tests

Peu de mise en place
nécessaire et tout développeur sait réaliser ce genre de tests

Mise en place d'outils et de communication entre les services nécessaire

Peu de mise en place
nécessaire et tout développeur sait réaliser ce genre de tests

Toute une architecture à
mettre en place, nécessite une infrastructure particulière

Fiabilité

Les tests automatisés par la CI / CD permettent d'assurer une fiabilité de ce qui est produit

Robustesse

Les enjeux pour le projet / l'entreprise

Le produit est testé en permanence, on s'assure donc qu'aucun développeur n'apporte de régression.

Même sur les fonctionnalités qu'il ne pensait pas impacter !

Gain en maintenabilité

Et c'est surtout ce point qui vous permettra de justifier auprès des décideurs le coût élevé vu précédemment.

Investir sur les tests c'est investir sur un produit fiable, robuste et aisément maintenable.

Les acteurs des tests

MOA : Maîtrise d'ouvrage

A pour objectif de rédiger le cahier des charges fonctionnel, préciser le besoin, piloter le projet et parfois pour effectuer la recette fonctionnelle (si elle n'est pas automatisée à 100%)

Les acteurs des tests

MOE : Maîtrise d'oeuvre

Responsable de la conception technique et s'assure de la mise en place des tests, leur taux de couverture, ainsi que de leur automatisation.

C'est vous !

Les acteurs des tests

Testeurs & clients

Les testeurs, souvent associés à la MOA, ont fréquemment pour objectif de réaliser le cahier de recettes, contenant les scénarios fonctionnels à tester pour le bon fonctionnement de l'application (nous en reparlerons)

 

Aujourd'hui, ils sont souvent plus sollicités en début de projet uniquement pour bien définir les users stories qui feront offices de cas de tests et donc de cahier de recette. Car les recettes sont automatisées via des méthodologies de tests comme le BDD

(nous en reparlerons aussi)

 

Les clients finaux, quand à eux vont tester le produit final et s'assurer qu'il répond bien aux attentes du produit. Ils utilisent idéalement un cahier de recettes pour leurs feedbacks.

Couverture

Dans l'idéal, il est demandé de viser 100% de couverture de tests, rien ne doit être laissé "au hasard". Bien que difficile en pratique, des méthodologie permettent de s'en approcher.

Briques logicielles

Que doit-on tester ?

Chaque brique logicielle composant votre projet doit être testé unitairement.
Vous devez également tester fonctionnellement vos projets. 

Idéalement, vous devez également réaliser des tests d'interfaces (et / ou d'acceptation) et des tests de montée en charges.

Fiabilité, performances, scalabilité,...

Le but étant de rendre notre application fiable, robuste, performante, maintenable et évolutive dans le temps.
Rien que ça !

Déroulement d'un test

Développement de tests

Un test se déroule selon plusieurs étapes...

Exécution des tests

Validation / Invalidation par ensemble

Points de contrôle avant déploiement

Mise à jour du cahier de recettes

Les différents types de tests

Les outils et s'adapter au contexte

Pour choisir quels outils utilisés pour réaliser nos tests, il faut une fois de plus se référer à la technologie et le contexte du projet.

 

Quelques exemples... (Mais il y'en a trop)

  • Mobile : Graddle                                                                         
  • .Net : NUnit, MSTest,
  • Java : JUnit,
  • Web : PHPUnit, Jasmine (js), jest (node)

Je vous invite à chercher ceux qui peuvent correspondre à vos technologies habituelles ou d'entreprise.

 

 

Différents types de tests

Il existe de nombreux tests différents, en voici les principaux et ceux que l'on va voir ensemble

 

  • Tests unitaires
  • Tests d'intégration / fonctionnel
  • Tests d'interface
  • Tests d'acceptation
  • Tests de sécurité (aussi mais c'est pas le but de la formation)                     
         

 

Autres types de tests : Tests de montée en charge, tests d'exploitabilité, vérification de disponibilité immédiate

 

Les tests unitaires

Un test unitaire est utilisé afin de pouvoir vérifier atomiquement que chaque élément de notre code. On va donc vérifier que le code produit bien le résultat attendu.

A savoir :

  • Systématique pour chaque projet !
  • Réfléchir efficacement à ce qui doit être testé, inutile de tester si 1 + 1 = 2.
  • Test Driven Development (TDD): Méthodologie récente visant à démarrer ses développements par des tests unitaires

MSTest est un framework de tests que l'on va utiliser tout au long de notre formation. 

 

Les choses à savoir :

  • Le test se fait sur une classe tout à fait normale
  • Il suffit de mettre les attributs [TestClass] au dessus de la classe
  • Et [TestMethod] au dessus de chaque méthode qui sera considérée comme un test

MSTest

MSTest est un framework de tests que l'on va utiliser tout au long de notre formation. Au cas où voici la liste des attributs MsTests :

  • [TestClass] : Attribut définissant une classe comme une classe de test 
  • [TestMethod] : Méthode de test traduit comme un test
  • [TestInitialize] : Méthode exécutée avant chaque TestMethod
  • [TestCleanup] : Méthode exécutée après chaque TestMethod
  • [ClassInitialize] : Méthode d'initialisation de classe
  • [ClassCleanup] : Méthode de destruction de classe
  • [AssemblyInitialize] : Méthode d'initialisation d'assemblie
  • [AssemblyCleanup] : Méthode de nettoyage de l'assemblie
  • [TestCategory("name")] : Catégorise un ou plusieurs tests
  • [Ignore] : Ignore un test

MSTest - Attributs

Il est également possible de réaliser des assertions, visant à vérifier qu'un contenu correspond à ce qui est attendu, quelque soit la comparaison effectuée.

Exemples : 

  • Assert.IsTrue(booleanValue);
  • Assert.AreEqual(a, b);
  • Assert.IsNull(element);
  • ...

MSTest - Assertions

Si besoin de plus d'informations sur la réalisation de tests MSTest, visitez :
https://docs.microsoft.com/fr-fr/dotnet/core/testing/unit-testing-with-mstest

MSTest - Documentation

Tester ses exceptions

Lors de vos développements, vous allez certainement gérer ou créer des exceptions. Ces exceptions doivent également être testées afin de vous assurer de leur utilité.

Utilisation de Assert.ThrowException

Utilisation de Assert.ThrowsException

Délégué pour appeler la méthode qui doit générer une exception

Les différents cas d'utilisation de votre code peuvent donc être testé et doivent être testés afin de s'assurer que tout est maîtrisé.

  • Le nom du projet de test doit toujours être nommé : ProjectTested.UnitTests.
    Par exemple, le projet est nommé FizzBuzz. Le projet de tests unitaires sera FizzBuzz.UnitTests

     
  • Le nom de la classe que l'on test :
    NomClassTests
    Par exemple on test la classe Customer, la classe de test sera CustomerTests.

    A noter une particularité ici, si vous devez séparer vos tests car des tests sur une même classes sont nombreux sur une méthode, vous pouvez faire une classe spécifique pour ces tests et les regrouper :
    NomClass_MethodNameTests.

    Par exemple Customer_LoginTests

Conventions de nommage

Il existe des conventions à respecter pour vos tests

  • Nommage de la méthode de test :
    Method_Scenario_ExpectedBehavior
    Par exemple : ReadAnimalName_EmptyFile_ReturnsError

    Méthode : La méthode testée
    Scenario : Le scénario (chemin d'exécution) du test
    ExpectedBehavior : Le résultat attendu
     
  • Le contenu du test (un peu hors nommage, mais autant le voir ici quand même) :
    Arrange
    Act
    Assert


    Nous avons normalement vu de nombreux exemple durant la formation de ce "Triple A for testing"

Conventions de nommage

Il existe des conventions à respecter pour vos tests

Workshop

Vous devez réaliser un projet de tests unitaires sur une calculatrice simple.

Cette calculatrice est une classe à part entière et elle contient les méthodes :

  • Add (numberOne, numberTwo)
  • Substract (numberOne, numberTwo)
  • Divide (numberOne, numberTwo) ==> Attention au type du résultat de la division & Pensez à gérer la division par 0
  • Multiply (numberOne, numberTwo)

 

L'objectif est de réaliser cette classe et également de faire les 5 4 tests unitaires qui correspondent.

Tentez de faire des tests multiples avec des DataRow
Pensez, si vous y arrivez à faire un TestInitialize qui permettra d'éviter de dupliquer du code.

Tests avec paramètres

Il est possible de tester en ajoutant des paramètres d'entrées à vos méthodes de tests, ceci est souvent utile afin de pouvoir tester différentes valeurs initiales pour vos tests.

Ce test sera donc exécuté trois fois, avec trois ensemble de paramètres différents.
Attention, il n'est pas utile d'en abuser !
Mais ça peut s'avérer pratique pour tester plusieurs cas ou associer des données "cohérentes" aux tests.

Exercice tests unitaires

Je vais vous envoyer un code du "célèbre" exercice FizzBuzz.
 

Vous allez devoir développer le célèbre FizzBuzz :

  • Une méthode avec un paramètre d'entrée (number)
  • Cette méthode retourne un string
    • Si c'est un nombre négatif, levez une exception de type ArgumentException
    • Si c'est un multiple de 3, retourne "Fizz"
    • Si c'est un multiple de 5, retourne "Buzz"
    • Si c'est un multiple de 3 et 5, retourne "FizzBuzz"
    • Si c'est multiple de ni l'un ni l'autre retourne le nombre en chaîne de caractère

Vous allez devoir réfléchir aux différents tests à réaliser et les réaliser en .Net. Réalisez vos tests avec des DataRow.

 

Pensez à tous les chemins d'exécutions qu'il faut tester.

Envoyer FizzBuzz.zip

Exercice: Tests unitaires

Réalisez un projet de tests unitaires simple.
 

L'objectif est assez simple, vous devez réaliser les tests permettant de valider une date par sous ensemble ("jours-mois-année"). Le format d'entré est un string à valider.

Donc au final on veut une méthode isDateValid(string date) avec les tests unitaires nécessaires pour chaque étape de validation ci-dessous. Simplifiez vous la tâche en laissant tout en public et en créant des petites fonctions qui effectuent chaque étapes de la validation

Testez :

  • Le nombre de "-" doit être égal à 2
  • Les éléments entre les tirets doivent être numériques
  • Le mois doit être compris entre 1-12
  • L'année doit être comprise entre 2000 & l'année du jour
  • Le jour doit être compris en 1 et 31 (quelque soit le mois, pour ceux qui veulent un peu se challenger, implémentez le bon système de jours par rapport aux mois)

 Essayez de gérer les cas d'erreurs avec des exceptions !

Exercice: Tests unitaires

Pour cet exercice, vous allez devoir implémenter un jeu dont les règles se trouvent ici

https://www.codewars.com/kata/5941c545f5c394fef900000c

 

Votre objectif est d'implémenter le jeu ainsi que tous les tests unitaires du projet

Injection de dépendances

Concept issu de la POO permettant de limiter les conséquences des interactions entre les éléments de votre projet.

 

 

Il en existe 3 types :

  • Par paramètre : On passe un paramètre à la méthode du type abstrait de l'objet de dépendance
  • Par mutateur : Une propriété interne a notre classe reçoit en paramètre l'objet de dépendance
  • Par constructeur : On passe l'objet de dépendance directement au constructeur de notre objet.

La pratique la plus répandue aujourd'hui est de coupler l'injection par interface et l'injection par constructeur.

Démo Code

Injection de dépendances

Des frameworks d'injection de dépendances existent afin d'éviter la dernière étape du paramètre optionnel et du ??.

NInject

Autofac

Spring.NET

StructureMap

Unity

...

Nous ne rentrerons pas dans le détail des Framework d'Injection de dépendances, mais en gros, ils servent à gérer "automatiquement" vos interfaces et leurs dérivées. 

Exercice DI

Petit exercice pour travailler les injections de dependances

Envoyer DI_Exercice.md

Utiliser les Mocks

Démo Code

Les mocks permettent concrètement de simuler une classe sans avoir à l'instancier elle et tout ce qui l'incombe (paramètres, retours de méthodes particuliers,...)

Les Mocks sont utilisés pour plusieurs raisons :

  • Isolation de code : On simule le comportement d'une dépendance externe sans se soucier de cette dernière
     
  • Garder le contrôle de son environnement de test
     
  • Isolation des échecs : Si un de vos test échoue avec un Mock, c'est que le problème vient de votre côté
     
  • Rapidité et efficacité

Quelques exemples de Mock

Quand utiliser les Mocks

En soit, on pourrait absolument tout Mocker. Mais c'est une mauvaise pratique qui mène a des tests très volumineux inutilement.

Donc... Quand est-ce qu'on Mock ?

On Mock afin de remplacer une dépendance externe, l'objectif étant d'isoler nos classes et pouvoir les tester séparément.

 

C'est tout !

Je rappelle que l'on réalise ici des tests unitaires, c'est pourquoi l'on veut pas tester les dépendances en même temps, sinon en arrive à un test d'intégration.

Exercice Mock

Petit exercice pour travailler l'utilisation des Mock

Envoyer MockingExercice.md

  • Si vous souhaitez vraiment tester une méthode privée car vous voulez vous assurer de la logique d'un élément de votre application. Vous le pouvez.

Comment tester une méthode privée ?

La réponse simple : On ne test pas de méthode privée.
L'idée étant de mettre en place l'encapsulation et de "cacher" la logique dans des méthodes privées (Et aussi, on veut factoriser le code et le rendre testable efficacement). Ce que l'on veut tester, c'est ce qui peut être appelé de l'exterieur donc les méthodes publiques.

Des exceptions ?

Ma suggestion :

  • Mettre la méthode en internal
  • Utiliser l'attribut suivant :
[assembly: InternalsVisibleTo("YourUnitTestProjectName")]

Oui, j'ai mis un singe parce que c'est pas une bonne pratique de tester ses méthodes privées

Les tests d'intégration

Un test d'intégration permet de vérifier qu'il n'y a aucune régression sur l'existant suite aux modifications effectuées. (En termes de dépendances entre les éléments de votre appli)

A savoir :

  • Systématique pour chaque projet ! 
  • Plus complexe à mettre en œuvre car il doit vérifier les dépendances entre les éléments (Si une classe en utilise une autre par exemple ou un framework)
  • Ils se transforment en tests de non régression lorsqu'ils sont repassés
  • Souvent à réaliser quand il y a des services qui communiquent entre eux, ou une base de données, ou une API...

Démo : Tests intégration

Projet avec une base de données

Workshop complémentaire

Je vais vous envoyer un projet à tester sur lequel vous devez réaliser les tests d'intégration demandés.

Envoyer Integration_Tests_Exercice.md

Les tests d'interface

Les tests d'interface vérifient que les développements sont cohérents et fonctionnent sur toutes les plateformes cibles (par exemple, dans le web on vérifie chaque navigateurs)

A savoir :

  • Systématique pour chaque projet ! (Au moins de manière implicite / manuelle par le développeur)
  • S'informer sur les plateformes cibles potentielles est important ici
  • Il est aussi possible de les automatiser (Selenium) en paramétrant notre test avec les plateformes cibles et les vérifications sur ces plateformes.
  • Framework .Net
  • Met a disposition des classes de getsion d'interface
  • Permet de démarrer et interagir avec un navigateur grâce à un Driver

Sélénium

Selenium est un framework qui va nous permettre de réaliser nos tests d'interface, il permet par exemple d'ouvrir le navigateur, accéder à une URL, vérifier la présence d'un élément, cliquer sur un boutton, remplir un input,...

Sélénium IWebElement
L'interface IWebElement

Une classe des plus utilisé de Selenium est IWebElement, elle permet de réaliser plusieurs opérations sur notre navigateur, ainsi que d'utiliser les éléments qu'elle permet d'identifier.

 

Les méthodes à connaître sont : FindElement(), FindElements(), Navigate(), Close(), Quit().
 

Sur un élément récupéré, vous avez des méthodes telles que Click(), SendKeys(), ... 

Sélénium Locator
La classe By

La class By va nous permettre d'identifier de plusieurs façons nos éléments d'interface.

  • By.Id() : Par l'id de l'élément
  • By.ClassName() : Par nom de classe de l'élément
  • By.LinkText() : Par un contenu de lien
  • By.CssSelector() : Par selecteur css
  • By.Name() : Par nom de l'élément
  • By.TagName() : Par html tag
  • By.XPath() : Par expression XPath

 

Honnêtement, nous n'allons quasiment qu'utiliser du By.Id() dans cette formation, mais il peut être intéressant pour vous de voir les expressions XPath.

Sélénium

Les packages Nuget

Pour utiliser Selenium, il nous faudra ajouter deux packages Nuget au projet :

  • Selenium.WebDriver
  • Selenium.WebDriver.GeckoDriver

GeckoDriver est le driver pour Firefox, il est le plus simple des driver à utiliser car il n'y a pas de soucis de version exacte à matcher.

 

  • Chrome : Selenium.WebDriver.ChromeDriver
  • IE : Selenium.WebDriver.IEDriver
  • Edge : Selenium.WebDriver.MSEdgeDriver
  • Safari (pas de package requis) : safaridriver --enable

Sélénium

Créer un WebDriver

La première étape est assez simple, il nous faut créer le WebDriver. Pour l'instant et pour cette étape, vous pouvez faire ça directement depuis votre Program.cs

using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

IWebDriver driver = new FirefoxDriver(); // Ou new ChromeDriver() ou new SafariDriver(),...

Accéder à une page

driver.Navigate().GoToUrl("https://example.com");

Sélénium

Vérifier la présence d'un élément

Maintenant, nous pouvons utiliser le Driver pour réaliser différentes opérations relatives à notre interface.

IWebElement element = driver.FindElement(By.Id("my-element-id"));

if (element != null)
    Console.WriteLine("L'élément est présent !");
else
    Console.WriteLine("L'élément est introuvable.");

Cliquer sur un bouton

IWebElement button = driver.FindElement(By.Id("my-element-id"));
button.Click();

Remplir un input

IWebElement input = driver.FindElement(By.Id("my-element-id"));
input.Clear(); // optionnel, ça clear juste l'input
input.SendKeys("Valeur que je veux mettre dans mon input");

Exercice Tests d'interface

Tester une interface pour remplir des numéros de cartes bancaire

  • Je vous donner l'interface simple
     
  • Vous avez un docker-compose pour lancer l'interface (docker-compose up puis go sur http://localhost/Workshop.html)
     
  • Et un workshop assez guidé pour réaliser les différents tests d'interface sur cette petite interface

N'hésitez pas à me demander de l'aide

Les tests d'acceptation

Les tests d'acception permettent de vérifier que les scénarios utilisateurs définis à l'expression de besoin respectent bien les étapes et le résultat attendu. 

A savoir :

  • Systématique pour chaque projet ! (Au moins de manière implicite par les développeurs)
  • Peuvent être définis dès la phase de spécification.
  • Une méthodologie récente propose même des outils pour passer ces tests de manière automatisée ou en forçant les développeurs à les passer avant de pouvoir partager leurs développements.

Behavior Driven Development

  • Outils manuels (souvent utilisé lorsque des équipes de recette sont définies pour le projet) : QCHP, Cucumber, il en existe surement énormément, mais ils font tous à peu près la même chose. On décrit un scénario avec des étapes et un résultat attendu, le recetteur doit respecter les étapes et faire un retour quant au résultat attendu directement sur l'outil.
    Tant qu'un scénario bloque, il n'est pas possible de passer de l'environnement de recette (ou pré-prod) à l'environnement de production.
  • Behavior Driven Development : Ici, on parle de tests d'acceptation automatisés qui sont bien plus complexes à mettre en œuvre. On peut réaliser ça avec NUnit et Gherkin par exemple, ou Jest et Galerkin...

Tests d'acceptation - suite

Les tests de performances

Les tests de performances font exactement ce que leur nom indique, on parle aussi de tests de charge, tests d'usine,...

A savoir :

  • PAS systématique pour chaque projet, utilisé en cas de besoin de performances. 
  • On test si des fonctionnalités ont des temps de réponses suffisant ou si le réseau est de bonne qualité, on réalise des simulations d'utilisation massive pour s'assurer d'un service continue, on test les capacités serveurs (RAM, CPU,...) etc...

 

Demo tests de performances avec tests sur la durée d'exécution d'un bout de code

 

 

Je vous laisse un peu de temps pour faire de même et me poser des questions si ça n'est pas clair

Exemple simple tests performances

Exercice: Développement d'un jeu avec les différents tests

Choisissez un des sujet proposé (si possible un que vous n'avez pas déjà fait) et réalisez l'intégralité des tests unitaires, tests fonctionnels, tests de performances qui en découlent.

Pensez bien en tests atomiques pour les tests unitaires et en fonctionnalités pour les tests fonctionnels. Concernant les tests de performances, faites au mieux avec les moyens du bord.

Réalisez trois projets de tests différents, un pour les tests unitaires, un pour les tests fonctionnels, un pour les tests de performances

Outils - Tests de performance

Certains outils permettent de tester les performances de vos applications :

 

  • QTest
  • Datadog
  • NeoLoad
  • JMeter
  • ...

Conclusion sur les tests

Les tests sont une part importante des développements dans un projet et également une part importante de sa réussite.

L'estimation moyenne du pourcentage de temps (selon moi, j'ai cherché mais je n'ai pas trouvé d'étude) pris pour réaliser les tests sur un projet est compris entre 30% et 50% du temps !

 

D'où l'intérêt de la TDD, on fait des allers-retours entre les développements et les tests, les tests sont effectué au départ et les développements s'adaptent pour y répondre !

Introduction Intégration Continue

Nous allons faire une petite intégration à l'intégration continue avec Github Actions.

 

https://slides.com/cedricbrasseur/git-ci-cd/

Exercice tests fonctionnels

Vous devez tester une API en vérifiant que tous les endpoints fonctionnent bien comme il faut :

  • On test le code de retour (200, 404, etc...)
  • On vérifie que le résultat a bien impacté nos éléments comme il faut, c'est un test plus complet que l'unitaire. Exemple, on ajoute un livre : On vérifie le code retour 200 & on s'assure que le nombre de livre a augmenté de un.

 

Vous pouvez faire ça sur :

  • Une api à vous que vous souhaitez tester
  • Ou sur l'API que je vous envoie (en .Net)

Exercice tests d'interface

Voir le fichier Exercice_Tests_Interface.md

Les méthodologies de tests et recettes

L'équipe QA

Auparavant, lors des développement en cycle en V, une équipe était dédiée à la réalisation des tests et l'écriture du dossier de recettage. Ils avaient pour objectif de s'assurer du respect des fonctionnalités de l'application.

Ici aucune vérification de couverture de test n'est appliquée.

"Anciennes" méthodologies

La classique

De manière plus classique et actuelle, les tests peuvent être réalisés à la suite des développements. Ceci est une pratique encore très répandue en France, malgré son manque d'efficacité et son manque de contrôle de taux de couverture des tests.

Les tests unitaires

Définition, utilité et réalité

  • Un test unitaire est utilisé afin de pouvoir vérifier atomiquement que chaque élément de notre code fait ce qu'on attend de lui.
  • A une certaine époque, je n'utilisais les tests unitaires que pour tester grossièrement mon application à la fin de mes développements. 
  • Les tests unitaires sont souvent utilisés (à tort) comme des tests jetables, alors qu'ils doivent faire partie intégrante de votre intégration continue

Nous allons entamer votre apprentissage du TDD, mais sachez que vous ne serez sûrement pas encore experts à la fin de cette formation, à vous d'être assidu et pratiquer quand vous en avez la possibilité

Le TDD : Une méthodologie bien rodée et adaptée

Le TDD est une pratique qui a commencé à être réellement utilisée en 1999. Peu répandu en France à ma connaissance et pourtant... C'est un point si important ! On en parler juste avant, trop d'entreprise demandent à la QA pour réaliser des tests.

NON ! C'est à nous de tester nos développements

Les règles du TDD

Il y a trois grandes règles à respecter pour faire correctement du TDD

Les règles :

  • Première : Vous ne devez pas écrire de code projet tant que vous n’avez pas écrit un test unitaire d’échec.
  • Deuxième : Vous devez uniquement écrire le test unitaire suffisant pour échouer, l’impossibilité de compiler est un échec.
  • Troisième : Vous devez uniquement écrire le code projet suffisant pour réussir le test actuellement en échec (et faire passer les autres.)

Les tests et le code sont écrits ensemble, en commençant par les tests.

Garder des tests propre est primordiale

Maintenir ses tests c'est maintenir son code

Tous les concepts et conseils vu dans la partie précédente sont à appliquer dans vos tests unitaires. C'est important de le comprendre car c'est également un des avantages de l'utilisation de la méthode TDD.

Le Test Driven Development en agile

Pourquoi le TDD ?

Tout code doit être testé et en agile on doit être prêt à déployer toutes les 2 semaines (ou semaine). ça ne veut pas dire qu'on va forcément toujours délivrer tout ce qui est développé, mais on va déployer que des choses prêtes à être déployées et ce à un certain rythme (comparé à avant, ou on livrait tous les 3 mois)

Attention, la couverture de tests voulue est 100% mais c'est la valeur théorique quasi inatteignable

L'objectif des tests est de permettre n'importe quelle modification sans avoir peur de casser quelque chose.

Votre premier objectif est de tester chaque portion de code que vous développez

Le TDD

Les avantages de la méthodologie

  • En tant que développeur, c'est intéressant de tester ses développements grâce à des tests unitaires plutôt que d'utiliser un debugger. On a tous ce signe de victoire quand on fait passer un test, quel plaisir, pourquoi s'en priver ?
     
  • Le TDD est assez complexe à appréhender mais c'est une façon de développer qui vous permettra de devenir des développeurs sûrs de ce qu'ils déploient en production.
     
  • Quand vous développez des tests, vous écrivez votre documentation et vos exemples de code !  C'est important, c'est aussi un gain de temps et ce sont vos tests qui vont former les futurs développeurs sur votre projet et non une doc écrite sur du code copier/coller dans un PDF 5 ans auparavant.

Petite démo du TDD

Je vais faire un exemple en l'expliquant pas à pas devant vous.

Le but est de réaliser une stack de nombre en TDD.

 

Vous allez voir... Au début, il faut coder comme quelqu'un de stupide !

Exercice: TDD

Méthode TDD sur un sujet simple : Calculatrice

Réaliser un projet simple contenant des tests unitaires pour :

  • Vérifier qu'un paramètre est bien un nombre
  • Ajouter deux nombres,
  • Soustraire deux nombres,
  • Multiplier deux nombres, 
  • Diviser deux nombres,                                                   

Développez d'abord les tests unitaires, puis développez la classe (ou les si vous voulez) contenant vos méthodes prenant en paramètres deux nombres vérifiés pour en effectuer des opérations mathématiques.

Je conseil de réaliser un projet en .Net pour utiliser les tests MSTest (ou NUnit)

Behavior Driven Development (Intro)

  • Behavior Driven Development a commencé à voir le jour en 2006, Kent Beck, grand utilisateur de TDD à l'époque s'est rendu compte que ses tests unitaires se transformais au fur et à mesure en tests d'acceptance.
    Dan North a ajouté la notion de comportement et au lieu de parler te test, il parle de comportement. D'où le Behavior Driven Development.
     
  • D'où la naissance de l'ATDD,
     
  • Puis par induction, et en se référant au modèle agile qui est de plus en plus utilisé, Behavior Driven Development a été mis en place pour démarrer les développements directement depuis les users stories 

Introduction - Objectifs

Objectifs BDD :

  • L'objectif premier est comme on l'a vu juste avant de partir des users stories (scénarios)
  • Ces scénarios sont directement écris en anglais (ou autre langue)
  • Chaque scénario est défini en plusieurs étapes
  • Chaque étape fera office de test unitaire ou test d'interface
  • Le scénario sera quant à lui un test d'acceptation
  • On développe exactement ce qui est demandé, ni plus ni moins
  • Chaque élément est testé & couplé à une ATDD, les tests d'interfaces sont complets
  • Les tests peuvent être automatisés et exécutés en intégration continue
  • ...

(Graphique non représentatif)

BDD en vogue

Depuis son arrivée en 2006 / 2007, la popularité de la méthodologie de développement en se basant sur le comportement (BDD) n'a de cesse d'augmenter.

Pourquoi ?

Les avantages à l'usage

Vanguard Group Feedbacks

  • Un des premier grand utilisateur de BDD est le groupe Vanguard. Peu importe ce qu'ils font, ils ont publiés un article sur leur utilisation du BDD et les avantages qu'ils en ont tirés.

 

Voici la liste des avantages que j'ai pu en sortir :

  • Leur temps de développement de tests a diminué d'environ 40%
  • Le nombre de Defects (bugs) a diminué drastiquement
  • La durée pour mettre en production a diminué
  • La confiance des équipes en leur produit a augmenté, réduisant le stress et l'anxiété des employés travaillant dans un cadre maîtrisé et couvert par des tests
  • Quasiment zéro tests manuels sont effectués

J'irai même plus loin que ça, en disant que dans mon expérience, BDD permet de complètement retiré l'équipe de recettage à la fin de la chaîne en temps que testeurs QA.
Ils interviennent essentiellement lors de la phase de réalisation des scénarios.

Rappel sur les tests d'acceptation

Test d'acceptation : Réalisation d'un test visant à vérifier la conformité d'un produit par rapport aux spécifications définies.

Pendant très longtemps, ces tests étaient réalisées manuellement, soit par l'équipe de développement, soit par une équipe de recettage.

Automatisation :

  • L'automatisation de ses tests est réalisé grâce à des outils permettant de gérer un navigateur. Ceci s'appelle un Driver.
  • Avec ces tests, on peut réaliser exactement ce que l'utilisateur va réaliser sur son interface
  • On peut tester les scénarios utilisateurs d'échec ou de réussite
  • Des indicateurs (reporting) peuvent être générés,...

Des users stories au scénarios

Comme on l'a rapidement évoqué, le Behavior Driven Development a vu le jour afin de pouvoir directement démarrer des users stories utilisées en méthodes agiles afin de réaliser nos tests d'acceptation directement en tests d'interface, ou en tests unitaires.

User story: 
As a visitor
I want to Login
So I can access to profil page

Acceptance Criteria : 
Given visitor fill username and password
When visitor click on login button
Then user is connected and is on profil page
Feature : Login

Scenario : Login and go to profil page
 Given visitor fill username and password
 When visitor click on login button
 Then user is connected and is on profil page

User story

Scenario

BDD Définition 

Une méthodologie basée sur le comportement

On démarre des user stories pour créer des scénarios, ces derniers vont définir des étapes permettant de réaliser le scénario.
On établit donc un projet qui répond exactement à la demande du client selon la définition des scénarios utilisateurs.

Behavior Driven Development prends les principes du TDD et des méthodes agiles.

Les besoins utilisateurs sont traduits en code est sont directement testables.

Incluant un recettage automatisé en intégration continue.

Critères d'accepation

Explique ce qui défini qu'un système fonctionne correctement.

 

Ecris de manière à ce qu'ils soient toujours en Pass/Fail via une assertion.

Scénario

Définis les conditions des critères d'acceptations

 

Définis les étapes du scénario et les sorties voulues (que ce soit en terme de page accédée, en terme de résultat attendu par une étape, etc...)

 

Ici chaque étape n'est pas forcément une assertion

Critères d'acceptation VS Scenario

Les éléments d'un scénario

  • Concrètement un scénario correspond à la description d'une user story. Il a sa petite description aussi.
     
  • Chaque étape du scénario permet de définir ce scénario, ces étapes sont définies avec les mots clés suivants :
    • Given : L'ensemble des conditions initiales (user on page X)
    • When : Un évènement survient (user input)
    • Then : Une sortie ou plutôt condition d'acceptation est attendue (souvent avec une assertion via Assert)
    • And : Elément un peu complémentaire qui va juste compléter le mot clé précédent.

Gherkin - Qu'est-ce que c'est ? 

Structuration de nos scénarios dans une langue compréhensible par un client

C'est un langage spécifique au domaine qui décris les comportements attendus par notre logiciel. Attention, ça n'est que la partie qui en décris le comportement. Il peut être écrit dans n'importe quel langue (français, anglais,...).
Il agit également en tant que documentation de l'application.
On démarre toujours avec un fichier FeatureFile.

Exemple de FeatureFile

Gherkin - Qu'est-ce que c'est ? 

Structuration de nos scénarios dans une langue compréhensible par un client

Chaque étape d'un scénario fait office d'un test unique (pour ne pas dire unitaire et confondre avec le test unitaire classique).
Plusieurs mots clés possibles : Given, When, Then,...

Fichier FeatureFile complet

SpecFlow - Génération des tests

En .Net, on va utiliser SpecFlow nous permettant de générer nos StepDefinitions découlant de notre fichier FeatureFile vu précédement.

Exemple complet

Les concurrents de SpecFlow

Tout d'abord SpecFlow utilise Cucumber pour interpréter le Gherkin

Les autres outils pour faire du BDD :

  • SpecFlow pour le .Net, c'est celui qu'on va utiliser
  • Serenity (Open Source)
  • Jasmine (javascript)
  • minitest (small and fast)
  • JGiven (Java)
  • Cucumber (Gherkin !!)
  • ...

Cucumber

Cucumber est à la fois une automatisation des tests, des spécifications exécutables et de la documentation dite "vivante".

Cucumber - Step Definitions

Comme vu précédemment, les fichier FeatureFile contiennent la définition des étapes en anglais. 

SpecFlow / Cucumber permet de générer le fichier StepDefinition définissant le contenu de nos steps et donc de nos tests

  • Framework utilisant Cucumber
  • Gestion du Gherkin
  • Mise en place des StepDefinitions automatisée
  • Tests d'acceptation simple et intégré au Framework

Démo BDD

Pour mieux appréhender le BDD, nous allons voir un exemple concret réalisé sur une ATDD

C:\Users\cdric\OneDrive\Bureau\Formations\FormationBehaviorDD\git\SeleniumWebDriver

Le cahier de tests et recettes

Ce document a pour objectif de s'assurer du bon fonctionnement de l'intégralité du projet.
 

Il recense l'intégralité des tests effectués afin de faire office de guide dans la vérification de la conformité du produit.

Il contient généralement : le contexte du projet, les prérequis pour recetter ainsi que la liste complète des tests (unitaires et acceptations).

Contenu du cahier de recettes / tests

Avantages :

  • La gestion de la recette (des tests),
  • L’identification des besoins à satisfaire,
  • L’organisation de l’exécution du projet,
  • La constitution de l’équipe en charge du projet,
  • La répartition des tâches entre elles.                                                                     

Chaque test doit être décris en donnant à minima les informations suivantes :

  • Description détaillée de la fonctionnalité testée
  • Listing des étapes à suivre pour passer le test (contexte)
  • Explication du résultat attendu (que ce soit un test de réussite ou d'échec)
  • Nom du recetteur
  • Réponse au test par le recetteur
  • Commentaires

 

Le but de ce cahier de recette est donc d'être un guide pour la vérification de bonne conformité du produit. Si tous les tests du cahier de recettes passent au vert, nous assumons avoir vérifier le produit avant livraison.

L'équipe de recettage peut aussi réaliser les PV de recettes.
Les clients le peuvent également, mais généralement ils testent l'application sans respecter les étapes du cahier de recettes.

Ecriture d'un PV de recette

Exemple rapide

  • Assurance qualité du produit
  • Fiabilité des fonctionnalités proposées
  • Validation de conformité par le client via la signature du PV de recette
  • Eviter les problèmes après livraison
  • Le client s'engage à dire que la version du produit est conforme (ce qui peut éviter des débats sur ce qui sera de la maintenance corrective ou de la maintenance évolutive)

Objectifs d'un cahier de recette

Exercice Projet

Vous allez prendre tout le temps qu'il faut pour réaliser un cahier de recette le plus complet possible concernant le projet fil rouge sur lequel vous travaillez.
 

L'objectif est que je vous fasse des retours sur ce que vous proposez et comme je dois vous mettre une note pour chaque module, je vais devoir associer une note pour votre travail du jour (mais tranquille hein, ça va le faire)

Stratégies de tests avancées

La politique de tests est l'ensemble des règles et le document concernant les normes des tests qui doivent être réalisés pour considérer la qualité d'un logiciel.

Elle reprend, entre autres : 

  • Objectifs des tests : Les attentes, que ça soit en termes de fonctionnement, de performances, de qualité...
     
  • Normes et procédures : Gestion de la rédaction de tests (qui, quoi, quand,...), de leur automatisation, de leur taux d'acceptation d'automatisation, de leur fréquence d'exécution,...
     
  • Stratégie de tests : Comment les tests seront planifiés, conçus et exécutés ? Quels types de tests seront réalisés ? Et aussi présenter les outils que vous allez utiliser
     
  • Environnement de tests : Configuration (Docker ?), base de données, droits d'exécution, données de tests,...

Politique de tests

Suite...

  • Méthodologie de tests: Autrement inclusion de la conception et du passage du test dans la méthodologie de projet (sprint particulier ? Durant les sprints ? TDD ? BDD ?...)
     
  • Le suivi des anomalies : Mettre en place un outil de suivi des anomalies, outil de ticketing par exemple
     
  • Formation et compétences requises : A maintenir à jour et réaliser avec des organismes externes de préférence
     
  • Mesure des performances : Définir et présenter les indicateurs pour évaluer la performance logiciel ET celle des tests
     
  • Automatisation des tests

Politique de tests

Durant cette formation plus avancée, nous devons aborder la suite de tests suivante : 

  • Tests fonctionnels
  • Tests de compatibilité
  • Tests de performance
  • Tests d'utilisabilité
  • Tests de fiabilité
  • Tests de sécurité
  • Tests de maintenabilité
  • Tests de portabilité

Les différents types de tests

(De nombreux ont déjà été couverts dans les parties précédentes)

Les tests fonctionnels

Un test fonctionnel a pour objectif de valider un sous ensemble du logiciel (un fonctionnalité, un module,...) pour valider les spécifications fonctionnelles qui lui sont associées.

A savoir :

  • Systématique pour chaque projet ! 
  • Couvre un maximum de scénarios de l'application, ce sont des tests à réaliser régulièrement pour s'assurer de n'avoir aucune régression
  • S'effectue globalement avec les mêmes outils que les tests unitaires
  • Possibilité d'automatiser (sans code) ces tests en réalisant directement des tests de scénarios 

Les tests de compatibilité

Les tests d'interface, ou tests de compatibilité vérifient que les développements sont cohérents et fonctionnent sur toutes les plateformes cibles (par exemple, dans le web on vérifie chaque navigateurs et même différentes versions de ces derniers)

A savoir :

  • Systématique pour chaque projet ! (Au moins de manière implicite / manuelle par le développeur)
  • S'informer sur les plateformes cibles potentielles est important ici
  • Il est aussi possible de les automatiser (Selenium) en paramétrant notre test avec les plateformes cibles et les vérifications sur ces plateformes.

Outil tests de compatibilité

L'utilisation d'un framework comme Selenium permet de réaliser des tests de compatibilité automatisés, nous avons déjà abordé cette partie lorsque nous avons parlé de Behavior Driven Development.

Je vous invite à essayer par vous même en utilisant la base fournie pour réaliser vos tests sur différents navigateurs.

Possibilité de revoir un peu tout ça si nécessaire + Envoyer la base de travail avec Selenium en .Net

Les tests de performances

Les tests de performances font exactement ce que leur nom indique, on parle aussi de tests de charge, tests d'usine, tests de résilience, tests de disponibilité immédiate,...

A savoir :

  • PAS systématique pour chaque projet, utilisé en cas de besoin de performances. 
  • On test si des fonctionnalités ont des temps de réponses suffisant ou si le réseau est de bonne qualité, on réalise des simulations d'utilisation massive pour s'assurer d'un service continue, on test les capacités serveurs (RAM, CPU,...) etc...

Outils - Tests de performance

Certains outils permettent de tester les performances de vos applications :

 

  • QTest
  • Datadog
  • NeoLoad
  • JMeter
  • ...

Documentation

Datadog / Kubernates / Docker

Utilisation de JMeter plus en détails (cours complet)

Les tests d'utilisabilité

Ce sont des tests conçus afin de s'assurer de la simplicité d'utilisation du logiciel dans le but d'identifier les "obstacles" à l'utilisation de ce logiciel. Ces derniers assurent simplement la satisfaction des utilisateurs.

A savoir :

  • Peu automatisable, même si des outils existent pour tirer des indicateurs importants
  • Passe souvent par des feedbacks des utilisateurs finaux
  • Prend en compte plusieurs aspects 
    • Efficacité / simplicité d'utilisation (nombre de clicks pour une action par exemple)
    • Accessibilité et normes RGAA
    • Charte graphique efficace

Outils utilisabiltité

Ici, vous devez déjà connaître certains outils comme Google Analytics, Adobe Analytics, Matomo etc...

 

Ils permettent de connaître le nombre d'accès à une page, le nombre d'abandons sur une page en particulier, le nombre de retour à l'écran d'accueil etc... C'est pratique pour mesurer l'utilisabilité d'un produit et prendre des mesures nécessaires sur les aspects du projet qui ressortent de manière problématique.

 

Bon, vous n'êtes sûrement pas sans savoir que la CNIL a bloqué l'utilisation de Google Analytics.

 

Tutoriel complet utilisation Matomo

Les tests de fiabilité

C'est un sous ensemble des tests de performances que nous avons déjà abordé.  Ils découlent très souvent des documents nommés PRA / PCA que vous devez déjà connaître.

A savoir :

  • PAS systématique pour chaque projet, utilisé en cas de besoins particuliers (même si pas déconnant généralement)
  • Prend en compte des aspects tels que : 
    • Fiabilité
    • Gestion mémoire
    • Reprise d'activité et comportement face aux blocages
    • Scalabilité et longévité
    • Gestion d'un redémarrage

Documentation

Datadog / Kubernates / Docker

Les tests de sécurité

Les tests de sécurités sont abordés dans la formation concernant la sécurité, si besoin d'un rappel, voici un lien permettant d'y accéder :
Types d'analyses sécurité

A savoir :

  • Il existe plusieurs types d'analyses automatisées
    • SAST : Analyse statique du code
    • DAST : Analyse dynamique du code
    • IAST : Analyse interactive du code (dépendances)
  • Mais il existe aussi différent types d'analyses non automatisées, en passant par des audits externes ou des tests de pénétration à effectuer inter équipe.

Outil analyse sécurité

Pas de présentation particulière ici car nous l'avons déjà vu ensemble normalement.

Vous pouvez utiliser SonarCloud ou SonarQube par exemple pour réaliser une analyse en SAST de votre projet.

Si vous voulez aller plus loin (contexte entreprise), vous pouvez utiliser Checkmarx afin de réalisé les 3 types d'analyses automatisées, mais il faut savoir que ça a un coût non négligeable pour un projet quelque soit son envergure.

Les tests de maintenabilité

Les tests de maintenabilité, comme le nom le précise bien permettent d'évaluer la maintenabilité, l'évolutivité, la gestion des bugs et des dépendances d'un logiciel déjà mis en production.

A savoir :

  • Ce type de test est en partie automatisable mais pas complètement car c'est assez subjectif comme notion
  • Ces tests regroupent plusieurs aspects : 
    • Compréhensibilité / complexité du code
    • Détection des anomalies
    • Facilité d'évolution / modification du code
    • Documentation et gestion des dépendances

Outil de tests de maintenabilité

Nous avons déjà vu également les différents outils utilisables pour ce genre de tests.

 

Par exemple, l'analyse qualité proposée par SonarQube / SonarCloud correspond aux aspects automatisables.
De même pour la mise en place d'une intégration continue. Incluant donc la partie analyse syntaxique (Linting)

 

Cependant ils ne sont pas suffisant pour couvrir tous les aspects de la maintenabilité, il est nécessaire de compléter l'étude avec des actions manuels comme des audits prévus à cet effet

L'objectif de cet exercice est de vous faire avancer et vous aider à la mise en place d'une stratégie de tests pour votre projet de groupe
 

  • Démarrer et avancer au maximum sur le document de politique de tests concernant votre projet de groupe. Vous pouvez utiliser les grands titres présentés lors des deux premières slides de cette partie afin de savoir quoi intégrer dans ce document
     
  • Mettre en place les différents outils de tests pour les différents tests que vous comptez mettre en place pour votre projet.

Exercice

Evaluation

Partie pratique

BON COURAGE !

(après c'est fini)

Evaluation mise en place de tests unitaires

 

Je vais vous envoyer un fichier .md avec les règles.

Ainsi qu'un zip des éléments sur lesquels vous allez devoir créer les différents tests unitaires.

Tests & Recettes

By Cėdric Brasseur

Tests & Recettes

Formation sur les tests et recettes

  • 1,026