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
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
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
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
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
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
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))))
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
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
129. Todo el “valor para el
desarrollador” sin la
burocracia extra
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. 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
136. 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
153. 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
162. “MundoPepino es un conjunto de
pasos genéricos para testear una
aplicación Rails utilizando
Cucumber”
163. 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"
164. 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"
165. 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"