Ir para o conteúdo
ou

Software livre Brasil

Minha rede

 Voltar a Planeta do A...
Tela cheia Sugerir um artigo

Helio Costa - hlegius : Unit Testing em aplicações já existentes e sem teste

16 de Junho de 2014, 6:35 , por Software Livre Brasil - 0sem comentários ainda | Ninguém está seguindo este artigo ainda.
Visualizado 2 vezes

ad: salve o Feed do blog no seu leitor e passe a ler os posts antes d'eu divulgá-los.

Se você achou interessante começar uma aplicação com Test-Driven Development, o que dizer sobre um dos fatores mais comuns em nossa área que é assumir um projeto que já está em produção, porém não possui testes de unidade ?

Softwares legados também possuem direito de ter seu lugar ao sol !

Berlim Wall, 1980

Cenário clássico

Você entra para uma nova equipe de desenvolvimento. Como um tester acostumado com as práticas do Test-First, você vai cegamente à procura do diretório(s) com os testes para: executá-los afim de descobrir se configurou o ambiente corretamente; ler, afinal quer entender um pouco mais do projeto; depois de vasculhar /tests, /spec, /xpto/namespace/module/tests e não encontrar nada você descobre que: o projeto não possui testes!

Normal? Infelizmente sim - Há muitos desenvolvedores que não gostam de testes. Os motivos variam e é assunto futuro -, vários projetos que vi não possuiam testes at all. Em todas às vezes porém, meus gestores eram favoráveis a adoção e receptivos a mudança de comportamento que isto causaria.

Sem testes e com carta branca para começar a mudar o cenário. O que fazer agora ?

$ ./configure

Antes de tudo, você precisa ver como o projeto está feito. Passe umas horas ou dia olhando o que tem ali e por onde poderia começar a trabalhar. Após isto, vamos listar coisas importantes sobre o código que já funciona em produção:

  • Não faça testes de unidade do que já existe;
  • Não seja convencido a fazer testes de unidade do código existente;
  • É insanidade querer testar as partes de um código que já funciona. Não faça isso;
  • Não faça teste de unidade do código existente.

Motivo para todos itens acima é o mesmo: teste de unidade é seu guia para construir o software requisitado da menor e melhor forma possível. Ele é um guia e não uma Bug Tool. Se o código já está presente, você, se cair na tentação de fazer teste daquilo, forçará seu teste a passar naquele código. Seu teste pode até pegar um bug, mas você, novato no projeto, não saberá que é um bug e acabará mudando o teste para passar naquela condição bugada. Costumo dizer que testar código já feito é perder tempo.

Vou comentar dois cenários aqui: a) você precisa criar um módulo/integração/package novo dentro desse projeto legado; b) você precisa adicionar testes ao código existente.

Vamos lá :)

$ make all

Vou pegar os dois casos e comentários sem separado:

a) Você precisa criar um módulo/integração/package novo dentro desse projeto legado

Para mim, dentre os dois esse é o mais fácil. Tudo que você precisa fazer é começar o módulo novo de forma isolada. Ou seja: evite depender do código sem teste dentro do seu módulo novo. Você pode obter isso com o uso de Adapters. Crie seu módulo novo, seguindo Test-Driven Development e toda vez que precisar da colaboração de uma classe/objeto que não tem o devido teste, crie um Adaptador que isolará aquela dependência instável do seu código novo. Isso te dará maior confiabilidade no que está fazendo.

Isole toda a comunicação do seu módulo novo, com o uso de Façades.

Supondo que você está fazendo um módulo de pagamento, crie uma façade para seu código e a faça prover os recursos que o restante do software necessitar:

class PaymentFacade {
    public ... create(...);
    public ... createRecurrent(...);
    public ... getPayments(Datetime forDate);
    public ... cancelRecurrent(Integer paymentId);
    public ... processPayment(Integer paymentId);
    ....
}

Na sua Façade, trafegue valores escalares e não objetos do sistema. Isto tornará seu module de pagamento mais isolado e protegido do código não testado.

b) Você precisa adicionar testes ao código existente

Lembre-se: não adicione testes de unidade ao código já existente e sem teste. Partindo disto, seguimos:

Anticorruption Layer, DDD

Este é mais complicado. Costumo utilizar uma técnica do livro Domain-Driven Design de Eric Evans chamada Anti-corruption Layer.

A ideia aqui é fazer igual na figura: o "ACL" é o Anti Corruption Layer, a camada que irá defender seu código novo do código legado sem testes.

Dando um zoom nesta imagem, tudo que precisamos fazer é criar uma layer que conterá classes/objetos ou/e métodos em classes existentes que farão adapters/façades, traduzindo o que o sistema já tem para conseguirmos encaixar no que estamos fazendo.

DDD Zoom-in

Client System: seu sistema legado Anticorruption Layer: o meio entre seu sistema legado e seu módulo novo External: seu código novo, totalmente Test-First.

Não sinta-se intimidado em tentar fazer deploy de uma versão funcional com seus adapters, façades e anticorruption layer. Eu já mantive em produção por algumas semanas código "macabro", cheio de "fios pendurados" e coisas em aberto, até que eu pudesse ajustá-las para em deploys futuros, pudesse removê-los tranquilamente.

# make install

Berlim Wall, the fall

Agora que consegue deployar seu código novo e testado junto do software que tinha antes sem testes de uma forma até que harmoniosa e isolada, você precisa derrubar o muro de Berlim que construiu: você precisará refatorar seu código legado e sem testes para que comece a adicionar testes nele também. Ao adicionar testes no código refeito, você poderá remover os Adapters, Façades e até a Anticorruption Layer daquele pedaço que isolava o código sem testes do código "novo".

Isto é uma parte importante, pois você precisará fazer tudo de dentro para fora. Explico: fora é a parte mais próxima do seu cliente possível (Controller, API, etc); dentro é a parte mais próxima do código que está isolando/refatorando. Sempre venha de dentro para fora nas tuas refatorações, pela razão de que assim, você afetará a menor quantidade possível de classes, pois identificará logo de pronto até onde pretende refatorar, colocando logo na sequencia disto seus adapters/façades.

Concluíndo

Agora você tem um bom motivo para utilizar adapters e façades. Esse tipo de refatoração é uma das minhas favoritas, pois envolve muito de lidar com isolamentos bem construídos e como manter isto de forma que não quebrará todo o software. O resultado final é uma aplicação funcional com um toque de código novo e testado ao mesmo tempo.

Recados

Na próxima semana, 23/06/2014, não apresentarei um post novo sobre Test-First. Dia 30/06 (última segunda do mês) porém, voltarei com o tema semanal do blog. Aproveite para revisitar algum post ou mesmo discutir o tema com seus conhecidos ou comigo ;)


Fonte: http://hlegius.pro.br/post/unit-testing-em-aplicacoes-ja-existentes-e-sem-teste

0sem comentários ainda

Enviar um comentário

Os campos são obrigatórios.

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.