Primeiras aulas do curso C#: Testes de unidade e TDD com xUnit

C#: Testes de unidade e TDD com xUnit

Promovendo rápido feedback - Introdução

Boas vindas! Sou o instrutor Daniel Portugal e este é o curso C#: testes de unidade e TDD com xUnit.

Primeiramente, fazemos a seguinte pergunta: como saber se o código está funcionando?

Podemos depender de uma pessoa ou de uma equipe de teste para receber um feedback, porém é possível que demore demais. Então, temos que pensar em uma maneira de diminuir esse tempo e nos tornarmos mais independentes.

Neste curso, conheceremos e aprenderemos algumas técnicas que aumentam nossa segurança e confiança no código, como o uso de TDD e xUnit que veremos ao longo das aulas.

No Visual Studio, teremos uma solução contendo uma biblioteca de classes com o sistema de leilões que iremos trabalhar, evoluiremos esse sistema introduzindo testes automatizados para nos proporcionar essa eficácia.

Começaremos com a aplicação console, observando as questões trazidas para depois trabalharmos com xUnit. Ao longo do processo, conheceremos mais a fundo a janela Gerenciador de Testes ou Test Explorer do Visual Studio.

Essas automatizações nos retornarão um feedback mais rápido, sua organização nos permitirá comunicar o comportamento do sistema com eficiência, poderemos evitar quebra do código a cada nova funcionalidade implementada e por fim, tornaremos nosso programa melhor com este apoio.

Veremos que o teste é um método de uma classe, o qual terá algumas anotações no xUnit. Escreveremos este código dentro de um padrão específico Arrange, Act e Assert.

Esperamos que este curso seja de grande utilidade e que tenha despertado a curiosidade sobre os testes automatizados.

A seguir, escreveremos o sistema de leilão. Então, vamos lá!

Promovendo rápido feedback - Avaliando um leilão

No exercício anterior, criamos a solução e o projeto contendo as classes de negócios do sistema de leilão.

Com o Visual Studio, abrimos a classe Leilao.cs e começaremos a primeira implementação que avalia o melhor lance, ou seja, o maior valor dentre as ofertas.

No código, temos a criação das propriedades Lances e Peca, sendo esta última a peça leiloada. Quando o pregão terminar, há um ganhador representado pela nova propriedade Ganhador somente de leitura e escrita apenas internamente cujo tipo é Lance.

public Lance Ganhador { get; private set; }

Na declaração de TerminaPregao(), pegamos o maior lance e colocamos em Ganhador, o qual começa como NULL e termina com um valor do objeto de tipo Lances. Isso é feito a partir do método Last(), que resgata o último lance vencedor.

public void TerminaPregao()
{
    Ganhador = Lances.Last();
}

Em seguida, no topo do código importamos o namespace do Linq para usarmos este método de extensão. Assim, finalizamos a funcionalidade de avaliar a melhor oferta de um leilão.

Para ter certeza de sua correta execução, acesse a janela "Gerenciador de Soluções" e clique com o botão direito sobre o diretório "tests", selecionando "Adicionar > Novo Projeto..." para criar um projeto do tipo "Aplicativo do Console" ou "Console Application" que guarda todos os testes. Este será nomeado como Alura.LeilaoOnline.ConsoleApp.

Automaticamente é criada um ponto de entrada Main(), e neste crie os objetos que representam as classes. Começando por leilao, tem como parâmetro de Leilao() o nome do pintor "Van Gogh".

Porém, este último método não está sendo reconhecido no projeto porque precisamos fazer a referência do projeto que o contém. Então, clique com o botão direito do mouse sobre Dependências na janela "Gerenciador de Soluções", escolha "Adicionar Referência..." e selecione o item Alura.LeilaoOnline.Core para finalizar em "OK".

Depois, importe escrevendo using Alura.LeilaoOnline.Core no topo do código.

Insira outra variável em Main() para representar uma pessoa interessada no leilão chamada fulano, a qual é uma nova instância de Interessada() e chama a variável leilao. Depois, adicionamos mais uma pessoa interessada sob o nome maria com a mesma metodologia.

Ainda no mesmo bloco, dizemos que leilao recebe um lance com RecebeLance() de fulano valendo R$800,00 como parâmetro. Na sequência, escrevemos a mesma sentença para a oferta de R$900,00 de maria. Agora, imaginando que Fulano quer cobrir o último valor, inserimos mais uma linha com lance de R$1.000,00.

Depois, finalizamos o pregão com TerminaPregao(), verificando o ganhador e o valor imprimindo-os no console.

static void Main()
{
    var leilao = new Leilao("Van Gogh");
    var fulano = new Interessada("Fulano", leilao);
    var maria = new Interessada ("Maria", leilao);

    leilao.RecebeLance(fulano, 800);
    leilao.RecebeLance(maria, 900);
    leilao.RecebeLance(fulano, 1000);

    leilao.TerminaPregao();

    Console.WriteLine(leilao.Ganhador.Valor);
}

Executamos a aplicação com "Ctrl + F5" alterando o projeto de inicialização da solução como sendo o Console Application Alura.LeilaoOnline.ConsoleApp na barra superior.

opção Alura.LeilaoOnline.ConsoleApp em destaque no campo da barra superior

No console, vemos a janela apresentando apenas o valor ganhador "1000" de Fulano e assim, temos um código que verifica a funcionalidade. Podemos pensar em outras situações, como um outro lance de R$990,00 feito por Maria. Nesse cenário, a oferta vencedora continuaria sendo mil reais.

Ao adicionar esta nova situação, o terminal imprime este último valor, significando um funcionamento incorreto do programa. Logo, o código que contém Lances.Last() ainda não está funcionando.

Este exemplo de processo de teste com os diversos lances através de um código nos permite automatizar a verificação. Mas este ainda não está completo; no próximo passo veremos o que resta aplicar.

Promovendo rápido feedback - Estrutura de um teste automatizado

No passo anterior, vimos que o código da verificação não está completo, e resolveremos essa questão aqui demonstrando com a definição de algumas referências.

A primeira é encontrada aqui, e é uma proposta de padrão para arranjar e formatar o código em métodos que são testes unitários.

Devemos organizar os testes automatizados em três sessões funcionais chamadas AAA: Arrange, Act e Assert. A primeira propõe arranjar todas as pré-condições de entrada ou o cenário. Na segunda, deixamos claro o método testado e por último, verificamos os resultados esperados.

Agora, veremos se nosso código possui as três partes citadas; o cenário é constituído pelo objeto do leilão e seus interessados, bem como seus respectivos lances. Em seguida, o método a ser testado é o TerminaPregao(). Por fim, falta-nos verificar a última sessão.

Este Assert não está de forma automatizada por enquanto, pois ainda precisamos verificar por conta própria o resultado no console. Para fazer isso, adicione a variável valorEsperado com valor 1000 logo antes de Console.WriteLine().

Logo após esta linha, insira outra variável valorObtido que é igual a leilao.Ganhador.Valor, parâmetro retirado do comando de impressão. Para finalizar a verificação, adicione uma comparação com if() para imprimir a mensagem que indica se o valor esperado é igual ao obtido. Depois, usamos else para apontar o caso contrário.

static void Main()
{

//código omitido

    //Act - método sob teste
    leilao.TerminaPregao();

    //Assert
    var valorEsperado= 1000;
    var valorObtido = leilao.Ganhador.Valor;

    if (valorEsperado == valorObtido)
    {
        Console.WriteLine("TESTE OK");
    }
    else
    {
        Console.WriteLine("TESTE FALHOU");
    }
}

Assim, nossa sessão de Assert está automatizada. Logo, não precisamos mais nos preocupar em validar a expectativa observando o terminal diretamente, apenas vendo seu retorno.

Recebemos a mensagem de falha ao rodar a aplicação, afinal o último lance dado por Maria de R$990,00 não é o esperado, o que indica que o processo está completo e podemos arrumar o código. Portanto, usaremos estas três sessões para formatar nosso programa e garantir uma verificação rápida e segura.

Outra referência encontrada aqui apresenta um artigo de Martin Fowler que propõe outra maneira baseada em Given, When e Then. Também é um padrão associado com o anterior.

De volta ao Visual Studio, corrigimos o problema ordenando os lances pelo valor com OrderBy() na declaração de TerminaPregao().

public void TerminaPregao()
{
    Ganhador = Lances
    .OrderBy(l = l.Valor)
    .Last();
}

Ao executarmos novamente, o teste é aprovado após a correção no código.

Outro ponto levantado nas referências é o Unit Test Methods, considerado a parte mais interna para teste do software onde verificamos uma unidade de trabalho. Em geral, é representado por um método em uma classe, mas não necessariamente todos são testados unitariamente.

Com o primeiro teste finalizado, arrumamos o código criando um método estático void em Program chamado LeilaoComVariosLances(), onde extraímos o bloco das três sessões anteriores de Main() e o inserimos neste novo método declarado.

Assim, chamamos este novo método dentro de Main(). Antes deste escopo, declaramos outro método chamado LeilaoComApenasUmLance() e o inserimos em Main() com uma cópia do mesmo conteúdo extraído anteriormente, excluindo os lances de Maria para deixar apenas os de Fulano cujo valor esperado passa a ser de R$800,00. Desta forma, temos dois cenários de teste.

static void Main()
{
    LeilaoComVariosLances();
    LeilaoComApenasUmLance();
}

Executamos a aplicação para ver a informação dos dois testes. Ainda, nosso código está bastante grande, pois copiamos o bloco de verificação com as três sessões em cada um dos novos métodos. Podemos extrair o corpo de if() e else para um novo método Verifica() antes de LeilaoComVariosLances().

Interpolamos a última string para verificar quais eram os valores esperados e obtidos. Assim, podemos chamar Verifica() recebendo o valorEsperado e valorObtido dentro dos métodos LeilaoComVariosLances() e LeilaoComApenasUmLance().

Ainda, podemos melhorar o programa ainda mais adicionando cores ao console para cada resultado com ForegroundColor e ConsoleColor, capturando a cor original e retornando-a ao final.

private static void Verifica(double esperado, double obtido)
{
    var cor = Console.ForegroundColor;
    if (esperado == obtido)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("TESTE OK");
    }
    else
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(
            $"TESTE FALHOU! Esperado: {esperado}, obtido: {obtido}.");
    }
    Console.ForegroundColor = cor;
}

Teste o resultado alterando temporariamente o valor do maior lance e rodando no console. Vimos que alguns recursos eram preexistentes, e no próximo passo veremos algumas bibliotecas que já realizam estes trabalhos.

Sobre o curso C#: Testes de unidade e TDD com xUnit

O curso C#: Testes de unidade e TDD com xUnit possui 181 minutos de vídeos, em um total de 56 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana