Procédure pas à pas : créer et exécuter des tests unitaires pour le code managéWalkthrough: Create and Run Unit Tests for Managed Code

Cette procédure pas à pas décrit la création, l’exécution et la personnalisation d’une série de tests unitaires à l’aide du framework de tests unitaires Microsoft pour le code managé et de l’explorateur de tests de Visual Studio.This walkthrough will step you through creating, running, and customizing a series of unit tests using the Microsoft unit test framework for managed code and the Visual Studio Test Explorer. Vous commencez avec un projet C# qui est en développement, vous créez des tests qui utilisent son code, vous exécutez les tests et vous examinez les résultats.You start with a C# project that is under development, create tests that exercise its code, run the tests, and examine the results. Ensuite, vous pouvez modifier le code de votre projet et réexécuter les tests.Then you can change your project code and re-run the tests.

Cette rubrique contient les sections suivantes :This topic contains the following sections:

Préparation de la procédure pas à pasPrepare the walkthrough

Créer un projet de test unitaireCreate a unit test project

Créer la classe de testCreate the test class

Note

Cette procédure pas à pas utilise le framework de tests unitaires Microsoft pour le code managé.This walkthrough uses the Microsoft unit test framework for managed code. L’explorateur de tests peut également exécuter des tests depuis des frameworks de tests unitaires tiers qui ont des adaptateurs pour l’explorateur de tests.Test Explorer also can run tests from third party unit test frameworks that have adapters for Test Explorer. Pour plus d’informations, consultez Installer des frameworks de tests unitaires tiersFor more information, see Install third-party unit test frameworks

Note

Pour plus d’informations sur la façon d’exécuter des tests à partir d’une ligne de commande, consultez Procédure pas à pas : utilisation de l’utilitaire de test de ligne de commande.For information about how to run tests from a command line, see Walkthrough: using the command-line test utility.

PrérequisPrerequisites

Préparer la procédure pas à pasPrepare the walkthrough

  1. Ouvrez Visual Studio.Open Visual Studio.

  2. Dans le menu Fichier , pointez sur Nouveau , puis cliquez sur Projet.On the File menu, point to New and then click Project.

    La boîte de dialogue Nouveau projet s’affiche.The New Project dialog box appears.

  3. Sous Modèles installés, cliquez sur Visual C#.Under Installed Templates, click Visual C#.

  4. Dans la liste de types d’applications, cliquez sur Bibliothèque de classes.In the list of application types, click Class Library.

  5. Dans la zone Nom , tapez Bank , puis cliquez sur OK.In the Name box, type Bank and then click OK.

    Note

    Si le nom « Bank » est déjà utilisé, choisissez un autre nom pour le projet.If the name "Bank" is already used, choose another name for the project.

    Le nouveau projet Bank est créé et affiché dans l’Explorateur de solutions, avec le fichier Class1.cs ouvert dans l’éditeur de code.The new Bank project is created and displayed in Solution Explorer with the Class1.cs file open in the Code Editor.

    Note

    Si le fichier Class1.cs n’est pas ouvert dans l’éditeur de code, double-cliquez sur ce fichier dans l’Explorateur de solutions pour l’ouvrir.If the Class1.cs file is not open in the Code Editor, double-click the file Class1.cs in Solution Explorer to open it.

  6. Copiez le code source de l’Exemple de projet pour la création de tests unitaires.Copy the source code from the Sample Project for Creating Unit Tests.

  7. Remplacez le contenu d’origine de Class1.cs par le code de l’Exemple de projet pour la création de tests unitaires.Replace the original contents of Class1.cs with the code from the Sample Project for Creating Unit Tests.

  8. Enregistrez le fichier avec le nom BankAccount.csSave the file as BankAccount.cs

  9. Dans le menu Générer , cliquez sur Générer la solution.On the Build menu, click Build Solution.

    Vous avez maintenant un projet nommé Bank.You now have a project named Bank. Il contient le code source à tester et des outils avec lesquels le tester.It contains source code to test and tools to test it with. L’espace de noms pour Bank, BankAccountNS, contient la classe publique BankAccount, dont vous testerez les méthodes dans les procédures suivantes.The namespace for Bank, BankAccountNS, contains the public class BankAccount, whose methods you will test in the following procedures.

    Dans ce démarrage rapide, nous nous concentrons sur la méthode Debit . Cette méthode est appelée quand de l’argent est retiré d’un compte et contient le code suivant :In this quick start, we focus on the Debit method.The Debit method is called when money is withdrawn an account and contains the following code:

// method under test
public void Debit(double amount)
{
    if(amount > m_balance)
    {
        throw new ArgumentOutOfRangeException("amount");
    }
    if (amount < 0)
    {
        throw new ArgumentOutOfRangeException("amount");
    }
    m_balance += amount;
}

Créer un projet de test unitaireCreate a unit test project

Condition préalable: suivez les étapes de la procédure Prepare the walkthrough.Prerequisite: Follow the steps in the procedure, Prepare the walkthrough.

Pour créer un projet de test unitaireTo create a unit test project

  1. Dans le menu Fichier , choisissez Ajouter, puis Nouveau projet....On the File menu, choose Add, and then choose New Project ....

  2. Dans la boîte de dialogue Nouveau Projet, développez Installé, développez Visual C#, puis choisissez Test.In the New Project dialog box, expand Installed, expand Visual C#, and then choose Test.

  3. Dans la liste des modèles, sélectionnez Projet de test unitaire.From the list of templates, select Unit Test Project.

  4. Dans la zone Nom , entrez BankTests, puis choisissez OK.In the Name box, enter BankTest, and then choose OK.

    Le projet BankTests est ajouté à la solution Bank .The BankTests project is added to the the Bank solution.

  5. Dans le projet BankTests , ajoutez une référence à la solution Bank .In the BankTests project, add a reference to the Bank solution.

    Dans l’Explorateur de solutions, sélectionnez Références dans le projet BankTests puis choisissez Ajouter une référence… dans le menu contextuel.In Solution Explorer, select References in the BankTests project and then choose Add Reference... from the context menu.

  6. Dans la boîte de dialogue Gestionnaire de références, développez Solution puis cochez l’élément Bank .In the Reference Manager dialog box, expand Solution and then check the Bank item.

Créer la classe de testCreate the test class

Nous avons besoin d’une classe de test pour vérifier la classe BankAccount .We need a test class for verifying the BankAccount class. Nous pouvons utiliser UnitTest1.cs qui a été généré par le modèle de projet, mais nous devons donner au fichier et à la classe des noms plus descriptifs.We can use the UnitTest1.cs that was generated by the project template, but we should give the file and class more descriptive names. Nous pouvons effectuer cela en une seule étape en renommant le fichier dans l’Explorateur de solutions.We can do that in one step by renaming the file in Solution Explorer.

Changement du nom d’un fichier de classeRenaming a class file

Dans l’Explorateur de solutions, sélectionnez le fichier UnitTest1.cs dans le projet BankTests.In Solution Explorer, select the UnitTest1.cs file in the BankTests project. Dans le menu contextuel, choisissez Renommer, puis renommez le fichier BankAccountTests.cs.From the context menu, choose Rename, and then rename the file to BankAccountTests.cs. Choisissez Oui dans la boîte de dialogue qui vous demande si vous souhaitez remplacer le nom de toutes les références du projet par « UnitTest1 ».Choose Yes on the dialog that asks if you want to rename all references in the project to the code element 'UnitTest1'. Cette opération a pour effet de remplacer le nom de la classe par BankAccountTest.This step changes the name of the class to BankAccountTest.

Le fichier BankAccountTests.cs contient maintenant le code suivant :The BankAccountTests.cs file now contains the following code:

// unit test code
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BankTests
{
    [TestClass]
    public class BankAccountTests
    {
        [TestMethod]
        public void TestMethod1()
        {
        }
    }
}

Ajouter une instruction using au projet testéAdd a using statement to the project under test

Nous pouvons également ajouter une instruction using à la classe pour nous permettre d’appeler le projet testé sans utiliser de noms qualifiés complets.We can also add a using statement to the class to let us to call into the project under test without using fully qualified names. En haut du fichier de classe, ajoutez :At the top of the class file, add:

using BankAccountNS;

Spécifications de la classe de testTest class requirements

La configuration minimale requise pour une classe de test est la suivante :The minimum requirements for a test class are the following:

  • L’attribut [TestClass] est requis dans le framework de tests unitaires Microsoft pour le code managé pour toute classe qui contient les méthodes de test unitaire à exécuter dans l’explorateur de tests.The [TestClass] attribute is required in the Microsoft unit testing framework for managed code for any class that contains unit test methods that you want to run in Test Explorer.

  • Chaque méthode de test à exécuter avec l’explorateur de tests doit avoir l’attribut [TestMethod].Each test method that you want Test Explorer to run must have the [TestMethod]attribute.

    Vous pouvez avoir d’autres classes dans un projet de test unitaire qui n’ont pas l’attribut [TestClass] , et vous pouvez avoir d’autres méthodes dans les classes de test qui n’ont pas l’attribut [TestMethod] .You can have other classes in a unit test project that do not have the [TestClass] attribute, and you can have other methods in test classes that do not have the [TestMethod] attribute. Vous pouvez utiliser ces autres classes et méthodes dans vos méthodes de test.You can use these other classes and methods in your test methods.

Créer la première méthode de testCreate the first test method

Dans cette procédure, nous écrirons des méthodes de test unitaire pour vérifier le comportement de la méthode Debit de la classe BankAccount .In this procedure, we will write unit test methods to verify the behavior of the Debit method of the BankAccount class. La méthode est répertoriée ci-dessus.The method is listed above.

En analysant la méthode testée, nous déterminons qu’il existe au moins trois comportements qui doivent être vérifiés :By analyzing the method under test, we determine that there are at least three behaviors that need to be checked:

  1. La méthode lève une exception ArgumentOutOfRangeException si le montant du débit est supérieur au solde.The method throws an ArgumentOutOfRangeException if the debit amount is greater than the balance.

  2. Elle lève également l’exception ArgumentOutOfRangeException si le montant du débit est inférieur à zéro.It also throws ArgumentOutOfRangeException if the debit amount is less than zero.

  3. Si les contrôles en 1.) et 2.) sont satisfaisants, la méthode soustrait le montant du solde du compte.If the checks in 1.) and 2.) are satisfied, the method subtracts the amount from the account balance.

    Dans notre premier test, nous vérifions qu’un montant valide (inférieur au solde du compte et supérieur à zéro) retire le montant approprié du compte.In our first test, we verify that a valid amount (one that is less than the account balance and that is greater than zero) withdraws the correct amount from the account.

Pour créer une méthode de testTo create a test method

  1. Ajoutez une instruction using BankAccountNS; au fichier BankAccountTests.cs.Add a using BankAccountNS; statement to the BankAccountTests.cs file.

  2. Ajoutez la méthode suivante à cette classe BankAccountTests :Add the following method to that BankAccountTests class:

    // unit test code
    [TestMethod]
    public void Debit_WithValidAmount_UpdatesBalance()
    {
        // arrange
        double beginningBalance = 11.99;
        double debitAmount = 4.55;
        double expected = 7.44;
        BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
    
        // act
        account.Debit(debitAmount);
    
        // assert
        double actual = account.Balance;
        Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
    }
    

    La méthode est plutôt simple.The method is rather simple. Nous mettons en place un nouvel objet BankAccount avec un solde de début, puis nous retirons un montant valide.We set up a new BankAccount object with a beginning balance and then withdraw a valid amount. Nous utilisons la méthode du framework de tests unitaires Microsoft pour le code managé AreEqual pour vérifier que le solde de fin correspond à ce que nous attendions.We use the Microsoft unit test framework for managed code AreEqual method to verify that the ending balance is what we expect.

Spécifications des méthodes de testTest method requirements

Une méthode de test doit répondre aux spécifications suivantes :A test method must meet the following requirements:

  • La méthode doit être décorée avec l’attribut [TestMethod] .The method must be decorated with the [TestMethod] attribute.

  • La méthode doit retourner void.The method must return void.

  • La méthode ne peut pas avoir de paramètres.The method cannot have parameters.

Générer et exécuter le testBuild and run the test

Pour générer et exécuter le testTo build and run the test

  1. Dans le menu Générer , choisissez Générer la solution.On the Build menu, choose Build Solution.

    En l’absence d’erreurs, la fenêtre UnitTestExplorer apparaît avec Debit_WithValidAmount_UpdatesBalance répertorié dans le groupe Tests non exécutés .If there are no errors, the UnitTestExplorer window appears with Debit_WithValidAmount_UpdatesBalance listed in the Not Run Tests group. Si l’explorateur de tests n’apparaît pas après une génération réussie, sélectionnez Test dans le menu, puis Fenêtres, puis Explorateur de tests.If Test Explorer does not appear after a successful build, choose Test on the menu, then choose Windows, and then choose Test Explorer.

  2. Sélectionnez Exécuter tout pour exécuter le test.Choose Run All to run the test. Pendant que le test s’exécute, la barre d’état en haut de la fenêtre s’anime.As the test is running the status bar at the top of the window is animated. À l’issue de la série de tests, la barre devient verte si toutes les méthodes de test ont réussi, ou rouge si l’un des tests a échoué.At the end of the test run, the bar turns green if all the test methods pass, or red if any of the tests fail.

  3. Dans ce cas, le test échoue.In this case, the test does fail. La méthode de test est déplacée vers le groupe Échecs de testsThe test method is moved to the Failed Tests. .group. Sélectionnez la méthode dans l’explorateur de tests pour en afficher les détails en bas de la fenêtre.Select the method in Test Explorer to view the details at the bottom of the window.

Vérifier votre code et exécuter à nouveau vos testsFix your code and rerun your tests

Analyser les résultats des testsAnalyze the test results

Le résultat de test contient un message qui décrit l’échec.The test result contains a message that describes the failure. Pour la méthode AreEquals, un message affiche ce qui était attendu (le paramètre Expected<XXX>) et ce qui a été reçu réellement (le paramètre Actual<YYY>).For the AreEquals method, message displays you what was expected (the (Expected<XXX>parameter) and what was actually received (the Actual<YYY> parameter). Nous nous attendions à ce que le solde décline par rapport au solde de début, mais il a plutôt augmenté du montant du retrait.We were expecting the balance to decline from the beginning balance, but instead it has increased by the amount of the withdrawal.

Un réexamen du code Debit indique que le test unitaire a réussi à trouver un bogue.A reexamination of the Debit code shows that the unit test has succeeded in finding a bug. Le montant du retrait est ajouté au solde du compte quand il doit être soustrait.The amount of the withdrawal is added to the account balance when it should be subtracted.

Corriger le bogueCorrect the bug

Pour corriger l’erreur, remplacez simplement la ligneTo correct the error, simply replace the line

m_balance += amount;

parwith

m_balance -= amount;

Réexécuter le testRerun the test

Dans l’explorateur de tests, choisissez Exécuter tout pour réexécuter le test.In Test Explorer, choose Run All to rerun the test. La barre rouge/verte devient verte, et le test est déplacé vers le groupe Tests réussis .The red/green bar turns green, and the test is moved to the Passed Tests group.

Utiliser les tests unitaires pour améliorer votre codeUse unit tests to improve your code

Cette section décrit comment un processus itératif d’analyse, de développement de test unitaire et de refactorisation peut vous aider à rendre votre code de production plus fiable et efficace.This section describes how an iterative process of analysis, unit test development, and refactoring can help you make your production code more robust and effective.

Analyser les problèmesAnalyze the issues

Après avoir créé une méthode de test pour vérifier qu’un montant valide est correctement déduit dans la méthode Debit , nous pouvons nous tourner vers les cas restants dans notre analyse d’origine :After creating a test method to confirm that a valid amount is correctly deducted in the Debit method, we can turn to remaining cases in our original analysis:

  1. La méthode lève une exception ArgumentOutOfRangeException si le montant du débit est supérieur au solde.The method throws an ArgumentOutOfRangeException if the debit amount is greater than the balance.

  2. Elle lève également l’exception ArgumentOutOfRangeException si le montant du débit est inférieur à zéro.It also throws ArgumentOutOfRangeException if the debit amount is less than zero.

    Créer les méthodes de testCreate the test methods

    Une première tentative de création d’une méthode de test pour résoudre ces problèmes semble prometteuse :A first attempt at creating a test method to address these issues seems promising:

//unit test method
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = -100.00;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // act
    account.Debit(debitAmount);

    // assert is handled by ExpectedException
}

Nous utilisons l’attribut ExpectedExceptionAttribute pour déclarer que la bonne exception a été levée.We use the ExpectedExceptionAttribute attribute to assert that the right exception has been thrown. L’attribut entraîne l’échec du test à moins qu’une exception ArgumentOutOfRangeException ne soit levée.The attribute causes the test to fail unless an ArgumentOutOfRangeException is thrown. L’exécution du test avec à la fois les valeurs debitAmount positives et négatives puis en modifiant temporairement la méthode testée pour lever une exception ApplicationException générique quand le montant est inférieur à zéro indique que le test se comporte correctement.Running the test with both positive and negative debitAmount values and then temporarily modifying the method under test to throw a generic ApplicationException when the amount is less than zero demonstrates that test behaves correctly. Pour tester le cas où le montant retiré est supérieur au solde, il suffit d’effectuer les opérations suivantes :To test the case when the amount withdrawn is greater than the balance, all we need to do is:

  1. Créez une méthode de test nommée Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.Create a new test method named Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.

  2. Copiez le corps de la méthode depuis Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange vers la nouvelle méthode.Copy the method body from Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange to the new method.

  3. Définissez debitAmount sur un nombre supérieur au solde.Set the debitAmount to a number greater than the balance.

    Exécuter les testsRun the tests

    L’exécution des deux méthodes avec des valeurs différentes pour debitAmount montre que les tests gèrent correctement nos cas restants.Running the two methods with different values for debitAmount demonstrates that the tests adequately handle our remaining cases. L’exécution des trois tests confirme que tous les cas présents dans notre analyse d’origine sont traités correctement.Running all three tests confirm that all cases in our original analysis are correctly covered.

    Poursuivre l’analyseContinue the analysis

    Toutefois, les deux dernières méthodes de test sont également quelque peu troublantes.However, the last two test methods are also somewhat troubling. Nous ne pouvons pas être certains de la condition du code qui lève une exception quand l’un ou l’autre des tests est exécuté.We cannot be certain which condition in the code under test throws when either test runs. Un moyen de faire la différence entre les deux conditions serait utile.Some way of differentiating the two conditions would be helpful. Quand nous réfléchissons au problème, il devient clair que l’identification de la condition qui n’a pas été respectée augmenterait notre confiance dans les tests.As we think about the problem more, it becomes apparent that knowing which condition was violated would increase our confidence in the tests. Ces informations seraient également très probablement utiles pour le mécanisme de production qui gère l’exception quand elle est levée par la méthode testée.This information would also very likely be helpful to the production mechanism that handles the exception when it is thrown by the method under test. La génération d’informations supplémentaires quand la méthode lève une exception aiderait tous les éléments concernés, mais l’attribut ExpectedException ne peut pas fournir ces informations.Generating more information when the method throws would assist all concerned, but the ExpectedException attribute cannot supply this information..

    En examinant encore la méthode testée, nous constatons que les deux instructions conditionnelles utilisent un constructeur ArgumentOutOfRangeException qui accepte le nom de l’argument comme paramètre :Looking at the method under test again, we see both conditional statements use an ArgumentOutOfRangeException constructor that takes name of the argument as a parameter:

throw new ArgumentOutOfRangeException("amount");

En effectuant des recherches dans MSDN Library, nous découvrons qu’il existe un constructeur qui génère des informations bien plus élaborées.From a search of the MSDN Library, we discover that a constructor exists that reports far richer information. ArgumentOutOfRangeException(String, Object, String) inclut le nom de l’argument, la valeur de l’argument et un message défini par l’utilisateur.ArgumentOutOfRangeException(String, Object, String) includes the name of the argument, the argument value, and a user-defined message. Nous pouvons refactoriser la méthode testée pour utiliser ce constructeur.We can refactor the method under test to use this constructor. Encore mieux, nous pouvons utiliser les membres de type disponibles publiquement pour spécifier les erreurs.Even better, we can use publicly available type members to specify the errors.

Refactoriser le code testéRefactor the code under test

Nous définissons d’abord deux constantes pour les messages d’erreur au niveau de la portée d’une classe :We first define two constants for the error messages at class scope:

// class under test
public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount less than zero";

Nous modifions ensuite les deux instructions conditionnelles dans la méthode Debit :We then modify the two conditional statements in the Debit method:

// method under test
// ...
    if (amount > m_balance)
    {
        throw new ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
    }

    if (amount < 0)
    {
        throw new ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
    }
// ...

Refactoriser les méthodes de testRefactor the test methods

Dans notre méthode de test, nous commençons par supprimer l’attribut ExpectedException .In our test method, we first remove the ExpectedException attribute. À sa place, nous interceptons l’exception levée et vérifions qu’elle a été levée dans l’instruction de condition appropriée.In its place, we catch the thrown exception and verify that it was thrown in the correct condition statement. Toutefois, nous devons maintenant choisir entre deux options pour vérifier nos conditions restantes.However, we must now decide between two options to verify our remaining conditions. Par exemple, dans la méthode Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange , nous pouvons effectuer l’une des actions suivantes :For example in the Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange method, we can take one of the following actions:

  • Déclarer que la propriété ActualValue de l’exception (le deuxième paramètre du constructeur ArgumentOutOfRangeException ) est supérieure au solde de début.Assert that the ActualValue property of the exception (the second parameter of the ArgumentOutOfRangeException constructor) is greater than the beginning balance. Cette option nécessite de tester la propriété ActualValue de l’exception par rapport à la variable beginningBalance de la méthode de test, mais aussi de vérifier que la propriété ActualValue est supérieure à zéro.This option requires that we test the ActualValue property of the exception against the beginningBalance variable of the test method, and also requires then verify that the ActualValue is greater than zero.

  • Déclarer que le message (le troisième paramètre du constructeur) inclut le DebitAmountExceedsBalanceMessage défini dans la classe BankAccount .Assert that the message (the third parameter of the constructor) includes the DebitAmountExceedsBalanceMessage defined in the BankAccount class.

    La méthode StringAssert.Contains dans le framework de tests unitaires Microsoft nous permet de vérifier la deuxième option sans les calculs requis par la première option.The StringAssert.Contains method in the Microsoft unit test framework enables us to verify the second option without the calculations that are required of the first option.

    Une deuxième tentative de révision de Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange pourrait ressembler à :A second attempt at revising Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange might look like:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // act
    try
    {
        account.Debit(debitAmount);
    }
    catch (ArgumentOutOfRangeException e)
    {
        // assert
        StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
    }
}

Retester, réécrire et réanalyserRetest, rewrite, and reanalyze

Lorsque nous retestons les méthodes de test avec des valeurs différentes, nous obtenons les informations suivantes :When we retest the test methods with different values, we encounter the following facts:

  1. Si nous interceptons l’erreur correcte à l’aide d’une assertion où debitAmount est supérieur au solde, l’assertion Contains passe, l’exception est ignorée et la méthode de test passe alors.If we catch the correct error by using an assert where debitAmount that is greater than the balance, the Contains assert passes, the exception is ignored, and so the test method passes. Il s’agit du comportement que nous souhaitons.This is the behavior we want.

  2. Si nous utilisons un debitAmount inférieur à 0, l’assertion échoue, car un message d’erreur inapproprié est retourné.If we use a debitAmount that is less than 0, the assert fails because the wrong error message is returned. L’assertion échoue également si nous introduisons une exception ArgumentOutOfRange temporaire à un autre point dans le chemin de code de la méthode testée.The assert also fails if we introduce a temporary ArgumentOutOfRange exception at another point in the method under test code path. Cela aussi est approprié.This too is good.

  3. Si la valeur de debitAmount est valide (autrement dit, inférieure au solde mais supérieure à zéro), aucune exception n’est interceptée et l’assertion n’est donc jamais interceptée.If the debitAmount value is valid (i.e., less than the balance but greater than zero, no exception is caught, so the assert is never caught. La méthode de test réussit.The test method passes. Cela ne convient pas, car nous souhaitons que la méthode de test échoue si aucune exception n’est levée.This is not good, because we want the test method to fail if no exception is thrown.

    Le troisième fait est un bogue dans notre méthode de test.The third fact is a bug in our test method. Pour essayer de résoudre le problème, nous ajoutons une assertion Fail à la fin de la méthode de test pour gérer le cas où aucune exception n’est levée.To attempt to resolve the issue, we add a Fail assert at the end of the test method to handle the case where no exception is thrown.

    Cependant, un nouveau test montre que le test échoue maintenant si l’exception correcte est interceptée.But retesting shows that the test now fails if the correct exception is caught. L’instruction catch réinitialise l’exception et la méthode continue à s’exécuter. Elle échoue sur la nouvelle assertion.The catch statement resets the exception and the method continues to execute, failing at the new assert. Pour résoudre le nouveau problème, nous ajoutons une instruction return après StringAssert.To resolve the new problem, we add a return statement after the StringAssert. Le nouveau test confirme que nous avons résolu nos problèmes.Retesting confirms that we have fixed our problems. Notre version finale de Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange ressemble à ce qui suit :Our final version of the Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange looks like the following:

[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
    // arrange
    double beginningBalance = 11.99;
    double debitAmount = 20.0;
    BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);

    // act
    try
    {
        account.Debit(debitAmount);
    }
    catch (ArgumentOutOfRangeException e)
    {
        // assert
        StringAssert.Contains(e.Message, BankAccount. DebitAmountExceedsBalanceMessage);
        return;
    }
    Assert.Fail("No exception was thrown.");
}

Dans cette section finale, le travail que nous avons fait en améliorant notre code de test a conduit à des méthodes de test plus fiables et plus instructives.In this final section, the work that we did improving our test code led to more robust and informative test methods. Plus important encore, l’analyse supplémentaire a également abouti à une amélioration du code dans notre projet testé.But more importantly, the extra analysis also led to better code in our project under test.