Saltar para o conteúdo

Behavior Driven Development

Origem: Wikipédia, a enciclopédia livre.
Navegação no histórico de edições: ← ver edição anterior (dif) ver edição seguinte → (dif) ver última edição → (dif)


Behavior Driven Development (BDD ou ainda uma tradução Desenvolvimento Guiado por Comportamento) é uma técnica de desenvolvimento Ágil que encoraja colaboração entre desenvolvedores, setores de qualidade e pessoas não-técnicas ou de negócios num projeto de software. Foi originalmente concebido em 2003, por Dan North [1] como uma resposta à Test Driven Development (Desenvolvimento Guiado por Testes), e tem se expandido bastante nos últimos anos[2].

O foco em BDD é a linguagem e interações usadas no processo de desenvolvimento de software. Desenvolvedores que usam BDD (Behavior-Driven developers) usam sua língua nativa em combinação com a linguagem ubíqua (ubiquitous language) usada no processo de desenvolvimento de software. Isso permite que os desenvolvedores foquem em por quê o código deve ser criado, ao invés de detalhes técnicos, e minimiza traduções entre linguagem técnica na qual o código é escrito e outras linguagens de domínio, usuários, clientes, gerência do projeto, etc.


Dan North criou o primeiro framework de BDD, JBehave[1], em Java, seguido de um framework em Ruby a nível de história chamado RBehave[1], o qual foi depois incorporado ao projeto RSpec. Ele também trabalhou com David Chelimsky, Aslak Hellesøy e outros para desenvolver o framework RSpec e também escrever "The RSpec Book: Behaviour Driven Development with RSpec, Cucumber, and Friends". O primeiro framework baseado em histórias no RSpec foi posteriormente substituído pelo Cucumber[3], desenvolvido principalmente por Alask Hellesøy.


Práticas de BDD

As práticas de BDD incluem:

  • Envolver as partes interessadas no processo através de Outside-in Development (Desenvolvimento de Fora pra Dentro)
  • Usar exemplos para descrever o comportamento de uma aplicação ou unidades de código
  • Automatizar os exemplos para prover um feedback rápido e testes de regressão
  • Usar deve (should em inglês) na hora de descrever o comportamento de software para ajudar esclarecer responsabilidades e permitir que funcionalidades do software sejam questionadas
  • Usar dublês de teste (mocks, stubs, fakes, dummies, spies) para auxiliar na colaboração entre módulos e códigos que ainda não foram escritos


Desenvolvimento de Fora pra Dentro (Outside-In Development)

BDD é guiado pelos valores de negócios; que é o benefício trazido para o negócio no qual a aplicação está sendo produzida. A única maneira na qual o benefício pode ser percebido é através de interfaces de usuário para a aplicação, comumente (mas nem sempre) a interface gráfica de usuário.

Da mesma maneira, cada trecho de código, começando com a interface de usuário, pode ser considerado como sendo um cliente de outros módulos de código no qual a interface é utilizada. Cada elemento de código provê algum comportamento, o qual em colaboração com outros elementos provê o comportamento da aplicação.

A primeira parte de código de produção que os desenvolvedores que usam BDD implementam é a interface de usuário, pois dessa maneira os desenvolvedores podem se beneficiar com um feedback rápido para saber se a interface está adequada ou não. Através de código, e usando princípios de design e refatoração, desenvolvedores descobrem colaboradores para a interface de usuário, e posteriormente para cada unidade de código. Isso os ajuda a aderirem o princípio de YAGNI, desde que cada trecho de código de produção é requerido pelos negócios ou por outro trecho de código já escrito.


Cenários, ou Exemplos da Aplicação

Em BDD, um desenvolvedor, algum profissional do setor de qualidade ou até mesmo o cliente podem esclarecer os requisitos quebrando-os em exemplos espefícicos. Um exemplo de requisito de uma aplicação de vendas poderia ser: "Itens reembolsados ou substituídos devem ser retornados para o estoque". Esse requisito pode ser quebrado em dois exemplos de cenários, como:

Cenário 1: Itens reembolsados devem retornar para o estoque

  • Dado que um cliente compra um jumper preto
  • E eu tenho três jumper pretos no estoque
  • Quando ele retorna com o jumper preto para reembolso
  • Então eu devo ter quatro jumpers pretos no estoque

Cenário 2: Itens substituídos devem ser retornados ao estoque

  • Dado que uma cliente compra um vestido azul
  • E eu tenho dois vestidos azuis no estoque
  • E eu tenho três vestidos pretos no estoque
  • Quando ela retorna com o vestido para uma troca por um preto
  • Então eu devo ter três vestidos azuis no estoque
  • E dois vestidos pretos no estoque


Cada cenário é um exemplo, escrito para ilustrar um aspecto específico de comportamento da aplicação.

Ao discutir os cenários os participantes se pergutam se a saída descrita sempre resulta daqueles eventos ocorridos no dado contexto. Isso ajuda a desvendar outros cenários e esclarecer os requisitos[4]. Por exemplo, um especialista do domínio pode notar que itens reembolsados não são sempre devolvidos ao estoque e então reorganizar os requisitos para algo do tipo "Itens reembolsados ou substituídos devem retornar ao estoque a não ser que estejam defeituosos". Este, por sua vez, ajuda os participantes a melhorar os requisitos, levando a uma melhor estimativa de quanto tempo aqueles requisitos levarão para serem implementados.

As palavras Dado que, Quando e Então (Given, When e Then em inglês) são quase sempre usadas para guiar os cenários, mas não são obrigatórias.

Os cenários podem ser automatizados se uma ferramenta para que a automatização a nível de interface de usuário possa ser feita existir. Caso não exista alguma ferramenta, então pode ser possível automatizar o próximo nível, como o nível de Controlador, caso esteja sendo usado o padrão de projeto MVC.

Exemplos e Comportamento a nível de Unidade

Os mesmos princípios de exemplos, usando contextos, eventos e resultados podem ser usados para guiar o desenvolvimento a nível de unidade. Por exemplo, os exemplos seguintes descrevem um aspecto do comportamento de uma lista:

Exemplo 1: Novas listas são vazias

  • Dado que uma nova lista é criada
  • Então a lista deve estar vazia.

Exemplo 2: Listas com alguma coisa dentro não podem estar vazias

  • Dado que uma nova lista é criada
  • Quando eu adiciono um objeto a ela
  • Então a lista não deve estar vazia


Ambos exemplos são necessários para descrever o comportamento do método estaVazia de uma lista e obter os benefícios do mesmo. Estes exemplos podem ser automatizados utilizando até mesmo algum framework de TDD. Em BDD cada exemplo é comumente encapsualado num único método de teste, onde o nome do método é a descrição completa do comportamento. Por exemplo, usando Java e JUnit 4, os exemplos acima se tornariam:

public class ListaTest {

   @Test
   public void deveSaberSeEstaVazia() {
      Lista lista1 = new Lista();
      assertTrue(lista1.estaVazia());

      Lista lista2 = new Lista();
      lista2.adicionar(new Object());
      assertFalse(lista2.estaVazia());
   }
}

Às vezes a diferença entre contexto, eventos e resultados pode ser mais explícita. Por exemplo:

public class ComportamentoDoControladorDeJanela {

    @Test
    public void deveFecharJanelas() {
        
        // Dado que
        ControladorDeJanela controlador = new ControladorDeJanela("Meu Quadro");
        Quadro quadro = new Quadro();
        
        // Quando
        controlador.fecharJanelas();
        
        // Então
        garantirQue(!frame.estaAparecendo());
    }
}

No entanto o exemplo é fraseado, o efeito deve ser o de descrever o comportamento do código em questão. Por exemplo, a partir dos exemplos acima poderia ser gerado:

  • Lista deve saber quando ela está vazia
  • Controlador de janela deve fechar janelas

A descrição é útil quando o teste falha, provendo documentação do comportamento do código para qualquer um interessado em Listas ou Controladores de janelas. Uma vez que os exemplos foram escritos eles são então rodados e o código para que eles possam rodar e passar é escrito, da mesma maneira que em TDD.

Usando Dublês de Teste

Defensores de BDD alegam que o uso de "deve" (should) e "garantirQue" (ensureThat) em exemplos de BDD incentivam os desenvolvedores a questionarem se as responsabilidade que eles estão atribuindo aos seus objetos são apropriados, ou se elas podem ser delegadas ou movidas inteiramente para outros objetos. Um objeto que é mais simple que o código de colaboração e provê a mesma interface, porém com um comportamento mais previsível, pode ser injetado no código que precisa dele, e os exemplos de comportamento do código podem ser escrito usandos estes objetos ao invés da versão de produção.

Estes objetos pode ser criados manualmente ou usando um framework de mocks como Mockito, Moq, NMock, Rhino Mocks, JMock, EasyMock.

Questionando responsabilidades dessa meneira, e utilizando dublês de teste para cumprir os papéis necessários para os objetos de colaboração, incentivam o uso de Interfaces Baseadas em Papéis. Isso também ajuda a manter o código de implementação dos objetos pequenos e com baixo acoplamento.


Ferramentas

  • ASSpec - ActionScript 3
  • BDoc - Extracting documentation from unit tests, supporting behaviour driven development
  • BDD in Python is core module doctest
  • Bumblebee - Extract documentation from JUnit tests with support for adding text, code-snippets, screenshots and more. Puts focus on the end-user.
  • beanSpec - Java
  • CppSpec - C++
  • cfSpec - ColdFusion
  • CSpec - C
  • dSpec - Delphi
  • Concordion - a Java automated testing tool for BDD that uses plain English to describe behaviors.
  • Cucumber - Plain text + Ruby. Works against Java, .NET, Ruby, Flex or any web application via Watir or Selenium.
  • easyb - Groovy/Java
  • EasySpec - Groovy, usable in Java. Developer also working on Perception a tool for doing Context/Specification reporting for many different tools.
  • GSpec - Groovy
  • Instinct - Java
  • JavaStubs - Java - BDD framework supporting partial-mocking/method stubbing
  • JBehave - Java
  • JDave - Java
  • JFXtras Test - JavaFX
  • JSpec - JavaScript
  • JSSpec - JavaScript
  • NBehave - .Net
  • NSpec - .Net
  • NSpecify - .Net
  • NUnit - Another implementation of BDD framework in .Net with focus on specification testing
  • PHPSpec - PHP
  • Pyccuracy - Behavior-driven framework in Python.
  • Pyhistorian - General purpose BDD Story Runner in Python (internal DSL, not plain-text)
  • RSpec - Ruby
  • ScalaTest - Scala
  • specs - Scala
  • spec-cpp - C++
  • Specter - Another implementation of BDD framework in .Net with focus on specification readability
  • StoryQ - .Net 3.5, can be integrated with NUnit to provide both specification readability and testing
  • tspec - Groovy (Thai syntax)


Referências


Ligações Externas