Archive for the ‘bdd’ Category

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium - Parte III

sexta-feira, maio 29th, 2009

Seguindo com a série de posts iniciada aqui e aqui, trataremos agora da implementação dos passos especificados no nosso Cenário.

Antes de tudo é bom entender o que é o tal Test Driven Development, de onde vieram boa parte das idéias por trás do BDD.

Test Driven Development prega o desenvolvimento através de pequenas iterações onde existe primeiro a escrita de casos testes que definem o que precisa ser implementado e depois a produção de código necessário para que estes casos de testes sejam atendidos. Não vou explicar pq TDD é legal, uma busca rápida no google vai lhe dar muitos argumentos.

O BDD evolui a idéia do TDD no sentido que começamos o desenvolvimento do sistema com foco no comportamento esperado pelo cliente e expressamos esse comportamento através de uma linguagem mais adequada e mais próxima da natural. Isso ajuda bastante ao discutirmos requisitos com o cliente e no próprio entendimento pela equipe: nossa documentação é nosso código.

Quando construímos nossa User Story e fizemos o Cucumber rodá-la, mesmo com tudo pendente, fizemos isso para guiar nosso desenvolvimento olhando de fora para dentro: o que nosso cliente e espera (User Story), como ele espera (AcceptanceCriterias).

A partir de agora criaremos código para atender as essas expectativas e somente isso.

Por enquanto todos os nossos passos contidos no arquivo features/step_definitions/gerenciar_pessoas_steps.rb estão marcados como pendentes através do método pending

Comecemos então pelo primeiro passo:

Dado que estou na listagem de pessoas

A primeiro momento poderíamos implementar esse passo de forma específica no arquivo features/step_definitions/gerenciar_pessoas_steps.rb

Mas vamos a uma reflexão: geralmente iniciamos os cenários partindo de um determinado ponto do sistema, seria muito interessante definir esse passo de forma genérica, assim poderíamos escrever novos cenários com passos similares, por exemplo:

Dado que eu estou em listagem de cidades

sem a necessidade de implementar um novo passo. Para isso iremos mover o pedaço de código relativo ao passo acima para um novo arquivo features/step_definitions/passos_compartilhados.rb e nele iremos generalizar o passo parametrizando-o

Onde visit é um método do webrat para “visitar” a página especificada e path_to é um helper do Cucumber para definirmos rotas em nossos passos.

Executemos o cucumber novamente:

cucumber features –language pt

Na saída do comando verificamos que não foi possível encontrar um mapeamento para “listagem de pessoas”. Faremos esse mapeamento no arquivo features/support/paths.rb

Vamos executar o cucumber novamente e verificar a saída:

Agora temos outro relato: não existe o método pessoas_path por simplesmente ainda não termos um Controller chamado pessoas. O próximo passo de bebê seria adicionar um controller para pessoas e definir a rota. De toda forma como esse é um simples crud criaremos logo um scaffold através do gerador do rspec, executamos a migration de criação da tabela de passoas e preparamos o banco de teste:

script/generate rspec_scaffold pessoa nome:string endereco:string email:string rake db:migrate rake db:test:prepare

Executamos novamente o cucumber e agora temos o primeiro passo “verde” :D

Temos um outro passo pendente que também pode (e deve) ser generalizado, tiramos o seguinte trecho de código do arquivo features/step_definitions/gerenciar_pessoas_steps.rb e o levamos para features/step_definitions/passos_compartilhados.rb

e o alteramos para

Executamos novamente o cucumber

Precisamos agora de um link chamado “Nova pessoa” na nossa listagem. O script de geração de scaffold já gerou um link só que com o nome em inglês: “New pessoa”. Vamos no arquivo app/views/pessoas/index.html.erb e renomeamos:

<%= link_to ‘Nova pessoa’, new_pessoa_path %>

para

<%= link_to ‘Nova pessoa’, new_pessoa_path %>

Rodando o cucumber mais uma vez:
O negócio tá melhorando, já temos 2 passos “verdes”, partimos agora para os próximos passos:

E defino nome com o valor “Fulano de Tal”
E defino endereco com o valor “Rua Sicrano, 32″
E defino email com o valor “fulano@exemplo.com.br”

Como vocês podem ver, os três passos tem a mesma estrutura, vamos generalizá-lo também. Remova o seguinte trecho de código do arquivo features/step_definitions/gerenciar_pessoas_steps.rb

e adicione o código abaixo no features/step_definitions/passos_compartilhados_steps.rb

Ao ver o saida do cucumber uma alegria: só faltam dois passos!

Salvar o registro é um passo que pode existir em vários cenários, não é algo específico deste. Moveremos então o trecho de código abaixo de features/step_definitions/gerenciar_pessoas_steps.rb para features/step_definitions/passos_compartilhados.rb

E o alteramos para:

Rodamos o cucumber novamente
Percebemos a necessidade de alterar a descrição do botão no arquivo app/views/pessoas/new.html.erb

<%= f.submit ‘Create’ %>

para

<%= f.submit ‘Salvar’ %>

Agora sim, estamos quase lá:
Esvaziamos agora o arquivo features/step_definitions/gerenciar_pessoas_steps.rb pois o último passo também é algo genérico, pode ser aproveitado em outros cenários e funcionalidades. No futuro talvez adicionemos um passo específico da funcionalidade a medida que alteramos nossa User Story. Movemos a definição do último passo para features/step_definitions/passos_compartilhados.rb

Ao rodar o cucumber novamente vemos a necessidade de mudar a mensagem de retorno do método create do nosso controller

Fazemos isso:

Finalizamos assim a implementação da funcionalidade.

Talvez você tenha achado um tanto chato fazer passo por passo código que poderia ser previsto, mas a idéia em TDD é justamente essa: passos de bebê.

No próximo post trataremos da utilização do webrat em modo selenium.

Críticas e comentários são bem-vindos! Até mais! :D

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium - Parte II

quinta-feira, maio 28th, 2009

Continuando nossa série de artigos sobre BDD iniciada aqui, hoje trataremos da construção de cenários.

Cenários (Scenarios),  são perspectivas de utilização que validam um ou mais critérios de aceitação (Acceptance Criterias).

No BDD definimos Cenários seguindo o modelo:

Dado [pré-condição]
Quando [evento]
Então [pós-condição]

Em Dado definimos tudo o que precisamos antes para Quando o evento ocorrer Então verificarmos o resultado.

Exemplo em uma User Story Completa:

    Funcionalidade: Gerenciar Pessoas
     Como um usuário do sistema
     Eu quero gerenciar o cadastro de pessoas
     Para utilizar este cadastro em outros pontos do sistema

    Cenário: Adicionar Pessoa Válida
         Dado que estou em listagem de pessoas
         E vou para "Nova pessoa"
         E defino nome com o valor "Fulano de Tal"
        E defino endereco com o valor "Rua Sicrano, 32"
        E defino email com o valor "fulano@exemplo.com.br"
        Quando salvar o registro
        Então preciso ver "Pessoa Cadastrada com Sucesso."

Ok, ok, até agora você leu bastante mas não botou a mão na massa, que tal tornamos a User Story acima executável utilizando o Cucumber?

Mas primeiro, o que é o Cucumber?

O Cucumber é uma reescrita do Story Runner do RSpec com suporte a internacionalização, ajudantes para o Webrat e um monte de outros recursos legais.

Um Story Runner como o próprio nome já diz serve para executar User Stories, algo que converge para a tal documentação executável.

Criando o Projeto de Exemplo

Obs.: Meu ambiente de desenvolvimento roda Ubuntu 9.04, talvez seja necessário adaptar alguns destes passos ao seu próprio ambiente.

rails exemplobdd

cd exemplobdd

Para instalar o cucumber e suas dependências vamos alterar o arquivo de configuração do ambiente de teste adicionando as gems necessárias.

Para instalar o Cucumber e suas dependências agora é só rodar:

rake gems:install RAILS_ENV=test

Com o Cucumber instalado precisamos agora “inicializá-lo” no nosso projeto.

script/generate cucumber

Após o comando acima estará criada no nosso projeto uma estrutura de pastas onde colocaremos nossas User Stories e passos para atender aos Cenários. Dentro da pasta features crie o arquivo gerenciar_pessoas.feature

Nossa feature criada, agora executamos

cucumber features –language pt

E obtemos a seguinte saída:
Criamos nossa feature mas ainda não definimos os passos do Cenário.

1 scenario (1 undefined) 7 steps (7 undefined)

O Cucumber é um cara legal e já nos dá uma sugestão de como defini-los, faremos agora um CTRL+C e CTRL+V da sugestão para dentro do arquivo features/step_definitions/gerenciar_pessoas_steps.rb

Ao executar o cucumber novamente

cucumber features –language pt


vemos agora que apesar de nossos passos estarem definidos ainda estão todos marcados como pendente, o primeiro passo acusa isso e os subsequentes não são executados.

1 scenario (1 pending)
7 steps (6 skipped, 1 pending)

No próximo post trataremos do conceito de TDD, passos compartilhados no Cucumber e utilização do Webrat para testes funcionais. Quem viver verá! :D

Introducão ao BDD com Cucumber, RSpec, Webrat e Selenium - Parte I

quinta-feira, maio 28th, 2009

Behaviour-Driven Development (BDD) ou Desenvolvimento Dirigido por Comportamento é uma evolução no pensamento por trás do Test Driven Development (TDD) e Acceptance Test Driven Planning.

O objetivo é dar ao TDD e o DDD (Domain Driven Design) uma visão integrada, fazendo o relacionamento entre essas duas abordagem ficar mais evidente de forma que o desenvolvimento seja focado em entregar algo de valor para o negócio de forma priorizada e verificável.

Para que esse objetivo seja alcançado é definido um vocabulário comum (Ubiquitous Language para pessoas familiarizadas com o conceito de DDD) que une quem entende de tecnologia com as pessoas que entendem do negócio. A idéia é que gerentes, usuários, analistas, desenvolvedores, testadores, enfim, todos envolvidos no projeto se expressem nos mesmos termos sobre o sistema em desenvolvimento.

O BDD apresenta um framework baseado em três princípios:

1. A área de negócios e a de tecnologia precisam se referir a mesma parte do sistema da mesma forma
-
Tudo é comportamento

2. Toda parte do sistema precisa ter um valor identificável e verificável para o negócio
-
Valor de negócio

3. Analisar, projetar e planejar tudo de cima a baixo tem retorno decrescente.
- O suficiente é suficiente

Se você está achando que BDD é apenas um novo nome para uma série de boas práticas existentes, você não está de todo errado. O objetivo do BDD é juntar todas essas boas práticas existentes sob uma só bandeira com uma terminologia consistente e sem ambiguidades.

User Story (História do Usuário)

“Uma User Story descreve funcionalmente o que será valioso para os usuários e aos compradores de um software.” Mike Cohn

Uma User Story precisa ser

I ndependente
N egóciável
V aliosa ao comprador
E stimável
S mall (pequena)
T estável

Story Card

No processo do BDD um especialista no assunto tratado(geralmente um usuário comum) trabalha com um analista de negócios para identificar um requisito de negócio. Este requisito é expresso utilizando um cartão.

A idéia da User Story ser escrita em um cartão ao invés de outra mídia permite nos manter no princípio Small (que a Story seja pequena). Se uma User Story ultrapassar os limites de um cartão talvez já seja hora de desmembrá-la.

Na escrita da User Story utilizamos o seguinte modelo:

Como um [pessoa ou papel desempenhado]

Eu quero [funcionalidade]

Para [benefício ou valor dessa funcionalidade ao negócio]

No cartão definimos também os critérios para a sua aceitação (Acceptance Criterias). Uma User Story só estará pronta quando todos seus critérios de aceitação forem atendidos.

Exemplo de Story Card:

Como um autor
Eu quero adicionar e gerenciar posts
Para blogar

Nota: Um post precisa ter nome, conteudo e status
Nota: O status de um post pode ser PUBLICADO ou NAO_PUBLICADO
Nota: Um post é criado com o status inicial NAO_PUBLICADO

No nosso próximo post veremos o conceito de Cenário de utilização e tornaremos uma User Story executável em projeto Rails através do Cucumber

Fontes:
http://behaviour-driven.org/
http://www.milfont.org/tech/2009/03/29/palestra-behaviour-driven-development/
User Stories Applied - Mike Cohn