Creare uno unit test basato sui dati
È possibile usare il framework di unit test Microsoft (MSTest) per il codice gestito per configurare un metodo di unit test per recuperare i valori da un'origine dati. Il metodo viene eseguito successivamente per ogni riga nell'origine dati, che semplifica il test di un'ampia gamma di input usando un singolo metodo.
Uno unit test basato sui dati può usare uno dei tipi seguenti:
- dati inline con l'attributo
DataRow
- dati membro che usano l'attributo
DynamicData
- da un provider di origine noto usando l'attributo
DataSource
Il metodo sottoposto a test
Si supponga, ad esempio, di avere:
Soluzione denominata
MyBank
che accetta ed elabora transazioni per diversi tipi di account.Progetto in
MyBank
denominatoBankDb
che gestisce le transazioni per gli account.Classe denominata
Maths
nel progettoBankDb
che esegue le funzioni matematiche per garantire che qualsiasi transazione sia vantaggiosa per la banca.Progetto di unit test denominato
BankDbTests
per testare il comportamento del componenteBankDb
.Classe unit test denominata
MathsTests
per verificare il comportamento della classeMaths
.
Verrà testato un metodo in Maths
che aggiunge due numeri interi usando un ciclo:
public int AddIntegers(int first, int second)
{
int sum = first;
for (int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
Test del metodo
Test inline basato sui dati
Per i test inline, MSTest usa DataRow
per specificare i valori usati dal test basato sui dati. Il test in questo esempio viene eseguito successivamente per ogni riga di dati.
[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 basato sui dati dei membri
MSTest utilizza l'attributo DynamicData
per specificare il nome, il tipo e il tipo di definizione (per impostazione predefinita viene utilizzato il tipo corrente) del membro che fornirà i dati usati dal test data-driven.
Nota
Prima di MSTest 3.8, l'enumerazione DynamicDataSourceType
aveva due membri, Property
e Method
. Il valore predefinito è Property
. A partire da MSTest 3.8, viene aggiunto un nuovo membro AutoDetect
all'enumerazione ed è l'impostazione predefinita. Non è quindi più necessario specificare 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});
}
È anche possibile eseguire l'override del nome visualizzato generato predefinito, usando la proprietà DynamicDataDisplayName
dell'attributo DynamicData
. La firma del metodo del nome visualizzato deve essere public static string
e accettare due parametri, il primo di tipo MethodInfo
e il secondo di tipo 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 basato sui dati del provider di origine
La creazione di uno unit test basato sull'origine dati prevede i passaggi seguenti:
Creare un'origine dati contenente i valori usati nel metodo di test. La sorgente dati può essere di qualsiasi tipo registrato nel computer che esegue il test.
Aggiungere una proprietà
TestContext
pubblica di tipo TestContext alla classe di test.Creare un metodo di unit test
Aggiungere un attributo DataSourceAttribute.
Utilizzare la proprietà DataRow indicizzatore per recuperare i valori usati in un test.
Creare un'origine dati
Per testare il metodo AddIntegers
, creare un'origine dati che specifica un intervallo di valori per i parametri e la somma che si prevede venga restituita. In questo esempio verrà creato un database Sql Compact denominato MathsData
e una tabella denominata AddIntegersData
che contiene i nomi e i valori di colonna seguenti
FirstNumber | SecondoNumero | Somma |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Aggiungere un oggetto TestContext alla classe di test
Il framework di unit test crea un oggetto TestContext
per archiviare le informazioni sull'origine dati per un test basato sui dati. Il framework imposta quindi questo oggetto come valore della proprietà TestContext
creata.
public TestContext TestContext { get; set; }
Nel metodo di test si accede ai dati tramite la proprietà indicizzatrice DataRow
dell'TestContext
.
Nota
.NET Core non supporta l'attributo DataSource. Se si tenta di accedere ai dati di test in questo modo in un progetto di unit test .NET Core, UWP o WinUI, verrà visualizzato un errore simile a "'TestContext' non contiene una definizione per "DataRow" e non è possibile trovare un metodo di estensione accessibile "DataRow" che accetta un primo argomento di tipo "TestContext" (manca una direttiva using o un riferimento all'assembly)".
Scrivere il metodo di test
Il metodo di test per AddIntegers
è piuttosto semplice. Per ogni riga nell'origine dati, chiamare AddIntegers
con i valori delle colonne FirstNumber e SecondNumber come parametri e verificare il valore restituito confrontandolo con il valore della colonna 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});
}
Specificare DataSourceAttribute
L'attributo DataSource
specifica la stringa di connessione per l'origine dati e il nome della tabella utilizzata nel metodo di test. Le informazioni esatte nella stringa di connessione variano a seconda del tipo di origine dati in uso. In questo esempio è stato usato un database SqlServerCe.
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]
Cautela
La stringa di connessione può contenere dati sensibili, ad esempio una password. La stringa di connessione viene archiviata in testo normale nel codice sorgente e nell'assembly compilato. Limitare l'accesso al codice sorgente e all'assembly per proteggere queste informazioni riservate.
L'attributo DataSource ha tre costruttori.
[DataSource(dataSourceSettingName)]
Un costruttore con un parametro usa le informazioni di connessione archiviate nel file di app.config per la soluzione. Il dataSourceSettingsName è il nome dell'elemento Xml nel file di configurazione che specifica le informazioni di connessione.
L'uso di un file app.config consente di modificare il percorso dell'origine dati senza apportare modifiche allo unit test stesso. Per informazioni su come creare e usare un file app.config, vedere Procedura dettagliata: Uso di un file di configurazione per definire un'origine dati
[DataSource(connectionString, tableName)]
Il costruttore DataSource
con due parametri specifica la stringa di connessione per l'origine dati e il nome della tabella che contiene i dati per il metodo di test.
Le stringhe di connessione dipendono dal tipo di origine dati, ma deve contenere un elemento Provider che specifica il nome invariante del provider di dati.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Usare TestContext.DataRow per accedere ai dati
Per accedere ai dati nella tabella AddIntegersData
, usare l'indicizzatore TestContext.DataRow
.
DataRow
è un oggetto DataRow, quindi recuperare i valori delle colonne in base ai nomi di indice o colonna. Poiché i valori vengono restituiti come oggetti, convertirli nel tipo appropriato:
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
Eseguire il test e visualizzare i risultati
Al termine della scrittura di un metodo di test, compilare il progetto di test. Il metodo di test viene visualizzato in Esplora Test nel gruppo Test non eseguiti. Mentre esegui, scrivi e riesegui i test, Esplora test visualizza i risultati in gruppi di Test falliti, Test superatie Test non eseguiti. È possibile scegliere Esegui tutti i per eseguire tutti i test oppure scegliere Esegui per scegliere un subset di test da eseguire.
La barra dei risultati del test nella parte superiore di Esplora test viene animata durante l'esecuzione del test. Alla fine dell'esecuzione del test, la barra sarà verde se tutti i test sono stati superati o rossi se uno dei test non è riuscito. Un riepilogo dell'esecuzione del test viene visualizzato nel riquadro dei dettagli nella parte inferiore della finestra Esplora test. Selezionare un test per visualizzare i dettagli del test nel riquadro inferiore.
Nota
È presente un risultato per ogni riga di dati e anche un risultato di riepilogo. Se il test è stato superato in ogni riga di dati, l'esecuzione di riepilogo viene visualizzata come Superato. Se il test non è riuscito in una riga di dati, l'esecuzione di riepilogo viene visualizzata come Failed.
Se hai eseguito uno dei metodi AddIntegers_FromDataRowTest
, AddIntegers_FromDynamicDataTest
o AddIntegers_FromDataSourceTest
nel nostro esempio, la barra dei risultati diventa rossa e il metodo viene spostato nei Test falliti. Un test basato sui dati ha esito negativo se uno qualunque dei metodi iterati dalla fonte dati fallisce. Quando si sceglie un test basato sui dati non riuscito nella finestra Test Explorer, nel riquadro dei dettagli vengono visualizzati i risultati di ogni iterazione identificata dall'indice della riga di dati. Nell'esempio viene visualizzato che l'algoritmo AddIntegers
non gestisce correttamente i valori negativi.
Quando il metodo sottoposto a test viene corretto e il test viene ripetuto, la barra dei risultati diventa verde e il metodo di test viene spostato nel gruppo Test Superato.
Contenuto correlato
- Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow
- Microsoft.VisualStudio.TestTools.UnitTesting.Assert
- Testa unitariamente il tuo codice
- Eseguire unit test con Esplora test
- Scrivere unit test per .NET con il framework di unit test Microsoft