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 in successione per ogni riga nell'origine dati, rendendo più semplice testare una un'ampia varietà di input con un singolo metodo.
Uno unit test basato sui dati può usare uno dei tipi seguenti:
- dati inline con l'attributo
DataRow
- dati dei membri che usano l'attributo
DynamicData
- da un provider di origine noto usando l'attributo
DataSource
Metodo sottoposto a test
Come esempio, si supponga di avere:
Una soluzione denominata
MyBank
che accetta ed elabora transazioni per diversi tipi di account.Un progetto in
MyBank
denominatoBankDb
, che gestisce le transazioni per gli account.Una classe denominata
Maths
nel progettoBankDb
, che esegue le funzioni matematiche per garantire che tutte le transazioni siano vantaggiose per la banca.Un progetto di unit test denominato
BankDbTests
, per testare il comportamento del componenteBankDb
.Una classe di unit test denominata
MathsTests
, per verificare il comportamento della classeMaths
.
Verrà testato un metodo in Maths
che somma due numeri interi con 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 basato sui dati inline
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 usa DynamicData
l'attributo per specificare il nome, il tipo (proprietà, il metodo predefinito) e la definizione del tipo (per impostazione predefinita viene usato il tipo corrente) del membro che fornirà i dati usati dal test basato sui dati.
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 DynamicDataDisplayName
proprietà 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 che contiene i valori usati nel metodo di test. L'origine dati può essere di qualsiasi tipo registrato nel computer che esegue il test.
Aggiungere una proprietà pubblica
TestContext
di tipo TestContext alla classe di test.Creare un metodo di unit test
Aggiungere un DataSourceAttribute attributo.
Usare la proprietà DataRow dell'indicizzatore per recuperare i valori da usare in un test.
Creare un'origine dati
Per testare il metodo AddIntegers
, creiamo un'origine dati che specifica un intervallo di valori per i parametri e la somma restituita prevista. Nell'esempio verrà creato un database Sql Compact denominato MathsData
e una tabella denominata AddIntegersData
che contiene i nomi di colonna e i valori seguenti
FirstNumber | SecondNumber | Sum |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Aggiungere un oggetto TestContext alla classe di test
Il framework unit test crea un oggetto TestContext
per archiviare le informazioni sull'origine dati per un test basato sui dati. Il framework imposta quindi l'oggetto come valore della proprietà TestContext
creata.
public TestContext TestContext { get; set; }
Nel metodo di test si accede ai dati tramite la proprietà dell'indicizzatore DataRow
di 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 ad 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 della colonna FirstNumber e SecondNumber come parametri e verificare il valore restituito rispetto al 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 usata 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")]
Attenzione
Il stringa di connessione può contenere dati sensibili, ad esempio una password. Il stringa di connessione viene archiviato 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 dispone di tre costruttori.
[DataSource(dataSourceSettingName)]
Un costruttore con un solo parametro usa le informazioni di connessione archiviate nel file app.config per la soluzione. Il nome dell'elemento XML nel file di configurazione che specifica le informazioni di connessione è dataSourceSettingsName.
L'uso di un file app.config consente di modificare il percorso dell'origine dati senza apportare modifiche allo unit test. 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 variano a seconda del tipo di origine dati, ma devono contenere un elemento Provider che specifica il nome invariante del provider di dati.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Usare TestContext.DataRow per l'accesso ai dati
Per accedere ai dati nella tabella AddIntegersData
, usare l'indicizzatore TestContext.DataRow
. DataRow
è un oggetto DataRow, pertanto i valori delle colonne vengono recuperati in base all'indice o ai nomi delle colonne. 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. Quando si eseguono, si scrivono e si rieseguono i test, Esplora test visualizza i risultati nei gruppi Test non superati, Test superati e Test non eseguiti. È possibile scegliere Esegui tutto per eseguire tutti i test oppure scegliere Esegui per selezionare un sottoinsieme di test da eseguire.
La barra dei risultati dei test nella parte superiore di Esplora test viene animata durante l'esecuzione dei test. Al termine del test, la barra diventa verde se tutti i test sono stati superati oppure rossa se almeno uno dei test ha avuto esito negativo. Nel riquadro dei dettagli nella parte inferiore della finestra Esplora test appare un riepilogo dell'esecuzione dei test. Selezionare un test per visualizzarne i dettagli nel riquadro inferiore.
Nota
Viene visualizzato 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 visualizza Superato. Se il test non è stato superato in una riga di dati, l'esecuzione di riepilogo visualizza Non superato.
Se è stato eseguito uno dei metodi o AddIntegers_FromDataSourceTest
AddIntegers_FromDynamicDataTest
nell'esempioAddIntegers_FromDataRowTest
, la barra dei risultati diventa rossa e il metodo di test viene spostato nei test non superati. Un test basato sui dati non riesce se uno dei metodi di cui si esegue l'iterazione dall'origine dati ha esito negativo. Quando si sceglie un test basato sui dati non riuscito nella finestra Esplora test, il riquadro dei dettagli visualizza i risultati di ogni iterazione identificata dall'indice delle righe di dati. Nel nostro esempio, risulta che l'algoritmo AddIntegers
non gestisce correttamente i valori negativi.
Dopo avere corretto il metodo sottoposto a test ed eseguito nuovamente il test, la barra dei risultati diventa verde e il metodo di test viene spostato nel gruppo Test superati.
Contenuto correlato
- Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow
- Microsoft.VisualStudio.TestTools.UnitTesting.Assert
- Eseguire unit test del codice
- Eseguire unit test con Esplora test
- Scrittura di unit test per .NET con il framework di unit test Microsoft per il codice gestito