Bases de test unitaire
Cette rubrique décrit les notions de base relatives à l'écriture et le test unitaire en cours de exécution dans l'explorateur de tests de Visual Studio.Elle contient les sections suivantes :
Unit testing overview
- Quick starts
The MyBank Solution example
Creating the unit test projects
Writing your tests
Running tests in Test Explorer
Running and viewing tests from the Test Explorer toolbar
Running tests after every build
Filtering and grouping the test list
Debugging unit tests
Additional tools for unit tests
Generating application code from tests
Generating multiple tests by using data driven test methods
Analyzing unit test code coverage
Isolating unit test methods with Microsoft Fakes
Présentation de test unitaire
Le nouvel explorateur de tests de Visual Studio est conçu pour aider les développeurs et les équipes qui incorporent les tests unitaires dans leurs méthodes de développement logiciel.Les tests unitaires vous aident à vérifier l'exactitude de votre programme en vérifiant que le code de votre application fait ce que vous attendez qu'il fasse.Dans le test unitaire, vous analysez la fonctionnalité de votre programme pour découvrir les comportements discrets testables que vous pouvez tester comme des unités.Vous utilisez une infrastructure de test unitaire pour créer des tests de ces comportements et enregistrer les résultats de ces tests.
Le test unitaire a le plus grand effet lorsqu'il fait partie intégrante de votre flux de travail de développement de logiciel.Dès que vous écrirez une fonction ou un autre bloc de code d'application, vous créez des tests unitaires qui vérifient le comportement du code en réponse à niveau, à la limite, et aux cas non valides de données d'entrée, et qui vérifient les hypothèses explicites ou implicites effectuées par le code.Dans une pratique en matière de développement de logiciels appelé le développement piloté par test, vous créez des tests unitaires avant d'écrire le code, vous utilisez les tests unitaires comme la documentation de conception et caractéristiques fonctionnelles de la fonctionnalité.
L'explorateur de tests fournit une méthode flexible et efficace pour exécuter vos tests unitaires et afficher leurs résultats dans Visual Studio.Visual Studio installe les infrastructures de test unitaire Microsoft pour le code managé et du code natif.L'explorateur de tests peut également exécuter la partie tierce et ouvrir les infrastructures de test unitaire de source qui ont l'implémentation des interfaces de complément explorateur de tests.Vous pouvez ajouter plusieurs de ces infrastructures dans le gestionnaire d'extensions Visual Studio et la galerie Visual Studio.Consultez Comment : installer des infrastructures de tests unitaires tiers.
Les vues de l'explorateur de tests peuvent afficher tous vos tests, ou uniquement les tests qui ont réussi, a échoué, n'ont pas encore été exécutés, ou ont été ignorés.Vous pouvez filtrer les tests dans un affichage en correspondant au texte dans la zone de recherche au niveau global ou en sélectionnant l'un des filtres intégrés.Vous pouvez exécuter toute sélection de tests à tout moment.Lorsque vous utilisez Visual Studio Ultimate, vous pouvez exécuter des tests automatiquement après chaque build.Les résultats d'une série de tests sont immédiatement évidents dans la barre réussite/échec en haut de la fenêtre explorateur.Les détails d'un résultat de méthode de test s'affichent lorsque vous sélectionnez le test.
Démarrage rapide
Pour une introduction au test unitaire qui vous guide directement dans l'encodage, consultez l'une de ces rubriques :
l'exemple de solution de MyBank
Dans cette rubrique, nous utilisons le développement d'une application fictive appelée MyBank comme exemple.Vous n'avez pas besoin du code réel pour suivre les explications dans cette rubrique.Les méthodes de test sont écrites en C# et présenté à l'aide de l'infrastructure de test unitaire Microsoft pour le code managé, toutefois, les concepts sont transférées facilement à d'autres langages et infrastructures.
Notre premier test à une conception pour l'application d' MyBank inclut un composant de comptes qui représente un compte individuel et ses transactions avec la banque, et un composant de base de données qui représente la fonctionnalité pour regrouper et gérer des comptes.
Créons une solution MyBank qui contient 2 projets:
Accounts
BankDb
Notre premier test à concevoir le projet d' Accounts contiennent une classe pour stocker des données de base concernant un compte, d'une interface qui spécifie les fonctionnalités communes de tout type de compte, comme déposer et supprimer des ressources du compte, et d'une classe dérivée de l'interface qui représente un compte actuel.Nous commençons les projets de comptes en créant des fichiers sources suivantes :
AccountInfo.cs définit les données de base d'un compte.
IAccount.cs définit une interface standard d' IAccountpour un compte, notamment des méthodes pour déposer et supprimer des ressources d'un compte et pour récupérer le solde de compte.
CheckingAccount.cs contient la classe d' CheckingAccount qui implémente l'interface d' IAccounts pour un compte actuel.
Nous savons par expérience d'une manière qu'un retrait d'un compte actuel doit faire est de s'assurer que la quantité retirée est moins que le solde de compte.Pour que nous substituons la méthode d' IAccount.Withdaw dans CheckingAccount avec une méthode qui vérifie cette condition.La méthode peut se présenter de la manière suivante :
public void Withdraw(double amount)
{
if(m_balance >= amount)
{
m_balance -= amount;
}
else
{
throw new ArgumentException(amount, "Withdrawal exceeds balance!")
}
}
Maintenant que nous avons du code, il est temps pour tester.
Création d'un projet de test unitaire
Un projet de test unitaire indique généralement la structure d'un projet de code unique.Dans l'exemple de MyBank, vous ajoutez des projets de test à deux unités nommés AccountsTests et BankDbTests à la solution d' MyBanks .Les noms de projet de test sont arbitraires, mais l'adoption d'une convention d'affectation de noms standard est recommandé.
Pour ajouter un nouveau projet de test unitaire à une solution
Dans le menu Fichier , choisissez Nouveau puis choisissez Projet (clavier CTRL + décalage + N).
Dans la boîte de dialogue nouveau projet, développez le nœud Installé , sélectionnez le langage que vous souhaitez utiliser pour votre projet de test, puis choisissez Test.
Pour utiliser l'une des infrastructures de test unitaire Microsoft, choisissez projet de test unitaire de la liste des modèles de projet.Sinon, choisissez le modèle de projet de l'infrastructure de test unitaire que vous souhaitez utiliser.Pour tester le projet Accounts de notre exemple, vous nommeriez le projet AccountsTests.
Attention Toutes les infrastructures tiers et ouvertes de test unitaire de source fournissent un modèle de projet Visual Studio.Consultez le document d'infrastructure pour plus d'informations sur la création d'un projet.
Dans votre projet de test unitaire, ajoutez une référence au projet de code sous test, dans notre exemple aux comptes projet.
Pour créer la référence au projet de code :
Sélectionnez le projet dans l'Explorateur de solutions.
Dans le menu Projet, sélectionnez Ajouter une référence.
Dans la boîte de dialogue gestionnaire de référence, ouvrez le nœud Solution et choisissez Projets.Vérifiez le nom du projet de code et fermez la boîte de dialogue.
Chaque projet de test unitaire contient des classes qui reflètent les noms des classes dans le projet de code.Dans notre exemple, le projet d' AccountsTests contiendrait les classes suivantes :
La classe d' AccountInfoTests contient les méthodes de test unitaire pour la classe d' AccountInfo dans le projet d' BankAccount.
La classe d'CheckingAccountTests contient les méthodes de test unitaire pour la classe d' CheckingAccount .
Écrire vos tests
L'infrastructure de test unitaire que vous utilisez et Visual Studio Intellisense vous guiderez en créant des tests unitaires pour un projet de code.Pour s'exécuter dans l'explorateur de tests, la plupart des infrastructures requièrent que vous ajoutez des attributs spécifiques pour identifier des méthodes de test unitaire.Les infrastructures offrent également un moyen - habituel par les instructions d'assertion ou la méthode attribut- à indiquent si la méthode de test est réussi ou échoué.D'autres attributs identifient des méthodes facultatives d'installation qui sont à l'initialisation de la classe et avant chaque méthode de test et méthodes de démontage exécutées après chaque méthode de test et avant que la classe est perdue.
Le modèle aaa de. (réorganisez, agissez, assertion) est une méthode courante des tests unitaires en écriture pour une méthode à tester.
La section de Réorganiser d'une méthode de test unitaire initialise des objets et définit la valeur des données passées à la méthode à tester.
La section de effet appelle la méthode à tester avec les paramètres réorganisés.
La section de Assertion vérifie que l'action de la méthode testée se comporte comme prévu.
Pour tester la méthode d' CheckingAccount.Withdraw de notre exemple, nous pouvons écrire deux tests : il qui vérifie le comportement standard de la méthode, et il qui vérifie qu'un retrait de plus que l'équilibre échouera.Ajoutez les méthodes suivantes à la classe CheckingAccountTests.
[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
// arrange
double currentBalance = 10.0;
double withdrawal = 1.0;
double expected = 9.0;
var account = new CheckingAccount("JohnDoe", currentBalance);
// act
account.Withdraw(withdrawal);
double actual = account.Balance;
// assert
Assert.AreEqual(expected, actual);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Withdraw_AmountMoreThanBalance_Throws()
{
// arrange
var account = new CheckingAccount("John Doe", 10.0);
// act
account.Withdraw(1.0);
// assert is handled by the ExcpectedException
}
Notez qu' Withdraw_ValidAmount_ChangesBalance utilise une instruction explicite d' Assert pour déterminer si la méthode de test réussit ou échoue, tandis que Withdraw_AmountMoreThanBalance_Throws utilise l'attribut d' ExpectedException pour déterminer la réussite de la méthode de test.Sous les décrit, une infrastructure de test unitaire encapsule les méthodes de test dans le test/instructions catch.Dans la plupart des cas, si une exception est interceptée, de échec de méthode de test et est ignoré.l'attribut d' ExpectedException fait passer la méthode de test si l'exception spécifiée est levée.
Pour plus d'informations sur les infrastructures de test unitaire Microsoft, consultez l'une des rubriques suivantes :
Exécution de tests dans l'explorateur de tests
Lorsque vous générez le projet de test, les tests s'affichent dans l'explorateur de tests.Si l'explorateur de tests n'est pas visible, sélectionnez Test dans le menu, choisissez Fenêtres, puis choisissez explorateur de tests.
Lorsque vous exécutez, entrez, puis réexécutez les tests, affiche dans l'explorateur de tests les résultats aux groupes par défaut Échec des tests, Tests réussis, Tests ignorés et Pas exécuter des tests.Vous pouvez choisir un en-tête de groupe pour ouvrir la vue qui affiche tous elles des tests à ce groupe.
Tests exécutants et de visionnements de la barre d'outils de l'explorateur de tests
La barre d'outils de l'explorateur de tests vous aide à détecter, planifier, et exécuter les tests que vous intéresse.
Vous pouvez choisir Exécuter tout pour exécuter tous les tests, ou choisissez Exécutez… pour sélectionner un sous-ensemble de tests à exécuter.Après avoir exécuté un ensemble de tests, un résumé de la série de tests s'affiche en bas de la fenêtre explorateur de tests.Sélectionnez un test pour afficher les détails de ce test dans le volet inférieur.Choisissez Ouvrir un test du menu contextuel (clavier : F12) pour afficher le code source du test sélectionné.
Exécution de tests après chaque build
Attention |
---|
Les tests unitaires en cours de exécution après chaque build est pris en charge uniquement dans Visual Studio final. |
Pour exécuter vos tests unitaires après chaque build locale, choisissez Test dans le menu standard, choisissez Exécuter des tests après génération dans la barre d'outils de l'explorateur de tests. |
Filtrage et regroupant la liste de tests
Lorsque vous avez un grand nombre de tests, vous pouvez entrer la zone de recherche de l'explorateur de tests pour filtrer la liste par la chaîne spécifiée.Vous pouvez limiter votre événement de filtrage supplémentaire en sélectionnant dans la liste de filtres.
Pour regrouper vos tests par catégorie, sélectionnez le bouton Grouper par . |
Pour plus d'informations, consultez Exécution de tests unitaires avec Test Explorer.
Tests unitaires de débogage
Vous pouvez utiliser l'explorateur de tests pour démarrer une session de débogage de vos tests.L'exécution pas - à - pas votre code avec le débogueur Visual Studio vous guide de façon transparente dans les deux sens entre les tests unitaires et le projet de test.Pour démarrer le débogage
Dans l'éditeur Visual Studio, définissez un point d'arrêt dans une ou plusieurs méthodes de test que vous souhaitez déboguer.
[!REMARQUE]
Étant donné que les méthodes de test peuvent s'exécuter dans n'importe quel ordre, définissez des points d'arrêt dans toutes les méthodes de test que vous souhaitez déboguer.
Dans l'explorateur de tests, sélectionnez les méthodes de test puis choisissez Déboguer les tests sélectionnés dans le menu contextuel.
Pour plus d'informations sur le debuggeur, consultez Débogage dans Visual Studio.
Outils supplémentaires pour les tests unitaires
Générer le code d'application des tests
Si vous écrivez vos tests avant d'écrire votre code de projet, vous pouvez utiliser Intellisense pour générer des classes et des méthodes dans votre code de projet.Écrivez une instruction dans une méthode de test qui appelle la classe ou la méthode que vous souhaitez générer, puis ouvre le menu Intellisense dans l'appel.Si l'appel est à un constructeur de la classe, choisissez Générer un nouveau type le menu et suivez l'assistant pour insérer la classe dans votre projet de code.Si l'appel est une méthode, choisissez générez la nouvelle méthode du menu Intellisense.
Générer plusieurs tests à l'aide de les méthodes de test pilotées par des données
[!REMARQUE]
Ces procédures s'appliquent uniquement aux méthodes de test que vous écrivez à l'aide de l'infrastructure de test unitaire Microsoft pour le code managé.Si vous utilisez une version différente, consultez la documentation d'infrastructure pour la fonctionnalité équivalente.
Les méthodes de test pilotées par des données vous permettent de vérifier une plage de valeurs dans une seule méthode de test unitaire.Pour créer une méthode de test unitaire piloté par des données, décorer avec la méthode avec un attribut d' DataSource qui spécifie la source de données et la table qui contient les valeurs de la variable que vous souhaitez tester.Dans le corps de la méthode, vous assignez des valeurs de ligne à des variables à l'indexeur d' TestContext.DataRow[ColumnName] .
Par exemple, supposons que nous ajoutons une méthode inutile à la classe d' CheckingAccount nommée AddIntegerHelper.AddIntegerHelper ajoute deux entiers.
Pour créer un test piloté par des données de la méthode d' AddIntegerHelper , nous créons d'abord une base de données Access nommée AccountsTest.accdb et une table nommée AddIntegerHelperData.Le tableau d' AddIntegerHelperData définit des colonnes pour spécifier la première et les seconds opérandes de l'addition et d'une colonne pour spécifier le résultat attendu.Nous remplissons un certain nombre de lignes de valeurs appropriées.
[DataSource(
@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\MyBank\TestData\AccountsTest.accdb",
"AddIntegerHelperData"
)]
[TestMethod()]
public void AddIntegerHelper_DataDrivenValues_AllShouldPass()
{
var target = new CheckingAccount();
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.AddIntegerHelper(x, y);
Assert.AreEqual(expected, actual);
}
La méthode avec attributs s'exécute une fois pour chaque ligne de la table.L'explorateur de tests signale un échec de test pour la méthode si les itérations l'une des échouent.Le volet des détails de résultats pour la méthode indique la méthode de mode de exécution/échouer pour chaque ligne de données.
Pour plus d'informations, consultez Comment : créer un test unitaire piloté par des données.
Couverture du code d'analyse de test unitaire
[!REMARQUE]
La couverture du code de test unitaire est disponible pour le code natif et les langages managés et toutes les infrastructures de test unitaire qui peuvent être exécutés par l'infrastructure de test unitaire.
Vous pouvez déterminer la proportion de votre code du produit testé réellement par vos tests unitaires à l'aide de l'outil de couverture du code Visual Studio.Vous pouvez exécuter la couverture du code sur les tests sélectionnés ou sur tous les tests d'une solution.Résultats de la couverture du code de la fenêtre affiche le pourcentage des blocs de code du produit ayant fait la ligne, la fonction, la classe, l'espace de noms et le module.
Pour exécuter la couverture du code pour les méthodes de test dans une solution :
Choisissez Tests dans le menu de Visual Studio puis choisissez analysez la couverture du code.
Choisissez l'une des options suivantes :
Tests sélectionnés exécute les méthodes de test que vous avez sélectionnées dans l'explorateur de tests.
Tous les tests exécute toutes les méthodes de test dans la solution.
Les résultats de couverture s'affichent dans la fenêtre résultats de la couverture du code.
Pour plus d’informations, consultez Utilisation de la couverture du code pour déterminer la quantité de code testé.
Isolation des méthodes de test unitaire avec Microsoft Fakes
[!REMARQUE]
Les false Microsoft est uniquement disponible dans Visual Studio final.Des faux Microsoft peuvent être utilisés uniquement avec les méthodes de test que vous écrivez en utilisant des infrastructures de test unitaire pour le code managé.
Le problème
Les méthodes de test unitaire qui se concentrent sur vérifier le code interne dans une fonction peut être difficile d'écrire lorsque la méthode sous les fonctions d'appels de test qui présentent des dépendances externes.Par exemple, les méthodes de classe de l'exemple d' CheckingAccount doivent être éventuellement des appels au composant d' BankDb pour mettre à jour la base de données principale.Nous pouvons refactoriser la classe d' CheckingAccount pour se présenter comme suit :
class CheckingAccount : IAccount
{
public CheckingAccount(customerName, double startingBalance, IBankDb bankDb)
{
m_bankDb = bankDb;
// set up account
}
public void Withdraw(double amount)
{
if(m_balance >= amount)
{
m_balance = m_MyBankDb.Withdraw(m_accountInfo.ID, amount);
}
else
{
throw new ArgumentException(amount, "Withdrawal exceeds balance!")
}
}
private IBankDb m_bankDb = null;
// ...
Les tests unitaires de cette méthode d' CheckingAccount.Withdraw peuvent maintenant échouer en raison de les problèmes provoquées par l'appel à m_bankDb.Withdraw.La base de données ou la connexion réseau peut être perdue ou des autorisations sur la base de données peuvent être erronées.Un échec de l'appel d' m_bankDB.Withdraw ferait échouer test pour les raisons qui ne sont pas liés à son code interne.
La solution de faux Microsoft
Les false Microsoft crée un assembly contenant les classes et les méthodes que vous pouvez substituer pour les classes dans les méthodes de test unitaire qui provoquent des dépendances.Une classe de remplacement dans le module généré de faux déclare une méthode et un délégué pour chaque méthode publique dans le composant cible.Dans une méthode de test, vous implémentez le délégué pour créer le comportement exact de l'appel de dépendance dans la méthode à tester.
Dans notre exemple, nous pouvons créer un assembly de valeur false pour le projet d' BankDb , puis utilisons la classe d' StubIBankDb générée par des faux et qui dérive de l'interface d' IBankDb pour supprimer l'incertitude provoquée par les interactions avec la base de données.Une version modifed de la méthode de test d' Withdraw_ValidAmount_ChangesBalance ensuite ressemblerait à ceci :
[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
// arrange
double currentBalance = 10.0;
double withdrawal = 1.0;
double expected = 9.0;
// set up the Fakes object and delegate
var stubBankDb = new MyBank.Stubs.StubIBankDb();
stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
var account = new CheckingAccount("JohnDoe", currentBalance, stubBankDb);
// act
account.Withdraw(withdrawal);
double actual = account.Balance;
// assert
Assert.AreEqual(expected, actual);
}
Cette ligne dans la méthode de test :
stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
implémente le délégué de valeur false pour la méthode d' Withdraw à l'aide d'une expression de lamba.Les appels de méthode d' stubBankDb.Withdraw le délégué et retourne donc toujours la valeur spécifiée, qui permet à la méthode de test pour vérifier de manière fiable le comportement de la méthode d' Accounts .
Plus sur des faux Microsoft
Microsoft truque utilise deux approches à créer des classes de remplacement :
Les stubs génèrent les classes dérivées de remplacement de l'interface parente de la classe de dépendance cible.Les méthodes stub peuvent être substituées pour les méthodes virtuelles publiques de classe cible.
Instrumentation d'exécution d'utilisationde cales de détourner les appels à une méthode cible à une méthode de remplacement du shim pour les méthodes non virtuelles.
Dans les deux approches, vous utilisez les délégués générés des appels à la méthode de dépendance pour spécifier le comportement souhaité dans la méthode de test.
Pour plus d’informations, consultez Isolation du code sous test avec Microsoft Fakes.