cukesalad 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>