O que é teste de unidade?
- 10 mins read
- By Marjan Venema
- Updated on abril 26, 2024
Navigate to
Testes Unitários: Tutorial Sobre o que é, Como Fazer + Ferramentas a Utilizar
O que é Teste de Unitário?
Os testes unitários são essenciais. Sem eles, você está pisando sobre casca de ovos o tempo todo.
Isso é o que você ouve, pelo menos.
Mas por que isso acontece? E o que isso significa, afinal?
Vamos mergulhar no assunto.
O teste unitário consiste em verificar o comportamento das menores unidades em sua aplicação.
Tecnicamente, isso seria uma classe ou até mesmo um método de classe em línguas orientadas a objetos, e seria um procedimento ou função em línguas processuais e funcionais.
Funcionalmente, pode ser um conjunto de classes intimamente relacionadas. Como um “Cervo” e suas classes de suporte ”Cabeça”, “Rabo” e “Movimento”.
O que você considera uma unidade de trabalho é o que faz sentido para você. Não há regras rígidas e claras. Desde que isso o ajude a entender e pensar sobre sua aplicação.
Isso é diferente daquilo que é um teste unitário.
O que Faz um Teste Unitário um Teste Unitário?
Michael Feathers (autor de “Working Effectively with Legacy Code”) colocou a distinção no nível do processo e do sistema.
Os testes unitários precisam funcionar isoladamente porque precisam funcionar rapidamente.
Todo o conjunto de testes unitários de uma aplicação precisa funcionar em minutos, de preferência em segundos. Você verá o porquê mais tarde.
É por isso que os testes unitários não podem utilizar nenhum processo ou sistema externo. Nenhuma operação de E/S (input/output) de qualquer tipo (banco de dados, arquivo, console, rede) exceto o registro de falhas nos testes e talvez a leitura da configuração padrão de alternância de recursos no início de uma execução de teste.
Se seu código de teste (ou as bibliotecas que utiliza) fizer E/S ou acessar qualquer coisa fora de seu processo, não é um teste unitário, e sim um teste de integração.
Qual é o Propósito dos Testes Unitários?
Muitos dizem que o objetivo dos testes unitários é validar que cada unidade de trabalho se comporta como projetada, esperada ou pretendida. E que você pode executar seus testes unitários toda vez que alguém faz uma mudança. Com apenas o apertar de um botão.
Mas o verdadeiro propósito do teste unitário é fornecer-lhe feedback quase instantâneo sobre o projeto e a implementação de seu código.
A criação de testes unitários, ou melhor, a facilidade ou dificuldade com que você pode criá-los lhe diz exatamente o quão testável é seu código. O quão bem você o projetou. E se você escutá-los, ao invés de fazer gambiarras para superar qualquer dificuldade, todos ganham.
Veja como.
Quais São os Benefícios dos Testes Unitários?
Os testes unitários proporcionam muitos benefícios.
Tenho certeza que você já deve estar se perguntando como conseguir tudo isso.
Como Escrever Testes Unitários (Usando as Melhores Práticas)
Criar testes unitários é o mesmo que desenvolver qualquer código, mas há uma diferença.
Você cria um código de aplicação funcional para resolver um problema para seus clientes.
Você cria testes unitários para resolver os problemas que surgem no desenvolvimento do código da aplicação.
Adivinhe o que isso significa.
Sim, você é seu próprio cliente! E, claro, você quer tornar sua vida o mais fácil possível
Portanto, aproveite ao máximo essas melhores práticas.
Quando um teste depende de como outro teste mudou o ambiente (valores de variáveis, conteúdo de coleções, etc.), você terá dificuldade em acompanhar as condições iniciais para cada teste. Mais importante ainda, quando você obtiver resultados inesperados, você sempre se perguntará se as condições do teste ou o código de produção os causaram.
Use métodos de configuração e classes de utilidade aninhadas, se desejar, mas evite hierarquias de classes de teste e classes de utilidade geral. Isso evitará que você tenha que caçar através de diversas classes base ou unidades de classe de utilidade para encontrar os valores que um teste utiliza.
Quando uma ação deve ter mais de um efeito, teste cada um deles em um método diferente. Quando você se sentir tentado a usar mais de uma afirmação, pergunte-se se você está afirmando o fato mais significativo.
Resistir ao impulso de usar gambiarras e “automágica”. As gambiarras só abordam os sintomas, e a automágica reduz a transparência necessária para descobrir por que um teste que deveria ser bem-sucedido é reprovado ou, pior ainda, por que um teste que deveria ser reprovado é bem-sucedido.
Enfrente o que está causando a dor usando os meios mais diretos possíveis. Com bastante frequência, você pode fazer mudanças simples para tornar pelo menos parte de uma classe mais testável. “Working effectively with Legacy Code” de Michael Feathers é um excelente recurso para isso.
Armadilhas Comuns em Testes Unitários
Erros simples podem te fazer tropeçar seriamente. Pior ainda, eles podem te acalmar com uma falsa sensação de segurança.
Estes são os erros que você quer evitar
É uma indicação de que você está testando após o fato (em vez de uma abordagem de test-first), e está criando dores de cabeça para você mesmo ao acompanhar quais testes estão completos e devem ser bem sucedidos e quais testes falham por estarem incompletos.
Quando você não começa com um teste reprovado, você não saberá se ele é bem sucedido porque você tem um erro em seu teste ou porque o código funcional está correto.
Idealmente, você deseja executar todos os testes unitários em cada etapa de um ciclo vermelho-verde-refatorar, quer você use isso com ou sem uma abordagem de test-first, como TDD e BDD.
Os testes lentos interrompem seu fluxo.
A propósito, não há problema em usar um framework de testes unitários (veja abaixo) para escrever testes (mais) lentos, mas eles não são testes unitários, e você quer mantê-los em um conjunto de testes separado.
Isso lhe dará dores de cabeça quando os testes falharem em um ambiente e forem bem-sucedidos em outro.
Acompanhe-me agora. Você está quase lá.
Aqui estão algumas ferramentas e técnicas para você usar.
Ferramentas e Técnicas de Testes Unitários
Frameworks de Testes Unitários
Os frameworks de testes unitários fornecem tudo o que você precisa para criar testes unitários
Você pode encontrar um ou mais frameworks de teste unitário para quase todas as linguagens de programação por aí.
Teste Unitário Runners
Teste unitário runners descobrem os testes em seu código de teste automaticamente, executam todos os testes ou uma seleção específica, e depois reportam os resultados do teste.
Eles vêm como extensões de IDE e como utilitários autônomos de linha de comando. Você pode usar estes últimos em scripts de compilação, de modo que as builds de integração falhem quando um merge quebra o código existente.
Os frameworks de teste unitário têm seus próprios runners, mas você também pode encontrar runners dedicados que podem descobrir e executar testes escritos usando múltiplos frameworks.
Bibliotecas de Mock
Mocking libraries allow you to create test doubles, or fakes, easily.
Bibliotecas de mock permitem facilmente criar dublês e imitações para testes.
Você os utiliza para fornecer uma classe em teste com instâncias de suas classes colaboradoras. Desta forma, você pode facilmente personalizar o comportamento dos colaboradores de acordo com as necessidades de seu teste.
Injeção de Dependência / Inversão de Controle
Inversão de Controle, ou Injeção de Dependência, é um padrão de projeto que você usa para romper laços fortes entre as classes.
Em vez da classe A instanciar uma classe B5, você a fornece com uma instância do ancestral mais abstrato do B5 que dá à A os métodos e propriedades que ela precisa.
Facilita o teste unitário de uma classe com colaboradores, pois é muito mais fácil lhe fornecer imitações.
Speed up your Agile planning and execution!
Signup for a FREE Trial of Nimble Agile