Criar um teste de unidade controlado por dados
É possível usar a estrutura de teste de unidade da Microsoft (MSTest) para o código gerenciado para configurar um método de teste de unidade para recuperar valores de uma fonte de dados. O método é executado sucessivamente para cada linha na fonte de dados, o que facilita o teste de uma variedade de entradas usando um único método.
Um teste de unidade controlado por dados pode usar qualquer um dos seguintes tipos:
- dados embutidos usando o atributo
DataRow
- dados membros usando o atributo
DynamicData
- de algum provedor de origem conhecido usando o atributo
DataSource
O método em teste
Por exemplo, vamos supor que você tenha:
Uma solução chamada
MyBank
que aceita e processa transações para diferentes tipos de contas.Um projeto em
MyBank
chamadoBankDb
que gerencia as transações das contas.Uma classe chamada
Maths
no projetoBankDb
que executa as funções matemáticas para garantir que qualquer transação seja vantajosa para o banco.Um projeto de teste de unidade chamado
BankDbTests
para testar o comportamento do componenteBankDb
.Uma classe de teste de unidade chamada
MathsTests
para verificar o comportamento da classeMaths
.
Testaremos um método em Maths
que adiciona dois números inteiros usando um loop:
public int AddIntegers(int first, int second)
{
int sum = first;
for (int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
Testar o método de teste
Teste controlado por dados embutido
Para testes embutidos, o MSTest usa DataRow
para especificar valores usados pelo teste controlado por dados. Neste exemplo, o teste é executado sucessivamente para cada linha de dados.
[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});
}
Teste membro controlado por dados
O MSTest usa o atributo DynamicData
para especificar o nome, o tipo (propriedade, o padrão ou o método) e definir o tipo (por padrão, o tipo atual é usado) do membro que fornecerá os dados usados pelo teste controlado por dados.
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});
}
Também é possível substituir o nome de exibição padrão gerado, usando a propriedade DynamicDataDisplayName
do atributo DynamicData
. A assinatura do método de nome de exibição deve ser public static string
e aceitar dois parâmetros, o primeiro do tipo MethodInfo
e o segundo do 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))]
Teste controlado por dados do provedor de origem
A criação de um teste de unidade orientado a fonte de dados envolve as seguintes etapas:
Criar uma fonte de dados que contém os valores a serem usados no método de teste. A fonte de dados pode ser de qualquer tipo que esteja registrado no computador que executa o teste.
Adicione uma propriedade
TestContext
pública do tipo TestContext à classe de teste.Crie um método de teste de unidade
Adicione um atributo DataSourceAttribute a ele.
Usar o propriedade do indexador DataRow para recuperar os valores que você pode usar em um teste.
Criar uma fonte de dados
Para testar o método AddIntegers
, crie uma fonte de dados que especifica um intervalo de valores para os parâmetros e a soma que você espera que seja retornada. Neste exemplo, criaremos um banco de dados do SQL Compact chamado MathsData
e uma tabela chamada AddIntegersData
que contém os seguintes nomes de coluna e valores
FirstNumber | SecondNumber | Somar |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Adicionar um TestContext à classe de teste
A estrutura de teste de unidade cria um objeto TestContext
para armazenar as informações de fonte de dados de um teste orientado a dados. Em seguida, a estrutura define esse objeto como o valor da propriedade TestContext
que você criou.
public TestContext TestContext { get; set; }
Em seu método de teste, os dados são acessados por meio da propriedade do indexador DataRow
do TestContext
.
Observação
O .NET Core não dá suporte ao atributo DataSource. Se tentar acessar os dados de teste dessa forma em um projeto de teste de unidade do .NET Core, UWP ou WinUI, aparecerá um erro semelhante a "TestContext não contém uma definição para 'DataRow' e nenhum 'DataRow' do método de extensão acessível que aceita um primeiro argumento do tipo 'TestContext' pode ser encontrado (alguma diretiva em uso ou uma referência de assembly está ausente?)".
Escrever o método de teste
O método de teste de AddIntegers
é bastante simples. Para cada linha na fonte de dados, chame AddIntegers
com os valores de coluna FirstNumber e SecondNumber como parâmetros e verifique o valor retornado no valor da coluna 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});
}
Especificar o DataSourceAttribute
O atributo DataSource
especifica a cadeia de conexão para a fonte de dados e o nome da tabela a ser usada no método de teste. As informações exatas na cadeia de conexão são diferentes, dependendo do tipo de fonte de dados que você está usando. Neste exemplo, usamos um banco de dados SqlServerCe.
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]
Cuidado
A cadeia de conexão pode conter dados confidenciais (por exemplo, uma senha). A cadeia de conexão é armazenada em texto sem formatação no código-fonte e no assembly compilado. Restrinja o acesso ao código-fonte e ao assembly para proteger essas informações confidenciais.
O atributo DataSource tem três construtores.
[DataSource(dataSourceSettingName)]
Um construtor com um parâmetro usa informações de conexão armazenadas no arquivo app.config para a solução. O dataSourceSettingsName é o nome do elemento XML no arquivo de configuração que especifica as informações de conexão.
O uso de um arquivo app.config permite que você altere o local da fonte de dados sem fazer alterações no teste de unidade propriamente dito. Para obter informações sobre como criar e usar um arquivo app.config, confira Passo a passo: Usando um arquivo de configuração para definir uma fonte de dados
[DataSource(connectionString, tableName)]
O construtor DataSource
com dois parâmetros especifica a cadeia de conexão da fonte de dados e o nome da tabela que contém os dados para o método de teste.
As cadeias de conexão dependem do tipo de fonte de dados, mas elas devem conter um elemento Provedor que especifica o nome invariável do provedor de dados.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Usar o TestContext.DataRow para acessar os dados
Para acessar os dados na tabela AddIntegersData
, use o indexador TestContext.DataRow
. DataRow
é um objeto DataRow, para que seja possível recuperar valores de colunas por índice ou nomes de colunas. Como os valores são retornados como objetos, converta-os para o tipo apropriado:
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
Executar o teste e exibir os resultados
Ao terminar de escrever um método de teste, compile o projeto de teste. O método de teste é exibido em Gerenciador de Testes, no grupo Testes Não Executados. Conforme você executa, escreve e executa novamente os testes, o Gerenciador de Testes exibe os resultados em grupos de Testes Reprovados, Testes Aprovados e Testes Não Executados. Você pode escolher Executar Tudo para executar todos os testes ou Executar para escolher um subconjunto de testes a serem executados.
A barra de resultados de teste na parte superior do Gerenciador de Testes é animada enquanto o teste é executado. Ao final da execução de teste, a barra ficará verde se todos os testes passaram ou vermelha se algum dos testes falhou. Um resumo da execução de teste é exibido no painel de detalhes na parte inferior da janela do Gerenciador de Testes. Selecione um teste para exibir seus detalhes no painel inferior.
Observação
Há um resultado para cada linha de dados e também um resumo de resultados. Se o teste foi aprovado em cada linha de dados, o resumo de execução mostra como Aprovado. Se o teste falhou em alguma linha de dados, o resumo de execução mostra como Falha.
Se você executou o método AddIntegers_FromDataRowTest
, AddIntegers_FromDynamicDataTest
AddIntegers_FromDataSourceTest
de nosso exemplo, a barra de resultados fica vermelha e o método de teste é movido para Testes Reprovados. Um teste controlado por dados falha se um dos métodos iterados da fonte de dados falha. Quando você escolhe um teste controlado por dados que foi reprovado na janela Gerenciador de Testes, o painel de detalhes exibe os resultados de cada iteração que é identificada pelo índice de linha de dados. Em nosso exemplo, parece que o algoritmo AddIntegers
não manipula valores negativos corretamente.
Quando o método em teste é corrigido e o teste é novamente executado, a barra de resultados ficará verde e o método de teste é movido para o grupo Teste Aprovado.
Conteúdo relacionado
- Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow
- Microsoft.VisualStudio.TestTools.UnitTesting.Assert
- Realizar teste de unidade do seu código
- Executar testes de unidade com o Gerenciador de Testes
- Escrever testes de unidade para o .NET com a estrutura de teste de unidade da Microsoft