Créer un test unitaire piloté par les données
Vous pouvez utiliser l’infrastructure de test unitaire de Microsoft (MSTest) pour le code managé afin de configurer une méthode de test unitaire permettant de récupérer des valeurs auprès d’une source de données. La méthode est exécutée successivement pour chaque ligne de la source de données, ce qui permet de tester facilement diverses entrées à l’aide d’une seule méthode.
Un test unitaire piloté par les données peut utiliser l’un des types suivants :
- données inline à l’aide de l’attribut
DataRow
- données membres à l’aide de l’attribut
DynamicData
- à partir d’un fournisseur de source connu à l’aide de l’attribut
DataSource
Méthode testée
Par exemple, vous avez :
Une solution appelée
MyBank
, qui accepte et traite les transactions de différents types de compte.Un projet dans
MyBank
, appeléBankDb
, qui gère les transactions des comptes.Une classe appelée
Maths
dans le projetBankDb
, qui remplit les fonctions mathématiques permettant de vérifier que les transactions sont avantageuses pour la banque.Un projet de test unitaire appelé
BankDbTests
pour tester le comportement du composantBankDb
.Une classe de test unitaire appelée
MathsTests
pour vérifier le comportement de la classeMaths
.
Nous allons tester une méthode dans Maths
qui additionne deux entiers en utilisant boucle :
public int AddIntegers(int first, int second)
{
int sum = first;
for (int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
Tester la méthode de test
Test piloté par les données inline
Pour les tests inline, MSTest utilise DataRow
pour spécifier les valeurs utilisées par le test piloté par les données. Le test de cet exemple s’exécute successivement pour chaque ligne de données.
[TestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
[DataRow(0, 0, 1)] // The test run with this row fails
public void AddIntegers_FromDataRowTest(int x, int y, int expected)
{
var target = new Maths();
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Test piloté par les données des membres
MSTest utilise l’attribut DynamicData
pour spécifier le nom, le type (propriété, valeur par défaut ou méthode) et le type de définition (le type actuel est utilisé par défaut) du membre qui fournit les données utilisées par le test piloté par les données.
public static IEnumerable<object[]> AdditionData
{
get
{
return new[]
{
new object[] { 1, 1, 2 },
new object[] { 2, 2, 4 },
new object[] { 3, 3, 6 },
new object[] { 0, 0, 1 }, // The test run with this row fails
};
}
}
[TestMethod]
[DynamicData(nameof(AdditionData))]
public void AddIntegers_FromDynamicDataTest(int x, int y, int expected)
{
var target = new Maths();
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Il est également possible d’écraser le nom d’affichage généré par défaut à l’aide de la propriété DynamicDataDisplayName
de l’attribut DynamicData
. La signature de la méthode de nom d’affichage doit être public static string
et accepter deux paramètres, le premier de type MethodInfo
et le second de type object[]
.
public static string GetCustomDynamicDataDisplayName(MethodInfo methodInfo, object[] data)
{
return string.Format("DynamicDataTestMethod {0} with {1} parameters", methodInfo.Name, data.Length);
}
[DynamicData(nameof(AdditionData), DynamicDataDisplayName = nameof(GetCustomDynamicDataDisplayName))]
Test piloté par les données du fournisseur de source
La création d’un test unitaire piloté par les sources de données comprend les étapes suivantes :
Créez une source de données qui contient les valeurs que vous utilisez dans la méthode de test. La source de données peut correspondre à n’importe quel type inscrit sur la machine qui exécute le test.
Ajoutez une propriété
TestContext
publique de type TestContext à la classe de test.Créer une méthode de test unitaire
Ajoutez-y un attribut DataSourceAttribute.
Utilisez la propriété d’indexeur DataRow pour récupérer les valeurs que vous utilisez dans un test.
Création d'une source de données
Pour tester la méthode AddIntegers
, créez une source de données qui spécifie une plage de valeurs pour les paramètres et la somme à retourner. Dans cet exemple, nous allons créer une base de données SQL Compact nommée MathsData
et une table nommée AddIntegersData
, qui contient les noms et valeurs de colonnes suivants
FirstNumber | SecondNumber | SUM |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Ajouter un objet TestContext à la classe de test
Le framework de tests unitaires crée un objet TestContext
pour stocker les informations de source de données d’un test piloté par les données. Le framework définit ensuite cet objet en tant que valeur de la propriété TestContext
que vous créez.
public TestContext TestContext { get; set; }
Dans votre méthode de test, vous accédez aux données via la propriété d’indexeur DataRow
de TestContext
.
Notes
.NET Core ne prend pas en charge l’attribut DataSource. Si vous essayez d’accéder aux données de test de cette manière dans un projet de test unitaire .NET Core, UWP ou WinUI, une erreur de type « "TestContext" ne contient pas de définition pour "DataRow" et aucune méthode d’extension accessible "DataRow" acceptant un premier argument de type "TestContext" n’a été localisée (une directive using ou une référence d’assembly est-elle manquante ?) » se produit.
Écrire la méthode de test
La méthode de test de AddIntegers
est relativement simple. Pour chaque ligne de la source de données, appelez AddIntegers
avec les valeurs de colonne FirstNumber et SecondNumber en tant que paramètres, puis vérifiez la valeur retournée par rapport à la valeur de colonne Sum :
[TestMethod]
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
public void AddIntegers_FromDataSourceTest()
{
var target = new Maths();
// Access the data
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Spécifier DataSourceAttribute
L’attribut DataSource
spécifie la chaîne de connexion de la source de données et le nom de la table que vous utilisez dans la méthode de test. Les informations exactes de la chaîne de connexion varient selon le genre de source de données que vous utilisez. Dans cet exemple, nous avons utilisé une base de données SqlServerCe.
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]
Attention
La chaîne de connexion peut contenir des données sensibles (par exemple, un mot de passe). La chaîne de connexion est stockée en texte brut dans le code source et dans l’assembly compilé. Restreignez l’accès au code source et à l’assembly pour protéger ces informations sensibles.
L’attribut DataSource a trois constructeurs.
[DataSource(dataSourceSettingName)]
Un constructeur avec un seul paramètre utilise les informations de connexion stockées dans le fichier app.config de la solution. dataSourceSettingsName est le nom de l’élément XML contenu dans le fichier config, qui spécifie les informations de connexion.
L’utilisation d’un fichier app.config vous permet de changer l’emplacement de la source de données sans changer le test unitaire lui-même. Pour plus d’informations sur la création et l’utilisation d’un fichier app.config, consultez Procédure pas à pas : utilisation d’un fichier de configuration pour définir une source de données
[DataSource(connectionString, tableName)]
Le constructeur DataSource
avec deux paramètres spécifie la chaîne de connexion de la source de données et le nom de la table qui contient les données de la méthode de test.
Les chaînes de connexion dépendent du type de la source de données. Toutefois, elles doivent contenir un élément Provider qui spécifie le nom invariant du fournisseur de données.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Utiliser TestContext.DataRow pour accéder aux données
Pour accéder aux données de la table AddIntegersData
, utilisez l’indexeur TestContext.DataRow
. Comme DataRow
est un objet DataRow, récupérez les valeurs de colonne par noms d’index ou de colonnes. Dans la mesure où les valeurs sont retournées en tant qu’objets, convertissez-les vers le type approprié :
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
Exécuter le test et afficher les résultats
Une fois que vous avez fini d’écrire une méthode de test, générez le projet de test. La méthode de test apparaît dans l’Explorateur de tests, dans le groupe Tests non exécutés. Tandis que vous exécutez, écrivez et réexécutez vos tests, l’Explorateur de tests affiche les résultats dans les groupes Échecs de tests, Tests réussis et Tests non exécutés. Vous pouvez choisir Exécuter tout pour exécuter tous vos tests ou Exécuter pour sélectionner un sous-ensemble de tests à exécuter.
La barre des résultats des tests en haut de l’Explorateur de tests s’anime pendant l’exécution de votre test. À la fin de la série de tests, la barre est verte en cas de réussite de tous les tests, ou rouge en cas d’échec de l’un des tests. Un résumé de la série de tests s’affiche dans le volet d’informations, en bas de la fenêtre Explorateur de tests. Sélectionnez un test pour en afficher les détails dans le volet inférieur.
Notes
Il existe un résultat pour chaque ligne de données et un résultat récapitulatif. Si le test a réussi sur chaque ligne de données, le récapitulatif de l’exécution indique Réussite. Si le test a échoué sur une ou plusieurs lignes de données, le récapitulatif de l’exécution indique Échec.
Si vous avez exécuté la méthode AddIntegers_FromDataRowTest
, AddIntegers_FromDynamicDataTest
ou AddIntegers_FromDataSourceTest
dans notre exemple, la barre des résultats devient rouge et la méthode de test est déplacée vers le groupe Échecs de tests. Un test piloté par les données échoue si l’une des méthodes itérées de la source de données échoue également. Quand vous choisissez un test piloté par les données à l’état d’échec dans la fenêtre Explorateur de tests, le volet d’informations affiche les résultats de chaque itération identifiée par l’index de ligne de données. Dans notre exemple, il semble que l’algorithme AddIntegers
ne gère pas correctement les valeurs négatives.
Quand la méthode testée est corrigée et que le test est réexécuté, la barre des résultats devient verte et la méthode de test est déplacée vers le groupe Tests réussis.
Contenu connexe
- Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow
- Microsoft.VisualStudio.TestTools.UnitTesting.Assert
- Tests unitaires de votre code
- Exécuter des tests unitaires avec l'Explorateur de tests
- Écrire des tests unitaires pour .NET avec l’infrastructure de tests unitaires Microsoft