Testes unitários são um método de verificação de unidades individuais de código fonte. Uma unidade pode ser considerado uma classe por completo ou apenas uma função ou procedimento.
Os testes unitários devem ser o maior grupo de testes desenvolvido para um produto. O Mike Cohen criou à alguns anos atrás uma estrutura sob a forma de uma pirâmide, do que deve ser a importância dada a cada grupo de testes. A pirâmide é semelhante à que se encontra na imagem abaixo. Podem encontrar mais informação sobre esse assunto nesse artigo.
A utilização de testes unitários é bastante benéfica para qualquer que seja o produto desenvolvido. De seguida aponto aquilo que eu considero serem os principais benefícios da sua utilização. É apenas uma opinião pessoal e não reflete necessariamente a opinião da comunidade.
Principais benefícios da utilização de testes unitários
- A abordagem unitária (ou modular) usada por este tipo de testes elimina a dependência de outros módulos externos.
- Conseguimos testar partes de um projeto sem existir a necessidade de todas as partes estarem concluídas ou disponíveis.
- A equipa de desenvolvimento consegue identificar e corrigir o problema muito rapidamente, uma vez que o tempo que passou entre o momento de criação e o momento em que foi encontrado o erro é muito pouco.
- É muito mais fácil obter uma larga cobertura do código testado permitindo assim perceber e distinguir qual o código exercitado e qual o código que nunca foi usado. O que pode acontecer porque ainda não criamos testes que façam uso dessa zona do código ou porque detectamos uma zona morta, isto é, um pedaço de código que independentemente das condições iniciais nunca será atingido.
- Os custos associados à criação e à execução destes testes são sempre menores quando comparados com os custos de testes funcionais.
- Permite a fácil e rápida inclusão num sistema de continuos integration.
- A rápida eliminação dos defeitos de software leva por um lado a melhoria global dos produtos que se está a desenvolver, mas por outro lado garantir que cada módulo funciona corretamente antes de o começarmos a utilizar em conjunto com outros facilita muito o seu processo de integração num produto porque garante que os erros aqui encontrados irão corresponder a problemas de integração e não problemas na construção dos vários módulos.
Muitas das vezes as equipas de trabalho, não querem escrever os testes unitários porque não percebem o que estes são importantes ou porque têm ideias pré-concebidas sobre o assunto. Ideias como “é perda de tempo”, ou “se existirem bugs eles serão apanhados mais à frente” ou ainda “são testes a equipa de testes que os crie” entre muitas outras. De seguida apresentam-se alguns desses principais equívocos e o porque desse ponto de vista estar errado.
Alguns equívocos ou ideias tipicamente erradas acerca de testes de software :
- Um dos principais equívocos para a não criação de testes unitários é acreditar que os bugs irão ser todos apanhados na fase de testes de integração. Mas quando os erros chegam a esta fase o tempo de resolução é sempre muito mais elevado porque já não identificamos de modo tão exato a localização do problema e temos de andar à procura do mesmo através de várias camadas ou através de vários módulos. Por outro lado é muito mais fácil atingir as diferentes possibilidades de utilização de um método através da sua utilização direta do que tentar fazer o mesmo a partir da utilização destes por outros módulos.
- Outro grande equívoco para a não criação de testes unitários é a de que os programadores acreditam que irão perder muito tempo. Uma grande parte deles acreditam que são bons programadores e que nunca cometem erros. Mas o desenvolvimento de software é uma operação bastante complexa, e errar é uma condição da natureza humana.
- Os erros criados são de algum modo triviais ou pouco importantes. Mas colectivamente estes podem resultar num período excessivo de integração resultando por fim numa ultrapassagem dos tempos definidos para a entrega do projeto.
- Percebendo a importância dos mesmos é necessários começar a criá-los. E existem alguns aspectos que quando tidos em conta ajudam a melhorar a qualidade dos testes desenvolvido e por consequência a sua eficácia. Dou apenas alguns exemplos daquilo que me parece importante.
Algumas boas práticas para a criação de Testes Unitários:
- Garantir que cada teste é independente dos restantes. Um bom modo de despistar este tipo de dependências é correr sempre os testes por uma ordem aleatória. De modo a que independentemente da ordem o resultado de cada teste não pode variar.
- Cada comportamento deve apenas ser especificado por um único teste de modo a evitar que mudanças no comportamento da aplicação obriguem à alteração de muitos testes.
- Os vários módulos devem ser testados de forma independente de modo a evitar uma sobreposição entre os testes e o comportamento.
- Cada teste criado deve ser de fácil leitura de modo a facilitar o trabalho a elementos que continuem o trabalho algum tempo depois. Estes devem ter um nome elucidativo da sua função, e na implementação do mesmo deve ser claro o que é que está a ser testado.
- Antes de iniciar uma alteração importante garantir que todos os testes unitários estão a passar. De modo a termos a certeza que após as alterações ao software os possíveis problemas existentes foram por nós introduzidos.
- Garantir que os bugs encontrados durante esta fase são corrigidos antes de iniciarmos a fase seguinte.
- Criar um ambiente limpo para a execução de cada teste. O resultado do teste anterior não pode influenciar o resultado do teste atual apenas porque de algum modo correu mal ou deixou o ambiente em mau estado. É uma boa prática cada teste ante de executar o “core” da sua atividade colocar o ambiente numa estado conhecido e fiável. Esta situação vai garantir que os resultados obtidos são de confiança.
- Devem ser utilizados stubs ou mocks de modo a testar de forma mais eficiente. Estes dois termos embora bastante semelhantes e muitas vezes confundidos são diferentes. Uma boa distinção entre ambos pode ser encontrado neste excelente artigo do Martin Fowler (Mocks aren’t Stubs).
- Devem ser feitas alterações ao código usado nos testes unitários sempre que forem desenvolvidas melhorias no código alvo dos testes.
Uma abordagem adequada para com os testes unitários proporciona uma rápida detecção de erros de software, numa fase em que a sua correção será bastante rápida dado que a implementação ainda está bastante fresca na mente do programador. A eficiência e a qualidade são melhor representados quanto mais cedo no ciclo de desenvolvimento estiverem os testes. Uma boa utilização de estratégias de testes, uma gestão adequada do processo de testes, e um uso adequado de ferramentas de teste ajudam a maximizar o esforço de teste. Todas estas opções ajudam a um processo de desenvolvimento de boa qualidade que beneficiam a empresa e o produto desenvolvido.
Existe um largo conjunto de ferramentas que permitem a rápida criação de testes unitários. Para algumas das linguagens de programação mais conhecidas como o Java e o C# as seguintes utilitários podem ser considerados válidas opções para a criação de testes unitários.
Por muitas das vezes que tentamos criar testes existem dependências que não estão concluídas, ou partes do software as quais não nos queremos preocupar. Podemos para esses casos criar stubs e mocks para simular esse comportamento. Alguns exemplos de aplicativos desse género são os abaixo indicados:
- Easymock (para ser usado em Java)
- Mockito (para ser usado em Java)
- Rhino Mocks (para ser usado em .Net)
- EasyMock.NET (para ser usado em .Net)
- Existem muitos mais recursos para além dos aqui referidos, usei apenas aqueles que já usei e que são de algum modo de utilização livre.
- Existem muitos recursos na Web que ajudam a tentar compreender como é que criamos e para que servem os testes unitários, mas aqueles que mais me ajudaram a compreender o tema foram os que eu indique abaixo.
Bibliografia
http://www.codeproject.com/Articles/5772/Advanced-Unit-Test-Part-V-Unit-Test-Patterns
http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/
http://blog.goyello.com/2011/10/06/three-pillars-of-unit-tests/
http://www.youtube.com/watch?v=szVYZOvtJks&feature=related
http://martinfowler.com/articles/mocksArentStubs.html
http://readwrite.com/2008/08/13/12_unit_testing_tips_for_software_engineers
Bom, até à próxima.