BDD com Cucumber

2,656 views

Published on

Introdução ao BDD com Cucumber

Published in: Technology
2 Comments
8 Likes
Statistics
Notes
No Downloads
Views
Total views
2,656
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
118
Comments
2
Likes
8
Embeds 0
No embeds

No notes for slide

BDD com Cucumber

  1. 1. DesenvolvimentoBaseado em TestesBDD + CucumberEduardo Mendesedumendes@gmail.com
  2. 2. @dudumendesIntrodução
  3. 3. AgendaBDDCucumber
  4. 4. @dudumendesBDD
  5. 5. TDD Abordagem de desenvolvimento de software em que os testes direcionam a implementação do software
  6. 6. TDDFavorece o design de softwareExpressa o comportamento do códigoDocumenta o código
  7. 7. @dudumendesTestes 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. 8. Expectativas dos usuáriosCasos de UsoEstórias de UsuárioAmbas não possuem mecanismos de validação quetraduzam as expectativas dos usuários
  9. 9. @dudumendes BDDBehaviour Driven Development
  10. 10. @dudumendesBDDBehaviour Driven Design
  11. 11. @dudumendesBDD“Behaviour-Driven Development is about implementingan application by describing its behaviour from theperspective of its stakeholders.” David Chemlimsky
  12. 12. Entender o mundo a partir da visao doBDD 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 projetorespeito a implementar uma aplicação pela descriçãodo seu comportamento a partir da perspectiva de seusstakeholders.” David Chemlimsky
  13. 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. 14. @dudumendesBDDPrincípios Enough is enough Deliver stakeholder value It’s all behaviour
  15. 15. @dudumendesBDDPrincí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. 16. @dudumendes redCiclo do BDD red refactor green refactor Passo green Cenário
  17. 17. @dudumendesBDDO 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. 18. @dudumendesBDDO 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. 19. @dudumendesBDDO 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. 20. @dudumendesBDDO Ciclo Desenvolvedores Automatizam cenários que orientam o desenvolvimento Descrevem comportamentos esperados Implementam os comportamentos Refatoram
  21. 21. @dudumendesProcesso do BDD
  22. 22. @dudumendesEstórias no BDD
  23. 23. BDDEstó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. 24. BDDEstó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. 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. 26. Estrutura de uma estóriaConnextra 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. 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. 28. redCiclo do BDD refactor red gre refactor Passo gre Cenário
  29. 29. @dudumendesCucumber
  30. 30. Cucumber Framework BDD Open Source baseado em RSpec Criado por Aslak Hellesøy Versão atual 1.2.1
  31. 31. CucumberCaracterísticas Implementação em Ruby Estórias de usuário baseadas em textos Suporte a Injeção de dependências
  32. 32. Cucumberem 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. 33. @dudumendesCucumber em 03 passosPasso 1 - Escrever uma estória
  34. 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. 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. 36. @dudumendesEstórias no Cucumberarquivos 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. 37. Cucumber em 03 passosPasso 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
  38. 38. @dudumendescucumber
  39. 39. @dudumendescontinuação: snippets
  40. 40. @dudumendesResultadoO cucumber encontrou a feature tentou executá-la mas não sabe como executá-laO cucumber sugeriu algumas dicas do código
  41. 41. @dudumendesCucumber em 03 passosPasso 2 - Criar o arquivo de passos
  42. 42. @dudumendesEstórias no Cucumberarquivos em Ruby com sufixo “_steps”localização features/step_definitionsexecução comando cucumber
  43. 43. @dudumendes greeter_steps.rbGiven /^a greeter$/ do pending # express the regexp above with the code you wish you hadendWhen /^I send it the greet message$/ do pending # express the regexp above with the code you wish you hadendThen /^I should see "(.*?)"$/ do |arg1| pending # express the regexp above with the code you wish you hadend
  44. 44. @dudumendesCucumber em 03 passosPasso 3 - Dar implementação às estórias
  45. 45. @dudumendes greeter_steps.rbGiven /^a greeter$/ do @greeter = CucumberGreeter.newendWhen /^I send it the greet message$/ do @message = @greeter.greetendThen /^I should see "(.*?)"$/ do |greeting| @message.should == greetingend
  46. 46. @dudumendes
  47. 47. @dudumendesclass CucumberGreeter def greet "Hello Cucumber" endendGiven /^a greeter$/ do @greeter = CucumberGreeter.newendWhen /^I send it the greet message$/ do @message = @greeter.greetendThen /^I should see "(.*?)"$/ do |greeting| expect(@message).to eql greetingend
  48. 48. @dudumendes
  49. 49. Cucumber PassosEscrever uma estória Arquivo de texto de extensão .featureRecuperar os snippetsCriar o arquivo de passos
  50. 50. Estórias no CucumberEstórias em arquivos de textos 01 Narrativa (Narrative) * Cenários (Scenarios)Narrativa Opcional As a, In order to, I want to
  51. 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. 52. @dudumendesGherkin Features Step definitionsFeature: Aplicação Scenario: Given When ThenInternacionalização Inglês é o padrão # language: pt
  53. 53. @dudumendesGherkinFeature ThenScenario AndScenario Outline ButScenarios |Given “”When #
  54. 54. @dudumendesGherkin --i18n cucumber --i18n pt
  55. 55. @dudumendesExercício Criar uma versão em português para o Hello World
  56. 56. Esquema de CenáriosScenario 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. 57. Esquemas de cenáriosNos cenários os parâmetros devem ser envolvidoscom sinais “<” e “>” Eles devem ser declarados como esquemas de cenáriosApós um cenário informam-se os valores válidos paraos parâmetros em um tabela determinada por“Cenários:”
  58. 58. @dudumendes# language: ptFuncionalidade: 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 |
  59. 59. @dudumendesO comando cucumber
  60. 60. @dudumendesOrganizando featuresComando 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. 61. @dudumendes# language: ptFuncionalidade: 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
  62. 62. @dudumendesOrganizando features
  63. 63. @dudumendesOrganizando featuresComando cucumber sem opções serão procurados todos os arquivos .rb e .featurePara projetos pequenos caminho mais simples é organizar os arquivos dentro do diretório featuresPara projetos maiores crie subdiretorios para cada feature vários arquivos em cada diretório com um subconjunto de ceários coesos
  64. 64. @dudumendesOrganizando featuresfeatures 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. 65. @dudumendesA vida de um cenárioNo 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. 66. @dudumendesTags 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. 67. @dudumendesTags@aprovada @sprint_1Funcionalidade: paciente solicita consulta @em_progresso Cenario: paciente seleciona horario disponivelcucumber --tags @em_progresso
  68. 68. @dudumendesTagscucumber --tags @cuc, @umbercucumber --tags @cuc || @umber executa todos os cenário com @cuc OU @umbercucumber --tags @cuc --tags @umbercucumber --tags @cuc && @umber executa todos os cenário com @cuc E @umbercucumber --tags ~@umbercucumber --tags !@umber executa todos os cenário sem @umber
  69. 69. @dudumendesPasso-a-passo
  70. 70. @dudumendesGiven When Then
  71. 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çãoEsta associação é feita através de expressões regulares
  72. 72. @dudumendesPassosUm passo candidato (StepCandidate) de umafeature deve estar associado a uma implementaçãode passo em um arquivo de passos Caso esteja: passed Caso contrário: undefined
  73. 73. @dudumendesDefinição de passosCriação do arquivo de feature Quando você cria uma feature executa o cucumber cenários indefinidos passos indefinidos snippets de código
  74. 74. @dudumendes Executa Cenário Existe Não Passo Cenário Lê 1.º passo definição? Indefinido Indefinido Sim Executa código Exceção SimLê 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. 75. @dudumendes# language: ptFuncionalidade: 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. 76. @dudumendesDefinição de passosCriação do arquivo de passos Cria-se o arquivo de passosDado /^um hotel com "(.*?)" quartos e "(.*?)" reservas$/ do |total_de_quartos, total_de_reservas|end
  77. 77. @dudumendesGiven / When / ThenO 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. 78. @dudumendesGivenDado 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. 79. @dudumendesWhenQuando 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. 80. @dudumendesThenEntã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. 81. @dudumendesAnd / ButE / 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"
  82. 82. @dudumendes
  83. 83. @dudumendesPassos compostos
  84. 84. @dudumendesPassos CompostosEm 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áriosNeste contexto, os cenários compostos são úteis
  85. 85. @dudumendesPassos CompostosPassos compostos permitem criar grupos de execuçãode passos ligados a um único passo, o que pode sermuito útil e poderoso
  86. 86. @dudumendesFuncionalidade: 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. 87. @dudumendesCená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. 88. @dudumendesFuncionalidade: 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. 89. @dudumendesFuncionalidade: 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. 90. @dudumendesQuando /^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. 91. @dudumendesExercícioCompletar a feature da Transferência e fazer passar
  92. 92. @dudumendesHooks
  93. 93. @dudumendesHooksBefore Executado antes de cada cenárioAfter Executado depois de cada cenárioAfterStep Executado após cada passo
  94. 94. @dudumendesBefore 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. 95. @dudumendesBackgroundContexto, Cenario de Fundo Before, After, AfterStep Não possuem descrição na feature Background Similar ao Before Permite escrever passos na feature
  96. 96. @dudumendesFuncionalidade: 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
  97. 97. @dudumendesTabelas em passos
  98. 98. @dudumendesFuncionalidade: 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. 99. @dudumendesDado /^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 hadendDado /^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 hadendEntao /^a primeira mao deve ganhar da segunda mao$/ do pending # express the regexp above with the code you wish you had
  100. 100. @dudumendesDado 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. 101. @dudumendesDado /^uma mao com as seguintes cartas$/ do |cartas| cartas.hashes.each {|hash| @primeira_mao << Carta.new(hash) }endDado /^outra mao com as seguintes cartas$/ do |cartas| cartas.hashes.each {|hash| @segunda_mao << Carta.new(hash) }end
  102. 102. @dudumendesExercíciofazer passar a feature
  103. 103. @dudumendesExercício
  104. 104. @dudumendesCriar a feature e fazer passarDados  os  negociantes:  |nome|rank||Larry|Estagio  3||Moe|Estagio  1||Curly|Estagio  2|Quando  os  negociantes  são  ordenados  pelo  nomeEntão  os  comerciantes  devem  vir  na  seguinte  ordem:|nome|rank||Curly|Estagio  2||Larry|Estagio  3||Moe|Estagio  1|
  105. 105. @dudumendesRails + cucumber + rspecpequena dose
  106. 106. @dudumendesrails new showtime
  107. 107. @dudumendesGemfilegroup :development, :test do gem "rspec-rails" gem "webrat"endgroup :test do gem "cucumber-rails" gem ”database_cleaner”end
  108. 108. @dudumendesbundle installrails generate rspec:install (dependencias do rspec)rails generate cucumber:install (dependencias do cucumber)rake db:migraterake db:test:preparerake specrake cucumber
  109. 109. @dudumendes /features/horario.featureFuncionalidade: 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"
  110. 110. @dudumendessnippet
  111. 111. @dudumendes features/step_definitions/horario_steps.rb# encoding: utf-8# language: ptDado /^um filme$/ do @filme = Filme.create!endQuando /^eu configuro o horario para "(.*?)" às "(.*?)"$/ do |data, hora| @filme.update_attribute(:horario_data, Date.parse(data)) @filme.update_attribute(:horario_hora, hora)endEntão /^o horario deve ser "([^"]*)"$/ do |horario| expect(@filme.horario).to eql horarioend
  112. 112. @dudumendesCriar 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. 113. @dudumendesapp/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
  114. 114. @dudumendesValidando o modelo
  115. 115. @dudumendesrails generate model Email de:text para:text mensagem:text
  116. 116. @dudumendesrequire spec_helperdescribe Email do pending "add some examples to (or delete) #{__FILE__}"end
  117. 117. @dudumendesrequire spec_helperdescribe 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" endend
  118. 118. @dudumendes
  119. 119. @dudumendesrequire spec_helperdescribe 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" endend
  120. 120. @dudumendes
  121. 121. @dudumendesapp/models/email.rbclass Email < ActiveRecord::Base attr_accessible :mensagem, :paraend
  122. 122. @dudumendesapp/models/email.rbclass Email < ActiveRecord::Base attr_accessible :mensagem, :para validates_presence_of :paraend
  123. 123. @dudumendesrequire spec_helperdescribe 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" endend
  124. 124. @dudumendes
  125. 125. @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" it "mensagem é obrigatória" endend
  126. 126. @dudumendes
  127. 127. require spec_helper @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" endend
  128. 128. @dudumendesclass 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 => trueend
  129. 129. @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 endend
  130. 130. @dudumendesclass 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 => trueend
  131. 131. @dudumendesBibliografia 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.

×