Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo explica como criar, executar e personalizar uma série de testes de unidade usando a estrutura de teste de unidade da Microsoft para código gerenciado e o Visual Studio Test Explorer. Você começa com um projeto em C# que está em desenvolvimento, cria testes que exercem seu código, executam os testes e examinam os resultados. Em seguida, você altera o código do projeto e executa os testes novamente. Se você quiser uma visão geral conceitual dessas tarefas antes de passar por essas etapas, consulte noções básicas de teste de unidade. Se você quiser gerar testes automaticamente a partir do código existente, consulte Criar esboços de métodos de teste de unidade a partir do código.
Criar um projeto para testar
Abra o Visual Studio.
Na janela inicial, escolha Criar um novo projeto.
Pesquise e selecione o modelo de projeto do Aplicativo de Console em C# para .NET e clique em Avançar.
Nota
Se você não encontrar o modelo Console App, poderá instalá-lo na janela Criar um novo projeto. Na mensagem Não encontrou o que precisa?, escolha o link Instalar mais ferramentas e recursos. Em seguida, no Visual Studio Installer, escolha a carga de trabalho Desenvolvimento de área de trabalho do .NET.
Dê ao projeto o nome Bank e clique em Avançar.
Escolha a estrutura de destino recomendada ou o .NET 8 e, em seguida, escolha Criar.
O projeto do Banco é criado e exibido no Gerenciador de Soluções com o arquivo Program.cs aberto no editor de código.
Nota
Se Program.cs não estiver aberto no editor, clique duas vezes no arquivo Program.cs no Gerenciador de Soluções para abri-lo.
Substitua o conteúdo de Program.cs pelo seguinte código C# que define uma classe, BankAccount:
using System; namespace BankAccountNS { /// <summary> /// Bank account demo class. /// </summary> public class BankAccount { private readonly string m_customerName; private double m_balance; private BankAccount() { } public BankAccount(string customerName, double balance) { m_customerName = customerName; m_balance = balance; } public string CustomerName { get { return m_customerName; } } public double Balance { get { return m_balance; } } public void Debit(double amount) { if (amount > m_balance) { throw new ArgumentOutOfRangeException("amount"); } if (amount < 0) { throw new ArgumentOutOfRangeException("amount"); } m_balance += amount; // intentionally incorrect code } public void Credit(double amount) { if (amount < 0) { throw new ArgumentOutOfRangeException("amount"); } m_balance += amount; } public static void Main() { BankAccount ba = new BankAccount("Mr. Bryan Walton", 11.99); ba.Credit(5.77); ba.Debit(11.22); Console.WriteLine("Current balance is ${0}", ba.Balance); } } }
Renomeie o arquivo como BankAccount.cs clicando com o botão direito do mouse e escolha Renomear na Gerenciador de Soluções.
No menu Build, clique em Build Solution (ou pressione Ctrl + SHIFT + B).
Agora você tem um projeto com métodos que você pode testar. Neste artigo, os testes se concentram no método Debit
. O método Debit
é chamado quando o dinheiro é retirado de uma conta.
Criar um projeto de teste de unidade
No menu Arquivo, selecione Adicionar>Novo Projeto.
Dica
Você também pode clicar com o botão direito do mouse na solução no Gerenciador de Soluções e escolher Adicionar>Novo Projeto.
Digite test na caixa de pesquisa, selecione C# como o idioma e, em seguida, selecione o Projeto de teste do MSTest em C# para o modelo do .NET e clique em Avançar.
Nota
No Visual Studio 2019 versão 16.9, o modelo de projeto MSTest é Projeto de Teste de Unidade.
Nomeie o projeto como BankTests e clique em Avançar.
Escolha a estrutura de destino recomendada ou o .NET 8, em seguida, clique em Criar.
A partir do Visual Studio 2022 versão 17.10, você também pode selecionar um executor de teste. Para o executor de testes, você pode escolher VSTest ou MSTest. Para obter mais informações sobre a diferença entre os executores de teste, confira Comparação entre Microsoft.Testing.Platform e VSTest.
O projeto BankTests é adicionado à solução Bank.
No projeto BankTests, adicione uma referência ao projeto Bank.
No Gerenciador de Soluções, selecione Dependências no projeto BankTests e, em seguida, escolha Adicionar Referência (ou Adicionar referência de projeto) no menu de clique com o botão direito do mouse.
Na caixa de diálogo Gerenciador de Referências, expanda Projetos, selecione Solução e, em seguida, marque o item Banco.
Escolha OK.
Criar a classe de teste
Crie uma classe de teste para verificar a classe BankAccount
. Você pode usar o arquivo UnitTest1.cs que foi gerado pelo modelo de projeto, mas fornecer ao arquivo e à classe nomes mais descritivos.
Renomear um arquivo e uma classe
Para renomear o arquivo, em do Gerenciador de Soluções, selecione o arquivo UnitTest1.cs no projeto BankTests. No menu de clique com o botão direito do mouse, escolha Renomear (ou pressione F2), e renomeie o arquivo para BankAccountTests.cs.
Para renomear a classe, posicione o cursor no
UnitTest1
no editor de código, clique com o botão direito do mouse e escolha Renomear (ou pressione F2). Digite BankAccountTests e, em seguida, pressione Enter.
O arquivo BankAccountTests.cs agora contém o seguinte código:
// The 'using' statement for Test Tools is in GlobalUsings.cs
// using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BankTests
{
[TestClass]
public class BankAccountTests
{
[TestMethod]
public void TestMethod1()
{
}
}
}
Adicionar uma instrução using
Adicione uma instrução using
à classe de teste para permitir chamadas ao projeto em teste sem usar nomes totalmente qualificados. Na parte superior do arquivo de classe, adicione:
using BankAccountNS;
Requisitos de classe de teste
Os requisitos mínimos para uma classe de teste são:
O atributo
[TestClass]
é necessário em qualquer classe que contenha métodos de teste de unidade que você deseja executar no Gerenciador de Testes.Cada método de teste que você deseja reconhecer o Gerenciador de Testes deve ter o atributo
[TestMethod]
.
Você pode ter outras classes em um projeto de teste de unidade que não têm o atributo [TestClass]
e pode ter outros métodos em classes de teste que não têm o atributo [TestMethod]
. Você pode chamar essas classes e métodos dos seus métodos de teste.
Criar o primeiro método de teste
Neste procedimento, você escreve métodos de teste de unidade para verificar o comportamento do método Debit
da classe BankAccount
.
Há pelo menos três comportamentos que precisam ser verificados:
O método gerará um ArgumentOutOfRangeException se o valor do débito for maior que o saldo.
O método gerará um ArgumentOutOfRangeException se o valor do débito for menor que zero.
Se o valor do débito for válido, o método subtrairá o valor do débito do saldo da conta.
Dica
Você pode excluir o método de TestMethod1
padrão, pois não o usará neste passo a passo.
Para criar um método de teste
O primeiro teste verifica se um valor válido (ou seja, um menor que o saldo da conta e maior que zero) retira o valor correto da conta. Adicione o seguinte método à classe BankAccountTests
:
[TestMethod]
public void Debit_WithValidAmount_UpdatesBalance()
{
// Arrange
double beginningBalance = 11.99;
double debitAmount = 4.55;
double expected = 7.44;
BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
// Act
account.Debit(debitAmount);
// Assert
double actual = account.Balance;
Assert.AreEqual(expected, actual, 0.001, "Account not debited correctly");
}
O método é simples: ele configura um novo objeto BankAccount
com um saldo inicial e, em seguida, retira um valor válido. Ele usa o método Assert.AreEqual para verificar se o saldo final é o esperado. Métodos como Assert.AreEqual
, Assert.IsTruee outros são frequentemente usados em testes de unidade. Para obter mais informações conceituais sobre como escrever um teste de unidade, confira Escrever seus testes.
Requisitos do método de teste
Um método de teste deve atender aos seguintes requisitos:
Está decorado com o atributo
[TestMethod]
.Ele retorna
void
.Ele não pode ter parâmetros.
Compilar e executar o teste
No menu Criar, escolha Criar Solução (ou pressione Ctrl + SHIFT + B).
Se o Gerenciador de Testes não estiver aberto, abra-o escolhendo Teste >Gerenciador de Testes (ou Teste >Windows>Gerenciador de Testes) na barra de menus superior (ou pressione Ctrl + E, T ).
Escolha Executar Tudo para executar o teste (ou pressione Ctrl + R, V).
Enquanto o teste está em execução, a barra de status na parte superior da janela do Gerenciador de Testes é animada. No final da execução do teste, a barra ficará verde se todos os métodos de teste forem aprovados ou vermelhos se algum dos testes falhar.
Nesse caso, o teste falha.
Selecione o método no Gerenciador de Testes para exibir os detalhes na parte inferior da janela.
Corrigir seu código e executar novamente seus testes
O resultado do teste contém uma mensagem que descreve a falha. Talvez seja necessário ir mais a fundo para ver esta mensagem. Para o método AreEqual
, a mensagem exibe o que era esperado e o que realmente foi recebido. Você esperava que o saldo diminuísse, mas, em vez disso, aumentou pelo valor do saque.
O teste de unidade revelou um bug: o valor do saque foi adicionado ao saldo da conta quando deveria ser subtraído.
Corrigir o bug
Para corrigir o erro, no arquivo BankAccount.cs, substitua a linha:
m_balance += amount;
por:
m_balance -= amount;
Executar novamente o teste
Em Explorador de Testes, escolha Executar Tudo para executar novamente o teste (ou pressione Ctrl + R, V). A barra vermelha/verde fica verde para indicar que o teste foi aprovado.
Usar testes de unidade para melhorar seu código
Esta seção descreve como um processo iterativo de análise, desenvolvimento de teste de unidade e refatoração pode ajudá-lo a tornar seu código de produção mais robusto e eficaz.
Analisar os problemas
Você criou um método de teste para confirmar se um valor válido foi deduzido corretamente no método Debit
. Agora, verifique se o método gera uma ArgumentOutOfRangeException se o valor do débito é:
- maior que o saldo ou
- menor que zero.
Criar e executar novos métodos de teste
Crie um método de teste para verificar o comportamento correto quando o valor do débito for menor que zero:
[TestMethod]
public void Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange()
{
// Arrange
double beginningBalance = 11.99;
double debitAmount = -100.00;
BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
// Act and assert
Assert.ThrowsException<System.ArgumentOutOfRangeException>(() => account.Debit(debitAmount));
}
Use o método ThrowsException para afirmar que a exceção correta foi gerada. Esse método faz com que o teste falhe, a menos que um ArgumentOutOfRangeException seja gerado. Se você modificar temporariamente o método em teste para gerar uma ApplicationException mais genérica quando o valor do débito for menor que zero, o teste se comportará corretamente, ou seja, ele falhará.
Para testar o caso quando o valor retirado for maior que o saldo, execute as seguintes etapas:
Crie um novo método de teste chamado
Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
.Copiar o corpo do método de
Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange
para o novo método.Defina o
debitAmount
como um número maior que o saldo.
Execute os dois testes e verifique se eles são aprovados.
Continuar a análise
O método que está sendo testado pode ser aprimorado ainda mais. Com a implementação atual, não temos como saber qual condição (amount > m_balance
ou amount < 0
) levou à exceção gerada durante o teste. Nós sabemos apenas que um ArgumentOutOfRangeException
foi lançado em algum lugar no método. Seria melhor se pudéssemos dizer qual condição em BankAccount.Debit
fazia com que a exceção fosse lançada (amount > m_balance
ou amount < 0
) para que possamos ter certeza de que nosso método está verificando corretamente seus argumentos.
Examine o método que está sendo testado (BankAccount.Debit
) novamente e observe que ambas as instruções condicionais usam um construtor ArgumentOutOfRangeException
que usa apenas o nome do argumento como um parâmetro:
throw new ArgumentOutOfRangeException("amount");
Há um construtor que você pode usar que relata informações muito mais avançadas: ArgumentOutOfRangeException(String, Object, String) inclui o nome do argumento, o valor do argumento e uma mensagem definida pelo usuário. Você pode refatorar o método em teste para usar esse construtor. Melhor ainda, use membros de tipo disponíveis publicamente para especificar os erros.
Refatorar o código em teste
Primeiro, defina duas constantes para as mensagens de erro no escopo da classe. Coloque as definições na classe em teste, BankAccount
:
public const string DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
public const string DebitAmountLessThanZeroMessage = "Debit amount is less than zero";
Em seguida, modifique as duas instruções condicionais no método Debit
:
if (amount > m_balance)
{
throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
}
if (amount < 0)
{
throw new System.ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
}
Refatorar os métodos de teste
Refatore os métodos de teste removendo a chamada a Assert.ThrowsException. Encapsule a chamada a Debit()
em um bloco try/catch
, capture a exceção específica que é esperada e verifique a mensagem associada. O método Microsoft.VisualStudio.TestTools.UnitTesting.StringAssert.Contains fornece a capacidade de comparar duas cadeias de caracteres.
Agora, o Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
pode ter esta aparência:
[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
// Arrange
double beginningBalance = 11.99;
double debitAmount = 20.0;
BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
// Act
try
{
account.Debit(debitAmount);
}
catch (System.ArgumentOutOfRangeException e)
{
// Assert
StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
}
}
Retestar, reescrever e reanalisar
Atualmente, o método de teste não lida com todas as situações que deveria. Se o método em teste, o método Debit
, não lançar um ArgumentOutOfRangeException quando o debitAmount
for maior que o saldo (ou menor que zero), o método de teste será aprovado. Esse cenário não é bom porque você deseja que o método de teste falhe se nenhuma exceção for lançada.
Esse resultado é um bug no método de teste. Para resolver o problema, adicione uma declaração Assert.Fail no final do método de teste para lidar com o caso em que nenhuma exceção é gerada.
Uma nova execução do teste mostra que agora o teste falha se a exceção correta é capturada. O bloco catch
captura a exceção, mas o método continua a ser executado e falha na nova declaração Assert.Fail. Para resolver esse problema, adicione uma instrução return
após o StringAssert
no bloco catch
. Executar novamente o teste confirma que você corrigiu esse problema. A versão final do Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange
tem esta aparência:
[TestMethod]
public void Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange()
{
// Arrange
double beginningBalance = 11.99;
double debitAmount = 20.0;
BankAccount account = new BankAccount("Mr. Bryan Walton", beginningBalance);
// Act
try
{
account.Debit(debitAmount);
}
catch (System.ArgumentOutOfRangeException e)
{
// Assert
StringAssert.Contains(e.Message, BankAccount.DebitAmountExceedsBalanceMessage);
return;
}
Assert.Fail("The expected exception was not thrown.");
}
Conclusão
As melhorias no código de teste levaram a métodos de teste mais robustos e informativos. Mas, mais importante, eles também melhoraram o código em teste.
Dica
Este passo a passo usa a estrutura de teste de unidade da Microsoft para código gerenciado. O Gerenciador de Testes também pode executar testes em estruturas de teste de unidade de terceiros que têm adaptadores para o Gerenciador de Testes. Para saber mais, consulte Instalar estruturas de teste de unidade de terceiros.
Conteúdo relacionado
Para obter informações sobre como executar testes de uma linha de comando, consulte VSTest.Console.exe opções de linha de comando.