BDD – Vantagens e desvantagens no uso em Automação de Testes

BDD (Behavior Driven Development) vem sido adotado por muitas equipes de desenvolvimento como forma de documentação de regras de negócio e seus critérios de aceitação. Por se tratar de uma “documentação viva” ou “documentação executável”, ele consegue amarrar todo o processo de desenvolvimento à sua especificação, proporcionando assim uma fácil rastreabilidade dos pontos impactados por alterações nas regras de negócio. Por sua escrita ser de alto nível (fácil entendimento por todo o time) baseada no comportamento do sistema é comumente associado como uma técnica de testes de software, PORÉM é uma técnica criada para ser utilizada no DESENVOLVIMENTO do CÓDIGO DA APLICAÇÃO.

Uma vez que a automação de testes em todos os níveis (unitário, integração e interface) vem ganhando força nas equipes com o intuito de garantir a qualidade da entrega  de forma ágil e que, na maioria dos casos, são estruturadas através de códigos de programação, o uso do BDD vem sido adotado também nos testes automatizados. Contudo existem vantagens e desvantagens da sua adoção, bem como pré-requisitos que devem atendidos para que seu uso gere valor ao processo de desenvolvimento.

 

Antes de iniciarmos a discussão, vamos entender algumas premissas do BDD:

  • BDD é uma técnica e não uma ferramenta. Essa técnica é baseada em um padrão de escrita (Gherkin). Cucumber, SpecFlow e outros frameworks são ferramentas utilizadas para “ligar” a documentação no formato BDD ao código de programação.
  • BDD deve descrever o comportamento do sistema sem entrar em detalhes técnicos ou de implementação.
  • BDD deve manter uma linguagem de alto nível, onde qualquer pessoa do time, mesmo que não tenha domínio técnico das tecnologias, consiga entender claramente o objetivo da feature e seus cenários.
  • BDD deve ser gerado por todo o time. Mesmo que tenha um único responsável em sua escrita, todo o time deve colaborar para a criação das features e seus cenários.
  • BDD não precisa ser necessariamente a única documentação do seu projeto. Outros tipos de documentação podem ser utilizados, caso necessário, para especificação de detalhes técnicos como wireframes, swagger, diagramas de fluxo de dados etc.
  • BDD pode ser e deve utilizado em conjunto com outras técnicas de desenvolvimento como TDD, ATDD etc.
  • O arquivo do BDD (feature) deve ser único e todos do projeto devem consumi-lo de um único ponto. Assim é garantido que qualquer alteração impacte em todos os pontos que ele está vinculado.

 

Vantagens:

União de todos os códigos: Os códigos das automações de todos os níveis ficarão “amarrados” à uma “única documentação” e, caso esta seja alterada por uma mudança de requisitos, todos os códigos deverão ser refatorados, gerando uma cultura de melhoria/manutenção contínua das baterias de testes do sistema.

 

Reuso “forçado”: Dependendo da organização dos seus “Step Definitions”  você é obrigado a reutilizar steps já implementados, visto que as ferramentas não permitem duas definições com o mesmo texto. Um exemplo clássico é “When salvo o formulário”, se você tem formulários que serão salvos em diferentes features, logo em diferentes telas do sistema ou em diferentes pontos do seu código, pode descobrir que a implementação do passo que fez para uma feature já automatizada é exatamente igual ao passo de uma feature em implementação. Reuso é uma premissa de um bom código, seja de automação de testes ou de sistema. “Do not repeat yourself!” reconheça padrões de utilização, implementação e agrupe-os de forma a não ter que implementar a mesma função de forma diferente em diferentes pontos do seu código!

 

Entendimento e implementação do conceito de “Datadriven”: Os “Scenario Outline + Examples Tables” nada mais são que uma abstração de alto nível de um conceito antigo na automação de testes conhecido como “Datadriven”, que consiste na ideia que uma rotina, cenário ou fluxo com passos idênticos podem variar o resultado esperado de acordo com os dados utilizados. Quase todos orquestradores de testes disponibilizam suporte à técnica, porém o código para implementação pode ser um pouco complexo e envolver outras tecnologias como planilhas, arquivos csv, dentre outros. Utilizando Scenrio Outline basta adicionar uma linha na tabela de “Examples” para cada conjunto de dados a ser testado e pronto, a ferramenta utilizada para interpretar seu BDD vai fazer todo o trabalho para executar o cenário uma vez para cada linha da tabela.

 

Organização do código: O padrão Feature + StepDefinitions é obrigatório para o funcionamento de um código baseado em BDD. Pode não parecer muito e a organização não deve ser resumir só a isso, mas já é um primeiro passo para um código modular e organizado. Por incrível que pareça, existem muitos códigos de testes construídos sem nenhum padrão e muitas vezes em uma só classe >=O.

 

Tags everywhere: Segmentar os testes de acordo com criticidade (crítico, não crítico, fluxo principal, fluxo alternativo, fluxo de exceção etc), funcionalidade (login, cadastro, relatório etc), cobertura (smoke testes), tipos (api, web, end-to-end etc) e status da automação (automatizado, wip, manual etc) é essencial para traçar boas estratégias de execução de acordo com a necessidade do time em diferentes estágios do processo de desenvolvimento. O uso de tags tanto nos cenários como nas features e a fácil implementação da segmentação dos testes nas ferramentas é uma mão na roda na hora de definir essas estratégias.

 

Desvantagens:

Passagem de parâmetros entre steps: Umas dos dilemas do uso de BDD para os testes automatizados é forma da passagem de parâmetros entre os steps. Ao escrever o cenário a regra é não repetir o mesmo dado em dois steps distintos, ex:

 

                          Repete o valor de usuário “jose” no Given e no Then

 

Isso é necessário para que a escrita não fique “verbosa”, repetitiva e para que os pontos de possíveis  manutenções sejam minimizados. Como a implementação de cada step é feita em métodos distintos dentro de uma ou várias classes de step definitions temos que definir estratégias para compartilhamento dessa informação entre estes. Não existe uma resposta única de melhor prática, vai depender de sua implementação e arquitetura: variável global na classe, uma classe estática com todos os parâmetros utilizados na automação, dentre outras técnicas.

Talvez não seja aquela desvantagem “nossa, e agora?” mas dificulta um pouco a compreensão do código que ficaria mais simples e intuitivo em uma implementação utilizando um padrão AAA (Arrange, Act and Assert), por exemplo. Alguns frameworks como o “Serenity BDD” para Java tem funções específicas para tratar essa situação, facilitando a implementação do teste.


Inserção de lógicas de repetição e condicionais devido à reuso e comportamento dos dados: Este é um anti-padrão para codificação de testes automatizados principalmente por que o uso desses recursos, nestes casos, gera uma necessidade de testes do seu código que já é, isso mesmo, de TESTES. Além disso a dificuldade de entendimento do fluxo do teste e dificuldade de manutenção são outros pontos que contribuem para estas técnicas se tornarem anti-paterns em códigos de teste. Como uma automação de testes que usa BDD é atrelada a uma documentação de alto nível, orientada ao negócio, muitas vezes um mesmo step pode ter fluxos diferentes de execução de acordo com o dado informado na feature, gerando a necessidade de implementação de condicionais e loops para que seja adequado à esta variação.

 

Alguns steps não terão ação de teste: Sim, isso pode ser uma realidade dentro do seu projeto! Uma informação importante para o comportamento do sistema pode não gerar uma ação em tela ou uma chamada em uma API e aí você terá que implementar um método vazio para suprir a necessidade do BDD.

 

Ações do usuário são importantes para os testes funcionais de interface: Detalhes de implementação, como qual tipo de elemento o usuário irá interagir (botão, campo, combo-box), são importantes para entender os objetivos dos testes de interface. Como boa prática de escrita de BDD, detalhes de implementação não devem ser descritos nos cenários, gerando assim uma ausência de informação valiosa para o teste. Esta boa prática de escrita do BDD também leva ao negligenciamento dos testes de componentes específicos da interface de acordo com a implementação adotada, ex: Escolha do sexo em um formulário de cadastro foi implementado com combo-box ou foi implementado como um radio-button? Para cada caso podem ser necessários testes diferentes na interface, porém o comportamento do negócio não muda.

 

Detalhes técnicos importam para testes de API: Uma vez que estamos testando uma API algumas informações técnicas são relevantes para construir os testes como: qual método estamos executando (GET, POST, DELETE etc), quais os tipos dos parâmetros que teremos que passar (interger, string, array etc), contrato (json ou xml) dentre outros. Se colocarmos as informações que precisamos para o teste a feature não fica legível para os que não tem conhecimento técnico aprofundado, se não colocamos o teste implementado ficará muito abstrato e poderá não contemplar todos os possíveis pontos a serem testados. Times cujo o produto final é uma API que será consumida por outras aplicações podem levar em consideração o comportamento dessa para basear a escrita de suas features e não o comportamento de toda a solução que ela fará parte, desde que todos os envolvidos no projeto consigam entender o que está sendo descrito.

 

Autor: José Mário Pedrosa de Sousa

Arquiteto e Consultor de Testes na Base2

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *