Compartilhar via


Noções básicas de teste de unidade

Este tópico descreve as Noções básicas de gravar e executar o teste de unidade no Visual Studio Test Explorer.Ele contém as seguintes seções:

Visão geral de teste de unidade

  • Início rápido

O exemplo de solução de MyBank

Criando projetos de teste de unidade

Escrever seus testes

Executando testes no Gerenciador de testes

  • Executando e exibindo os testes na barra de ferramentas do Gerenciador de testes

  • Executando testes depois de cada compilação

  • Filtragem e agrupamento de lista de teste

Depuração de testes de unidade

Ferramentas adicionais para testes de unidade

  • Geração de código do aplicativo de testes

  • Gerar vários testes usando dados controlados por métodos de teste

  • Análise de cobertura de código de teste de unidade

  • Isolando os métodos de teste de unidade com o Microsoft Fakes

Visão geral de teste de unidade

Gerenciador de testes do Visual Studio foi projetado para oferecer suporte a desenvolvedores e equipes que incorporam testes de unidade em suas práticas de desenvolvimento de software.Testes de unidade ajuda a garantir a exatidão do seu programa, confirmando que o código do aplicativo faz o que você espera que ele faça.Em testes de unidade, analisar a funcionalidade do programa para descobrir os comportamentos podem ser testados discretos que você pode testar como indivíduo unidades.Você usa um framework de teste de unidade para criar testes desses comportamentos e relatar os resultados desses testes.

Teste de unidade tem o efeito maior quando é parte integrante do seu fluxo de trabalho de desenvolvimento de software.Assim que você escrever uma função ou outro bloco de código do aplicativo, você pode criar testes de unidade que verifique o comportamento do código em resposta a standard, limites e casos incorretos de dados de entrada e que se suposições explícitas ou implícitas feitas pelo código.Em uma prática de desenvolvimento de software conhecida como desenvolvimento baseado em testes, criar testes de unidade antes de escrever o código para usar os testes de unidade como documentação de design e especificações funcionais da funcionalidade.

O Gerenciador de testes fornece uma maneira flexível e eficiente para executar seus testes de unidade e exibir seus resultados no Visual Studio.O Visual Studio instala a estruturas de código gerenciado e nativo de testes de unidade de Microsoft.O Gerenciador de testes também pode executar código aberto e de terceiros estruturas de teste de unidade que implementaram interfaces de complemento do Gerenciador de testes.Você pode adicionar muitas dessas estruturas por meio do Gerenciador de extensões do Visual Studio e na Galeria do Visual Studio.Consulte Como instalar estruturas de teste de unidade de terceiros

Exibições do Gerenciador de teste podem exibir todos os seus testes ou apenas os testes que passaram, falharam, ainda não foram executados ou foram ignorados.Você pode filtrar os testes em qualquer modo, o texto correspondente na caixa de pesquisa no nível global ou selecionando um dos filtros predefinidos.Você pode executar qualquer seleção dos testes a qualquer momento.Quando você usa Visual Studio Ultimate, você pode executar testes automaticamente depois de cada compilação.Os resultados de uma execução de teste são imediatamente aparentes na barra de aprovação/reprovação na parte superior da janela do explorer.Detalhes do resultado de um método de teste são exibidos quando você seleciona o teste.

Início rápido

Para obter uma introdução ao teste de unidade que leva você diretamente no código, consulte um destes tópicos:

O exemplo de solução de MyBank

Neste tópico, usamos o desenvolvimento de um aplicativo fictício chamado MyBank como exemplo.Não é necessário o código real que siga as explicações neste tópico.Métodos de teste são escritos em c# e apresentados usando o Microsoft Unit Testing Framework para código gerenciado, no entanto, os conceitos são facilmente transferidos para outros idiomas e estruturas.

Solução de MyBank

Nossa primeira tentativa de um projeto para o MyBank aplicativo inclui um componente de contas que representa uma conta individual e suas transações com o banco e um componente de banco de dados que representa a funcionalidade de agregar e gerenciar as contas individuais.

Criamos um MyBank solução que contém dois projetos:

  • Accounts

  • BankDb

Nossa primeira tentativa de criação de Accounts projeto contém uma classe para manter informações básicas sobre uma conta, uma interface que especifica a funcionalidade comum de qualquer tipo de conta, como depositando e retirando ativos da conta, e uma classe derivada da interface que representa uma conta bancária.Começamos os projetos de contas criando os seguintes arquivos de origem:

  • AccountInfo.csDefine as informações básicas de uma conta.

  • IAccount.csdefine um padrão IAccountinterface para uma conta, incluindo métodos para depositar e retirar ativos de uma conta e recuperar o saldo da conta.

  • CheckingAccount.cscontém o CheckingAccount classe que implementa o IAccounts interface para uma conta bancária.

Sabemos de experiência que uma coisa que faça uma retirada de uma conta bancária certificar-se de que a quantidade retirada é menor que o saldo da conta.Portanto, substituir o IAccount.Withdaw método no CheckingAccount com um método que verifica para essa condição.O método pode ter esta aparência:

public void Withdraw(double amount)
{
    if(m_balance >= amount)
    {
        m_balance -= amount;
    }
    else
    {
        throw new ArgumentException(amount, "Withdrawal exceeds balance!")
    }
}

Agora que temos alguns códigos, é hora de testar.

Criando projetos de teste de unidade

Um projeto de teste de unidade geralmente espelha a estrutura de um projeto de código única.O exemplo de MyBank, você adiciona dois projetos de teste de unidade chamados AccountsTests e BankDbTests para o MyBanks solução.Os nomes de projeto de teste são arbitrários, mas adotar uma convenção de nomenclatura padrão é uma boa idéia.

Para adicionar um projeto de teste de unidade para uma solução:

  1. Sobre o arquivo menu, escolha novo e, em seguida, escolha projeto (teclado: Ctrl + Shift + N).

  2. Na caixa de diálogo Novo projeto, expanda o instalados nó, escolha o idioma que você deseja usar para seu projeto de teste e, em seguida, escolha teste.

  3. Para usar uma das estruturas de teste de unidade do Microsoft, escolha o projeto de teste de unidade da lista de modelos de projeto.Caso contrário, escolha o modelo de projeto da unidade da estrutura de teste que você deseja usar.Para testar o Accounts projeto do nosso exemplo, você deve nomear o projeto AccountsTests.

    Observação de cuidadoCuidado

    Nem todas as estruturas de teste de unidade de código aberto e de terceiros fornecem um modelo de projeto do Visual Studio.Consulte o documento do framework para obter informações sobre como criar um projeto.

  4. Em seu projeto de teste de unidade, adicione uma referência ao projeto de código sob teste, em nosso exemplo para o projeto de contas.

    Para criar a referência ao projeto de código:

    1. Selecione o projeto no Gerenciador de Soluções.

    2. Sobre o projeto menu, escolha adicionar referência.

    3. Na caixa de diálogo Gerenciador de referências, abra o solução nó e escolha projetos.Selecione o nome do projeto de código e feche a caixa de diálogo.

Cada projeto de teste de unidade contém classes que refletem os nomes das classes no projeto de código.Em nosso exemplo, o AccountsTests projeto conterá as seguintes classes:

  • AccountInfoTestsclasse contém os métodos de teste de unidade para o AccountInfo classe o BankAccount projeto

  • CheckingAccountTestsclasse contém os métodos de teste de unidade para CheckingAccount classe.

Escrever seus testes

O teste de unidade do framework que você usa e Visual Studio IntelliSense irá guiá-lo através da criação de testes de unidade para um projeto de código.Para executar o Gerenciador de testes, a maioria das estruturas exigem que você adicione atributos específicos para identificar os métodos de teste de unidade.As estruturas também fornecem uma maneira — normalmente por meio de declarar atributos de método ou instruções — para indicar se o método de teste foi aprovado ou reprovado.Outros atributos identificam os métodos de instalação opcional na classe de inicialização e antes de cada método de teste e métodos de subdivisão que serão executados após cada método de teste e antes que a classe é destruída.

O padrão AAA (Arrange, Act, Assert) é uma maneira comum de escrever testes de unidade para um método em teste.

  • O organizar inicializa os objetos de seção de um método de teste de unidade e define o valor dos dados que são passados para o método sendo testado.

  • O Act seção invoca o método sendo testado com os parâmetros organizados.

  • O Assert seção verifica se a ação do método em teste se comporta conforme o esperado.

Para testar o CheckingAccount.Withdraw método do nosso exemplo, podemos escrever dois testes: um que verifica o comportamento padrão do método e que verifica se uma retirada de mais do que o saldo falhará.No CheckingAccountTests classe, podemos adicionar métodos a seguir:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;
    var account = new CheckingAccount("JohnDoe", currentBalance);
    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;
    // assert
    Assert.AreEqual(expected, actual);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Withdraw_AmountMoreThanBalance_Throws()
{
    // arrange
    var account = new CheckingAccount("John Doe", 10.0);
    // act
    account.Withdraw(1.0);
    // assert is handled by the ExpectedException
}

Observe que Withdraw_ValidAmount_ChangesBalance usa explícito Assert instrução para determinar se o método de teste é aprovado ou reprovado, enquanto Withdraw_AmountMoreThanBalance_Throws usa o ExpectedException atributo para determinar o sucesso do método de teste.Nos bastidores, uma estrutura de teste de unidade encapsula os métodos de teste em instruções try/catch.Na maioria dos casos, se uma exceção é detectada, o método de teste falhará e a exceção será ignorada.O ExpectedException atributo faz com que o método de teste passar se a exceção especificada.

Para obter mais informações sobre as estruturas de testes de unidade da Microsoft, consulte um dos seguintes tópicos:

Definindo o tempo limite

Para definir um tempo limite em um método de teste individual:

[TestMethod]
[Timeout(2000)]  // Milliseconds
public void My_Test()
{ ...
}

Para definir o tempo limite para o máximo permitido:

[TestMethod]
[Timeout(TestTimeout.Infinite)]  // Milliseconds
public void My_Test ()
{ ...
}

Executando testes no Gerenciador de testes

Quando você compila o projeto de teste, os testes são exibidos no Gerenciador de testes.Se o Gerenciador de testes não estiver visível, escolha teste no menu do Visual Studio, escolha Windowse, em seguida, escolha Gerenciador de testes.

Gerenciador de testes de unidade

Como executar, gravar e executar novamente os testes, a exibição padrão do Gerenciador de testes exibe os resultados em grupos de testes com falha, testes aprovados, ignorado testes e Not Run Tests.Você pode escolher um cabeçalho de grupo para abrir a exibição que exibe todos os testes no grupo.

Executando e exibindo os testes na barra de ferramentas do Gerenciador de testes

A barra de ferramentas do Gerenciador de testes ajuda a descobrir, organizar e executar os testes que você está interessado.

Executar testes na barra de ferramentas do Gerenciador de testes

Você pode escolher executar todos para executar todos os testes, ou executar para escolher um subconjunto de testes a serem executados.Depois de executar um conjunto de testes, um resumo da execução de teste é exibida na parte inferior da janela do Gerenciador de testes.Selecione um teste para exibir os detalhes desse teste no painel inferior.Escolha abrir teste no menu de contexto (teclado: F12) para exibir o código-fonte para o teste selecionado.

Executando testes depois de cada compilação

Observação de cuidadoCuidado

Executando testes de unidade após cada compilação tem suporte apenas no Visual Studio Ultimate.

Executado após a compilação

Para executar seus testes de unidade após cada compilação local, escolha teste no menu padrão, escolha executar testes após compilação na barra de ferramentas do Gerenciador de testes.

Filtragem e agrupamento de lista de teste

Quando você tiver um grande número de testes, você pode digitar na caixa de pesquisa do Gerenciador de testes para filtrar a lista por cadeia de caracteres especificada.Você pode restringir o evento de filtro mais escolhendo na lista de filtros.

Categorias de filtro de pesquisa

Botão de grupo do Gerenciador de teste

Para agrupar testes por categoria, escolha o Group By botão.

Para obter mais informações, consulte Executando testes de unidade com o Gerenciador de Testes

Depuração de testes de unidade

Você pode usar o Gerenciador de testes para iniciar uma sessão de depuração para os testes.Depurar seu código com o depurador do Visual Studio perfeitamente leva para frente e para trás entre o projeto sob teste e os testes de unidade.Para iniciar a depuração:

  1. No editor do Visual Studio, defina um ponto de interrupção em um ou mais métodos de teste que você deseja depurar.

    ObservaçãoObservação

    Como os métodos de teste podem ser executado em qualquer ordem, defina pontos de interrupção em todos os métodos de teste que você deseja depurar.

  2. No Gerenciador de testes, selecione os métodos de teste e escolha depurar testes selecionados no menu de atalho.

Para obter mais informações sobre o depurador, consulte Depurando no Visual Studio.

Ferramentas adicionais para testes de unidade

Geração de código do aplicativo de testes

Se você estiver escrevendo seus testes antes de escrever seu código de projeto, você pode usar o IntelliSense para gerar classes e métodos no seu código de projeto.Escrever uma instrução em um método de teste que chama a classe ou método que você deseja gerar, abra o menu do IntelliSense sob a chamada.Se a chamada é para um construtor de uma nova classe, escolha gerar novo tipo no menu e siga o Assistente para inserir a classe em seu projeto de código.Se a chamada é para um método, escolha gerar novo método menu do IntelliSense.

Gerar método Stub Intellisense Menu

Gerar vários testes usando dados controlados por métodos de teste

ObservaçãoObservação

Esses procedimentos aplicam-se apenas para testar métodos que você escrever usando o Microsoft unit test framework para código gerenciado.Se você estiver usando uma estrutura diferente, consulte a documentação do framework para funcionalidade equivalente.

Métodos de teste orientado a dados permitem verificar um intervalo de valores em um método de teste de unidade.Para criar um método de teste de unidade orientado a dados, decorar o método com um DataSource atributo que especifica os dados de origem e a tabela que contém os valores de variáveis que você deseja testar.No corpo do método, você deve atribuir os valores de linha a variáveis usando a TestContext.DataRow[ColumnName] indexador.

Por exemplo, suponha que podemos adicionar um método desnecessário para a CheckingAccount classe chamada AddIntegerHelper.AddIntegerHelperadiciona dois números inteiros.

Para criar um teste orientado a dados para o AddIntegerHelper método, primeiro criamos um banco de dados denominado AccountsTest.accdb e uma tabela chamada AddIntegerHelperData.O AddIntegerHelperData tabela define colunas para especificar o primeiro e o segundo operando da adição e uma coluna para especificar o resultado esperado.Vamos preencher um número de linhas com valores apropriados.

    [DataSource(
        @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\MyBank\TestData\AccountsTest.accdb", 
        "AddIntegerHelperData"
    )]
    [TestMethod()]
    public void AddIntegerHelper_DataDrivenValues_AllShouldPass()
    {
        var target = new CheckingAccount();
        int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
        int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]); 
        int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
        int actual = target.AddIntegerHelper(x, y);
        Assert.AreEqual(expected, actual);
    }

O método de atributo é executado uma vez para cada linha na tabela.O Gerenciador de testes relata uma falha de teste para o método se qualquer uma das iterações falharem.O painel de detalhes de resultados de teste para o método mostra o método de status aprovado/reprovado para cada linha de dados.

Para obter mais informações, consulte Como criar um teste de unidade orientado a dados

Análise de cobertura de código de teste de unidade

ObservaçãoObservação

Cobertura de código de teste de unidade está disponível para todas as estruturas de teste de unidade que podem ser executadas pela estrutura de teste de unidade e de idiomas nativos e gerenciados.

Você pode determinar a quantidade de código do produto que realmente está sendo testado por seus testes de unidade usando a ferramenta de cobertura de código do Visual Studio.Você pode executar a cobertura de código em testes selecionados ou em todos os testes em uma solução.A janela Code Coverage Results exibe a porcentagem dos blocos que foram exercidos por linha, função, classe, namespace e módulo de código do produto.

Para executar a cobertura de código para métodos de teste em uma solução

  1. Escolha testes no menu do Visual Studio e escolha analisar cobertura de código.

  2. Escolha um destes comandos:

    1. Testes selecionados executa os métodos de teste que você selecionou no Gerenciador de testes.

    2. Todos os testes executa todos os métodos de teste na solução.

Resultados da cobertura aparecem na janela Code Coverage Results.

Resultados da cobertura de código

Para obter mais informações, consulte Usando cobertura de código para determinar quanto código está sendo testado.

Isolando os métodos de teste de unidade com o Microsoft Fakes

ObservaçãoObservação

Microsoft Fakes está disponível apenas no Visual Studio Ultimate.Microsoft Fakes pode ser usado somente com métodos de teste que você escrever usando estruturas de teste de unidade para código gerenciado.

O problema

Métodos de teste de unidade foco sobre como verificar o código interno em uma função pode ser difícil escrever quando o método em chamadas de teste funciona que apresentam dependências externas.Por exemplo, os métodos das CheckingAccount exemplo de classe provavelmente deve fazer chamadas para o BankDb componente para atualizar o banco de dados principal.Podemos refatorar o CheckingAccount classe ser semelhante à seguinte:

class CheckingAccount : IAccount
{
    public CheckingAccount(customerName, double startingBalance, IBankDb bankDb)
    {
        m_bankDb = bankDb;
        // set up account
    }

    public void Withdraw(double amount)
    {
        if(m_balance >= amount)
        {
            m_balance = m_MyBankDb.Withdraw(m_accountInfo.ID, amount);
        }
        else
        {
            throw new ArgumentException(amount, "Withdrawal exceeds balance!")
        }
    }

    private IBankDb m_bankDb = null;
    // ...

Os testes de unidade desse CheckingAccount.Withdraw método agora pode falhar devido a problemas causados pela chamada para m_bankDb.Withdraw.O banco de dados ou conexão de rede pode ser perdida ou as permissões no banco de dados podem estar erradas.Uma falha no m_bankDB.Withdraw chamada faria com que o teste falhar por razões que não estão relacionadas ao seu código interno.

A solução Microsoft Fakes

Microsoft Fakes cria um assembly que contém classes e métodos que você pode substituir para classes em métodos de teste de unidade que causam dependências.Uma classe substituto no módulo Fakes gerado declara um método e um delegado para cada método público no componente de destino.Em um método de teste, você deve implementar o delegado para criar o comportamento exato da chamada de dependência no método que você deseja testar.

Em nosso exemplo, podemos criar um assembly de Fakes para o BankDb do projeto e, em seguida, usar o StubIBankDb que é gerado pelo falsificações e que deriva de classe a IBankDb interface para remover a incerteza causada por interações com o banco de dados.Uma versão modificado o Withdraw_ValidAmount_ChangesBalance método de teste ficaria assim:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;

    // set up the Fakes object and delegate
    var stubBankDb = new MyBank.Stubs.StubIBankDb();
    stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
    var account = new CheckingAccount("JohnDoe", currentBalance, stubBankDb);

    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;

    // assert
    Assert.AreEqual(expected, actual);
}

Essa linha no método de teste:

stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }

implementa os Fakes delegar o Withdraw método usando uma expressão de lamba.O stubBankDb.Withdraw método chama o delegado e então sempre retorna o valor especificado, o que permite que o método de teste verificar confiavelmente o comportamento do Accounts método.

Mais sobre o Microsoft Fakes

Microsoft Fakes usa duas abordagens para criar as classes de substituto:

  1. Stubs gerar classes substituto derivadas da interface pai da classe de dependência de destino.Métodos stub podem substituir métodos virtuais públicos da classe de destino.

  2. Correções usa a instrumentação de tempo de execução para desviar as chamadas para um método de destino para um método de correção de substituto para métodos não virtuais.

Em ambas as abordagens, você pode usar os delegados gerados de chamadas para o método de dependência para especificar o comportamento desejado no método de teste.

Para obter mais informações, consulte Isolando código em teste com falsificação da Microsoft.