Como os desenvolvedores aplicam os testes unitários?

Pessoal, o objetivo deste post é saber um pouco mais sobre os Testes Unitários. Neste caso, não vou colocar definições, muita teoria, etc.

A minha intenção é procurar apresentar um pouco mais da prática destes testes, como ele é realizado, como que o desenvolvedor começou a utilizar estes testes e assim por diante.

Para isso, contei com a ajuda de dois experientes desenvolvedores: Jair Rillo Junior e Maurício Hiroshi Nagaoka!

Segue uma entrevista com estes feras:

1. Como foi começar a fazer testes unitários? Vocês decidiram por conta própria ou por exigência de algum projeto, etc?

 Jair: Comecei por conta própria quando estava estudando sobre JUnit e TDD (Test-Driven Development). No primeiro projeto real que eu usei, o seu uso não era obrigatório porém era incentivado pelo time de arquitetura.

No segundo projeto (e o maior que eu já trabalhei) no início comecei a utilizar por conta própria, só que logo depois foi utilizado por todo o projeto.

 Maurício: Eu comecei a fazer testes unitários automatizados por conta própria. Lá pelos idos de 2000, eu trabalhava em um lugar em que tínhamos bastante liberdade p/ experimentar. Foi quando um colega e eu lemos o livro do Kent Beck, Extreme Programming Explained (http://goo.gl/EJyJC), e a gente se empolgou tentando aplicar o máximo possível de práticas do XP que a gente podia.

2. Como você vê a importância de testar o seu código?

Jair: Não importa o tamanho do projeto, sem teste unitário é impossível garantir boa qualidade do mesmo.

Diferente do que muitos pensam, teste unitário não ajuda apenas a testar os métodos de forma automática. Ele ajuda também em um melhor design da aplicação. Design no sentido de organização e utilização de classes/objetos, evitando o alto acoplamento entre as classes.

Quando algum método começa a se tornar dificil de testar, é um sinal claro de alto acoplamento e excesso de responsabilidade do mesmo. Com TDD, isso é descoberto facilmente na fase inicial de densenvolvimento.

 Maurício: Há, no mínimo, três benefícios que são de fundamental importância:

1) o código é testado o mais rápido possível e o mais frequentemente possível evitando o “vôo cego”, em que o programador escreve código durante dias pra só depois começar a testar e descobrir se tem algo funcionando;

2) ao final do desenvolvimento, você terá um conjunto de testes automatizados que podem ser facilmente executados (automaticamente, a qualquer momento) que te darão a “paz de espírito” de saber que o que quer que você tenha alterado/introduzido não quebrou nada do que já funcionava, isto é, que você não introduziu nenhuma regressão;

3) a vantagem principal é que ao pensar em testes logo no início do desenvolvimento, você desenha sua implementação de maneira a facilitar os testes unitários automatizados. Isto faz com que seu código fique melhor modularizado, mais coeso e menos acoplado pois você passa a pensar melhor nas responsabilidades de cada classe e acaba dividindo melhor estas responsabilidades entre as classes.

3. Quanto tempo é reservado para realizar os testes?

Jair: Não dá para mensurar o tempo. Quando se usa prática TDD, o teste é escrito junto com o código. Na verdade, o teste é escrito primeiro que o próprio código em sí.

 Maurício: Normalmente, quando estimamos o tempo de desenvolvimento já está incluído o tempo de se realizar os testes unitários, isto é, de implementá-los, já que eles nada mais são do que programas que utilizam o código que você está escrevendo.  É difícil mensurar quanto tempo é gasto com a elaboração de testes unitários pois ela ocorre simultanemente ao desenvolvimento do código propriamente dito.

4. É possível escrever testes para tudo o que for codificado?

Jair: Depende muito do ambiente que o software irá rodar. Em modo geral, quando se usa algum recurso externo (arquivo xml, banco de dados, etc) a resposta é não. Um exemplo: Se o sistema utiliza banco de dados não dá para fazer um teste unitário simulando uma base de dados, tem que ter, mesmo que em memória, uma base de dados para testes. Esse tipo de teste não é considerado unitário e sim integrado.

Em um mundo perfeito, o ideal é criar uma suite de testes automatizados, composto por teste unitário, integrado e funcional. Esse tipo de prática é bastante divulgada em ALM (Application Lifecycle Management).

 Maurício: É desejável, mas nem sempre possível ou mesmo compensador.

Esta dificuldade ocorre principalmente com código legado, que não foi escrito pensando-se em “testabilidade”, que acaba ficando monolítico e, por consequência, difícil de ser testado isoladamente. Alguns frameworks (bibliotecas) de desenvolvimento facilitam enquanto outros dificultam a criação de testes unitários automatizados.

Em alguns casos também pode-se chegar à conclusão de que não é compensador o esforço para se testar determinada unidade de código.

5. Que tipo de defeito é identificado nestes testes?

 

Jair: O objetivo do teste unitário é testar a menor parte do software, que no caso, é um método. O objetivo é escrever testes unitários para TODOS os cenários que o método for executado. Idealmente, todas as linhas de código de um software deve ser coberta por um teste unitário.

 Maurício: Em teoria qualquer tipo, mas basicamente o foco é em defeitos de funcionalidade, isto é, se a unidade de código (normalmente a classe, no caso de Java) faz o que deveria fazer.

6. Como você se organiza com os testes unitários? É criado um checklist para validar cada componente, classe, etc?

Jair: Não existe essa organização formal. Como já tido, o teste é escrito antes mesmo do código. Para cada cenário é escrito um teste diferente e o código é executado para verificar se existe erro ou não. Apenas quando não existir mais erro, um novo cenário é escrito.

O fato é que mesmo com testes unitários, não dá para prever todos os cenários na primeira fase de desenvolvimento.

O processo básico é o seguinte: Quando um novo erro é encontrado, seja pela equipe de testes ou pelo cliente, primeiro se escreve um teste unitário para comprovar o defeito e depois é corrigido o código.

 Maurício: Normalmente escrevo código utilizando TDD (Test Driven Development), que nada mais é do que você desenvolver seu código e, em paralelo, os testes unitários para exercitá-lo. Basicamente é um ciclo que se repete com os seguintes passos:

1) escreva um teste (sim, o teste é escrito antes do código!)

2) escreva o código para atender ao teste

3) refatore

4) se há mais coisas para serem testadas ou implementadas, volte ao passo 1; senão, fim.

7. Foi identificado uma melhora no desenvolvimento do sistema da época em que não aplicavam testes unitários em relação a situação atual que é realizado estes testes?

Jair: Embora não dê para mensurar, a melhora foi de fato gigantesca. Não apenas em relação a entrega para a equipe de testes, mas também por causa que defeitos antigos, agora cobertos por testes unitários, não voltaram à aparecer.

Maurício: Minha resposta é subjetiva, mas acho que a melhora mais sensível é a redução do número de ciclos em que o código transita entre o time de testes e o de desenvolvimento devido à redução de bugs que um código mais exercitado, mais maduro, apresenta. Se você pensar de maneira mais imediatista, pode chegar à conclusão que o tempo de desenvolvimento aumenta, afinal gasta-se tempo escrevendo os testes unitários. Mas se você ver um por uma perspectiva um pouco mais ampla, vai perceber que o ganho trazido pela redução na quantidade destes ciclos que mencionei é altamente compensadora.

Muito interessante as respostas, achei bem legal saber da iniciativa de começar a fazer testes unitários por conta própria, isto demonstra uma boa consciência entre a galera de desenvolvimento! Gostaria de agradecer ao Maurício e ao Jair pelas respostas, estão muito boas!

Espero que seja um incentivo para quem ainda não pratica testes unitários!

Para saber mais:

– TDD (Test Driven Development);  (TDD) ou em português Desenvolvimento dirigido por testes é uma técnica de desenvolvimento de software que baseia em um ciclo curto de repetições: Primeiramente o desenvolvedor escreve um caso de teste automatizado que define uma melhoria desejada ou uma nova funcionalidade. Então, é produzido código que possa ser validado pelo teste para posteriormente o código ser refatorado para um código sob padrões aceitáveis.

– ALM (Application Lifecycle management):  Todo o processo que guia a vida útil de uma aplicação desde a sua concepção, passando pela construção, operação e evolução.

 

Abraços.

Vinicius Sabadoti

Anúncios

Sobre Vinicius Sabadoti

Analista de Testes, gamemaníaco, cocólatra, adora escutar música, tocar um pouco de guitarra e fazer boas amizades. Ver todos os artigos de Vinicius Sabadoti

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: