SlideShare une entreprise Scribd logo
1  sur  131
Télécharger pour lire hors ligne
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
Entender o mundo a partir da visao do


BDD
                         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á
“Desenvolvimento orientado a comportamento diz
                         envolvido no projeto

respeito a implementar uma aplicação pela descrição
do seu comportamento a partir da perspectiva de seus
stakeholders.”


                               David Chemlimsky
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




                                      red




Ciclo do BDD
                                      red


                          refactor
                                             green


               refactor
                                     Passo
                                                     green



                               Cenário
@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]
red




Ciclo do BDD              refactor
                                      red

                                             gre
               refactor
                                     Passo
                                                   gre

                               Cenário
@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




                                             greeter_steps.rb

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
@dudumendes




Cucumber em 03 passos
Passo 3 - Dar implementação às estórias
@dudumendes




                                    greeter_steps.rb
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
@dudumendes
@dudumendes




class CucumberGreeter
  def greet
    "Hello Cucumber"
  end

end
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|
  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
                      Features

                      Step definitions




Feature:                 Aplicação

  Scenario:
    Given When Then
Internacionalização
  Inglês é o padrão
  # language: pt
@dudumendes




Gherkin
Feature            Then
Scenario           And
Scenario Outline   But
Scenarios          |
Given              “”
When               #
@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        cucumber features

      medico        executa todos

      dentario   cucumber features/seguro

      vida          apenas os de seguro

   previdencia   cucumber features/seguro/medico

      prbl          somente os médicos

      vgbl
@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
Passos
                                                      @dudumendes




   Um passo candidato (StepCandidate) de uma
   feature deve estar associado a uma implementação
   de passo em um arquivo de passos
                                   Arquivo de Passos

                                   cenario_a_steps.rb
        feature_X.feature
                                Dado um contexto
        Cenario: Cenario A
                                      implementação
 Dado um contexto
                                Quando algo acontecer
 Quando algo acontecer
                                      implementação
 Então Alguma coisa acontece
                                Então Alguma coisa acontece
                                      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




                                  Existe        Não
                                                              Passo                  Cenário
             Lê 1.º passo       definição?                   Indefinido               Indefinido

                                      Sim

                               Executa código                  Exceção     Sim
Lê próximo                     de definição do                                            Pendente?
                                                              lançada?
  passo                            passo
                                                                                   Não
                                                      Não
                         Sim      Existe                                                        Sim
                               outro passo

                                      Não
                                                                         Cenário           Cenário
                                                                          Falho           Pendente
                                 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 liberdade
de 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


 /features/horario.feature

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"
@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
@dudumendes
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"

            it "para é inválido com email inválido"

            it "mensagem é obrigatória"

      end
end
@dudumendes
@dudumendes




app/models/email.rb

class Email < ActiveRecord::Base
  attr_accessible :mensagem, :para
end
@dudumendes




app/models/email.rb

class Email < ActiveRecord::Base
  attr_accessible :mensagem, :para

  validates_presence_of :para
end
@dudumendes

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
require 'spec_helper'                                           @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" 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
@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" 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.

Contenu connexe

Tendances

Principais Técnicas de Elicitação de Requisitos
Principais Técnicas de Elicitação de RequisitosPrincipais Técnicas de Elicitação de Requisitos
Principais Técnicas de Elicitação de RequisitosNorton Guimarães
 
Implantação de um Processo de Teste de Software - Randerson Melville
Implantação de um Processo de Teste de Software - Randerson Melville Implantação de um Processo de Teste de Software - Randerson Melville
Implantação de um Processo de Teste de Software - Randerson Melville minastestingconference
 
Perfil do usuário, Personas, Cenários, Storyboard em IHC
Perfil do usuário, Personas, Cenários, Storyboard em IHCPerfil do usuário, Personas, Cenários, Storyboard em IHC
Perfil do usuário, Personas, Cenários, Storyboard em IHCRos Galabo, PhD
 
Introduction to BDD with Cucumber for Java
Introduction to BDD with Cucumber for JavaIntroduction to BDD with Cucumber for Java
Introduction to BDD with Cucumber for JavaSeb Rose
 
Padrões de Projeto - Design Patterns e Anti-Patterns
Padrões de Projeto - Design Patterns e Anti-PatternsPadrões de Projeto - Design Patterns e Anti-Patterns
Padrões de Projeto - Design Patterns e Anti-PatternsRodrigo Kono
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de SoftwareCapgemini
 
Automação de teste de software
Automação de teste de softwareAutomação de teste de software
Automação de teste de softwareQualister
 
DevCamp - O papel de um testador em uma equipe ágil
DevCamp - O papel de um testador em uma equipe ágilDevCamp - O papel de um testador em uma equipe ágil
DevCamp - O papel de um testador em uma equipe ágilElias Nogueira
 
Workshop Agile Testing Mindset
Workshop Agile Testing MindsetWorkshop Agile Testing Mindset
Workshop Agile Testing MindsetElias Nogueira
 
Introdução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaIntrodução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaFabrício Campos
 
Bdd – with cucumber and gherkin
Bdd – with cucumber and gherkinBdd – with cucumber and gherkin
Bdd – with cucumber and gherkinArati Joshi
 
Qualidade de Software: Modelos e normas
Qualidade de Software: Modelos e normasQualidade de Software: Modelos e normas
Qualidade de Software: Modelos e normasAlex Camargo
 
Áreas de Conhecimento da Engenharia de Software
Áreas de Conhecimento da Engenharia de SoftwareÁreas de Conhecimento da Engenharia de Software
Áreas de Conhecimento da Engenharia de SoftwareElaine Cecília Gatto
 
Mta1 aula-04 Framework DECIDE
Mta1 aula-04 Framework DECIDEMta1 aula-04 Framework DECIDE
Mta1 aula-04 Framework DECIDEAlan Vasconcelos
 
Bdd com cucumber + java + selenium
Bdd com cucumber + java + seleniumBdd com cucumber + java + selenium
Bdd com cucumber + java + seleniumSandy Maciel
 
Palestra ALATS SP - FIAP Teste de Software
Palestra ALATS SP - FIAP  Teste de SoftwarePalestra ALATS SP - FIAP  Teste de Software
Palestra ALATS SP - FIAP Teste de SoftwareElias Nogueira
 
Validação e Testes de software
Validação e Testes de softwareValidação e Testes de software
Validação e Testes de softwareRondinelli Mesquita
 
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgi
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgiTutorial BizAgi - Modelagem de Processos com BPMN e BizAgi
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgiRildo (@rildosan) Santos
 

Tendances (20)

Principais Técnicas de Elicitação de Requisitos
Principais Técnicas de Elicitação de RequisitosPrincipais Técnicas de Elicitação de Requisitos
Principais Técnicas de Elicitação de Requisitos
 
Qualidade de Software
Qualidade de SoftwareQualidade de Software
Qualidade de Software
 
Implantação de um Processo de Teste de Software - Randerson Melville
Implantação de um Processo de Teste de Software - Randerson Melville Implantação de um Processo de Teste de Software - Randerson Melville
Implantação de um Processo de Teste de Software - Randerson Melville
 
Perfil do usuário, Personas, Cenários, Storyboard em IHC
Perfil do usuário, Personas, Cenários, Storyboard em IHCPerfil do usuário, Personas, Cenários, Storyboard em IHC
Perfil do usuário, Personas, Cenários, Storyboard em IHC
 
Introduction to BDD with Cucumber for Java
Introduction to BDD with Cucumber for JavaIntroduction to BDD with Cucumber for Java
Introduction to BDD with Cucumber for Java
 
Padrões de Projeto - Design Patterns e Anti-Patterns
Padrões de Projeto - Design Patterns e Anti-PatternsPadrões de Projeto - Design Patterns e Anti-Patterns
Padrões de Projeto - Design Patterns e Anti-Patterns
 
Testes de Software
Testes de SoftwareTestes de Software
Testes de Software
 
Automação de teste de software
Automação de teste de softwareAutomação de teste de software
Automação de teste de software
 
DevCamp - O papel de um testador em uma equipe ágil
DevCamp - O papel de um testador em uma equipe ágilDevCamp - O papel de um testador em uma equipe ágil
DevCamp - O papel de um testador em uma equipe ágil
 
Workshop Agile Testing Mindset
Workshop Agile Testing MindsetWorkshop Agile Testing Mindset
Workshop Agile Testing Mindset
 
Introdução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem práticaIntrodução ao Teste de Software - Uma abordagem prática
Introdução ao Teste de Software - Uma abordagem prática
 
Design Centrado no Usuário
Design Centrado no UsuárioDesign Centrado no Usuário
Design Centrado no Usuário
 
Bdd – with cucumber and gherkin
Bdd – with cucumber and gherkinBdd – with cucumber and gherkin
Bdd – with cucumber and gherkin
 
Qualidade de Software: Modelos e normas
Qualidade de Software: Modelos e normasQualidade de Software: Modelos e normas
Qualidade de Software: Modelos e normas
 
Áreas de Conhecimento da Engenharia de Software
Áreas de Conhecimento da Engenharia de SoftwareÁreas de Conhecimento da Engenharia de Software
Áreas de Conhecimento da Engenharia de Software
 
Mta1 aula-04 Framework DECIDE
Mta1 aula-04 Framework DECIDEMta1 aula-04 Framework DECIDE
Mta1 aula-04 Framework DECIDE
 
Bdd com cucumber + java + selenium
Bdd com cucumber + java + seleniumBdd com cucumber + java + selenium
Bdd com cucumber + java + selenium
 
Palestra ALATS SP - FIAP Teste de Software
Palestra ALATS SP - FIAP  Teste de SoftwarePalestra ALATS SP - FIAP  Teste de Software
Palestra ALATS SP - FIAP Teste de Software
 
Validação e Testes de software
Validação e Testes de softwareValidação e Testes de software
Validação e Testes de software
 
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgi
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgiTutorial BizAgi - Modelagem de Processos com BPMN e BizAgi
Tutorial BizAgi - Modelagem de Processos com BPMN e BizAgi
 

Similaire à BDD com Cucumber

RSpec - Desenvolvimento Baseado em Teste
RSpec - Desenvolvimento Baseado em TesteRSpec - Desenvolvimento Baseado em Teste
RSpec - Desenvolvimento Baseado em TesteEduardo Mendes
 
Dito Tech Talk RSpec
Dito Tech Talk RSpecDito Tech Talk RSpec
Dito Tech Talk RSpecguest49d83b2
 
Bdd rails 3
Bdd rails 3Bdd rails 3
Bdd rails 3tchandy
 
Behaviour driven development, com jbehave
Behaviour driven development, com jbehaveBehaviour driven development, com jbehave
Behaviour driven development, com jbehaveMarcelo Zeferino
 
Bdd Cucumber
Bdd CucumberBdd Cucumber
Bdd Cucumbervarandasi
 
[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors
[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors
[GUTS-RS] GUTS Testing Games - Jogo BDD WarriorsGUTS-RS
 
BDD em Testes de Serviço
BDD em Testes de ServiçoBDD em Testes de Serviço
BDD em Testes de ServiçoRafael Lima
 
Aplicações Web - um estudo sobre React
Aplicações Web - um estudo sobre ReactAplicações Web - um estudo sobre React
Aplicações Web - um estudo sobre ReactJean Carlo Emer
 
Domain-Driven-Design
Domain-Driven-DesignDomain-Driven-Design
Domain-Driven-DesignWende Mendes
 
Domain-Driven-Design
 Domain-Driven-Design Domain-Driven-Design
Domain-Driven-DesignWende Mendes
 
Todas as abordagens de testes dentro do ágil
Todas as abordagens de testes dentro do ágilTodas as abordagens de testes dentro do ágil
Todas as abordagens de testes dentro do ágilElias Nogueira
 
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...Isaac de Souza
 
NITECH - EVENT STORM
NITECH - EVENT STORM NITECH - EVENT STORM
NITECH - EVENT STORM NitechAcademy
 
NITECH - EVENT STORM revisado 25Set.pdf
NITECH - EVENT STORM revisado 25Set.pdfNITECH - EVENT STORM revisado 25Set.pdf
NITECH - EVENT STORM revisado 25Set.pdfNitechAcademy
 

Similaire à BDD com Cucumber (20)

BDD com Cucumber
BDD com CucumberBDD com Cucumber
BDD com Cucumber
 
RSpec - Desenvolvimento Baseado em Teste
RSpec - Desenvolvimento Baseado em TesteRSpec - Desenvolvimento Baseado em Teste
RSpec - Desenvolvimento Baseado em Teste
 
Cucumber
CucumberCucumber
Cucumber
 
Cucumber-QA_Night
Cucumber-QA_NightCucumber-QA_Night
Cucumber-QA_Night
 
Behaviour-Driven Development com Ruby
Behaviour-Driven Development com RubyBehaviour-Driven Development com Ruby
Behaviour-Driven Development com Ruby
 
Dito Tech Talk RSpec
Dito Tech Talk RSpecDito Tech Talk RSpec
Dito Tech Talk RSpec
 
Bdd rails 3
Bdd rails 3Bdd rails 3
Bdd rails 3
 
Behaviour driven development, com jbehave
Behaviour driven development, com jbehaveBehaviour driven development, com jbehave
Behaviour driven development, com jbehave
 
Bdd Cucumber
Bdd CucumberBdd Cucumber
Bdd Cucumber
 
[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors
[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors
[GUTS-RS] GUTS Testing Games - Jogo BDD Warriors
 
BDD em Testes de Serviço
BDD em Testes de ServiçoBDD em Testes de Serviço
BDD em Testes de Serviço
 
Aplicações Web - um estudo sobre React
Aplicações Web - um estudo sobre ReactAplicações Web - um estudo sobre React
Aplicações Web - um estudo sobre React
 
Domain-Driven-Design
Domain-Driven-DesignDomain-Driven-Design
Domain-Driven-Design
 
Domain-Driven-Design
 Domain-Driven-Design Domain-Driven-Design
Domain-Driven-Design
 
Todas as abordagens de testes dentro do ágil
Todas as abordagens de testes dentro do ágilTodas as abordagens de testes dentro do ágil
Todas as abordagens de testes dentro do ágil
 
BDD em Ação
BDD em AçãoBDD em Ação
BDD em Ação
 
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...
Esquenta TDC - Como DDD e principalmente Domain Model contribuem na construçã...
 
NITECH - EVENT STORM
NITECH - EVENT STORM NITECH - EVENT STORM
NITECH - EVENT STORM
 
NITECH - EVENT STORM revisado 25Set.pdf
NITECH - EVENT STORM revisado 25Set.pdfNITECH - EVENT STORM revisado 25Set.pdf
NITECH - EVENT STORM revisado 25Set.pdf
 
BDD: Cucumber + Selenium + Java
BDD: Cucumber + Selenium + JavaBDD: Cucumber + Selenium + Java
BDD: Cucumber + Selenium + Java
 

Plus de Eduardo Mendes

JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosEduardo Mendes
 
Angular JS - Fundamentos
Angular JS - FundamentosAngular JS - Fundamentos
Angular JS - FundamentosEduardo Mendes
 
Singleton - Padrão de Projeto
Singleton - Padrão de ProjetoSingleton - Padrão de Projeto
Singleton - Padrão de ProjetoEduardo Mendes
 
Introdução à Internet, Http e HTML
Introdução à Internet, Http e HTMLIntrodução à Internet, Http e HTML
Introdução à Internet, Http e HTMLEduardo Mendes
 
Estimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEstimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEduardo Mendes
 
Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Eduardo Mendes
 
Validações no Ruby on Rails
Validações no Ruby on Rails Validações no Ruby on Rails
Validações no Ruby on Rails Eduardo Mendes
 
Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Eduardo Mendes
 

Plus de Eduardo Mendes (20)

JavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a ObjetosJavaScript - Introdução com Orientação a Objetos
JavaScript - Introdução com Orientação a Objetos
 
AngularJS - Rotas
AngularJS - RotasAngularJS - Rotas
AngularJS - Rotas
 
Angular JS - Fundamentos
Angular JS - FundamentosAngular JS - Fundamentos
Angular JS - Fundamentos
 
Singleton - Padrão de Projeto
Singleton - Padrão de ProjetoSingleton - Padrão de Projeto
Singleton - Padrão de Projeto
 
Layout Fluido
Layout FluidoLayout Fluido
Layout Fluido
 
Web Design Responsivo
Web Design ResponsivoWeb Design Responsivo
Web Design Responsivo
 
Html - Aula 4
Html - Aula 4Html - Aula 4
Html - Aula 4
 
Html - Aula 3
Html - Aula 3Html - Aula 3
Html - Aula 3
 
Introdução à Internet, Http e HTML
Introdução à Internet, Http e HTMLIntrodução à Internet, Http e HTML
Introdução à Internet, Http e HTML
 
ExtJS-4
ExtJS-4ExtJS-4
ExtJS-4
 
Jquery 2
Jquery 2Jquery 2
Jquery 2
 
Jquery
JqueryJquery
Jquery
 
Estimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de SoftwareEstimativas de Esforço - Engenharia de Software
Estimativas de Esforço - Engenharia de Software
 
Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2Java web 6 JSP Expression Language Taglib parte 2
Java web 6 JSP Expression Language Taglib parte 2
 
Validações no Ruby on Rails
Validações no Ruby on Rails Validações no Ruby on Rails
Validações no Ruby on Rails
 
Padrão Iterator
Padrão IteratorPadrão Iterator
Padrão Iterator
 
Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)Padroes Template-Method (Método Gabarito)
Padroes Template-Method (Método Gabarito)
 
Padrão Command
Padrão CommandPadrão Command
Padrão Command
 
Padrão Fachada
Padrão FachadaPadrão Fachada
Padrão Fachada
 
Padrão Adapter
Padrão AdapterPadrão Adapter
Padrão Adapter
 

BDD com Cucumber

  • 1. Desenvolvimento Baseado em Testes BDD + Cucumber Eduardo Mendes edumendes@gmail.com
  • 5. TDD Abordagem de desenvolvimento de software em que os testes direcionam a implementação do software
  • 6. TDD Favorece o design de software Expressa o comportamento do código Documenta o código
  • 7. @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
  • 8. 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
  • 11. @dudumendes BDD “Behaviour-Driven Development is about implementing an application by describing its behaviour from the perspective of its stakeholders.” David Chemlimsky
  • 12. Entender o mundo a partir da visao do BDD 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á “Desenvolvimento orientado a comportamento diz envolvido no projeto respeito a implementar uma aplicação pela descrição do seu comportamento a partir da perspectiva de seus stakeholders.” David Chemlimsky
  • 13. 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
  • 14. @dudumendes BDD Princípios Enough is enough Deliver stakeholder value It’s all behaviour
  • 15. @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
  • 16. @dudumendes red Ciclo do BDD red refactor green refactor Passo green Cenário
  • 17. @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
  • 18. @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
  • 19. @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
  • 20. @dudumendes BDD O Ciclo Desenvolvedores Automatizam cenários que orientam o desenvolvimento Descrevem comportamentos esperados Implementam os comportamentos Refatoram
  • 23. 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
  • 24. 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
  • 25. 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
  • 26. 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]
  • 27. 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]
  • 28. red Ciclo do BDD refactor red gre refactor Passo gre Cenário
  • 30. Cucumber Framework BDD Open Source baseado em RSpec Criado por Aslak Hellesøy Versão atual 1.2.1
  • 31. Cucumber Características Implementação em Ruby Estórias de usuário baseadas em textos Suporte a Injeção de dependências
  • 32. 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
  • 33. @dudumendes Cucumber em 03 passos Passo 1 - Escrever uma estória
  • 34. 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]
  • 35. 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]
  • 36. @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
  • 37. 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
  • 40. @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
  • 41. @dudumendes Cucumber em 03 passos Passo 2 - Criar o arquivo de passos
  • 42. @dudumendes Estórias no Cucumber arquivos em Ruby com sufixo “_steps” localização features/step_definitions execução comando cucumber
  • 43. @dudumendes greeter_steps.rb 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
  • 44. @dudumendes Cucumber em 03 passos Passo 3 - Dar implementação às estórias
  • 45. @dudumendes greeter_steps.rb 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
  • 47. @dudumendes class CucumberGreeter def greet "Hello Cucumber" end end 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| expect(@message).to eql greeting end
  • 49. Cucumber Passos Escrever uma estória Arquivo de texto de extensão .feature Recuperar os snippets Criar o arquivo de passos
  • 50. 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
  • 51. 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 (!-- )
  • 52. @dudumendes Gherkin Features Step definitions Feature: Aplicação Scenario: Given When Then Internacionalização Inglês é o padrão # language: pt
  • 53. @dudumendes Gherkin Feature Then Scenario And Scenario Outline But Scenarios | Given “” When #
  • 55. @dudumendes Exercício Criar uma versão em português para o Hello World
  • 56. 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
  • 57. 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:”
  • 58. @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 |
  • 60. @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
  • 61. @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
  • 63. @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
  • 64. @dudumendes Organizando features features seguro cucumber features medico executa todos dentario cucumber features/seguro vida apenas os de seguro previdencia cucumber features/seguro/medico prbl somente os médicos vgbl
  • 65. @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
  • 66. @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
  • 67. @dudumendes Tags @aprovada @sprint_1 Funcionalidade: paciente solicita consulta @em_progresso Cenario: paciente seleciona horario disponivel cucumber --tags @em_progresso
  • 68. @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
  • 70. @dudumendes Given When Then
  • 71. Passos @dudumendes Um passo candidato (StepCandidate) de uma feature deve estar associado a uma implementação de passo em um arquivo de passos Arquivo de Passos cenario_a_steps.rb feature_X.feature Dado um contexto Cenario: Cenario A implementação Dado um contexto Quando algo acontecer Quando algo acontecer implementação Então Alguma coisa acontece Então Alguma coisa acontece implementação Esta associação é feita através de expressões regulares
  • 72. @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
  • 73. @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
  • 74. @dudumendes Executa Cenário Existe Não Passo Cenário Lê 1.º passo definição? Indefinido Indefinido Sim Executa código Exceção Sim Lê próximo de definição do Pendente? lançada? passo passo Não Não Sim Existe Sim outro passo Não Cenário Cenário Falho Pendente Cenário Passou
  • 75. @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
  • 76. @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
  • 77. @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
  • 78. @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
  • 79. @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
  • 80. @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
  • 81. @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"
  • 84. @dudumendes Passos Compostos Em BDD, o autor de cenários deve possuir a liberdade de 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
  • 85. @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
  • 86. @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
  • 87. @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
  • 88. @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
  • 89. @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"
  • 90. @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
  • 91. @dudumendes Exercício Completar a feature da Transferência e fazer passar
  • 93. @dudumendes Hooks Before Executado antes de cada cenário After Executado depois de cada cenário AfterStep Executado após cada passo
  • 94. @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
  • 95. @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
  • 96. @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
  • 98. @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
  • 99. @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
  • 100. @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'} ]
  • 101. @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
  • 104. @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|
  • 105. @dudumendes Rails + cucumber + rspec pequena dose
  • 107. @dudumendes Gemfile group :development, :test do gem "rspec-rails" gem "webrat" end group :test do gem "cucumber-rails" gem ”database_cleaner” end
  • 108. @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
  • 109. @dudumendes /features/horario.feature 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"
  • 111. @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
  • 112. @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
  • 113. @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
  • 115. @dudumendes rails generate model Email de:text para:text mensagem:text
  • 116. @dudumendes require 'spec_helper' describe Email do pending "add some examples to (or delete) #{__FILE__}" end
  • 117. @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
  • 119. @dudumendes 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" it "para é inválido com email inválido" it "mensagem é obrigatória" end end
  • 121. @dudumendes app/models/email.rb class Email < ActiveRecord::Base attr_accessible :mensagem, :para end
  • 122. @dudumendes app/models/email.rb class Email < ActiveRecord::Base attr_accessible :mensagem, :para validates_presence_of :para end
  • 123. @dudumendes 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
  • 125. @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
  • 127. require 'spec_helper' @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" do email = Email.create(:para => "invalido") expect(email).to have(1).error_on(:para) end it "mensagem é obrigatória" end end
  • 128. @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
  • 129. @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" 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
  • 130. @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
  • 131. @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.