Pruebas BDD de
      Aceptación con Ruby
                   Sergio Gil y Luismi Cavallé




Agile Spain 2010
Historias de Usuario
[A story] has to be a description of a
requirement and its business benefit,
 and a set of criteria by which we all
       ...
Anatomía de una historia
Feature: Serve coffee
  In order to earn money
  Customers should be able to
  buy coffee at all ...
Anatomía de una historia
    Feature: Serve coffee
      In order to earn money             Narrativa
      Customers shou...
Narrativa

Feature: Serve coffee
 In order to earn money
 Customers should be able to
 buy coffee at all times
Narrativa
                          Título

Feature: Serve coffee
 In order to earn money
 Customers should be able to
 bu...
Narrativa

     Feature: Serve coffee
          In order to earn money
          Customers should be able to

  Rol     bu...
Narrativa

Feature: Serve coffee
 In order to earn money
 Customers should be able to
 buy coffee at all times

          ...
Narrativa

                           Beneficio
Feature: Serve coffee
                           ¿Por qué?
 In order to ea...
Regla de los 5 porqués
Regla de los 5 porqués

             ENSÉÑAME LA
               PASTA !!!!
Criterio de Aceptación

Scenario: Buy last coffee

 Given there are 1 coffees left in the machine
 And I have deposited 1$...
Criterio de Aceptación
                                    Contexto
Scenario: Buy last coffee

 Given there are 1 coffees ...
Criterio de Aceptación

Scenario: Buy last coffee

 Given there are 1 coffees left in the machine
 And I have deposited 1$...
Criterio de Aceptación

Scenario: Buy last coffee

 Given there are 1 coffees left in the machine
 And I have deposited 1$...
Criterio de Aceptación

Scenario: Buy last coffee

 Given there are 1 coffees left in the machine
 And I have deposited 1$...
Beneficio para el negocio
Programadores              Testers




Analistas       Clientes   Managers
Beneficio para el negocio
Programadores                                      Testers



              Historia de Usuario
...
Cucumber
Cucumber
Feature: Serve coffee
  In order to earn money
  Customers should be able to
  buy coffee at all times

Scenario:...
Pasos
Given a user “john” with password “secret”



    When he tries to login as “james”



    Then he should see an err...
Definición de pasos
Given a user “john” with password “secret”
Definición de pasos
   Given a user “john” with password “secret”



Given /^a user "(.+)" with password "(.+)"$/ do |logi...
Definición de pasos
      Given a user “john” with password “secret”



Given /^a user "(.+)" with password "(.+)"$/ do |l...
Definición de pasos
When he tries to login as “james”
Definición de pasos
    When he tries to login as “james”



When /^he tries to login as "(.+)"$/ do |login|
Definición de pasos
    When he tries to login as “james”



When /^he tries to login as "(.+)"$/ do |login|
  visit "/log...
Definición de pasos
Then he should see an error message
Definición de pasos
     Then he should see an error message




Then /^I should see an error message$/ do
Definición de pasos
     Then he should see an error message




Then /^I should see an error message$/ do
  assert page.h...
Demo
http://vimeo.com/12441999
+40 Idiomas
# language: es
Característica: Búsqueda de cursos
  Para asegurar el mejor uso de los cursos
  Los estudiantes...
Otros lenguajes
package cukes;

import cuke4duke.Given;
import java.util.List;
import java.util.ArrayList;

public class B...
Otros lenguajes
package cukes;

import cuke4duke.Given;
import java.util.List;
import java.util.ArrayList;

public class B...
Más funcionalidades...
Background
Feature: Multiple blog support

  Background:
    Given a global administrator named "Greg"
    And a blog name...
Tags
  @billing
  Feature: Verify billing

    @important
    Scenario: Missing product description

    Scenario: Several...
Hooks
Before do
  @browser = Browser.new
end

After do
  @browser.close
end
Hooks
Before do
  @browser = Browser.new   Around do |scenario, block|
end                          Timeout.timeout(3) do
...
Hooks
Before do
  @browser = Browser.new    Around do |scenario, block|
end                           Timeout.timeout(3) d...
Scenario Outline

Scenario Outline: eating
  Given there are <start> cucumbers
  When I eat <eat> cucumbers
  Then I shoul...
So far, so good?
• Historias de Usuario
• Beneficio para el negocio
• Cucumber
So far, so good?
• Historias de Usuario
• Beneficio para el negocio
• Cucumber

  Coming next...
• Testing de aceptación W...
Aceptación para Web:
     Capybara
DSL de interacción web
(navegador programático)
Usa el lenguaje del usuario

   class
  method
GET / POST
parameters
Usa el lenguaje del usuario

   class           page
  method           URL
GET / POST          link
parameters         fo...
visit "/wadus"
click_link "Add article"
click_link "Add article"
click "Add article"
fill_in "Title", :with => "Wadus"
fill_in "Title", :with => "Wadus"
choose "Option"
fill_in "Title", :with => "Wadus"
choose "Option"
check "Option"
fill_in "Title", :with => "Wadus"
choose "Option"
check "Option"
uncheck "Option"
fill_in "Title", :with => "Wadus"
choose "Option"
check "Option"
uncheck "Option"
select "1980", :from => "Birth Year"
fill_in "Title", :with => "Wadus"
choose "Option"
check "Option"
uncheck "Option"
select "1980", :from => "Birth Year"
cli...
fill_in "Title", :with => "Wadus"
choose "Option"
check "Option"
uncheck "Option"
select "1980", :from => "Birth Year"
cli...
within :css, ".article:first" do
  click_link "Edit"
end
Matchers
page.should have_content("Wadus")
page.should have_content("Wadus")
page.should_not have_content("Wadus")
page.should have_content("Wadus")
page.should_not have_content("Wadus")

page.should have_css(".article", :text => "Wadus")
page.should have_content("Wadus")
page.should_not have_content("Wadus")

page.should have_css(".article", :text => "Wadus"...
page.should have_content("Wadus")
page.should_not have_content("Wadus")

page.should have_css(".article", :text => "Wadus"...
page.should have_css(".article", :text => "Wadus") do |article|
  article.should have_css(".author", :text => "@porras")
 ...
save_and_open_page
Drivers
RackTest
RackTest
Basado en Rack
RackTest
Basado en Rack


    FAST!
RackTest
Basado en Rack


    FAST!
Sin Javascript
RackTest
Basado en Rack


    FAST!
Sin Javascript
 No es ‘real’
Selenium
Selenium
Basado en browsers programables
Selenium
Basado en browsers programables


          Javascript
Selenium
Basado en browsers programables


          Javascript
        Aceptación pura
Selenium
Basado en browsers programables


          Javascript
        Aceptación pura
           ¡LENTO!
Selenium
Basado en browsers programables


          Javascript
        Aceptación pura
           ¡LENTO!
         Un poc...
Selenium
Basado en browsers programables


          Javascript
        Aceptación pura
           ¡LENTO!
         Un poc...
Celerity / Culerity
Celerity / Culerity
   Basado en HTMLUnit
Celerity / Culerity
   Basado en HTMLUnit


       Javascript
Celerity / Culerity
   Basado en HTMLUnit


       Javascript
   Aceptación casi pura
Celerity / Culerity
   Basado en HTMLUnit


       Javascript
   Aceptación casi pura
      No muy lento
Celerity / Culerity
   Basado en HTMLUnit


       Javascript
   Aceptación casi pura
      No muy lento
          Java
Envjs
Envjs
Basado en SpiderMonkey
Envjs
Basado en SpiderMonkey


      Javascript
Envjs
Basado en SpiderMonkey


      Javascript
  Aceptación casi pura
Envjs
Basado en SpiderMonkey


      Javascript
  Aceptación casi pura
     No muy lento
Envjs
Basado en SpiderMonkey


      Javascript
  Aceptación casi pura
     No muy lento
         Ruby
Envjs
Basado en SpiderMonkey


      Javascript
  Aceptación casi pura
     No muy lento
         Ruby
    Un poco verde
RackTest




Selenium




 Culerity



            0   37.5   75.0   112.5   150.0
Valor para el
desarrollador
Excelente herramienta
   de verificación
Pero TDD no es QA
Pero TDD no es QA
             sólo
Dirige el desarrollo
“Outside-in testing is the best
way to avoid overengineering”



                    http://www.sarahmei.com/blog/2010/05/...
Up-front
Up-front




   M
Up-front




   C

   M
Up-front



   V

   C

   M
Up-front

   T

   V

   C

   M
Up-front

   T
           T

   V

   C

   M
Up-front

       T
T              T

       V

       C

       M
Outside-in
Outside-in

    F
Outside-in

    F


    V
Outside-in

    F


    V
    C
Outside-in

    F


    V
    C
    M
Outside-in

                     F
    F                            F

                 V           V
         V
F




   ...
“Tu interfaz es tu producto”




                   http://gettingreal.37signals.com/ch09_Interface_First.php
Permite otras prácticas
        ágiles
The Simplest Thing That
  Could Possibly Work
Dejar que el diseño “emerja”
Pair Programming
Refactorización contínua
Integración Contínua
Propiedad colectiva del código
Release Often
Continuous Deployment
Steak
A veces Cucumber
(historias en texto plano)
  no es la mejor opción
Todo el “valor para el
desarrollador” sin la
  burocracia extra
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
feature "Main page" do

 background do
   create_user :login => "wadus"
 end

 scenario "should show existing books" do
  ...
Demo
http://vimeo.com/12468092
Más amigos
Spork
Spork

Sin spork


Con spork


            0    3.25 6.50   9.75 13.00
Factorías
fixture_replacement
fixture_replacement
   factory_girl
fixture_replacement
   factory_girl
     machinist
fixture_replacement
   factory_girl
     machinist
      fixjour
fixture_replacement
   factory_girl
     machinist
      fixjour
      cranky
fixture_replacement
   factory_girl
     machinist
      fixjour
      cranky
        Ruby
module Factories

 def create_user(attrs = {})
   attrs = attrs.dup
   attrs[:name] ||= String.random(10)
   attrs[:email]...
Delorean
Delorean
Delorean

it "should show latest created user" do
  time_travel_to(3.minutes.ago) { create_user :name => "John" }
  time_t...
Database Cleaner
Database Cleaner


DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
Database Cleaner


DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean
Email Spec
Email Spec

mailbox_for("porras@example.com").should have(1).email

open_email "porras@example.com"

current_email.should ...
Webmock
Webmock


request(:post, "www.example.com").
                with(:body => "abc").
                should have_been_made.o...
MundoPepino
“MundoPepino es un conjunto de
pasos genéricos para testear una
   aplicación Rails utilizando
           Cucumber”
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"
...
Cuando visito   la página de creación de huerto
Entonces debo   ver la etiqueta H2 con el valor "Alta de Huerta"
Cuando vi...
Dado que tenemos un huerto llamado "H-01"
Y que dicho huerto tiene los siguientes aspersores:
| nombre | caudal | unidad c...
Recapitulando
• Aceptación Web
• Valor para los devs
• Steak (‘cause Cucumber
  is for veggies)
• Otros amiguitos...
Gracias!
Gracias!
                   @porras y @cavalle



                   ¿Preg untas?


Agile Spain 2010
BDD de Aceptación con Ruby
BDD de Aceptación con Ruby
BDD de Aceptación con Ruby
Upcoming SlideShare
Loading in …5
×

BDD de Aceptación con Ruby

2,732 views
2,653 views

Published on

Presented at AgileSpain 2010 in Madrid by Luismi Cavallé and Sergio Gil

0 Comments
6 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,732
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
41
Comments
0
Likes
6
Embeds 0
No embeds

No notes for slide

BDD de Aceptación con Ruby

  1. 1. Pruebas BDD de Aceptación con Ruby Sergio Gil y Luismi Cavallé Agile Spain 2010
  2. 2. Historias de Usuario
  3. 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. 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. 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. 6. Narrativa Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times
  7. 7. Narrativa Título Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times
  8. 8. Narrativa Feature: Serve coffee In order to earn money Customers should be able to Rol buy coffee at all times ¿Quién?
  9. 9. Narrativa Feature: Serve coffee In order to earn money Customers should be able to buy coffee at all times Funcionalidad ¿Qué?
  10. 10. Narrativa Beneficio Feature: Serve coffee ¿Por qué? In order to earn money Customers should be able to buy coffee at all times
  11. 11. Regla de los 5 porqués
  12. 12. Regla de los 5 porqués ENSÉÑAME LA PASTA !!!!
  13. 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. 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. 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. 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. 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. 18. Beneficio para el negocio Programadores Testers Analistas Clientes Managers
  19. 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. 20. Cucumber
  21. 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. 22. Pasos Given a user “john” with password “secret” When he tries to login as “james” Then he should see an error message
  23. 23. Definición de pasos Given a user “john” with password “secret”
  24. 24. Definición de pasos Given a user “john” with password “secret” Given /^a user "(.+)" with password "(.+)"$/ do |login, password|
  25. 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. 26. Definición de pasos When he tries to login as “james”
  27. 27. Definición de pasos When he tries to login as “james” When /^he tries to login as "(.+)"$/ do |login|
  28. 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. 29. Definición de pasos Then he should see an error message
  30. 30. Definición de pasos Then he should see an error message Then /^I should see an error message$/ do
  31. 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. 32. Demo
  33. 33. http://vimeo.com/12441999
  34. 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. 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. 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. 37. Más funcionalidades...
  38. 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. 39. Tags @billing Feature: Verify billing @important Scenario: Missing product description Scenario: Several products $ cucumber --tags @billing,~@important
  40. 40. Hooks Before do @browser = Browser.new end After do @browser.close end
  41. 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. 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. 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. 44. So far, so good? • Historias de Usuario • Beneficio para el negocio • Cucumber
  45. 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. 46. Aceptación para Web: Capybara
  47. 47. DSL de interacción web (navegador programático)
  48. 48. Usa el lenguaje del usuario class method GET / POST parameters
  49. 49. Usa el lenguaje del usuario class page method URL GET / POST link parameters form
  50. 50. visit "/wadus"
  51. 51. click_link "Add article"
  52. 52. click_link "Add article" click "Add article"
  53. 53. fill_in "Title", :with => "Wadus"
  54. 54. fill_in "Title", :with => "Wadus" choose "Option"
  55. 55. fill_in "Title", :with => "Wadus" choose "Option" check "Option"
  56. 56. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option"
  57. 57. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year"
  58. 58. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year" click_button "Save"
  59. 59. fill_in "Title", :with => "Wadus" choose "Option" check "Option" uncheck "Option" select "1980", :from => "Birth Year" click_button "Save" click "Save"
  60. 60. within :css, ".article:first" do click_link "Edit" end
  61. 61. Matchers
  62. 62. page.should have_content("Wadus")
  63. 63. page.should have_content("Wadus") page.should_not have_content("Wadus")
  64. 64. page.should have_content("Wadus") page.should_not have_content("Wadus") page.should have_css(".article", :text => "Wadus")
  65. 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. 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. 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. 68. save_and_open_page
  69. 69. Drivers
  70. 70. RackTest
  71. 71. RackTest Basado en Rack
  72. 72. RackTest Basado en Rack FAST!
  73. 73. RackTest Basado en Rack FAST! Sin Javascript
  74. 74. RackTest Basado en Rack FAST! Sin Javascript No es ‘real’
  75. 75. Selenium
  76. 76. Selenium Basado en browsers programables
  77. 77. Selenium Basado en browsers programables Javascript
  78. 78. Selenium Basado en browsers programables Javascript Aceptación pura
  79. 79. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO!
  80. 80. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO! Un poco frágil
  81. 81. Selenium Basado en browsers programables Javascript Aceptación pura ¡LENTO! Un poco frágil Java
  82. 82. Celerity / Culerity
  83. 83. Celerity / Culerity Basado en HTMLUnit
  84. 84. Celerity / Culerity Basado en HTMLUnit Javascript
  85. 85. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura
  86. 86. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura No muy lento
  87. 87. Celerity / Culerity Basado en HTMLUnit Javascript Aceptación casi pura No muy lento Java
  88. 88. Envjs
  89. 89. Envjs Basado en SpiderMonkey
  90. 90. Envjs Basado en SpiderMonkey Javascript
  91. 91. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura
  92. 92. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento
  93. 93. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento Ruby
  94. 94. Envjs Basado en SpiderMonkey Javascript Aceptación casi pura No muy lento Ruby Un poco verde
  95. 95. RackTest Selenium Culerity 0 37.5 75.0 112.5 150.0
  96. 96. Valor para el desarrollador
  97. 97. Excelente herramienta de verificación
  98. 98. Pero TDD no es QA
  99. 99. Pero TDD no es QA sólo
  100. 100. Dirige el desarrollo
  101. 101. “Outside-in testing is the best way to avoid overengineering” http://www.sarahmei.com/blog/2010/05/29/outside-in-bdd/
  102. 102. Up-front
  103. 103. Up-front M
  104. 104. Up-front C M
  105. 105. Up-front V C M
  106. 106. Up-front T V C M
  107. 107. Up-front T T V C M
  108. 108. Up-front T T T V C M
  109. 109. Outside-in
  110. 110. Outside-in F
  111. 111. Outside-in F V
  112. 112. Outside-in F V C
  113. 113. Outside-in F V C M
  114. 114. Outside-in F F F V V V F F C C C V V C C MM M M M
  115. 115. “Tu interfaz es tu producto” http://gettingreal.37signals.com/ch09_Interface_First.php
  116. 116. Permite otras prácticas ágiles
  117. 117. The Simplest Thing That Could Possibly Work
  118. 118. Dejar que el diseño “emerja”
  119. 119. Pair Programming
  120. 120. Refactorización contínua
  121. 121. Integración Contínua
  122. 122. Propiedad colectiva del código
  123. 123. Release Often
  124. 124. Continuous Deployment
  125. 125. Steak
  126. 126. A veces Cucumber (historias en texto plano) no es la mejor opción
  127. 127. Todo el “valor para el desarrollador” sin la burocracia extra
  128. 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. 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. 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. 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. 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. 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. 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. 135. Demo
  136. 136. http://vimeo.com/12468092
  137. 137. Más amigos
  138. 138. Spork
  139. 139. Spork Sin spork Con spork 0 3.25 6.50 9.75 13.00
  140. 140. Factorías
  141. 141. fixture_replacement
  142. 142. fixture_replacement factory_girl
  143. 143. fixture_replacement factory_girl machinist
  144. 144. fixture_replacement factory_girl machinist fixjour
  145. 145. fixture_replacement factory_girl machinist fixjour cranky
  146. 146. fixture_replacement factory_girl machinist fixjour cranky Ruby
  147. 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. 148. Delorean
  149. 149. Delorean
  150. 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. 151. Database Cleaner
  152. 152. Database Cleaner DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean
  153. 153. Database Cleaner DatabaseCleaner.strategy = :transaction DatabaseCleaner.clean
  154. 154. Email Spec
  155. 155. Email Spec mailbox_for("porras@example.com").should have(1).email open_email "porras@example.com" current_email.should have_subject("Bienvenido a Wadus 2.0") current_email.should have_text("Hola, porras")
  156. 156. Webmock
  157. 157. Webmock request(:post, "www.example.com"). with(:body => "abc"). should have_been_made.once
  158. 158. MundoPepino
  159. 159. “MundoPepino es un conjunto de pasos genéricos para testear una aplicación Rails utilizando Cucumber”
  160. 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. 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 el valor "Alta de Huerta" Dado que visito la página de creación de huerto Entonces debo ver la etiqueta H2 con el valor "Alta de Huerta"
  162. 162. Dado que tenemos un huerto llamado "H-01" Y que dicho huerto tiene los siguientes aspersores: | nombre | caudal | unidad caudal | | A-01 | 15 | m3 | | A-02 | 12 | m3 | | B-01 | 10 | m3 | Entonces tenemos en bbdd un huerto Y tenemos en bbdd tres aspersores Y el huerto "H-01" tiene en bbdd un aspersor "A-01" Y el aspersor "A-01" tiene en bbdd como caudal "15" Y tiene en bbdd como unidad caudal "m3" Y el huerto "H-01" tiene en bbdd un aspersor "A-02" Y el aspersor "A-02" tiene en bbdd como caudal "12" Y tiene en bbdd como unidad caudal "m3" Y el huerto "H-01" tiene en bbdd un aspersor "B-01" Y el aspersor "B-01" tiene en bbdd como caudal "10" Y tiene en bbdd como unidad caudal "m3"
  163. 163. Recapitulando • Aceptación Web • Valor para los devs • Steak (‘cause Cucumber is for veggies) • Otros amiguitos...
  164. 164. Gracias!
  165. 165. Gracias! @porras y @cavalle ¿Preg untas? Agile Spain 2010

×