Design Patterns para melhorar seus testes, Parte 2: StepBuilder

Na parte 1 da série, vimos como usar o padrão Builder e também falamos sobre Fluent Interfaces. Nesta parte, vamos continuar da pergunta que fiz na conclusão do post anterior:

"E quando eu tenho muitos campos obrigatórios? Como o Builder me ajudaria?"


O padrão StepBuilder

O padrão StepBuilder é uma variante do Builder que vimos anteriormente. Ele foi descrito por Marco Castigliego nesses dois excelentes posts: StepBuilder pattern e Building smart Builders.

O StepBuilder tem como objetivo resolver problemas do Builder tradicional. Segundo Marco, alguns problemas do Builder tradicional são:

  • Não guia o usuário pela criação do objeto
  • Existe sempre o risco de deixar o objeto em um estado inconsistente
  • O usuário pode chamar o método build a qualquer momento, mesmo sem ter a informação necessária

Como o StepBuilder funciona?

Na prática, o StepBuilder funciona através de um simples encadeamento de interfaces, cada uma representando um passo na criação de um objeto.

Vamos considerar como exemplo a classe Usuario do post anterior, mas com um campo de e-mail e somente um campo de endereço:



A construção do nosso objeto Usuario, considerando que todos os atributos da classe são obrigatórios, deverá consistir nos seguintes passos, respectivamente:

  • Nome
  • Cpf
  • Data de Nascimento
  • Endereço
  • E-mail
  • Informações

Para obtermos esse encadeamento de passos, o padrão preconiza a criação de uma interface para cada passo (step), contendo um método que retorna a interface do step seguinte. Exemplo:

public static interface NomeStep  
{
   CpfStep nome(String nome);
}

Basicamente, podemos criar um StepBuilder para a classe Usuario seguindo três etapas:

  • Criar uma classe para o StepBuilder (UsuarioStepBuilder.java)
  • Criar as interfaces para cada passo da construção do objeto
  • Criar uma classe interna (Steps) que implemente todas as interfaces que representam os passos (e, consequentemente, implementando seus métodos)

Um exemplo de StepBuilder criado seria:

Um exemplo de utilização do StepBuilder em um teste seria:


Exemplo: Preenchimento de um formulário extenso em um Page Object

Vamos considerar o mesmo contexto do post anterior: testes de UI automatizados (com Selenium WebDriver + Page Objects) para um sistema de cadastro de usuários.

Poderíamos criar um StepBuilder em uma classe separada, com o objetivo de preencher o formulário extenso em questão. Uma possível implementação seria:

Um exemplo de teste que utilize esse StepBuilder seria:


Vantagens e Desvantagens

Da mesma forma que o Builder tradicional, a vantagem do StepBuilder é a fantástica legibilidade que conseguimos obter nos nossos testes. Criar testes usando um StepBuilder se torna ainda mais simples e até divertido, visto que o usuário é praticamente "guiado" a construir o objeto da maneira correta.

Uma desvantagem clara é a maior quantidade de código que você precisa escrever. Recomendo considerar a criação de StepBuilders para objetos que são necessários em várias ocasiões.

Nos últimos meses, criei diversos StepBuilders para construir objetos complexos nos testes de um projeto onde trabalho. A legibilidade melhorou consideravelmente, a equipe que também mantém os testes gostou da ideia, e as manutenções estão sendo bem tranquilas.


Conclusão

Para finalizar, quero recomendar fortemente a leitura do post original do Marco sobre StepBuilder. Um ponto muito interessante que ele aborda é como criar StepBuilders com caminhos de decisão diferentes para gerar seus objetos.

O projeto no GitHub foi atualizado com os exemplos mostrados neste post. Fique à vontade para baixar/forkar o projeto e fazer seus testes.

Na próxima parte da série, a ideia é vermos o padrão Factory, mas ainda preciso amadurecer o conteúdo exato, hehe.

Qualquer problema/dúvida/sugestão, é só falar! Abraços e até o próximo post :)


Referências

http://rdafbn.blogspot.com.br/2012/07/step-builder-pattern_28.html
http://www.javacodegeeks.com/2013/05/building-smart-builders.html
http://stefanteixeira.com.br/2015/07/29/design-patterns-para-melhorar-seus-testes-parte-1-builder-fluent-interfaces/


Sobre o autor: Stefan Teixeira trabalha como QA Engineer e, desde o final de 2014, tem se aventurado no mundo DevOps. É Bacharel em Ciência da Computação pela UFRJ e MBA em Garantia de Qualidade de Software pela Escola Politécnica da UFRJ. Entusiasta de Testes Automatizados (e de tudo que possa ser automatizado!), Agile Testing e da cultura DevOps.

Contatos: stefanfk@gmail.com | Twitter | LinkedIn


comments powered by Disqus