Melhorando a cobertura de código e o ROI com testes de unidade em java
Melhorando a cobertura de código e o ROI com testes de unidade em java
A IMPORTÂNCIA DOS TESTES DE UNIDADE
Teste de unidade é um método de teste de software, pelo qual unidades individuais de código-fonte constituídas por conjuntos de um ou mais módulos de um programa de computador, juntamente com seus dados de controle associados, procedimentos de uso e procedimentos operacionais são testados para determinar se são adequados para uso.
Apesar de não gostarem muito de executá-los, os desenvolvedores reconhecem que os testes de unidade têm grande valor para detectar mais cedo defeitos no pipeline de desenvolvimento, onde eles são mais fáceis de corrigir, tornando o software melhor e acelerando a entrega.
O desafio é que os testes de unidade necessariamente requerem conhecimentos técnicos específicos do desenvolvedor e apesar das muitas ferramentas que ajudam na criação de testes funcionais, criar e manter testes de unidade ainda requer muito esforço manual, demorado e muitas vezes entediante. No entanto, o processo de criação de um teste de unidade é uma atividade benéfica por si só, pois ajuda os desenvolvedores a olhar seu código através de uma lente diferente, ao fazer uma revisão adicional no código.
Melhorando a cobertura de código e o ROI com testes de unidade em java
Melhorando a cobertura de código e o ROI com testes de unidade em java
Aumentar a cobertura e a eficiência dos testes
Os testes de unidade em Java têm tamanho reduzido e podem ser executados rapidamente antes que o código seja concluído. Eles também são muito mais fáceis de corrigir do que outros tipos de testes, devido ao seu escopo limitado.
Proporcionar mais rapidez para processos ágeis
Os processos ágeis dependem de suítes de teste eficientes, repetíveis e automatizadas para garantir que cada iteração não fique atolada em um ciclo de testes de complexidade desnecessária.
Maior qualidade e segurança
Os profissionais de desenvolvimento reconhecem que testar é a única maneira de garantir que o software esteja fazendo o que é necessário, mas as equipes geralmente não fazem testes suficientes ou os fazem muito tardiamente no ciclo de vida do desenvolvimento. A segurança, em particular, precisa ser incorporada em um aplicativo nos estágios iniciais, reforçando a necessidade de realizar os testes de segurança o mais cedo possível no pipeline de desenvolvimento.
Reduzir os custos a longo prazo
Corrigir defeitos encontrados pelos testes de unidade nos estágios iniciais de codificação é muito mais barato do que corrigi-los posteriormente. O investimento de curto prazo em automação de testes e infraestrutura para testes de unidade proporciona melhor qualidade do produto, segurança e entrega no prazo.
Desafios
Desafios
Apesar dos benefícios descritos acima, os desenvolvedores ainda apresentam resistências aos testes unitários, apesar da sua intenção de obter os melhores resultados. Os principais fatores de resistência são:
A criação de testes é um trabalho adicional e muitas vezes tedioso.
O teste de unidade é visto como o aspecto menos atrativo da programação, pois é um trabalho extra e cansativo. Além disso, criar um conjunto de testes abrangente e tentar manter as metas e os prazos do projeto são duas pressões antagônicas para as equipes de desenvolvimento.
A manutenção dos testes demanda investimento.
Assim como o código, os testes de unidade requerem manutenção. Qualquer alteração no código pode introduzir alterações nos testes associados. Não apenas os testes podem falhar devido a modificações na base do código, mas as falhas podem parecer que não estão relacionadas às alterações, levando à necessidade de triagem das falhas. A manutenção adicional cria a percepção de “trabalho dobrado” na mente de muitos desenvolvedores.
A simulação e o isolamento de unidades para teste são difíceis e demorados.
É fundamental isolar unidades para teste, mas isso requer simulação de dependências, o que pode ser um processo demorado.
.
FERRAMENTAS DE TESTE DE UNIDADE BASEADAS EM IA
O uso de tecnologias de teste de unidade com tecnologia baseada em Inteligência Artificial da Parasoft auxilia os desenvolvedores de Java a derrubar esses obstáculos, automatizando os aspectos rotineiros dos testes de unidade, incluindo criação, simulação e manutenção. Para acelerar a adoção, o Parasoft Jtest aproveita o investimento existente da equipe de desenvolvimento em estruturas de teste e simulação e libera tempo dos desenvolvedores, ao mesmo tempo em que agrega qualidade ao produto.
A automação realiza as partes simples e tediosas, liberando os desenvolvedores para fazer as atividades que exigem inteligência humana. Quanto maior for o nível de automação, menor tempo do teste de unidade e maior será o ROI.
.
DICAS PARA GESTORES E LÍDERES
.

Como os testes de unidade se encaixam no seu processo?
Modelo de maturidade dos testes de unidade
Os testes de unidade são a base de uma estratégia bem-sucedida de testes de desenvolvimento e devem ser adotados por qualquer organização que busque reduzir riscos e custos ao longo do ciclo de vida de desenvolvimento de seus aplicativos. Como um facilitador para a qualidade, os testes de unidade:
- Evitam a introdução de defeitos que consumiriam recursos valiosos se detectados posteriormente no processo de desenvolvimento.
- Reduzem o tempo necessário para corrigir problemas encontrados durante o teste.
- Reduzem os riscos associados a softwares defeituosos, que podem resultar em custos desnecessários, prejuízo à marca ou até mesmo a perda de vidas.
- Verificam a funcionalidade dos aplicativos o mais cedo possível e servem como uma forma de fornecer artefatos para rastreabilidade da conformidade.
- Melhoram principalmente o design e a manutenção do código.
Um bom modelo de maturidade é composto por quatro estágios:

1. Ad hoc
Nos estágios iniciais da adoção dos testes de unidade, os desenvolvedores criam e executam testes de unidade por iniciativa própria enquanto desenvolvem as funcionalidades. Não há políticas comuns nem uma diretriz de desenvolvimento estabelecida para realizar testes. O nível de maturidade neste ponto é baseado na experiência e na iniciativa dos profissionais. Não há centralização de ativos. Testes e artefatos de teste geralmente são criados como soluções únicas e podem ou não ser armazenados em uma máquina local. Os testes são criados sem considerar o negócio ou o caso de uso.
2. Reativo
O próximo nível depois do teste de unidade ad hoc é o reativo, onde a equipe percebe que a qualidade do software precisa ser aprimorada e está reconhecendo o impacto comercial que a má qualidade da aplicação pode causar. Também pode haver fatores externos, como segurança de software ou conformidade com padrões de segurança, que demandam uma abordagem mais rigorosa para os testes de unidade. Nesse nível de maturidade, a equipe e os gestores se comprometeram com os testes de unidade, mas a implementação é inconsistente em toda a organização ou até mesmo na base de código de um aplicativo específico. No nível reativo, o valor do teste de unidade é reconhecido, mas as definições inconsistentes de medição diminuem seu valor.
3. Proativo
Após a conscientização sobre os testes reativos, as empresas percebem a necessidade de padronizar a prática de testes de unidade em toda a organização. Uma política comum para testes de unidade é claramente documentada e as equipes reconhecem o teste de unidade como parte do processo de desenvolvimento. Os desenvolvedores padronizaram uma estrutura de teste e regularmente criam (e ampliam) testes de unidade em menos tempo.
O uso de uma abordagem orientada por dados para a tomada de decisões está em seus estágios iniciais. Uma política orientada por métricas aumenta a visibilidade, assim como um processo definido centralmente gerencia as atividades de teste de unidade. A equipe de desenvolvimento pode ver facilmente os resultados dos testes em seu ambiente de desenvolvimento e entendem o impacto das alterações no aplicativo.
Nesse nível, as organizações começam a ver benefícios reais de uma política de teste de unidade em toda a organização, geralmente pela diminuição tangível de defeitos graves. A maior visibilidade e rastreabilidade permite que os gestores tomem melhores decisões de negócios. O teste de unidade é institucionalizado como parte do processo e é um comportamento de desenvolvimento esperado e mensurável.
4. Otimizado
No nível otimizado dos testes de unidade, há um maior foco organizacional. As políticas são atualizadas regularmente como parte de um esforço de análise de causa raiz, para evitar que os defeitos sejam descobertos no controle de qualidade. As equipes de desenvolvimento estão testando de forma mais inteligente, fazendo uso total dos dados coletados durante o pipeline de desenvolvimento, para obter visibilidade da cobertura geral do aplicativo, identificar quaisquer lacunas nos testes e otimizar e focar os testes exatamente onde são mais necessários.
No estágio otimizado de maturidade as equipes de desenvolvimento de software evoluem de um modo de operação proativo para se tornarem times verdadeiramente orientados por dados, que usam políticas estabelecidas e ajustadas, aproveitando todos os recursos que as ferramentas modernas de automação de teste têm a oferecer. No estágio otimizado, as equipes analisam os dados coletados durante o desenvolvimento para tomar melhores decisões sobre a análise de impacto do teste.
.
.
MELHORES PRÁTICAS PARA ATUALIZAR CÓDIGO LEGADO COM SEGURANÇA
Para lidar com código legado, é preciso desenvolver uma maneira sustentável para gerenciar mudanças. Trabalhar com código legado pode ser uma barreira para um fluxo de trabalho ágil, mas é possível superar o desafio aproveitando as tecnologias apropriadas.
O que é código legado?
Muitas pessoas usam o termo “código legado” para significar simplesmente código antigo. Mas “antigo” e “legado” têm significados diferentes. Neste texto vamos definir o código legado como “qualquer código existente sobre o qual a equipe tenha conhecimento limitado”.
Código legado é a regra, não a exceção
Grande parte da infraestrutura de software no mundo hoje é executada em código legado. Então, a questão é como mitigamos os riscos associados ao código legado, quando precisamos fazer uma mudança?
O código legado pode ser uma barreira ao Agile
O problema com o código legado não é sua idade, mas sim o entendimento sobre como as alterações a serem feitas podem afetar a funcionalidade existente. As lacunas de conhecimento associadas ao código legado podem se tornar uma barreira, se você estiver fazendo a transição para uma nova metodologia de desenvolvimento, como Agile.
Aumentando a cobertura no código legado
O risco que o código legado em produção representa é relativamente baixo. Se estiver funcionando há anos, é provável que funcione nos próximos anos. Os riscos surgem quando você precisa fazer alterações nesse código legado para corrigir um defeito ou introduzir uma nova funcionalidade.
Quando as organizações decidem que precisam fazer alterações em uma base de código legada que passou por poucos testes, elas geralmente (e corretamente) determinam que precisam realizar mais testes na base de código, antes de começar a fazer alterações. A questão aqui é: como fazer isso?
Uma possibilidade é alocar recursos internos de desenvolvimento para escrever testes, antes de iniciar as alterações de código. Isso pode ter um custo enorme, tanto em termos financeiros, quanto de tempo investido que poderia ter sido utilizado no desenvolvimento de novas funcionalidades.
Uma segunda possibilidade é terceirizar a criação de testes de unidade para uma equipe externa. Isso pode economizar alguns custos, mas a desvantagem dessa abordagem é que desenvolvedores que não entendem o código acabam escrevendo os testes. Isso pode resultar em testes difíceis de manter porque não testam o código de forma adequada ou significativa o suficiente. Uma terceira possibilidade é adotar uma ferramenta para geração de testes de unidade. Essa abordagem pode economizar tempo, mas é ainda mais provável que resulte em testes insustentáveis e sem sentido do que a segunda abordagem. Para essas duas últimas abordagens, um alto número de cobertura de código pode ser alcançado, mas os testes podem apresentar um valor mínimo.
Crie testes em Java significativos e sustentáveis
O Parasoft Jtest é uma ferramenta que dispõe de uma interface amigável e oferece aos desenvolvedores um processo automático de criação de testes com base no código Java existente. Esse recurso gera um conjunto de testes com testes significativos, passíveis de manutenção e extensíveis para obter uma alta cobertura de código.
.
Atualize o código legado com confiança
Apresentamos a seguir um conjunto de etapas para atualizar o código legado com confiança.
.
1. Defina o escopo
Em vez de considerar toda a base de código legada, identifique as partes da base de código que precisam ser alteradas e concentre suas atividades de qualidade apenas nessas áreas do código. Em alguns casos, isso pode ser toda a base de código.
2. Automatize os testes existentes e capture a cobertura de código atual
Se a base de código legada já contiver alguns testes realizados, configure uma execução de teste repetível e automatizada, que execute os testes. Configure um mecanismo de cobertura de código para capturar a cobertura de código atual alcançada pelos testes existentes. Relate os resultados do teste e a cobertura do código para um local central, para facilitar a revisão por todas as partes interessadas. A Parasoft fornece ferramentas e painéis para ajudar a capturar e visualizar resultados de testes e cobertura de código em seus projetos.
3. Adicione cobertura de teste ausente
Utilizando o conhecimento sobre o estado atual da base de código, capture o comportamento atual do sistema criando testes onde existem lacunas de cobertura. Use uma ferramenta que ajude a criar rapidamente testes significativos para cobrir seu código legado.
A interface point-and-click do Parasoft Jtest permite que os desenvolvedores criem uma base de testes JUnit em massa, que inclui definições baseadas no código existente. O Jtest analisa todos os caminhos de código possíveis e gera um conjunto de testes de unidade com inteligência semelhante à humana para cobrir esses caminhos de código, configurando estados de objetos e simulações conforme necessário. Para casos em que o código legado não foi escrito prevendo a realização de testes, o Jtest também inclui a capacidade de criar testes que acessam diretamente métodos privados. O conjunto de regressão resultante é significativo, sustentável e extensível.
Quando a base de código legada tem alguns testes existentes, o Parasoft Jtest também pode realizar uma análise de lacuna de cobertura, que identifica testes existentes que podem ser clonados e modificados para alcançar partes não testadas do código. Essa abordagem produz novos testes, enquanto captura a “inteligência humana” já presente nos testes existentes, aumentando o retorno do seu investimento anterior na criação de testes.
Ao adicionar testes ausentes, é preciso obter o nível mais alto de cobertura razoavelmente possível. Entretanto, na maioria dos casos, atingir 100% de cobertura em toda a base de código não é prático. Um objetivo comum é atingir 80% de cobertura de código. Buscar mais cobertura do que isso diminui o retorno do investimento, já que os últimos 20% de cobertura de código geralmente são muito difíceis e demorados de serem alcançados.
4. Modifique o código com confiança
Quando você tiver uma boa cobertura a partir de uma perspectiva funcional, comece a fazer alterações na base de código com risco mínimo de prejudicar a funcionalidade existente. Modifique os testes criados anteriormente à medida que avança e adicione novos testes para as funcionalidades modificadas e as novas.
5. (Opcional) Execute ferramentas de análise estática e resolva violações
Outra prática que as equipes podem usar para modernizar uma base de código legada é executar ferramentas de análise estática no código e corrigir as violações relatadas. A análise estática pode ajudar a encontrar defeitos potenciais ou ocultos que estão incorporados ao código. Ao fazer isso, não perca tempo com verificadores de estilo ou de capacidade de manutenção. Em vez disso, concentre-se nas violações que apresentam um risco maior e estão relacionadas a sérios problemas de confiabilidade ou segurança.
É preciso fazer isso com cuidado, pois abordar violações de análise estática pode introduzir defeitos não intencionais no código. Por isso, é melhor executar esta etapa após o código ter sido coberto com testes. Os resultados da análise estática devem ser relatados a um local central, para que todas as partes interessadas possam revisar facilmente.
6. Monitore as métricas de qualidade do código
À medida que o desenvolvimento prossegue na base de código, monitore continuamente os resultados do teste, a cobertura do código e os resultados da análise estática na parte focada do código que está sendo alterada. Monitore as alterações a cada compilação como parte de um processo contínuo para garantir que a qualidade do software não piore. Isso permite identificar quando as melhores práticas não estão sendo seguidas e possibilitar ajustar o comportamento para garantir a qualidade do código alterado.
A Parasoft fornece uma poderosa plataforma de análise para capturar, correlacionar e relatar resultados de testes, análise de cobertura, violações de análise estática e outros dados de qualidade de software. A plataforma vai além dos relatórios estáticos. Ela também aplica análises adicionais para ajudar a identificar partes do aplicativo afetadas pelas mudanças. Aproveitando o conceito de grupos de recursos, é possível identificar um conjunto específico de arquivos ou diretórios e relatar cobertura, violações de análise estática e dados de métricas em relação ao escopo da base de código que está sendo alterada.

.
Como garantir a cobertura no código modificado
As etapas descritas acima ajudam a evitar que as alterações de código afetem negativamente as funcionalidades existentes, mas também é preciso estabelecer boas práticas para a base de código legada para o futuro. Manter um alto nível de cobertura escrevendo e atualizando testes à medida que o código evolui requer aceitação pela cultura organizacional. Para uma base de código grande e durante o período entre as tarefas específicas, pode ser difícil determinar se um conjunto apropriado de testes foi criado para o código atualizado.
Para resolver esse problema, as equipes devem medir a cobertura de código modificada, que é a quantidade de código que foi coberta pelos testes, considerando apenas o código que foi modificado entre duas compilações diferentes. Ao monitorar a cobertura do código modificado, a equipe pode se concentrar nas partes do código que estão sendo trabalhadas ativamente e ter confiança de que todas as alterações foram testadas.
Essa técnica funciona tanto se o ponto de partida para a base de código for um nível alto quanto baixo de cobertura. Em ambos os casos, impor um alto nível de cobertura de código modificado garantirá que todos os códigos novos e modificados sejam bem testados. Um objetivo comum para a cobertura de código modificado é 80%.
A Parasoft fornece tecnologia avançada que pode capturar automaticamente a cobertura do código modificado, notificando-o quando o código modificado (novo ou alterado) não estiver em conformidade com a política de cobertura.
.
As melhores práticas aprimoram a qualidade do código
As lacunas no conhecimento sobre o código legado representam riscos potenciais à medida que os desenvolvedores fazem alterações para manter ou estender a funcionalidade. As melhores práticas para processos e tecnologias compartilhadas aqui devem ajudar seu time a ganhar confiança para trabalhar em praticamente qualquer base de código e melhorar a qualidade do seu código legado.
A atuação conjunta entre Parasoft e a keeggo trazem mais qualidade de progressão aos nossos clientes, garantindo que a qualidade de código seja menos complexa e com objetivos claramente definidos, atuando sempre com uma alta política de cobertura.
Esse é um conteúdo dividido em duas partes, leia também o artigo: Entenda as armadilhas de código para ter direcionamento no aumento do ROI dos testes de Unidade em JAV para entender ainda mais sobre o assunto.