Preview only show first 10 pages with watermark. For full document please download

Bdd De Aceptación Con Ruby

1. Pruebas BDD de Aceptación con Ruby Sergio Gil y Luismi Cavallé Agile Spain 2010 2. Historias de Usuario 3. [A story] has to be a description of a requirement and its…

   EMBED


Share

Transcript

1. Pruebas BDD de Aceptación con Ruby Sergio Gil y Luismi Cavallé Agile Spain 2010 2. Historias de Usuario 3. [A story] has to be a description of a requirement and its business benefit, and a set of criteria by which we all agree that it is “done” – Dan North http://blog.dannorth.net/whats-in-a-story/ 4. Anatomía de una historia Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee 5. Anatomía de una historia Feature: Serve coffee In order to earn money Narrativa Customers should be able to buy coffee at all times Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee Criterio de Aceptación 6. Narrativa Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times 7. Narrativa Título Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times 8. Narrativa Feature: Serve coffee In order to earn money Customers should be able to Rol buy coffee at all times ¿Quién? 9. Narrativa Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Funcionalidad ¿Qué? 10. Narrativa Beneficio Feature: Serve coffee ¿Por qué? In order to earn money Customers should be able to buy coffee at all times 11. Regla de los 5 porqués 12. Regla de los 5 porqués ENSÉÑAME LA PASTA !!!! 13. Criterio de Aceptación Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee 14. Criterio de Aceptación Contexto Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee 15. Criterio de Aceptación Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ Eventos When I press the coffee button Then I should be served a coffee 16. Criterio de Aceptación Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Resultados Then I should be served a coffee 17. Criterio de Aceptación Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button NE Then I should be served a coffee O D 18. Beneficio para el negocio Programadores Testers Analistas Clientes Managers 19. Beneficio para el negocio Programadores Testers Historia de Usuario Token de comunicación / discusión Priorización según beneficio / valor Criterio común de “terminado” Analistas Clientes Managers 20. Cucumber 21. Cucumber Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Scenario: Buy last coffee Given there are 1 coffees left in the machine And I have deposited 1$ When I press the coffee button Then I should be served a coffee 22. Pasos Given a user “john” with password “secret” When he tries to login as “james” Then he should see an error message 23. Definición de pasos Given a user “john” with password “secret” 24. Definición de pasos Given a user “john” with password “secret” Given /^a user "(.+)" with password "(.+)"$/ do |login, password| 25. Definición de pasos Given a user “john” with password “secret” Given /^a user "(.+)" with password "(.+)"$/ do |login, password| User.create! :login => login, :password => password end 26. Definición de pasos When he tries to login as “james” 27. Definición de pasos When he tries to login as “james” When /^he tries to login as "(.+)"$/ do |login| 28. Definición de pasos When he tries to login as “james” When /^he tries to login as "(.+)"$/ do |login| visit "/login" fill_in "Username", :with => login fill_in "Password", :with => "secret" click_button "Login" end 29. Definición de pasos Then he should see an error message 30. Definición de pasos Then he should see an error message Then /^I should see an error message$/ do 31. Definición de pasos Then he should see an error message Then /^I should see an error message$/ do assert page.has_content?("Invalid credentials") end 32. Demo 33. http://vimeo.com/12441999 34. +40 Idiomas # language: es Característica: Búsqueda de cursos Para asegurar el mejor uso de los cursos Los estudiantes potenciales deberían poder buscar cursos Escenario: Búsqueda por materia Dado que hay 240 cursos, ninguno sobre "biología" Y hay 2 cursos A001, B205 sobre "biología" Cuando busco por "biología" Entonces debería ver los siguientes cursos: | Código de curso | | A001 | | B205 | 35. Otros lenguajes package cukes; import cuke4duke.Given; import java.util.List; import java.util.ArrayList; public class BellySteps { private List<String> belly = new ArrayList<String>(); @Given("I have (d+) cukes in my belly") public void bellyCukes(int cukes) { for(int i = 0; i < cukes; i++) { belly.add("cuke " + i); } } } 36. Otros lenguajes package cukes; import cuke4duke.Given; import java.util.List; import java.util.ArrayList; public class BellySteps { private List<String> belly = new ArrayList<String>(); @Given("I have (d+) cukes in my belly") public void bellyCukes(int cukes) { for(int i = 0; i < cukes; i++) { belly.add("cuke " + i); } } } (Given #"^I have entered ([d.]+) into the calculator$" (fn [number] (push-number (Float. number)))) 37. Más funcionalidades... 38. Background Feature: Multiple blog support Background: Given a global administrator named "Greg" And a blog named "Greg's anti-tax rants" And a customer named "Dr. Bill" And a blog named "Expensive Therapy" owned by "Dr. Bill" Scenario: Dr. Bill posts to his own blog Scenario: Dr. Bill tries to post to somebody else's blog Scenario: Greg posts to a client's blog 39. Tags @billing Feature: Verify billing @important Scenario: Missing product description Scenario: Several products $ cucumber --tags @billing,~@important 40. Hooks Before do @browser = Browser.new end After do @browser.close end 41. Hooks Before do @browser = Browser.new Around do |scenario, block| end Timeout.timeout(3) do block.call After do end @browser.close end end 42. Hooks Before do @browser = Browser.new Around do |scenario, block| end Timeout.timeout(3) do block.call After do end @browser.close end end Before('@foo') After('~@bar') 43. Scenario Outline Scenario Outline: eating Given there are <start> cucumbers When I eat <eat> cucumbers Then I should have <left> cucumbers Examples: | start | eat | left | | 12 | 5 | 7 | | 20 | 5 | 15 | 44. So far, so good? • Historias de Usuario • Beneficio para el negocio • Cucumber 45. So far, so good? • Historias de Usuario • Beneficio para el negocio • Cucumber Coming next... • Testing de aceptación Web • Beneficio para los devs • Alternativas a Cucumber 46. Aceptación para Web: Capybara 47. DSL de interacción web (navegador programático) 48. Usa el lenguaje del usuario class method GET / POST parameters 49. Usa el lenguaje del usuario class page method URL GET / POST link parameters form 50. visit "/wadus" 51. click_link "Add article" 52. click_link "Add article" click "Add article" 53. fill_in "Title", :with => "Wadus" 54. fill_in "Title", :with => "Wadus" choose "Option" 55. fill_in "Title", :with => "Wadus" choose "Option" check "Option" 56. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" 57. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year" 58. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year" click_button "Save" 59. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year" click_button "Save" click "Save" 60. within :css, ".article:first" do click_link "Edit" end 61. Matchers 62. page.should have_content("Wadus") 63. page.should have_content("Wadus") page.should_not have_content("Wadus") 64. page.should have_content("Wadus") page.should_not have_content("Wadus") page.should have_css(".article", :text => "Wadus") 65. page.should have_content("Wadus") page.should_not have_content("Wadus") page.should have_css(".article", :text => "Wadus") page.should have_css(".article", :count => 3) 66. page.should have_content("Wadus") page.should_not have_content("Wadus") page.should have_css(".article", :text => "Wadus") page.should have_css(".article", :count => 3) page.should have_xpath("//*[@class='article']") 67. page.should have_css(".article", :text => "Wadus") do |article| article.should have_css(".author", :text => "@porras") article.should have_css(".links") do |links| links.should have_css("a", :href => "http://wadus.info") links.should have_css("a", :href => "http://bit.ly/wadus") end end 68. save_and_open_page 69. Drivers 70. RackTest 71. RackTest Basado en Rack 72. RackTest Basado en Rack FAST! 73. RackTest Basado en Rack FAST! Sin Javascript 74. RackTest Basado en Rack FAST! Sin Javascript No es ‘real’ 75. Selenium 76. Selenium Basado en browsers programables 77. Selenium Basado en browsers programables Javascript 78. Selenium Basado en browsers programables Javascript Aceptación pura 79. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO! 80. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO! Un poco frágil 81. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO! Un poco frágil Java 82. Celerity / Culerity 83. Celerity / Culerity Basado en HTMLUnit 84. Celerity / Culerity Basado en HTMLUnit Javascript 85. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura 86. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura No muy lento 87. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura No muy lento Java 88. Envjs 89. Envjs Basado en SpiderMonkey 90. Envjs Basado en SpiderMonkey Javascript 91. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura 92. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento 93. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento Ruby 94. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento Ruby Un poco verde 95. RackTest Selenium Culerity 0 37.5 75.0 112.5 150.0 96. Valor para el desarrollador 97. Excelente herramienta de verificación 98. Pero TDD no es QA 99. Pero TDD no es QA sólo 100. Dirige el desarrollo 101. “Outside-in testing is the best way to avoid overengineering” http://www.sarahmei.com/blog/2010/05/29/outside-in-bdd/ 102. Up-front 103. Up-front M 104. Up-front C M 105. Up-front V C M 106. Up-front T V C M 107. Up-front T T V C M 108. Up-front T T T V C M 109. Outside-in 110. Outside-in F 111. Outside-in F V 112. Outside-in F V C 113. Outside-in F V C M 114. Outside-in F F F V V V F F C C C V V C C MM M M M 115. “Tu interfaz es tu producto” http://gettingreal.37signals.com/ch09_Interface_First.php 116. Permite otras prácticas ágiles 117. The Simplest Thing That Could Possibly Work 118. Dejar que el diseño “emerja” 119. Pair Programming 120. Refactorización contínua 121. Integración Contínua 122. Propiedad colectiva del código 123. Release Often 124. Continuous Deployment 125. Steak 126. A veces Cucumber (historias en texto plano) no es la mejor opción 127. Todo el “valor para el desarrollador” sin la burocracia extra 128. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 129. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 130. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 131. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 132. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 133. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 134. feature "Main page" do background do create_user :login => "wadus" end scenario "should show existing books" do create_book :title => "The Pragmatic Programmer" login_as "wadus" visit "/" page.should have_css(".book", :text => "The Pragmatic Programmer") end end 135. Demo 136. http://vimeo.com/12468092 137. Más amigos 138. Spork 139. Spork Sin spork Con spork 0 3.25 6.50 9.75 13.00 140. Factorías 141. fixture_replacement 142. fixture_replacement factory_girl 143. fixture_replacement factory_girl machinist 144. fixture_replacement factory_girl machinist fixjour 145. fixture_replacement factory_girl machinist fixjour cranky 146. fixture_replacement factory_girl machinist fixjour cranky Ruby 147. module Factories def create_user(attrs = {}) attrs = attrs.dup attrs[:name] ||= String.random(10) attrs[:email] ||= "#{String.random(10)}@example.com" User.create!(attrs) end def create_article(attrs = {}) attrs = attrs.dup attrs[:title] ||= String.random(10) attrs[:author] ||= create_user Article.create!(attrs) end end ... create_user create_user(:name => "Bartolo") create_article create_article(:author => create_user(:name => "Mr. Wadus")) 148. Delorean 149. Delorean 150. Delorean it "should show latest created user" do time_travel_to(3.minutes.ago) { create_user :name => "John" } time_travel_to(5.minutes.ago) { create_user :name => "Chris" } get '/' page.should have_content("John") page.should_not have_content("Chris") end 151. Database Cleaner 152. Database Cleaner DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean 153. Database Cleaner DatabaseCleaner.strategy = :transaction DatabaseCleaner.clean 154. Email Spec 155. Email Spec mailbox_for("[email protected]").should have(1).email open_email "[email protected]" current_email.should have_subject("Bienvenido a Wadus 2.0") current_email.should have_text("Hola, porras") 156. Webmock 157. Webmock request(:post, "www.example.com"). with(:body => "abc"). should have_been_made.once 158. MundoPepino 159. “MundoPepino es un conjunto de pasos genéricos para testear una aplicación Rails utilizando Cucumber” 160. Dado que tenemos un huerto Y una huerta Y un huerto "En el río" Y una huerta "En el castro" Y un huerto llamado "Regadío" Y una huerta llamada "Secano" Y 2 huertos Y 2 huertos "Regadío" Y 2 huertos llamados "Secano" Y 2 huertas llamadas "Secano" Y 3 huertas llamadas "H-01, H-02 y H-03" Entonces tenemos en bbdd 17 huertos Y tenemos en bbdd un huerto "En el río" Y tenemos en bbdd una huerta "En el castro" Y tenemos en bbdd 3 huertos "Regadío" Y tenemos en bbdd 5 huertas "Secano" Y tenemos en bbdd un huerto "H-01" Y tenemos en bbdd un huerto "H-02" Y tenemos en bbdd un huerto "H-03" 161. Cuando visito la página de creación de huerto Entonces debo ver la etiqueta H2 con el valor "Alta de Huerta" Cuando visito la página de alta de huerto Entonces debo ver la etiqueta H2 con el valor "Alta de Huerta" Cuando visito la página de nueva huerta Entonces debo ver la etiqueta H2 con e