Demais posts desta série:
Artigo do tipo Tutorial
Recursos especiais neste artigo:
Conteúdo sobre Engenharia, Artigo no estilo Curso Online.

Testes Unitários
A disciplina de testes é de suma importância para qualquer indústria e no caso da indústria de software não é diferente, existindo para isso diversos tipos de testes, cada um com sua finalidade. Um destes tipos é o teste unitário, que visa validar o comportamento da menor unidade de nosso código: o método. Através de testes unitários conseguimos validar as entradas possíveis e retornos esperados de nossos métodos, garantindo que o mesmo se comportará de acordo com nossa expectativa. Para apoiar os testes unitários existem diversos frameworks, sendo o NUnit um dos mais populares. Neste artigo, apresentaremos os principais conceitos, fundamentos e mitos que cercam a prática de testes unitários e demonstraremos na prática como implementar o mesmo em seus projetos. Esta é a primeira parte desta série, que terá continuidade na próxima edição com conceitos mais avançados como uso de Mocks, Stubs, cobertura e automação de testes unitários.


Em que situação o tema é útil
Este tema é útil na garantia da qualidade dos projetos de software. Com testes unitários bem definidos e implementados, é possível identificar e corrigir erros em tempo de desenvolvimento e além de aumentar a confiança da equipe e do cliente no projeto, consegue-se ainda um aumento na produtividade da equipe, além de identificar quais os pontos de seu sistema que possuem maior risco de incidência de exceções, através da análise da cobertura dos testes.

Atualmente um dos principais paradoxos no desenvolvimento de software é o paralelo entre Produtividade e Qualidade. No âmbito da produtividade discutem-se ferramentas, automações, reuso de código, novos recursos e linguagens mais simples. No âmbito da qualidade discute-se sobre padrões, boas práticas, organização e testes.

Todos estes aspectos representam um universo de informações e recursos, que em alguns momentos caminham em uma linha tênue entre Produtividade e Qualidade, sendo o teste um deles.

Partindo da essência da palavra “Teste”, analisando a definição do Aurélio temos: “Prova, verificação da eficiência ou bom funcionamento (de máquinas, materiais etc)”.

Em toda indústria, a questão dos testes é de suma importância para a qualidade final dos produtos desenvolvidos. Usemos a indústria automobilística como exemplo:

· O veículo passa por um “crash test” para avaliar o acionamento do air bag;

· O veículo passa por um teste de velocidade para avaliar o funcionamento dos componentes internos do motor;

· O veículo passa por um teste no túnel de vento para avaliar a desempenho aerodinâmico do mesmo.

Pois bem, a indústria de software assim como todas as outras, possui diversas técnicas e metodologias empregadas para garantir a qualidade e o bom funcionamento dos produtos desenvolvidos. Como exemplo, podemos citar:

· Testes funcionais – Testes que avaliam as funções do sistema, avaliando as saídas que o mesmo gera de acordo com determinadas entradas;

· Testes de carga – Testes que visam avaliar a performance do sistema diante de um determinada carga de uso do mesmo;

· Testes de Stress – Testes que visam elevar o sistema aos seus limites, para que se conheçam as limitações de uso do mesmo, os pontos de quebra e os sinais de escalabilidade do mesmo.

Enfim, existe uma infinidade de tipos e técnicas de testes de software, cada uma com o seu propósito. Alguns destes devem ser executados por profissionais de teste, outros por usuários comuns e outros pelo próprio desenvolvedor, como é o caso do teste unitário.

Por mais que o conceito de testes unitários tenha se popularizado mais nos últimos anos, o mesmo é antigo, criado na década de 70 com o Smalltalk.

Um teste unitário nada mais é do que um código que executa outro código e verifica se o mesmo foi executado corretamente. Além disso, o teste unitário é o teste de menor nível no desenvolvimento de software, ou seja, com ele testamos as menores estruturas comportamentais que temos em nossos softwares, que são os métodos.

Sendo assim, quando estamos falando de testar unitariamente o software, estamos falando em criar métodos para testar os comportamentos de nosso sistema. Por exemplo, se temos um método somar, teríamos o método de testes somarTest.

Quando escrevemos um teste unitário para um determinado método, desejamos garantir que o comportamento do mesmo seja exatamente como o esperado nas mais variadas possibilidades. A ideia é pegar os bugs logo que eles nasçam. Logo, o teste unitário se torna um ativo do projeto, ou seja, pode ser reutilizado e executado diversas vezes sem onerar o seu tempo.

Quando escrevemos testes unitários precisamos ter em mente algumas características para que possamos tirar o máximo proveito dos mesmos.

Uma destas características é que os testes devem ser automáticos e repetíveis, o que significa dizer que não deve haver a necessidade de interação humana na execução dos testes e que os mesmos devem poder ser executados mais de uma vez.

Além disso, os testes precisam ser fáceis de implementar, caso contrário gastaríamos mais tempo implementando o teste do que implementando a funcionalidade, sem contar que se os testes forem difíceis de serem implementados, os mesmos podem se tornar complexos e confusos, gerando problemas na manutenção dos mesmos.

Uma vez escritos os testes, os mesmos devem poder ser executados a qualquer momento, considerando também que qualquer membro da equipe deve estar apto a executar o mesmo.

Os testes precisam ter sua execução rápida, caso contrário, dependendo do volume de testes, poderia levar muito tempo para esperar o resultado do mesmo, além do que este tempo aumentaria cada vez mais a medida que o projeto fosse crescendo.

Testes Unitários VS Testes de Integração

Uma falha conceitual muito comum de ocorrer é com relação a testes unitários e testes de integração. Uma vez que uma ação é disparada no sistema, uma série de ações é desencadeada a partir da mesma. Quando falamos em realizar um teste unitário, estamos falando em testar um comportamento isoladamente, enquanto que quando falamos em realizar um teste de integração, estamos falando em executar um conjunto de comportamentos.

abrir imagem em nova janela

Figura 1. Exemplo de cenário de integração

Na Figura 1 temos um exemplo deste cenário onde a ação do usuário desencadeia uma série de ações até que a informação seja persistida na base de dados. Cada seta destas representa um possível ponto de falha do sistema e caso algum destes pontos gere um erro, toda a operação será comprometida. Desta forma, ocorrendo um erro neste cenário, não saberemos em qual dos componentes o erro está. Imaginando um cenário hipotético, se criássemos um código para testar o clique do botão salvar deste formulário, não estaríamos criando um teste unitário, mas sim um teste de integração, visto que estaríamos validando a comunicação entre diversos componentes de nosso sistema.

Para realizar o teste unitário de um método de nosso sistema, temos que ser capazes de isolar o comportamento do mesmo, de forma a garantir que outros elementos não tenham influência na execução e resultado que esperamos do mesmo. A compreensão destes conceitos é fundamental para escrevermos bons testes unitários, assim como para entendermos e utilizarmos corretamente o conceito de Mock.

Testes unitários e TDD são coisas diferentes ...

Quer ler esse conteúdo completo? Tenha acesso completo