cukesalad 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/Examples/Calculator/Gemfile +4 -0
  2. data/Examples/Calculator/Gemfile.lock +36 -20
  3. data/Examples/Calculator/README.md +7 -0
  4. data/Examples/Calculator/cucumber.yml +1 -1
  5. data/Examples/Calculator/features/addition.feature +1 -1
  6. data/Examples/Calculator/features/lib/{alternative → browser}/roles/calculating_web_user.rb +1 -1
  7. data/Examples/Calculator/features/lib/default/roles/calculating_individual.rb +3 -5
  8. data/Examples/Calculator/features/lib/default/tasks/reference/calculations.rb +4 -2
  9. data/Examples/Calculator/features/subtraction.feature +1 -1
  10. data/Examples/Calculator/lib/calculator_operations.rb +4 -0
  11. data/Examples/Calculator/lib/web_calculator.rb +17 -20
  12. data/Examples/Calculator/views/index.erb +7 -0
  13. data/Examples/Calculator/views/layout.erb +2 -0
  14. data/Gemfile.lock +12 -12
  15. data/VERSION +1 -1
  16. data/cukesalad.gemspec +2 -2
  17. data/features/README.markdown +39 -273
  18. data/features/a_simple_tutorial/README.markdown +277 -0
  19. data/features/creating_a_new_project.feature +24 -22
  20. data/features/defining_roles/README.md +29 -0
  21. data/features/{define_a_role.feature → defining_roles/define_a_role.feature} +8 -0
  22. data/features/{prepare_the_actor_for_the_role.feature → defining_roles/prepare_the_actor_for_the_role.feature} +0 -0
  23. data/features/defining_tasks/README.md +12 -0
  24. data/features/{define_a_task.feature → defining_tasks/define_a_task.feature} +58 -17
  25. data/features/{define_a_task_with_arguments.feature → defining_tasks/define_a_task_with_arguments.feature} +0 -0
  26. data/features/{remember_information_between_steps.feature → defining_tasks/remember_information_between_steps.feature} +0 -0
  27. data/features/expectations/README.md +21 -0
  28. data/features/{expressing_expectations.feature → expectations/expressing_expectations.feature} +0 -0
  29. data/features/lib/tasks/interactively_run.rb +5 -0
  30. data/features/lib/tasks/see_the_step_has.rb +1 -1
  31. data/lib/cukesalad/actor.rb +5 -5
  32. data/lib/cukesalad/cli.rb +1 -1
  33. data/lib/cukesalad/cucumber_steps.rb +3 -7
  34. data/lib/cukesalad/specifics.rb +3 -3
  35. data/lib/cukesalad/version.rb +1 -1
  36. data/spec/cukesalad/cli_spec.rb +1 -1
  37. metadata +35 -24
@@ -3,3 +3,7 @@ gem "cukesalad", ">=0.7"
3
3
  gem "rspec", ">=2.5.0", :require => 'spec'
4
4
  gem "capybara", ">=0.4.1.2"
5
5
  gem "sinatra", ">=1.2.0"
6
+
7
+ group :test, :development do
8
+ gem 'sinatra-reloader', '0.5.0'
9
+ end
@@ -7,38 +7,42 @@ GEM
7
7
  cucumber (>= 0.10.7)
8
8
  rdiscount (>= 1.6.8)
9
9
  rspec (>= 2.6.0)
10
- bcat (0.6.1)
10
+ backports (2.3.0)
11
+ bcat (0.6.2)
11
12
  rack (~> 1.0)
12
13
  builder (3.0.0)
13
- capybara (1.0.0)
14
+ capybara (1.1.1)
14
15
  mime-types (>= 1.16)
15
16
  nokogiri (>= 1.3.3)
16
17
  rack (>= 1.0.0)
17
18
  rack-test (>= 0.5.4)
18
- selenium-webdriver (~> 0.2.0)
19
+ selenium-webdriver (~> 2.0)
19
20
  xpath (~> 0.1.4)
20
- childprocess (0.1.9)
21
+ childprocess (0.2.2)
21
22
  ffi (~> 1.0.6)
22
- cucumber (1.0.0)
23
+ cucumber (1.0.2)
23
24
  builder (>= 2.1.2)
24
25
  diff-lcs (>= 1.1.2)
25
- gherkin (~> 2.4.1)
26
+ gherkin (~> 2.4.5)
26
27
  json (>= 1.4.6)
27
28
  term-ansicolor (>= 1.0.5)
28
- cukesalad (0.7.0)
29
- aruba (>= 0.3.5)
30
- cucumber (>= 0.10.0)
29
+ cukesalad (0.8.0)
30
+ aruba (= 0.4.3)
31
+ cucumber (= 1.0.2)
31
32
  rspec (>= 2.5.0)
32
- diff-lcs (1.1.2)
33
+ diff-lcs (1.1.3)
33
34
  ffi (1.0.9)
34
- gherkin (2.4.1)
35
+ gherkin (2.4.18)
35
36
  json (>= 1.4.6)
36
- json (1.5.3)
37
- json_pure (1.5.3)
37
+ json (1.5.4)
38
+ json_pure (1.5.4)
39
+ spruz (~> 0.2.8)
38
40
  mime-types (1.16)
41
+ monkey-lib (0.5.4)
42
+ backports
39
43
  nokogiri (1.5.0)
40
- rack (1.3.0)
41
- rack-test (0.6.0)
44
+ rack (1.3.2)
45
+ rack-test (0.6.1)
42
46
  rack (>= 1.0)
43
47
  rdiscount (1.6.8)
44
48
  rspec (2.6.0)
@@ -50,16 +54,27 @@ GEM
50
54
  diff-lcs (~> 1.1.2)
51
55
  rspec-mocks (2.6.0)
52
56
  rubyzip (0.9.4)
53
- selenium-webdriver (0.2.2)
54
- childprocess (>= 0.1.9)
57
+ selenium-webdriver (2.5.0)
58
+ childprocess (>= 0.2.1)
55
59
  ffi (>= 1.0.7)
56
60
  json_pure
57
61
  rubyzip
58
62
  sinatra (1.2.6)
59
63
  rack (~> 1.1)
60
- tilt (< 2.0, >= 1.2.2)
61
- term-ansicolor (1.0.5)
62
- tilt (1.3.2)
64
+ tilt (>= 1.2.2, < 2.0)
65
+ sinatra-advanced-routes (0.5.1)
66
+ monkey-lib (~> 0.5.0)
67
+ sinatra (~> 1.0)
68
+ sinatra-sugar (~> 0.5.0)
69
+ sinatra-reloader (0.5.0)
70
+ sinatra (~> 1.0)
71
+ sinatra-advanced-routes (~> 0.5.0)
72
+ sinatra-sugar (0.5.1)
73
+ monkey-lib (~> 0.5.0)
74
+ sinatra (~> 1.0)
75
+ spruz (0.2.13)
76
+ term-ansicolor (1.0.6)
77
+ tilt (1.3.3)
63
78
  xpath (0.1.4)
64
79
  nokogiri (~> 1.3)
65
80
 
@@ -71,3 +86,4 @@ DEPENDENCIES
71
86
  cukesalad (>= 0.7)
72
87
  rspec (>= 2.5.0)
73
88
  sinatra (>= 1.2.0)
89
+ sinatra-reloader (= 0.5.0)
@@ -14,4 +14,11 @@ To run these via a web front end, use:
14
14
 
15
15
  bundle exec cucumber -p alternative
16
16
 
17
+ To run the Calculator app
18
+
19
+ rackup lib/config.ru
20
+
21
+ Then, in a browser, navigate to http://localhost:[port]
22
+ (The port to use will be shown in the stdout)
23
+
17
24
  Enjoy!!
@@ -1,4 +1,4 @@
1
1
  default: --exclude features/lib/alternative/
2
- alternative: -r features/lib/alternative/ -r features/support/env.rb -r features/lib/default/tasks/
2
+ front_door: -r features/lib/browser/ -r features/support/env.rb -r features/lib/default/tasks/
3
3
  autotest: --color
4
4
  autotest-all: --color
@@ -5,7 +5,7 @@ Feature: Addition
5
5
 
6
6
  Scenario Outline: Find the sum of two numbers
7
7
  Given I am a Calculating Individual
8
- When I attempt to add: the number '<first_number>' and the number '<second_number>'
8
+ When I add, the number '<first_number>' and the number '<second_number>'
9
9
  Then I should see the answer '<result>'
10
10
 
11
11
 
@@ -6,7 +6,7 @@ require 'capybara'
6
6
  require 'capybara/dsl'
7
7
 
8
8
  Capybara.app = WebCalculator
9
- Capybara.default_driver = :rack_test
9
+ Capybara.default_driver = :selenium
10
10
 
11
11
  module CalculatingIndividual
12
12
 
@@ -1,4 +1,5 @@
1
1
  require 'calculator'
2
+ require 'calculator_operations'
2
3
 
3
4
  module CalculatingIndividual
4
5
 
@@ -8,10 +9,7 @@ module CalculatingIndividual
8
9
 
9
10
  def switch_on_the_calculator
10
11
  @calculator = Calculator.new
11
- @operate_with = {
12
- plus: :+,
13
- minus: :-
14
- }
12
+ @operate_with = CalculatorOperations::OPERATIONS
15
13
  end
16
14
 
17
15
  def enter value
@@ -22,7 +20,7 @@ module CalculatingIndividual
22
20
  if next_operator == :equals
23
21
  equals
24
22
  else
25
- @calculator.get_ready_to @operate_with[next_operator]
23
+ @calculator.get_ready_to @operate_with[next_operator.to_s]
26
24
  end
27
25
  end
28
26
 
@@ -1,3 +1,5 @@
1
+ require 'calculator_operations'
2
+
1
3
  module Calculations
2
4
 
3
5
  def follow_the_steps_for sum
@@ -5,10 +7,10 @@ module Calculations
5
7
  end
6
8
 
7
9
  def enter_numbers_and_operators_for sum
8
- operator = {"+" => :plus, "-" => :minus, "=" => :equals}
10
+ operators = CalculatorOperations::OPERATORS
9
11
  sum.each do | token |
10
12
  enter token.to_i if token =~ /\d+/
11
- press operator[token] if operator.include? token
13
+ press operators[token] if operators.include? token
12
14
  end
13
15
  end
14
16
  end
@@ -5,7 +5,7 @@ Feature: Subtraction
5
5
 
6
6
  Scenario Outline: Find the result of subtracting two numbers
7
7
  Given I am a Calculating Individual
8
- When I attempt to subtract, the number '<subtractor>' from the number '<subtractee>'
8
+ When I subtract, the number '<subtractor>' from the number '<subtractee>'
9
9
  Then I should see the answer '<result>'
10
10
 
11
11
 
@@ -0,0 +1,4 @@
1
+ module CalculatorOperations
2
+ OPERATORS = { '+' => :plus, '-' => :minus, '=' => :equals }
3
+ OPERATIONS = { 'plus' => :+, 'minus' => :-, 'equals' => '=' }
4
+ end
@@ -1,16 +1,25 @@
1
1
  require 'sinatra/base'
2
2
  require 'erb'
3
+
3
4
  $:.unshift(File.dirname(__FILE__), '.')
4
5
  require 'calculator'
5
-
6
- Sinatra::Base.enable :inline_templates
7
- Sinatra::Base.enable :sessions
6
+ require 'calculator_operations'
8
7
 
9
8
  class WebCalculator < Sinatra::Base
10
9
 
10
+ use Rack::Session::Pool
11
+
12
+ configure :development, :test do
13
+ require 'sinatra/reloader'
14
+ end
15
+
11
16
  helpers do
12
- def operate_with
13
- { 'plus' => :+, 'minus' => :-}
17
+ def available_operations
18
+ CalculatorOperations::OPERATIONS
19
+ end
20
+
21
+ def operate_with operator
22
+ available_operations[operator]
14
23
  end
15
24
 
16
25
  def persist calc
@@ -19,6 +28,7 @@ class WebCalculator < Sinatra::Base
19
28
 
20
29
  def display_result_from calc
21
30
  @display = calc.display
31
+ @operations = available_operations
22
32
  erb :index
23
33
  end
24
34
 
@@ -32,6 +42,7 @@ class WebCalculator < Sinatra::Base
32
42
 
33
43
  def display_result_from_session
34
44
  @display = session[:calc].display ||= 0
45
+ @operations = available_operations
35
46
  erb :index
36
47
  end
37
48
 
@@ -60,23 +71,9 @@ class WebCalculator < Sinatra::Base
60
71
  if equals_pressed?
61
72
  calculator.equals
62
73
  else
63
- calculator.get_ready_to operate_with[selected_operator]
74
+ calculator.get_ready_to operate_with(selected_operator)
64
75
  end
65
76
  persist calculator
66
77
  display_result_from calculator
67
78
  end
68
79
  end
69
-
70
- __END__
71
- @@ layout
72
- <h1>Calculator is Ready!</h1>
73
- <%= yield %>
74
-
75
- @@ index
76
- <form method="POST" action="/">
77
- <input type="text" disabled name="display" id="display" value="<%=@display %>" />
78
- <input type="text" name="number" id="number" />
79
- <input type="submit" name="operator" id="minus" text="-" value="minus" />
80
- <input type="submit" name="operator" id="plus" text="+" value="plus" />
81
- <input type="submit" name="operator" id="equals" text="=" value="equals" />
82
- </form>
@@ -0,0 +1,7 @@
1
+ <form method="POST" action="/">
2
+ <input type="text" disabled name="display" id="display" value="<%=@display %>" /><br/>
3
+ <input type="text" name="number" id="number" /><br/>
4
+ <% @operations.each do |key, value| %>
5
+ <input type="submit" name="operator" id="<%=key%>" text="<%=value%>" value="<%=key%>" />
6
+ <% end %>
7
+ </form>
@@ -0,0 +1,2 @@
1
+ <h1>Calculator is Ready!</h1>
2
+ <%= yield %>
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cukesalad (0.7.0)
5
- aruba (>= 0.3.5)
6
- cucumber (>= 0.10.0)
4
+ cukesalad (0.8.0)
5
+ aruba (= 0.4.3)
6
+ cucumber (= 1.0.2)
7
7
  rspec (>= 2.5.0)
8
8
 
9
9
  GEM
@@ -16,28 +16,28 @@ GEM
16
16
  cucumber (>= 0.10.7)
17
17
  rdiscount (>= 1.6.8)
18
18
  rspec (>= 2.6.0)
19
- bcat (0.6.1)
19
+ bcat (0.6.2)
20
20
  rack (~> 1.0)
21
21
  builder (3.0.0)
22
- childprocess (0.1.9)
22
+ childprocess (0.2.2)
23
23
  ffi (~> 1.0.6)
24
- cucumber (1.0.0)
24
+ cucumber (1.0.2)
25
25
  builder (>= 2.1.2)
26
26
  diff-lcs (>= 1.1.2)
27
- gherkin (~> 2.4.1)
27
+ gherkin (~> 2.4.5)
28
28
  json (>= 1.4.6)
29
29
  term-ansicolor (>= 1.0.5)
30
- diff-lcs (1.1.2)
30
+ diff-lcs (1.1.3)
31
31
  ffi (1.0.9)
32
32
  ffi (1.0.9-java)
33
- gherkin (2.4.1)
33
+ gherkin (2.4.18)
34
34
  json (>= 1.4.6)
35
- gherkin (2.4.1-java)
35
+ gherkin (2.4.18-java)
36
36
  json (>= 1.4.6)
37
37
  json (1.4.6)
38
38
  json (1.4.6-java)
39
39
  mime-types (1.16)
40
- rack (1.3.0)
40
+ rack (1.3.2)
41
41
  rake (0.8.7)
42
42
  rdiscount (1.6.8)
43
43
  relish (0.3.0)
@@ -54,7 +54,7 @@ GEM
54
54
  rspec-expectations (2.6.0)
55
55
  diff-lcs (~> 1.1.2)
56
56
  rspec-mocks (2.6.0)
57
- term-ansicolor (1.0.5)
57
+ term-ansicolor (1.0.6)
58
58
 
59
59
  PLATFORMS
60
60
  java
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
data/cukesalad.gemspec CHANGED
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
25
25
  s.default_executable = "cukesalad"
26
26
  s.require_paths = ["lib"]
27
27
 
28
- s.add_runtime_dependency "cucumber", ">=0.10.0"
28
+ s.add_runtime_dependency "cucumber", "1.0.2" # Version 1.0.4 experiences following error: 'Illformed requirement ["#<Syck::DefaultKey:0x000001034764a0> 0.8.4"]'
29
29
  s.add_runtime_dependency "rspec", ">=2.5.0"
30
- s.add_runtime_dependency "aruba", ">=0.3.5"
30
+ s.add_runtime_dependency "aruba", "0.4.3"
31
31
 
32
32
  s.add_development_dependency "bundler", "~> 1.0.0"
33
33
  s.add_development_dependency "rake", "~> 0.8.7"
@@ -1,299 +1,65 @@
1
- # Cuke Salad
1
+ ![RiverGlide logo](http://riverglide-live.heroku.com/attachments/branding/riverglide_logo_medium.png)
2
2
 
3
- _Cucumber, washed and ready to eat for Friction-free ATDD/BDD_
3
+ # cukesalad - a cucumber extension
4
4
 
5
- **This is a work in progress - feedback welcome**
6
- e-mail feedback to <talktous@riverglide.com>
5
+ _Cucumber, washed and ready to eat for friction-free ATDD/BDD_
7
6
 
8
- You can see our current list of intended features under issues:
9
- [https://github.com/RiverGlide/CukeSalad/issues?labels=Feature](https://github.com/RiverGlide/CukeSalad/issues?labels=Feature)
7
+ Cukesalad is an extension to cucumber that allows you to write scenarios without regular expression.
8
+ It encourages you to separte your code in neat, organised and focused parts.
9
+ With cukesalad you focus on expressing your intent not on regular expressions.
10
10
 
11
+ You can combine cukesalad with your regular step definitions.
11
12
 
12
- ## This project has step-free access!
13
+ * [Get the Gem](https://rubygems.org/gems/cukesalad)
14
+ * [Find it on Github](http://github.com/RiverGlide/CukeSalad)
13
15
 
14
- CukeSalad allows you to focus on the task at hand - expressing examples, the roles involved in those examples and what those roles can do with the product under development.
16
+ ## Synopsis
17
+ <iframe width="560" height="349" src="http://www.youtube.com/embed/UYN7p_7IlZ8" frameborder="0" allowfullscreen></iframe>
15
18
 
16
- With CukeSalad you don't need to write step-definitions.
19
+ There are no step-definitions required for this to work:
17
20
 
18
- Of course, you still have to write some code - but only the code that expresses:
21
+ When I attempt to add, the number '1' to the number '2'
19
22
 
20
- * the roles and the actions they can perform
21
- * the tasks and the actions involved in completing that task
22
-
23
- ## Goals->Tasks->Actions
24
- The terms *"actions"* and *"tasks"* above come from Task Analysis, as used in User Centred Design (UCD) of Human Computer Interfaces (HCI) a.k.a. User Experience (UX):
25
-
26
- * *Goal:* What we’re trying to achieve which has one or more…
27
- * *Tasks:* The high-level work-item that we complete to fulfil the goal, each having one or more…
28
- * *Actions:* The specific steps or interactions we execute to complete the task.
29
-
30
- More information about Goals, Tasks and Actions can be found in this [blog post](http://antonymarcano.com/blog/2011/03/goals-tasks-action/)
31
-
32
- Let's see how this works with a simple example...
33
-
34
- ## Install
35
-
36
- gem install cukesalad
37
-
38
- ## Let's Get started
39
-
40
- Create a new project called Calculator:
41
-
42
- cukesalad Calculator
43
-
44
- Or, if you have an existing cucumber project that you want to configure to use cukesalad, you can type:
45
-
46
- cukesalad
47
-
48
- ## Write Features
49
-
50
- In `features/`, let's create our first feature file - `a_place_to_start.feature`:
51
-
52
- Feature: A Place To Start
53
- As Callie, a calculating individual
54
- I want to know when my calculator is on
55
- So that I know when I can start calculating
56
-
57
- Scenario: Let's Begin
58
- Given I am a Calculating Individual
59
- When I attempt to switch on the calculator
60
- Then I should see the answer '0'
61
-
62
- Let's take a moment to understand this scenario:
63
-
64
- Scenario: Let's Begin
65
- Given I am a <some role>
66
- When I attempt to <do some task>
67
- Then I should <ask some question> '<expected answer>'
68
-
69
- To get this working, we don't need to write any steps. Instead, we describe tasks...
70
-
71
- ## Create Tasks
72
-
73
- Explaining how to do a _task_ is easy:
74
- Create a new file, `features/lib/tasks/switch_on_the_calculator.rb`
75
-
76
- Remember the step `When I attempt to switch on the calculator`
77
-
78
- in_order_to "switch on the calculator" do
79
- switch_on_the_calculator
80
- end
81
-
82
- Remember the step `Then I should see the answer '0'`
83
- Now we need `task/see_the_answer.rb`
84
-
85
- in_order_to "see the answer" do
86
- look_at_the_display
87
- end
88
-
89
- Now we've explained the _tasks_, we need to define the _role_ that performs them. In
90
- this example, we need to explain how the `CalculatingIndividual` _role_ works...
91
-
92
- ## Create Roles
93
-
94
- Remember the step `Given I am a Calculating Individual`?
95
-
96
- We explain a _role_ by creating a new file
97
- called `features/lib/roles/calculating_individual.rb`
98
-
99
- module CalculatingIndividual
100
-
101
- def switch_on_the_calculator
102
- @calculator = Calculator.new
103
- end
104
-
105
- def look_at_the_display
106
- @calculator.display
107
- end
108
- end
109
-
110
- You'll need a class called Calculator on the load path of course, but that's it.
111
-
112
- From your project folder, run (_note: '%' is our command prompt_)
113
-
114
- % cucumber
115
-
116
- We now have our first passing Feature, without creating a single step definition!
117
-
118
- ## Wash, rinse, repeat
119
-
120
- Let's try another scenario...
121
-
122
- Scenario Outline: Find the sum of two numbers
123
- Given I am a Calculating Individual
124
- And I was able to switch on the calculator
125
- When I attempt to add: the number '10' and the number '10'
126
- Then I should see the answer '20'
127
-
128
- Notice that we've reused 'switch on the calculator'.
129
-
130
- The new _When_ step has a slightly different layout.
131
- Let's examine that for a second... See below. Notice the ':' (colon) after `<do something>` followed by the name-value pairs:
132
-
133
- When I attempt to <do something>: <name> '<value>' <name> '<value>'
134
-
135
- You can also use a ',' (comma) in situations where a colon wouldn't quite work:
136
-
137
- When I attempt to <do something>, <name> '<value>' <name> '<value>'
138
-
139
- `<do something>` can be as many words as you like. You can have as many name-value pairs as you like.
140
-
141
- For this to work we need a task called `tasks/add.rb` that explains the individual actions required to complete the task:
142
-
143
- in_order_to "add" do
144
- enter @value_of(:the_number)
145
- press :plus
146
- enter @value_of(:and_the_number)
147
- press :equals
148
- end
149
-
150
- Notice how the `value_of` lines use symbols that correspond to the wording `'the number '10' to the number '10'` in the "When" step.
151
-
152
- There is some 'syntactic sugar' that we can use to dress this up a little and make it read nicer... a simple attribute mapping (using Ruby 1.9.x syntax):
153
-
154
- in_order_to "add", the_number: :first_number, to_the_number: :second_number do
155
- enter the :first_number
23
+ Instead, you write a **Task**:
24
+
25
+ in_order_to 'add', the_number: :first_number, and_the_number: :second_number do
26
+ enter the :first_number
156
27
  press :plus
157
- enter the :second_number
28
+ enter the :second_number
158
29
  press :equals
159
30
  end
160
31
 
161
- All we've done is mapped `:the_number` to `:first_number` and `:to_the_number` to `:second_number`. There is a special method called "the" that allows you to reference the mapped values rather than the symbols derived from the scenario.
162
-
163
- Now all we need to do is create the corresponding methods in `calculating_individual.rb`.
164
-
165
- module CalculatingIndividual
166
-
167
- def switch_on_the_calculator
168
- @calculator = Calculator.new
169
- @operate_with = {
170
- plus: :+,
171
- minus: :-
172
- }
173
- end
174
-
175
- def enter value
176
- @calculator.enter value.to_i
177
- end
178
-
179
- def press next_operator
180
- if next_operator == :equals
181
- equals
182
- else
183
- @calculator.get_ready_to @operate_with[next_operator]
184
- end
185
- end
186
-
187
- def equals
188
- @calculator.equals
189
- end
190
-
191
- def look_at_the_display
192
- @calculator.display
193
- end
194
- end
195
-
196
- Of course you'll have to [implement the calculator too](https://github.com/RiverGlide/CukeSalad/blob/master/Examples/Calculator/lib/calculator.rb)
197
-
198
- Now, you can run cucumber again:
199
-
200
- % cucumber
201
-
202
- There's no need to write `step_definitions`...
203
- Simply express the _roles_ and the _tasks_ in clear,
204
- concise, easy to read classes.
205
-
206
- If we want to know what things we can say, instead of trawling through a step-def ruby file, we can look in our tasks folder:
32
+ Each of the above methods `enter` and `press` must be implemented in a role.
207
33
 
208
- features/lib/default/tasks/
209
- ├── add.rb
210
- ├── calculate.rb
211
- ├── calculations.rb
212
- ├── see_the_answer.rb
213
- ├── subtract.rb
214
- └── switch_on_the_calculator.rb
34
+ Among these examples you will find a simple tutorial and a variety examples of using cukesalad.
215
35
 
216
- You can structure your tasks as you see fit. For example, as the project grows, it might end up looking like this:
36
+ _Cukesalad uses cukesalad to express all of its own examples._
217
37
 
218
- features/lib/default/tasks/
219
- ├── all_purpose
220
- | └── calculate.rb
221
- ├── arithmetic
222
- | ├── add.rb
223
- | ├── divide.rb
224
- | ├── multiply.rb
225
- | └── subtract.rb
226
- ├── extras
227
- | ├── recall_from_memory.rb
228
- | ├── store_in_memory.rb
229
- | └── switch_on_the_calculator.rb
230
- ├── questions
231
- | ├── see_the_answer.rb
232
- | ├── see_the_following_indicators.rb
233
- | └── switch_on_the_calculator.rb
234
- ├── trigonometry
235
- | ├── sine.rb
236
- | ├── cosine.rb
237
- | └── tangent.rb
238
- └── reference_material
239
- └── calculations.rb
38
+ ## Why use cukesalad?
240
39
 
241
- ## Alternative Roles
40
+ CukeSalad allows you to _focus on the task at hand_ - expressing examples, the roles involved in those examples and what those roles can do with the product under development.
242
41
 
243
- As our features _describe the value of a calculator application and not its
244
- implementation_, we have the opportunity to reuse them.
42
+ cukesalad encourages you to write only the code that expresses:
245
43
 
246
- In the Calculator example, we create a new _role_ in
247
- `./features/lib/alternative/roles/calculating_web_user.rb`, which we can swap
248
- into our tests using a Cucumber profile defined in `features/cucumber.yml`:
249
-
250
- default --exclude features/lib/alternative/
251
- alternative -r features/lib/alternative/ -r features/support/env.rb -r features/lib/default/tasks/
252
-
253
- We can run our alternative configuration like so:
44
+ * the roles and the actions they can perform
45
+ * the tasks and the actions involved in completing that task
254
46
 
255
- `%cucumber --profile alternative`
47
+ cukesalad helps you focus on expressions of intent rather than regular expressions.
256
48
 
257
- The Calculating Web User masquerades as the Calculating Individual from our
258
- previous example, and provides the same API, allowing us to reuse all of our
259
- existing features and _tasks_.
49
+ [More about why you would use cuke salad on the project wiki](https://github.com/RiverGlide/CukeSalad/wiki/Who-is-this-for)
260
50
 
261
- The alternative, `./lib/web_calculator.rb`, implementation is a simple [Sinatra](http://www.sinatrarb.com) application,
262
- which we drive with the [Capybara](http://github.com/jnicklas/capybara) web testing framework.
51
+ ## Goals->Tasks->Actions
52
+ The terms *"actions"* and *"tasks"* above come from Task Analysis, as used in User Centred Design (UCD) of Human Computer Interfaces (HCI) a.k.a. User Experience (UX):
263
53
 
264
- By writing a single new _role_ class we're able to reuse all of our existing features,
265
- _tasks_ and even the `Calculator` itself, which the web calculator delegates to in order to do its calculations.
54
+ * *Goal:* What were trying to achieve which has one or more…
55
+ * *Tasks:* The high-level work-item that we complete to fulfil the goal, each having one or more…
56
+ * *Actions:* The specific steps or interactions we execute to complete the task.
266
57
 
267
- After adding some more scenarios and tasks and an alternative "Calculating Individual" (see below for why), our Calculator directory structure currently looks like this...
58
+ More information about Goals, Tasks and Actions can be found in this [blog post](http://antonymarcano.com/blog/2011/03/goals-tasks-action/)
268
59
 
269
- ├── cucumber.yml
270
- ├── features
271
- │   ├── A_PlaceToStart.feature
272
- │   ├── Addition.feature
273
- │   ├── Complex_calculations.feature
274
- │   ├── Subtraction.feature
275
- │   ├── Typical_workflow.feature
276
- │   ├── lib
277
- │   │   ├── alternative
278
- │   │   │   ├── roles
279
- │   │   │   │   └── calculating_web_user.rb
280
- │   │   │   └── tasks
281
- │   │   └── default
282
- │   │   ├── roles
283
- │   │   │   └── calculating_individual.rb
284
- │   │   └── tasks
285
- │   │   ├── add.rb
286
- │   │   ├── perform.rb
287
- │   │   ├── see_the_answer.rb
288
- │   │   ├── subtract.rb
289
- │   │   └── switch_on_the_calculator.rb
290
- │   └── support
291
- │   └── env.rb
292
- ├── lib
293
- │   ├── calculator.rb
294
- │   └── web_calculator.rb
295
- └── spec
296
- ├── calculator_spec.rb
297
- └── web_calculator_spec.rb
60
+ ## Feedback
61
+ This project is 'always in beta' - feedback welcome
298
62
 
299
- Take a look around the examples and the code to see how it all works. We hope you enjoy reading as much as we enjoyed writing it.
63
+ * You can send us a [pull request](https://github.com/RiverGlide/CukeSalad/).
64
+ * Or, log a [feature request](https://github.com/RiverGlide/CukeSalad/issues?labels=Feature)
65
+ * Or e-mail feedback to <talktous@riverglide.com>