Créer un test unitaire piloté par les données
Vous pouvez utiliser le framework 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 une variété d’entrées en utilisant une même méthode.
Un test unitaire piloté par les données peut utiliser un des types suivants :
- données inline avec 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, supposons que vous disposez des éléments suivants :
Une solution appelée
MyBank
, qui accepte et traite les transactions pour 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 tests unitaires 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 intégrées
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 DynamicData
attribut pour spécifier le nom, le type et le type de définition (par défaut, le type actuel est utilisé) du membre qui fournira les données utilisées par le test piloté par les données.
Remarque
Avant MSTest 3.8, DynamicDataSourceType
énumération avait deux membres, Property
et Method
. La valeur par défaut était Property
. À compter de MSTest 3.8, un nouveau membre AutoDetect
est ajouté à l’énumération et est la valeur par défaut. Vous n’avez donc plus besoin de spécifier DynamicDataSourceType
.
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 de remplacer le nom d’affichage généré par défaut en utilisant 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 deuxième 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 source
La création d’un test unitaire piloté par une source 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 être de 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-lui un attribut DataSourceAttribute.
Utilisez la propriété d’indexeur DataRow pour récupérer les valeurs que vous utilisez dans un test.
Créer 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 qui doit être retournée. 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 les valeurs de colonnes suivants :
FirstNumber | SecondNumber | Sum |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Ajouter un 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
.
Remarque
.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, vous verrez 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é trouvée (une directive using ou une référence d’assembly est-elle manquante ?) ».
Écrire la méthode de test
La méthode de test pour AddIntegers
est relativement simple. Pour chaque ligne de la source de données, appelez AddIntegers
avec les valeurs des colonnes PremièreNombre et DeuxièmeNombre en tant que paramètres, puis vérifiez la valeur de retour par rapport à la valeur de la colonne Somme.
[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é. Limitez 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 de configuration 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 apporter de modifications au 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 pour la méthode de test.
Les chaînes de connexion dépendent du type de la source de données, mais 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 des colonnes via les noms d’index ou de colonnes. Comme 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 voir les résultats
Quand 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 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 de résultats des tests située en haut de Explorateur de tests est animée pendant l'exécution de vos tests. À la fin de la série de tests, la barre est verte si tous les tests ont réussi, ou elle est rouge si un ou plusieurs tests ont échoué. 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.
Remarque
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é l’une des méthodes AddIntegers_FromDataRowTest
, AddIntegers_FromDynamicDataTest
ou AddIntegers_FromDataSourceTest
dans notre exemple, la barre de résultats devient rouge et la méthode de test est déplacée vers les tests échoués . Un test piloté par les données échoue si une des méthodes itérées à partir de la source de données échoue. Quand vous choisissez un test piloté par les données qui a échoué 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 la ligne de données. Dans notre exemple, il apparaît que l’algorithme AddIntegers
ne gère pas correctement les valeurs négatives.
Lorsque la méthode sous test est corrigée et que le test est réexécuté, la barre de résultats devient verte et la méthode de test est déplacée vers le groupe Test Réussi.
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