segunda-feira, outubro 26, 2009

Benefícios econômicos da automação de testes unitários - Sua suite de testes é tão valiosa quanto seu código!

Hoje é consenso na engenharia de software e na comunidade ágil que realizar testes unitários automatizados é uma prática técnica fundamental para melhorar a qualidade do produto de software. Além disso, Michael Feathers em seu excelente livro "Working Effectively with Legacy Code" estudou e chegou a uma conclusão muito interessante e fundamental: O que é um sistema legado? É aquele em que o código não possui um conjunto abrangente de testes unitários automatizados.

Apesar das evidências, a maioria dos projetos de software e sistemas no mercado brasileiro e mundial não possuem suites de testes unitários automatizados. Portanto, a maioria dos sistemas já vira legado a partir do momento que entra em produção! As principais justificativas (e veremos que são desculpas, pois não se justificam) ditas por pessoas para não realizar testes unitários automatizados são as seguintes:
- O custo de colocar atividades de testes unitários automatizados encarecerá o projeto
- O cronograma ficará mais longo e, portanto, demorarei mais para entregar.
- Minha equipe não sabe ou não está treinada para realizar testes unitários automatizados

O objetivo deste artigo é justamente desmontar essas desculpas e mostrar os benefícios econômicos de realizar testes unitários automatizados. Os benefícios econômicos do uso de testes unitários evidenciarão que não realizá-los é uma atitude irracional do ponto de vista econômico.

Vamos então primeiro verificar quais são os benefícios de uma suite de testes unitários automatizados:
- Detecção imediata de defeitos em métodos. Estes defeitos costumam ser identificados rapidamente em testes unitários, mas possuem custo maior de análise e correção quando identificados apenas em um teste funcional de sistema.
- Melhor design detalhado e arquitetura, pois os testes unitários forçam os desenvolvedores a melhorar seu design para que ele se torne mais testável (é o famoso design for testability)
- Código mais estruturado e menos complexo.
- Melhor documentação do código. Cada teste unitário conta a estória e os objetivos de um método.
- Maior facilidade para refatorar código, o que diminui o tempo gasto na realização de manutenções evolutivas
- Diminuição do tempo de detecção e correção de manutenções corretivas, pois a suite de testes unitários automatizados garante que uma mudança em um ou mais trechos de código não impacte outras funcionalidades.

Agora vamos analisar os custos. Uma das justificativas para não se usar testes unitários automatizados é o custo de colocar atividades para realizá-los. Vamos então detonar mais uma vez esse mito e falácia. Muitos gerentes de projeto que não conhecem profundamente engenharia de software cometem esse erro de acreditar que o custo aumentará muito. O problema é que eles acreditam que o desenvolvedor apenas codifica, não testa. Essa é um grande erro. Todo desenvolvedor que seja minimamente profissional irá investir tempo testando seu código. Porém,muitos ainda fazem esses "testes" de forma totalmente manual e usando uma ferramenta que deveria ser pouco usada (apenas em casos extremos): o debug de código. Os gerentes acham que os desenvolvedores não testam, porém eles realizam "testes" sim: de forma manual e debugando código. Portanto, os desenvolvedores realizam uma atividade que não possui como saída um artefato evidente. Essa atividade "invisível" no cronograma dos gerentes será em sua maioria substituída por uma atividade com artefatos úteis e evidentes: testes unitários automatizados. Isso detona os dois primeiros mitos que levam as equipes a não fazer testes unitários automatizados: maior custo e maior tempo de cronograma.

Mas vamos considerar que a equipe é inexperiente em relação a automação de testes unitários. Vamos considerar então que o custo do projeto aumente em 10% (esse é um número bem elevado, o que não ocorrerá. Na prática a equipe se tornará mais produtiva realizando a automação). Num projeto de R$ 1.000.000,00 haveria então um gasto adicional de R$ 100.000,00 em treinamentos para a equipe e tempo extra para eles se acostumarem a realizar a automação.

Vamos agora dar números econômicos aos benefícios da automação de testes unitários:

- O melhor design, código estruturado, documentação e detecção imediata de defeitos podem reduzir de 10% a 50% os testes funcionais e especialmente os de aceitação e homologação (reduz a necessidade de dois ou mais ciclos/baterias de testes e diminui o número de defeitos detectados e a corrigir no momento de homologação). Além disso, melhora a percepção e a imagem de qualidade da equipe. Vide Boehm para essa conclusão.
- Durante o período de manutenção evolutiva e corretiva (o período em que o sistema entra em produção e que corresponde em média a 80% do ciclo de vida dessa aplicação) o tempo e custo de desenvolvedores investido para evoluções e correções é diminuído em torno de 10% a 30%. Isso ocorre devido à existência da suite de testes unitários automatizados que serve como documentação, facilita a detecção de defeitos recorrentes e potencializa a refatoração de código para permitir a inclusão de novas funcionalidades sem aumentar a entropia do sistema.

Portanto, vamos considerar que no nosso sistema exemplo de 1.000.000 de reais em torno de 30% do orçamento será para testes funcionais e de sistema (sem uso de automação de testes unitários). Portanto, podemos diminuir até 150.000 reais (no caso pessimista a redução seria de 30.000 reais) dos testes funcionais e gastamos 100.000 reais para realizar testes unitários automatizados (fora a redução dos testes "manuais" e debugs dos desenvolvedores).

Vamos considerar, como um exemplo, que durante a vida desse projeto gastaríamos mais 10.000.000 de reais em manutenções evolutivas e corretivas. Com a suite automatizada de testes unitários esse custo diminuiria entre 1.000.000 a 3.000.000 de reais!

Custo do projeto com automação de testes unitários automatizados: O mesmo, pois você apenas transfere atividades "invisíveis" (como debug e "testes" manuais dos desenvolvedores) e ainda reduz o número de ciclos de testes de sistema e homologação (portanto transfere custos de testes de sistema para testes unitários automatizados).

Benefício durante a manutenção do sistema em produção: Redução de pelo menos um milhão de reais (redução pessimista) em um investimento de 10 milhões durante a vida útil do software.

Resumindo, seu custo durante o projeto praticamente empata se você realizar testes unitários automatizados ou pode até ser menor. Além disso, você ganhará como benefício intangível uma melhor percepção de qualidade, pois os analistas de testes e os clientes encontrarão menos defeitos nos testes de sistemas e na homologação. E seu custo após a implantação em produção será muito menor, o que lhe trará um retorno sobre o investimento excelente sobre os testes unitários automatizados feitos.

A automação de testes unitários é economicamente relevante para o fornecedor (pois tem melhoria de qualidade e imagem), mas ainda mais relevante para o comprador (pois há benefício econômico real). Vai aí a dica para o fornecedor: realize os testes unitários automatizados e entregue como algo de valor agregado no seu serviço. Para o cliente: exija sempre uma suite de testes unitários automatizados junto com o produto de software.

Reforçando: É uma atitude irracional do ponto de vista econômico não criar uma suite abrangente de testes unitários automatizados.

8 Comentários:

At 11:38 AM, Anonymous Anônimo disse...

A realização de testes automatizados irá evitar que os desenvolvedores realizem seus proprios testes unitários e até um debug? Na minha opinião não. Com certeza os testes unitários in loco dos desenvolvedores não pegarão todas as possibilidades mas não haverá diminuição nessa tarefa. O debug só é feito para detectar onde está o erro. Imagino q continuará a ser feito no caso de erro encontrado por um teste automatizado, nao?

Ainda tenho dificuldades (até pq nunca trabalhei realizando testes unitários) em saber como fica essa divisão de trabalho...

Como fazer então com que o desenvolvedor utilize apenas o teste automatizado e não gaste tempo ele mesmo testando?

[]´s

Paula

 
At 11:43 AM, Blogger José Papo, MSc disse...

Olá Paula!

Pergunte para a maioria dos programadores (os que não automatizam testes) e eles te dirão que usam muito debug e muito "teste" manual. Agora fale com os desenvolvedores que já adquiriram o hábito de escrever testes unitários automatizados. eles te dirão que o uso de debug e "testes" manuais diminuiu consideravelmente. É como comentei: O debug é mal utilizado. Ele facilita o teste manual e acaba diminuindo o interesse pela escrita dos testes unitários de forma automatizada. Mas como descrevi no artigo, acaba sendo uma atitude irracional porque acaba gerando altos custos de manutenção no futuro.

 
At 2:11 PM, Blogger Shigueru disse...

Paula,

Os testes unitários automatizados são feitos pelos próprios desenvolvedores. Aqui não há divisão de trabalho. A ideia é que o desenvolvedor deixe de realizá-los manualmente e passe a escrevê-los (programá-los).

Reforço o ponto sobre o uso do debug. Debugar o código frequentemente é sintoma de alguma doença. Costumo dizer que debugar é apelar. É o último recurso que você usa quando realmente não sabe o que está acontecendo. Isso é grave. Nessas condições geralmente não há clareza no código. Não há logs que registrem um comportamento em específico.

Quando se escreve testes, a necessidade de debugar é reduzido drasticamente.

[]s

Shigueru.

 
At 2:32 PM, Blogger Vitor disse...

Se os testes unitários forem feitos de forma isolada, usando mocks e testando apenas o trecho de código que esta sendo desenvolvido, então acredito que a afirmativa de que "ajuda a detectar quebras em outras funcionalidades do sistema" não é verdadeira. Para que isso funcione eu tenho que testar a integração de meu trecho de código com outros trechos de código, e o teste não seria então unitário, mas sim integrado. No mais o artigo ficou muito bom, estou lendo o livro citado.

 
At 2:37 PM, Blogger José Papo, MSc disse...

Oi Vitor, Talvez eu não tenha explicado em detalhes. Quando comentei que os testes podem "ajudar a detectar quebras em outras funcionalidades do sistema" eu imaginei a seguinte situação. Imagine uma funcionalidade X que use um método A. Eu preciso alterar o método A para resolver algo da funcionalidade X. Agora imagine que outra funcionalidade Y faça reuso desse mesmo método A. Percebe que pode ocorrer algum problema? Os testes unitários podem vir a detectar se algo desse tipo ocorreu. E se ocorreu até ajudar a refatorar o código do método A se for o caso.

 
At 3:25 PM, Blogger Mauricio Aniche disse...

Olá Papo,

Você tem as referências para esses números que você citou no seu post? Seriam bastante úteis para minha dissertação de mestrado, que fala justamente sobre os benefícios de TDD.

 
At 8:45 AM, Blogger José Papo, MSc disse...

Olá Mauricio,

Os números percentuais foram retirados principalmente das minhas análises informais de sistemas com testes unitários e outros sem. Também através de artigos do Barry Boehm acerca da regra 1-10-100. Mas é isso mesmo, uma dissertação de mestrado mais formal e embasada em estudos de caso seria excelente para reforçar o que eu e outras pessoas do mercado já percebemos em análises menos formais. É um tema e tanto para um mestrado, mas recomendo que haja estudos de caso.

 
At 10:57 AM, Anonymous Anônimo disse...

Sempre é tempo de corrigir um erro...
O termo em inglês é
"Unit test"
----> teste de unidade!!!
unitário--> unitarian

Mas não é preciso ir até o inglês!
É um teste de "unidade" a unidade
aí é um método, uma classe,
um pacote... uma "unidade"!!

 

Postar um comentário

Links para este artigo:

Criar um link

<< Home


Veja as Estatísticas