Buscar

Testes de Software BDD + Cucumber

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 131 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 131 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 131 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Desenvolvimento
Baseado em Testes
BDD + Cucumber
Eduardo Mendes
edumendes@gmail.com
@dudumendes
Introdução
Agenda
BDD
Cucumber
@dudumendes
BDD
TDD
Abordagem de desenvolvimento de software em 
que os testes direcionam a implementação do 
software
TDD
Favorece o design de software
Expressa o comportamento do código
Documenta o código
@dudumendes
Testes unitários
Uma forma de aplicar o TDD
Traduzem as expectativas dos desenvolvedores 
sobre o comportamento do código
Fragilidade: Muito acoplado à implementação
Não traduz as expectativas dos usuários
Expectativas dos usuários
Casos de Uso
Estórias de Usuário
Ambas não possuem mecanismos de validação que 
traduzam as expectativas dos usuários
@dudumendes
BDD
Behaviour Driven Development
@dudumendes
BDD
Behaviour Driven Design
@dudumendes
BDD
“Behaviour-Driven Development is about implementing 
an application by describing its behaviour from the 
perspective of its stakeholders.”
David Chemlimsky
BDD
“Desenvolvimento orientado a comportamento diz 
respeito a implementar uma aplicação pela descrição 
do seu comportamento a partir da perspectiva de seus 
stakeholders.”
David Chemlimsky
Entender o mundo a partir da visao do 
STK_HD
Para entregar COISAS UTEIS
Entender o seu domínio
Seus desafios e oportunidades
As palavras que ele usa para descrever o 
comportamento que ele quer da 
aplicação
Mais que da visão de um stakeholder
Do ponto de vista de qualquer que está 
envolvido no projeto
Behaviour Driven Development
Uma abordagem no estilo TDD
Documentação executável
Melhora a comunicação dos times
Esclarece os mal-entendimentos entre clientes, 
especialistas de domínio, desenvolvedores
Pode ser utilizada por todos os envolvidos no 
projeto
@dudumendes
BDD
Princípios
Enough is enough
Deliver stakeholder value
It’s all behaviour
@dudumendes
BDD
Princípios
O bastante é o bastante
Trabalhar para alcançar as expectativas dos stakeholders, mas 
evitar fazer mais do que se é necessário fazer
Entregar valor ao stakeholder
Se você está fazendo algo que não entrega valor ou não aumenta 
sua habilidade de entrega de valor, pare e faça outra coisa
Tudo é sobre comportamento
Assim como podemos descrever o comportamento a partir da 
perspectivas dos stakeholders, também podemos descrever o 
comportamento de um código a partir de outro código que o utiliza
@dudumendes
Ciclo do BDD
red
red
greenrefactor
green
refactor
Cenário
Passo
@dudumendes
BDD
O Ciclo
Stakeholder e analista discutem os requisitos
os requisitos são organizados em funcionalidades 
(features)
podem ser quebradas em estórias
fazem sentido para o stakeholder
@dudumendes
BDD
O Ciclo
Stakeholder, analista e testador determinam os 
escopos das estórias
o analista pensa na funcionalidade de forma geral
o testador pensa em cenários concretos, com 
valores de entradas e saída
@dudumendes
BDD
O Ciclo
Cenários prioritários são identificados
Stakeholder especifica exatamente o que quer 
entregue
Desenvolvedores implementam o bastante para 
satisfazer os cenários e nada mais
@dudumendes
BDD
O Ciclo
Desenvolvedores
Automatizam cenários que orientam o 
desenvolvimento
Descrevem comportamentos esperados
Implementam os comportamentos
Refatoram
@dudumendes
Processo do BDD
@dudumendes
Estórias no BDD
BDD
Estórias e Comportamento
Estórias
Correspondem às Estórias de Usuário
Expressam o comportamento das explicações em 
alto nível
Necessidade de frameworks de estórias
Cucumber, JBehave
BDD
Estórias e Comportamento
Comportamento (ou Spec)
Correspondem às expectativas em nível de 
classe
Expressam o comportamento a nível de serviço/
componente
Estórias e Comportamento
Estórias de Usuário
Formado por um conjunto de Cenários 
(Scenarios) 
critérios de aceitação
Cada cenários possui
“entradas”, eventos e “resultados”
Utilizados em projetos ágeis
Behaviour
Expressado como métodos de testes
Define o que aplicação deve e não deve fazer
Estrutura de uma estória
Connextra Format
Título
Narrativa
As a [algum_papel]
I want [alguma_necessidade]
So that [beneficio/valor_da_caracteristica]
Critérios de aceitação (cenários)
Given [alguma(s)_condicao(oes)]
When [evento_ocorrer]
Then [certifico_algum_resultado]
Estrutura de uma estória
Título
Narrativa
Como um [algum_papel]
Eu quero [alguma_necessidade]
Para que [beneficio/valor_da_caracteristica]
Critérios de aceitação (cenários)
Dado [alguma(s)_condicao(oes)_entrada]
Quando [evento_ocorrer]
Então [certifico_algum_resultado]
Ciclo do BDD
red
red
grerefactor
gre
refactor
Cenário
Passo
@dudumendes
Cucumber
Cucumber
Framework BDD Open Source baseado em 
RSpec
Criado por Aslak Hellesøy
Versão atual 1.2.1
Cucumber
Características
Implementação em Ruby
Estórias de usuário baseadas em textos
Suporte a Injeção de dependências
Cucumber
em 03 passos
Escrever uma estória e executar a estória (.feature)
obter os snippets com os passos do teste
Criar o arquivos de passos a partir dos snippets
Dar implementação aos passos
@dudumendes
Cucumber em 03 passos
Passo 1 - Escrever uma estória
Estrutura de uma estória
Narrativa
As a [algum_papel]
I want [alguma_necessidade]
So that [beneficio/valor_da_caracteristica]
Cenário
Given [alguma(s)_condicao(oes)]
When [evento_ocorrer]
Then [certifico_algum_resultado]
Estrutura de uma estória
Narrative:
In order to [beneficio/valor_da_caracteristica]
As a [algum_papel]
I want to [alguma_necessidade]
Scenario: Nome do Cenário
Given [alguma(s)_condicao(oes)]
When [evento_ocorrer]
Then [certifico_algum_resultado]
@dudumendes
Estórias no Cucumber
arquivos
de texto com extensão “.feature”
localização
diretório features
o comando procura por um diretório “features”
execução
comando cucumber
busca o diretório
Cucumber em 03 passos
Passo 1 - Escrever uma estória
Feature: greeter says hello
 In order to test Cucumber
 As a developer
 I want a greeter to say hello
 Scenario: greeter says hello
 Given a greeter
 When I send it the greet message
 Then I should see "Hello Cucumber"
gretter_say_hello.feature
@dudumendes
cucumber
@dudumendes
continuação: snippets
@dudumendes
Resultado
O cucumber encontrou a feature
tentou executá-la
mas não sabe como executá-la
O cucumber sugeriu algumas dicas do código
@dudumendes
Cucumber em 03 passos
Passo 2 - Criar o arquivo de passos
@dudumendes
Estórias no Cucumber
arquivos
em Ruby com sufixo “_steps”
localização
features/step_definitions
execução
comando cucumber
@dudumendes
Given /^a greeter$/ do
 pending # express the regexp above with the code you wish you had
end
When /^I send it the greet message$/ do
 pending # express the regexp above with the code you wish you had
end
Then /^I should see "(.*?)"$/ do |arg1|
 pending # express the regexp above with the code you wish you had
end
greeter_steps.rb
@dudumendes
Cucumber em 03 passos
Passo 3 - Dar implementação às estórias
@dudumendes
Given /^a greeter$/ do
 @greeter = CucumberGreeter.new
end
When /^I send it the greet message$/ do
 @message = @greeter.greet
end
Then /^I should see "(.*?)"$/ do |greeting|
 @message.should == greeting
end
greeter_steps.rb
@dudumendes
@dudumendes
class CucumberGreeter
 def greet
 "Hello Cucumber"
 end
 
end
Given /^a greeter$/ do
 @greeter = CucumberGreeter.new
end
When /^I sendit the greet message$/ do
 @message = @greeter.greet
end
Then /^I should see "(.*?)"$/ do |greeting|
 expect(@message).to eql greeting
end
@dudumendes
Cucumber Passos
Escrever uma estória
Arquivo de texto de extensão .feature
Recuperar os snippets
Criar o arquivo de passos
Estórias no Cucumber
Estórias em arquivos de textos
01 Narrativa (Narrative)
* Cenários (Scenarios)
Narrativa 
Opcional
As a, In order to, I want to
Cenários no Cucumber
Cenários consistem em:
Título
Passos:
Given, When, Then
And
é possível colocar then antes do when
Cenários podem depender de outros
Comentários (!-- )
@dudumendes
Gherkin
Feature: 
Scenario:
Given When Then
Internacionalização
Inglês é o padrão
# language: pt
Aplicação
Step definitions
Features
@dudumendes
Gherkin
Feature
Scenario
Scenario Outline
Scenarios
Given
When
Then
And
But
| 
“”
#
@dudumendes
Gherkin --i18n
cucumber --i18n pt
@dudumendes
Exercício
Criar uma versão em português para o Hello World
Esquema de Cenários
Scenario Outline
É comum em testes de aceitação definir-se exemplos 
de cenários reais com valores para verificar o estado 
de pronto da aplicação
Neste caso é possível se utilizar esquemas de cenários
Esquemas de cenários
Nos cenários os parâmetros devem ser envolvidos 
com sinais “<” e “>”
Eles devem ser declarados como esquemas de 
cenários
Após um cenário informam-se os valores válidos para 
os parâmetros em um tabela determinada por 
“Cenários:”
@dudumendes
# language: pt
Funcionalidade: Depositar Dinheiro
 Esquema do Cenário: Depositar Dinheiro
 Dado um cliente especial com saldo atual de <saldo_inicial> reais
 Quando ele realizar um deposito no valor <deposito> reais
 Então o deposito deve ser realizado
 E o saldo da conta atualizado para <saldo_final> reais
 
 Cenarios: valores possiveis
 | saldo_inicial | deposito | saldo_final |
 | 200 | 100 | 300 |
 | 200 | 100 | 300 |
 | 200 | 100 | 300 | 
 | 200 | 100 | 300 |
@dudumendes
O comando cucumber
@dudumendes
Organizando features
Comando cucumber sem opções
serão procurados todos os arquivos .rb e .feature 
abaixo do diretório features
gera snippets para features indefinidas
cada Cenário e Passo tem comentários no final da 
linha
localização do cenário
nome do arquivo e número da linha
@dudumendes
# language: pt
Funcionalidade: Futuro hospede reserva um quarto
 A fim de proporcionar mais comodidade
 Como dono do hotel
 Eu gostaria que os futuros hospedes
 reservassem quartos pela internet
 Cenario: Reserva com sucesso
 Dado um hotel com "10" quartos e "0" reservas
@dudumendes
Organizando features
@dudumendes
Organizando features
Comando cucumber sem opções
serão procurados todos os arquivos .rb e .feature
Para projetos pequenos
caminho mais simples é organizar os arquivos dentro do 
diretório features
Para projetos maiores
crie subdiretorios para cada feature
vários arquivos em cada diretório com um subconjunto de 
ceários coesos
@dudumendes
Organizando features
features
seguro
medico
dentario
vida
previdencia
prbl
vgbl
cucumber features
executa todos
cucumber features/seguro
apenas os de seguro
cucumber features/seguro/medico
somente os médicos
@dudumendes
A vida de um cenário
No processo de software
Cada cenário de uma funcionalidade precisa ser descrito e 
aprovado
Durente a especificação, os cenários podem estar
pendentes de aprovação
em progresso
estados mistos em uma mesma feature
pode ser necessário testar um subjconjunto da suites de testes
@dudumendes
Tags para features/scenarios
É como uma annotation
pode ser utilizada para marcar features e/ou scenarios
scenarios herdam as tags de suas features
podem ser utilizadas para 
@dudumendes
Tags
@aprovada @sprint_1
Funcionalidade: paciente solicita consulta
@em_progresso
Cenario: paciente seleciona horario disponivel
cucumber --tags @em_progresso
@dudumendes
Tags
cucumber --tags @cuc, @umber
cucumber --tags @cuc || @umber
executa todos os cenário com @cuc OU @umber
cucumber --tags @cuc --tags @umber
cucumber --tags @cuc && @umber
executa todos os cenário com @cuc E @umber
cucumber --tags ~@umber
cucumber --tags !@umber
executa todos os cenário sem @umber
@dudumendes
Passo-a-passo
@dudumendes
Given
When
Then
@dudumendesPassos
Um passo candidato (StepCandidate) de uma 
feature deve estar associado a uma implementação 
de passo em um arquivo de passos
feature_X.feature
Cenario: Cenario A
Dado um contexto
Quando algo acontecer
Então Alguma coisa acontece
Arquivo de Passos
cenario_a_steps.rb
 Dado um contexto
 Quando algo acontecer
 Então Alguma coisa acontece
implementação
implementação
implementação
Esta associação é feita através de expressões regulares
@dudumendes
Passos
Um passo candidato (StepCandidate) de uma 
feature deve estar associado a uma implementação 
de passo em um arquivo de passos
Caso esteja: passed
Caso contrário: undefined
@dudumendes
Definição de passos
Criação do arquivo de feature
Quando você cria uma feature 
executa o cucumber
cenários indefinidos
passos indefinidos
snippets de código
@dudumendes
Executa
Cenário
Lê 1.º passo
Existe 
definição?
Lê próximo
passo
Passo
Indefinido
Pendente?Exceção lançada?
Existe 
outro passo
Cenário
Falho
Executa código 
de definição do 
passo
Não
Sim
Sim
Não
Cenário
Pendente
Sim
Cenário
Indefinido
Sim
Não
Não
Cenário
Passou
@dudumendes
# language: pt
Funcionalidade: Futuro hospede reserva um quarto
 A fim de proporcionar mais comodidade
 Como dono do hotel
 Eu gostaria que os futuros hospedes reservassem quartos pela internet
 Cenario: Reservar com sucesso
 Dado um hotel com "10" quartos e "0" reservas
@dudumendes
Definição de passos
Criação do arquivo de passos
Cria-se o arquivo de passos
Dado /^um hotel com "(.*?)" quartos e "(.*?)" 
reservas$/ do |total_de_quartos, total_de_reservas|
end
@dudumendes
Given / When / Then
O formato Connextra
Utilizados para descrever os passos de um teste de 
aceitação
servem para descrever o cenário de uma vida real
expressam comportamento esperado
@dudumendes
Given
Dado
Indica algo que se aceita como verdadeiro e certo em um cenário
Dado que tenho R$ 20 em minha conta
Dado que a Terra é redonda
Dado que hoje é sábado
É uma setença que descreve um contexto para os eventos e 
saídas que serão exercitados nos cenários
Não são pré-condições
@dudumendes
When
Quando
Indica o evento que ocorre naquele cenário
Quando eu saco R$ 10
Quando eu pulo da estratosfera
Melhor que se tenha um evento por cenário
melhor descrição da intenção de cada cenário
falhas não serão ocultadas quando mais que um evento 
for descrito
@dudumendes
Then
Então
Indica uma saída esperada
Então eu devo ter R$ 5 no final
Então eu devo pular antes de sair da atmosfera
Pode haver mais que uma saída por cenário
mas devem ser coesas
@dudumendes
And / But
E / Mas
Podem ser utilizados para complementar a descrição 
do Given e do Then
Cenario: Reserva com sucesso
 Dado um hotel com "10" quartos
 E com "0" reservas
 Quando um futuro hospede reservar "1" quarto
 Entao reservas será "1"
 E o número dos quartos será "9"
@dudumendes
@dudumendes
Passos compostos
@dudumendes
Passos Compostos
Em BDD, o autor de cenários deve possuir a liberdadede aprofundar o foco de um determinado cenário
esta situação pode ultrapassar o limite de um 
cenário inicial
um passo pode depender de passos utilizados em 
outros cenários
Neste contexto, os cenários compostos são úteis 
@dudumendes
Passos Compostos
Passos compostos permitem criar grupos de execução 
de passos ligados a um único passo, o que pode ser 
muito útil e poderoso
@dudumendes
Funcionalidade: Logar na aplicacao
 Cenário: Usuario existe
 Dado que o usuario "dudumendes" existe
 Dado que eu informei o login "dudumendes"
Dado /^que o usuario "(.*?)" existe$/ do |nome|
 # ...
end
Dado /^que eu informei o login "(.*?)"$/ do |nome|
 # ...
end
@dudumendes
 Cenário: Usuario existe
 Dado que o usuario "dudumendes" existe
 Dado que eu informei o login "dudumendes"
 Dado que "dudumendes" está logado
Dado /^que o usuario "(.*?)" existe$/ do |nome|
 # ...
end
Dado /^que eu informei o login "(.*?)"$/ do |nome|
 # ...
end
Dado /^que (.*?) está logado$/ do |nome|
 step "que o usuario #{nome} existe"
 step "que eu informei o login #{nome}"
end
@dudumendes
Funcionalidade: Transferir Dinheiro
 Cenário: Transferir Dinheiro
 Quando eu seleciono "conta corrente" como conta de origem
 E eu seleciono "poupanca" como conta de destino
 E eu informo que a quantidade é 20
 E solicito executar
Quando /^eu seleciono "(.*?)" como conta de origem$/ do |origem|
end
Quando /^eu seleciono "(.*?)" como conta de destino$/ do |destino|
end
Quando /^eu informo que a quantidade é (\d+)$/ do |valor|
end
Quando /^solicito executar$/ do
end
@dudumendes
Funcionalidade: Transferir Dinheiro
 Cenário: Transferir Dinheiro
 Quando eu seleciono "conta corrente" como conta de origem
 E eu seleciono "poupanca" como conta de destino
 E eu informo que a quantidade é 20
 E solicito executar
 
 Cenário: Transferir Dinheiro Resumido
 Quando eu transfiro 20 da "conta corrente" para a "poupanca"
@dudumendes
Quando /^eu transfiro (\d+) da (.*?) para a (.*?)$/ do |valor, origem, destino|
 step "eu seleciono #{origem} como conta de origem"
 step "eu seleciono #{destino} como conta de destino"
 step "eu informo que a quantidade é #{valor}"
 step "solicito executar"
end
@dudumendes
Exercício
Completar a feature da Transferência e fazer passar
@dudumendes
Hooks
@dudumendes
Hooks
Before
Executado antes de cada cenário
After
Executado depois de cada cenário
AfterStep
Executado após cada passo
@dudumendes
Before do
 puts "Isto executa antes de cada cenário"
end
After do
 puts "Isto executa depois de cada cenário"
end
AfterStep do
 puts "Isto executa depois de cada passo"
end
Before(“@cuc”) do
 puts "Isto executa antes de cada cenário com @cuc"
end
@dudumendes
Background
Contexto, Cenario de Fundo
Before, After, AfterStep
Não possuem descrição na feature
Background
Similar ao Before
Permite escrever passos na feature
@dudumendes
Funcionalidade: Convidar amigos
 Contexto: Usuario logado
 Dado que "dudumendes" esta logado
 
 Cenário: Convidar alguem que já é amigo
 
 Cenário: Convidar alguem que ainda não é amigo
@dudumendes
Tabelas em passos
@dudumendes
Funcionalidade: Baralho
 Cenário: tres do mesmo tipo ganha de dois pares
 Dado uma mao com as seguintes cartas
 | valor | naipe |
 | 2 | CORACAO |
 | 2 | ESPADAS |
 | 2 | PAUS |
 | 4 | OUROS |
 | A | CORACAO |
 E outra mao com as seguintes cartas
 | valor | naipe |
 | 2 | CORACAO |
 | 2 | ESPADAS |
 | 4 | PAUS |
 | 4 | OUROS |
 | A | CORACAO |
 
 Entao a primeira mao deve ganhar da segunda mao
@dudumendes
Dado /^uma mao com as seguintes cartas$/ do |table|
 # table is a Cucumber::Ast::Table
 pending # express the regexp above with the code you wish you had
end
Dado /^outra mao com as seguintes cartas$/ do |table|
 # table is a Cucumber::Ast::Table
 pending # express the regexp above with the code you wish you had
end
Entao /^a primeira mao deve ganhar da segunda mao$/ do
 pending # express the regexp above with the code you wish you had
@dudumendes
 Dado uma mao com as seguintes cartas
 | valor | naipe |
 | 2 | CORACAO |
 | 2 | ESPADAS |
 | 2 | PAUS |
 | 4 | OUROS |
 | A | CORACAO |
[
 { :valor => '2', :naipe => 'CORACAO'},
 { :valor => '2', :naipe => 'ESPADAS'},
 { :valor => '2', :naipe => 'PAUS'},
 { :valor => '4', :naipe => 'OUROS'},
 { :valor => 'A', :naipe => 'CORACAO'}
]
@dudumendes
Dado /^uma mao com as seguintes cartas$/ do |cartas|
 cartas.hashes.each {|hash|
 @primeira_mao << Carta.new(hash)
 }
end
Dado /^outra mao com as seguintes cartas$/ do |cartas|
 cartas.hashes.each {|hash|
 @segunda_mao << Carta.new(hash)
 }
end
@dudumendes
Exercício
fazer passar a feature
@dudumendes
Exercício
@dudumendes
Criar a feature e fazer passar
Dados	
  os	
  negociantes:	
  
|nome|rank|
|Larry|Estagio	
  3|
|Moe|Estagio	
  1|
|Curly|Estagio	
  2|
Quando	
  os	
  negociantes	
  são	
  ordenados	
  pelo	
  nome
Então	
  os	
  comerciantes	
  devem	
  vir	
  na	
  seguinte	
  ordem:
|nome|rank|
|Curly|Estagio	
  2|
|Larry|Estagio	
  3|
|Moe|Estagio	
  1|
@dudumendes
Rails + cucumber + rspec
pequena dose
@dudumendes
rails new showtime
@dudumendes
Gemfile
group :development, :test do
 gem "rspec-rails"
 gem "webrat"
end
group :test do
 gem "cucumber-rails"
 gem ”database_cleaner”
end
@dudumendes
bundle install
rails generate rspec:install (dependencias do rspec)
rails generate cucumber:install (dependencias do cucumber)
rake db:migrate
rake db:test:prepare
rake spec
rake cucumber
@dudumendes
Funcionalidade: Descrições
 Como um frequentador de cinema
 Eu quero ver horarios precisos e concisos
 Para que eu possa encontrar filmes que se encaixem no meu horario
 Cenário: Exibir minutos para horarios que não terminam em 00
 Dado um filme
 Quando eu configuro o horario para "2012-10-10" às "2:15pm"
 Então o horario deve ser "October 10, 2012 2:15pm"
/features/horario.feature
@dudumendes
snippet
@dudumendes
features/step_definitions/horario_steps.rb
# encoding: utf-8
# language: pt
Dado /^um filme$/ do
 @filme = Filme.create!
end
Quando /^eu configuro o horario para "(.*?)" às "(.*?)"$/ do |data, hora|
 @filme.update_attribute(:horario_data, Date.parse(data))
 @filme.update_attribute(:horario_hora, hora)
end
Então /^o horario deve ser "([^"]*)"$/ do |horario|
 expect(@filme.horario).to eql horario
end
@dudumendes
Criar o Model Filme
rails g model filme horario_data:date horario_hora:time
Além do modelo criará o spec spec/model/filme_spec.rb
rake db:migrate
rake db:test:prepare
@dudumendes
app/models/filme.rb
class Filme < ActiveRecord::Base
 attr_accessible :horario_data, :horario_hora
 
 def horario
 "#{data_formatada} #{hora_formatada}"
 end
 
 def data_formatada
 horario_data.strftime("%B %d, %Y")
 end
 
 def hora_formatada
 horario_hora.strftime("%l:%M%p").strip.downcase
 end
 
 
end
@dudumendes
Validando o modelo
@dudumendes
rails generate model Email de:text para:text 
mensagem:text
@dudumendes
require 'spec_helper'
describe Email do
 pending "add some examples to (or delete) #{__FILE__}"
end
@dudumendes
require 'spec_helper'
describe Email do
 context "validações:" do
 it "para é obrigatório"
 it "para é válido com email válido"
 it "para é inválido com email inválido"
 it "mensagem é obrigatória"end
end
@dudumendes
@dudumendesrequire 'spec_helper'
describe Email do
 context "validações:" do
 it "para é obrigatório" do
 email = Email.create
 expect(email).to have(1).error_on(:para)
 end
 it "para é válido com email válido"
 it "para é inválido com email inválido"
 it "mensagem é obrigatória"
 end
end
@dudumendes
@dudumendes
class Email < ActiveRecord::Base
 attr_accessible :mensagem, :para
end
app/models/email.rb
@dudumendes
class Email < ActiveRecord::Base
 attr_accessible :mensagem, :para
 
 validates_presence_of :para
end
app/models/email.rb
@dudumendes
# encoding: utf-8
require 'spec_helper'
describe Email do
 context "validações:" do
 it "de é obrigatório" do
 email = Email.create
 expect(email).to have(1).error_on(:de)
 end
 
 it "para é obrigatório"
 it "mensagem é obrigatória"
 it "de deve ser um email" do
 email = Email.create(:de => "de@email.com")
 expect(email).to have(:no).error_on(:de)
 end
 
 it "para deve ser um email"
 end
end
@dudumendes
@dudumendes
describe Email do
 context "validações:" do
 
 it "para é obrigatório" do
 email = Email.create
 expect(email).to have(1).error_on(:para)
 end
 
 it "para é válido com email válido" do
 email = Email.create(:para => "para@email.com")
 expect(email).to have(:no).error_on(:para)
 end
 
 it "para é inválido com email inválido"
 
 it "mensagem é obrigatória"
 
 end
end
@dudumendes
@dudumendes
# encoding: utf-8
require 'spec_helper'
describe Email do
 context "validações:" do
 
 it "para é obrigatório" do
 email = Email.create
 expect(email).to have(1).error_on(:para)
 end
 
 it "para é válido com email válido" do
 email = Email.create(:para => "para@email.com")
 expect(email).to have(:no).error_on(:para)
 end
 
 it "para é inválido com email inválido" do
 email = Email.create(:para => "invalido")
 expect(email).to have(1).error_on(:para)
 end
 
 it "mensagem é obrigatória"
 
 end
end
@dudumendes
class Email < ActiveRecord::Base
 attr_accessible :mensagem, :para
 
 validates_presence_of :para
 
 validates_format_of :para,
 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
 :allow_blank => true
end
@dudumendesdescribe Email do
 context "validações:" do
 
 it "para é obrigatório" do
 email = Email.create
 expect(email).to have(1).error_on(:para)
 end
 it "para é válido com email válido" do
 email = Email.create(:para => "para@email.com")
 expect(email).to have(:no).error_on(:para)
 end
 it "para é inválido com email inválido" do
 email = Email.create(:para => "invalido")
 expect(email).to have(1).error_on(:para)
 end
 
 it "mensagem é obrigatória" do
 email = Email.create
 expect(email).to have(1).error_on(:mensagem)
 end
 
 end
end
@dudumendes
class Email < ActiveRecord::Base
 attr_accessible :mensagem, :para
 
 validates_presence_of :para
 validates_presence_of :mensagem
 
 validates_format_of :para,
 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i,
 :allow_blank => true
end
@dudumendes
Bibliografia
BEHAVIOUR-DRIVEN DEVELOPMENT. http://
behaviour-driven.org/.
CHELIMSKY, David. The RSpec Book. PragBook, 
2011.
JBEHAVE. http://jbehave.org/reference/.
PUGH, Ken. Lean-Agile Acceptance Test-Driven 
Development: better software through collaboration. 
Addison-Wesley, 2010.

Outros materiais