cukesalad 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  source :rubygems
2
2
  gem "cucumber", "0.10.0"
3
- gem "cukesalad", ">=0.3.0"
3
+ gem "cukesalad", "0.6"
4
4
  gem "rspec", "2.5.0", :require => 'spec'
5
5
  gem "capybara", "0.4.1.2"
6
6
  gem "sinatra", "1.2.0"
@@ -24,7 +24,7 @@ GEM
24
24
  gherkin (~> 2.3.2)
25
25
  json (~> 1.4.6)
26
26
  term-ansicolor (~> 1.0.5)
27
- cukesalad (0.3.0)
27
+ cukesalad (0.6.0)
28
28
  aruba (= 0.3.5)
29
29
  cucumber (= 0.10.0)
30
30
  rspec (= 2.5.0)
@@ -70,6 +70,6 @@ PLATFORMS
70
70
  DEPENDENCIES
71
71
  capybara (= 0.4.1.2)
72
72
  cucumber (= 0.10.0)
73
- cukesalad (>= 0.3.0)
73
+ cukesalad (= 0.6)
74
74
  rspec (= 2.5.0)
75
75
  sinatra (= 1.2.0)
@@ -6,7 +6,7 @@ Feature: Addition
6
6
  Scenario Outline: Find the sum of two numbers
7
7
  Given I am a Calculating Individual
8
8
  And I was able to switch on the calculator
9
- When I attempt to add: the number '<first_number>' to the number '<second_number>'
9
+ When I attempt to add: the number '<first_number>' and the number '<second_number>'
10
10
  Then I should see the answer '<result>'
11
11
 
12
12
 
@@ -6,7 +6,7 @@ Feature: Complex Calculations
6
6
  Scenario Outline: Get the result of a more complex calculation
7
7
  Given I am a calculating individual
8
8
  And I was able to switch on the calculator
9
- When I attempt to calculate: with the following '<calculation>'
9
+ When I attempt to calculate, with the following '<calculation>'
10
10
  Then I should see the answer '<correct_result>'
11
11
 
12
12
  Examples:
@@ -1,11 +1,4 @@
1
- # This demonstrates how to use an attribute mapping
2
- # to make the interactions within the task read more naturally
3
- # In the scenario it might say "add: the number '5', to the number '10'
4
- # The form illustrated below simply maps the elements the_number and to_the_number
5
- # to alternative symbols that make the interactions read more like real instructions
6
- # See subtract.rb for a way of writing tasks that reuses the common interactions
7
- # required to perform calculations.
8
- in_order_to 'add', the_number: :first_number, to_the_number: :second_number do
1
+ in_order_to 'add', the_number: :first_number, and_the_number: :second_number do
9
2
  enter the :first_number
10
3
  press :plus
11
4
  enter the :second_number
@@ -2,7 +2,7 @@ in_order_to "switch on the calculator" do
2
2
  require 'rspec/expectations'
3
3
  extend RSpec::Matchers
4
4
 
5
- @calc = switch_on_the_calculator
5
+ switch_on_the_calculator
6
6
  self.should respond_to :enter
7
7
  self.should respond_to :press
8
8
  self.should respond_to :look_at_the_display
@@ -6,7 +6,7 @@ Feature: Subtraction
6
6
  Scenario Outline: Find the result of subtracting two numbers
7
7
  Given I am a Calculating Individual
8
8
  And I was able to switch on the calculator
9
- When I attempt to subtract: the number '<subtractor>' from the number '<subtractee>'
9
+ When I attempt to subtract, the number '<subtractor>' from the number '<subtractee>'
10
10
  Then I should see the answer '<result>'
11
11
 
12
12
 
data/README.md CHANGED
@@ -75,7 +75,7 @@ Create a new file, `features/lib/tasks/switch_on_the_calculator.rb`
75
75
  Remember the step `When I attempt to switch on the calculator`
76
76
 
77
77
  in_order_to "switch on the calculator" do
78
- @calc = switch_on_the_calculator
78
+ switch_on_the_calculator
79
79
  end
80
80
 
81
81
  Remember the step `Then I should see the answer '0'`
@@ -110,7 +110,7 @@ You'll need a class called Calculator on the load path of course, but that's it.
110
110
 
111
111
  From your project folder, run (_note: '%' is our command prompt_)
112
112
 
113
- % cucumber
113
+ % cucumber
114
114
 
115
115
  We now have our first passing Feature, without creating a single step definition!
116
116
 
@@ -121,30 +121,34 @@ Let's try another scenario...
121
121
  Scenario Outline: Find the sum of two numbers
122
122
  Given I am a Calculating Individual
123
123
  And I was able to switch on the calculator
124
- When I attempt to add: the number '10' to the number '10'
124
+ When I attempt to add: the number '10' and the number '10'
125
125
  Then I should see the answer '20'
126
126
 
127
127
  Notice that we've reused 'switch on the calculator'.
128
128
 
129
129
  The new _When_ step has a slightly different layout.
130
- Let's examine that for a second... Notice the ':' (colon) after <do something> and the name-value pairs:
130
+ Let's examine that for a second... See below. Notice the ':' (colon) after `<do something>` followed by the name-value pairs:
131
131
 
132
132
  When I attempt to <do something>: <name> '<value>' <name> '<value>'
133
133
 
134
- You can have as many name-value pairs as you like.
134
+ You can also use a ',' (comma) in situations where a colon wouldn't quite work:
135
+
136
+ When I attempt to <do something>, <name> '<value>' <name> '<value>'
135
137
 
136
- So, we need a task called `tasks/add.rb` that explains the individual actions required to complete the task:
138
+ `<do something>` can be as many words as you like. You can have as many name-value pairs as you like.
139
+
140
+ For this to work we need a task called `tasks/add.rb` that explains the individual actions required to complete the task:
137
141
 
138
142
  in_order_to "add" do
139
143
  enter @value_of(:the_number)
140
144
  press :plus
141
- enter @value_of(:to_the_number)
145
+ enter @value_of(:and_the_number)
142
146
  press :equals
143
147
  end
144
148
 
145
149
  Notice how the `value_of` lines use symbols that correspond to the wording `'the number '10' to the number '10'` in the "When" step.
146
150
 
147
- There is some 'syntactic sugar' that we can use to dress this up a little and make it read nicer... a simple attribute mapping:
151
+ 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):
148
152
 
149
153
  in_order_to "add", the_number: :first_number, to_the_number: :second_number do
150
154
  enter the :first_number
@@ -153,9 +157,9 @@ There is some 'syntactic sugar' that we can use to dress this up a little and ma
153
157
  press :equals
154
158
  end
155
159
 
156
- All we've done is mapped "the_number" to "first_number". There is a special method called "the" that allows you to reference the mapped values rather than the symbols derived from the scenario.
160
+ 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.
157
161
 
158
- Now all we need to do is modify our `calculating_individual.rb` to receive those calls...
162
+ Now all we need to do is create the corresponding methods in `calculating_individual.rb`.
159
163
 
160
164
  module CalculatingIndividual
161
165
 
@@ -188,6 +192,8 @@ Now all we need to do is modify our `calculating_individual.rb` to receive those
188
192
  end
189
193
  end
190
194
 
195
+ Of course you'll have to [implement the calculator too](https://github.com/RiverGlide/CukeSalad/blob/master/Examples/Calculator/lib/calculator.rb)
196
+
191
197
  Now, you can run cucumber again:
192
198
 
193
199
  % cucumber
@@ -196,14 +202,74 @@ There's no need to write `step_definitions`...
196
202
  Simply express the _roles_ and the _tasks_ in clear,
197
203
  concise, easy to read classes.
198
204
 
199
- After adding some more scenarios and tasks and an alternative "Calculating Individual" (see below for why), our finished Calculator directory structure looks like this...
205
+ 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:
206
+
207
+ features/lib/default/tasks/
208
+ ├── add.rb
209
+ ├── calculate.rb
210
+ ├── calculations.rb
211
+ ├── see_the_answer.rb
212
+ ├── subtract.rb
213
+ └── switch_on_the_calculator.rb
214
+
215
+ You can structure your tasks as you see fit. For example, as the project grows, it might end up looking like this:
216
+
217
+ features/lib/default/tasks/
218
+ ├── all_purpose
219
+ | └── calculate.rb
220
+ ├── arithmetic
221
+ | ├── add.rb
222
+ | ├── divide.rb
223
+ | ├── multiply.rb
224
+ | └── subtract.rb
225
+ ├── extras
226
+ | ├── recall_from_memory.rb
227
+ | ├── store_in_memory.rb
228
+ | └── switch_on_the_calculator.rb
229
+ ├── questions
230
+ | ├── see_the_answer.rb
231
+ | ├── see_the_following_indicators.rb
232
+ | └── switch_on_the_calculator.rb
233
+ ├── trigonometry
234
+ | ├── sine.rb
235
+ | ├── cosine.rb
236
+ | └── tangent.rb
237
+ └── reference_material
238
+ └── calculations.rb
239
+
240
+ ## Alternative Roles
241
+
242
+ As our features _describe the value of a calculator application and not its
243
+ implementation_, we have the opportunity to reuse them.
244
+
245
+ In the Calculator example, we create a new _role_ in
246
+ `./features/lib/alternative/roles/calculating_web_user.rb`, which we can swap
247
+ into our tests using a Cucumber profile defined in `features/cucumber.yml`:
248
+
249
+ default --exclude features/lib/alternative/
250
+ alternative -r features/lib/alternative/ -r features/support/env.rb -r features/lib/default/tasks/
251
+
252
+ We can run our alternative configuration like so:
253
+
254
+ `%cucumber --profile alternative`
255
+
256
+ The Calculating Web User masquerades as the Calculating Individual from our
257
+ previous example, and provides the same API, allowing us to reuse all of our
258
+ existing features and _tasks_.
259
+
260
+ The alternative, `./lib/web_calculator.rb`, implementation is a simple [Sinatra](http://www.sinatrarb.com) application,
261
+ which we drive with the [Capybara](http://github.com/jnicklas/capybara) web testing framework.
262
+
263
+ By writing a single new _role_ class we're able to reuse all of our existing features,
264
+ _tasks_ and even the `Calculator` itself, which the web calculator delegates to in order to do its calculations.
265
+
266
+ After adding some more scenarios and tasks and an alternative "Calculating Individual" (see below for why), our Calculator directory structure currently looks like this...
200
267
 
201
268
  ├── cucumber.yml
202
269
  ├── features
203
270
  │   ├── A_PlaceToStart.feature
204
271
  │   ├── Addition.feature
205
272
  │   ├── Complex_calculations.feature
206
- │   ├── LOOK_MA_NO_STEP_DEFS.txt
207
273
  │   ├── Subtraction.feature
208
274
  │   ├── Typical_workflow.feature
209
275
  │   ├── lib
@@ -230,29 +296,3 @@ After adding some more scenarios and tasks and an alternative "Calculating Indiv
230
296
  └── web_calculator_spec.rb
231
297
 
232
298
  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.
233
-
234
- ## Alternative Roles
235
-
236
- As our features _describe the value of a calculator application and not its
237
- implementation_, we have the opportunity to reuse them.
238
-
239
- In the Calculator example, we create a new _role_ in
240
- `./features/lib/alternative/roles/calculating_web_user.rb`, which we can swap
241
- into our tests using a Cucumber profile defined in `features/cucumber.yml`:
242
-
243
- default --exclude features/lib/alternative/
244
- alternative -r features/lib/alternative/ -r features/support/env.rb -r features/lib/default/tasks/
245
-
246
- We can run our alternative configuration like so:
247
-
248
- `%cucumber --profile alternative`
249
-
250
- The Calculating Web User masquerades as the Calculating Individual from our
251
- previous example, and provides the same API, allowing us to reuse all of our
252
- existing features and _tasks_.
253
-
254
- The alternative, `./lib/web_calculator.rb`, implementation is a simple [Sinatra](http://www.sinatrarb.com) application,
255
- which we drive with the [Capybara](http://github.com/jnicklas/capybara) web testing framework.
256
-
257
- By writing a single new _role_ class we're able to reuse all of our existing features,
258
- _tasks_ and even the `Calculator` itself, which the web calculator delegates to in order to do its calculations.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -1,11 +1,4 @@
1
- # This demonstrates how to use an attribute mapping
2
- # to make the interactions within the task read more naturally
3
- # In the scenario it might say "add: the number '5', to the number '10'
4
- # The form illustrated below simply maps the elements the_number and to_the_number
5
- # to alternative symbols that make the interactions read more like real instructions
6
- # See subtract.rb for a way of writing tasks that reuses the common interactions
7
- # required to perform calculations.
8
- in_order_to 'add', the_number: :first_number, to_the_number: :second_number do
1
+ in_order_to 'add', the_number: :first_number, and_the_number: :second_number do
9
2
  enter the :first_number
10
3
  press :plus
11
4
  enter the :second_number
@@ -2,7 +2,7 @@ in_order_to "switch on the calculator" do
2
2
  require 'rspec/expectations'
3
3
  extend RSpec::Matchers
4
4
 
5
- @calc = switch_on_the_calculator
5
+ switch_on_the_calculator
6
6
  self.should respond_to :enter
7
7
  self.should respond_to :press
8
8
  self.should respond_to :look_at_the_display
@@ -1,4 +1,12 @@
1
- #TODO: Consider exposing this detail in the examples since it shows you what to do
2
- in_order_to 'create a task', called: :name_of_task do
3
- write_file 'features/lib/tasks/some_task.rb', "in_order_to '#{the :name_of_task}' do\nend"
1
+ in_order_to 'create a task', called: :name_of_task, containing: :code do
2
+ file_name = the( :name_of_task ).gsub(" ", "_")
3
+
4
+ default_content =
5
+ "in_order_to '#{the :name_of_task}' do
6
+ #nothing
7
+ end"
8
+ content = the :code
9
+ content = default_content if content.nil?
10
+
11
+ write_file "features/lib/tasks/#{file_name}.rb", content
4
12
  end
@@ -0,0 +1,3 @@
1
+ in_order_to 'not previously take note of something' do
2
+ # nothing
3
+ end
@@ -1,7 +1,7 @@
1
- in_order_to "RunAScenario", containing: :step do
1
+ in_order_to "RunAScenario", containing: :steps do
2
2
  write_file 'features/a.feature', "Feature: A Feature
3
3
 
4
4
  Scenario: A Scenario
5
- #{the :step}"
5
+ #{the :steps}"
6
6
  run_simple unescape( 'cucumber features/a.feature' ), false
7
7
  end
@@ -0,0 +1,50 @@
1
+ Feature: Remember information between steps
2
+ As a Step Free Cuker
3
+ I want information captured in one step to be available in a later step
4
+ So that I can deal with situations where dynamic information is required in later steps
5
+
6
+ Background:
7
+ Given you are a Step Free Cuker
8
+ And you were able to create a new Cuke Salad project
9
+ And you were able to create a role: called 'NewCustomer'
10
+
11
+ Scenario: You can reuse information
12
+ Given you were able to create a task, called 'do something' containing
13
+ """
14
+ in_order_to 'do something', remembering: :value do
15
+ take_note_of :some_key, the( :value )
16
+ end
17
+ """
18
+ And you were able to create a task, called 'find that the thing remembered was' containing
19
+ """
20
+ in_order_to 'find that the thing remembered was' do
21
+ recall :some_key
22
+ end
23
+ """
24
+ When you attempt to run a scenario: containing
25
+ """
26
+ Given I am a New Customer
27
+ When I attempt to do something, remembering 'a value'
28
+ Then I should find that the thing remembered was 'a value'
29
+ """
30
+ Then you should see it has 'passed'
31
+
32
+ Scenario: You'll get feedback if you ask for something that wasn't noted
33
+ Given you did not previously take note of something
34
+ And you were able to create a task, called 'find that the thing remembered was' containing
35
+ """
36
+ in_order_to 'find that the thing remembered was' do
37
+ recall :some_key
38
+ end
39
+ """
40
+ When I attempt to run a scenario: containing
41
+ """
42
+ Given I am a New Customer
43
+ Then I should find that the thing remembered was 'a value'
44
+ """
45
+ Then I should see it has 'failed'
46
+ And I should see a reply that includes:
47
+ """
48
+ You tried to recall ':some_key' but no previous step appears to have taken note of that information
49
+ """
50
+
data/lib/actor.rb CHANGED
@@ -1,10 +1,11 @@
1
1
  require 'director'
2
2
 
3
3
  class Actor
4
-
4
+
5
5
  def initialize this_type_of_role, directed_by=Director.new
6
6
  @director = directed_by
7
7
  get_into_character_for this_type_of_role
8
+ @note_pad = {}
8
9
  end
9
10
 
10
11
  def perform described_task, details = {}
@@ -31,4 +32,16 @@ class Actor
31
32
  def value_of(symbol)
32
33
  @info[symbol]
33
34
  end
35
+
36
+ def take_note_of key, value
37
+ @note_pad.store key, value
38
+ end
39
+
40
+ def recall key
41
+ begin
42
+ @note_pad.fetch key
43
+ rescue KeyError
44
+ raise KeyError, "You tried to recall ':#{key}' but no previous step appears to have taken note of that information."
45
+ end
46
+ end
34
47
  end
data/lib/cukesalad.rb CHANGED
@@ -16,8 +16,8 @@ Given /^(?:I am|you are) a ([a-zA-Z ]+)$/ do |role|
16
16
  @actor = Actor.new(role)
17
17
  end
18
18
 
19
- When /^(?:I|you) (?:attempt to|was able to|were able to|did)? ([A-Z a-z_-]*)(?:[:|,] (.*))?$/ do | this_task, with_these_details, *and_more |
20
- info = understand_the with_these_details unless with_these_details.nil?
19
+ When /^(?:I|you) (?:attempt to|was able to|were able to|did)? ([A-Z a-z_-]*)(?:[:|,] (.*))?:?$/ do | this_task, details, *and_more |
20
+ info = understand_the details unless details.nil?
21
21
  info[info.keys.last] = and_more[0] unless and_more.empty?
22
22
  @actor.perform this_task, info unless info.nil?
23
23
  @actor.perform this_task if info.nil?
data/spec/actor_spec.rb CHANGED
@@ -33,8 +33,8 @@ end
33
33
  describe Actor do
34
34
 
35
35
  it "gets into character" do
36
- director = double("director")
37
36
  role_description = "Butler"
37
+ director = double("director")
38
38
  director.should_receive( :explain_the_role ).with( role_description ).and_return( Butler )
39
39
 
40
40
  actor = Actor.new role_description, director
@@ -68,5 +68,29 @@ describe Actor do
68
68
 
69
69
  actor.perform( task_description, details ).should == 5
70
70
  end
71
+
72
+ it "can take note of information" do
73
+ role_description = "Butler"
74
+
75
+ director = double("director")
76
+ director.should_receive( :explain_the_role ).with( role_description ).and_return( Butler )
77
+
78
+ actor = Actor.new role_description, director
79
+
80
+ actor.take_note_of :something, "of importance"
81
+ actor.recall( :something ).should == "of importance"
82
+ end
83
+
84
+ it "tells you when it can't find the information you're looking for" do
85
+ role_description = "Butler"
86
+
87
+ director = double("director")
88
+ director.should_receive( :explain_the_role ).with( role_description ).and_return( Butler )
89
+
90
+ actor = Actor.new role_description, director
91
+
92
+ lambda {actor.recall( :something )}.should raise_error KeyError,
93
+ "You tried to recall ':something' but no previous step appears to have taken note of that information."
94
+ end
71
95
  end
72
96
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: cukesalad
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.0
5
+ version: 0.6.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - RiverGlide
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-04-21 00:00:00 Z
13
+ date: 2011-04-22 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: cucumber
@@ -121,10 +121,12 @@ files:
121
121
  - features/lib/tasks/create_directories.rb
122
122
  - features/lib/tasks/not_create_a_role.rb
123
123
  - features/lib/tasks/not_create_a_task.rb
124
+ - features/lib/tasks/not_previously_take_note_of_something.rb
124
125
  - features/lib/tasks/run.rb
125
126
  - features/lib/tasks/run_a_scenario.rb
126
127
  - features/lib/tasks/see_a_reply.rb
127
128
  - features/lib/tasks/see_the_step_has.rb
129
+ - features/remember_information_between_steps.feature
128
130
  - features/support/env.rb
129
131
  - lib/actor.rb
130
132
  - lib/codify/const_name.rb
@@ -166,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
166
168
  requirements:
167
169
  - - ">="
168
170
  - !ruby/object:Gem::Version
169
- hash: -2598108803398810333
171
+ hash: -826541078781353768
170
172
  segments:
171
173
  - 0
172
174
  version: "0"