rspec-given 2.1.0.beta.4 → 2.1.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.old CHANGED
@@ -1,6 +1,6 @@
1
1
  # rspec-given
2
2
 
3
- Covering rspec-given, version 2.1.0.beta.3.
3
+ Covering rspec-given, version 2.1.0.beta.4.
4
4
 
5
5
  rspec-given is an RSpec extension to allow Given/When/Then notation in
6
6
  RSpec specifications. It is a natural extension of the experimental
@@ -23,7 +23,7 @@ _rspec-given_ is ready for production use.
23
23
 
24
24
  Here is a specification written in the rspec-given framework:
25
25
 
26
- <pre>
26
+ ```ruby
27
27
  require 'rspec/given'
28
28
  require 'spec_helper'
29
29
  require 'stack'
@@ -46,7 +46,7 @@ describe Stack do
46
46
  When { stack.push(:an_item) }
47
47
 
48
48
  Then { stack.depth.should == 1 }
49
- And { stack.top.should == :an_item }
49
+ Then { stack.top.should == :an_item }
50
50
  end
51
51
 
52
52
  context "when popping" do
@@ -62,7 +62,7 @@ describe Stack do
62
62
  When(:pop_result) { stack.pop }
63
63
 
64
64
  Then { pop_result.should == :an_item }
65
- And { stack.depth.should == 0 }
65
+ Then { stack.depth.should == 0 }
66
66
  end
67
67
  end
68
68
 
@@ -81,12 +81,12 @@ describe Stack do
81
81
  When(:pop_result) { stack.pop }
82
82
 
83
83
  Then { pop_result.should == :top_item }
84
- And { stack.top.should == :second_item }
85
- And { stack.depth.should == original_depth - 1 }
84
+ Then { stack.top.should == :second_item }
85
+ Then { stack.depth.should == original_depth - 1 }
86
86
  end
87
87
  end
88
88
  end
89
- </pre>
89
+ ```
90
90
 
91
91
  Let's talk about the individual statements used in the Given
92
92
  framework.
@@ -123,43 +123,44 @@ preconditions running before inner preconditions.
123
123
 
124
124
  #### Given examples:
125
125
 
126
- <pre>
126
+ ```ruby
127
127
  Given(:stack) { Stack.new }
128
- </pre>
128
+ ```
129
129
 
130
- The given block is lazily run if 'stack' is ever referenced in the
131
- test and the value of the block is bound to 'stack'. The first
132
- reference to 'stack' in the specification will cause the code block to
133
- execute. Futher references to 'stack' will reuse the previously
134
- generated value.
130
+ The block for the given clause is lazily run if 'stack' is ever
131
+ referenced in the test and the value of the block is bound to 'stack'.
132
+ The first reference to 'stack' in the specification will cause the
133
+ code block to execute. Futher references to 'stack' will reuse the
134
+ previously generated value.
135
135
 
136
- <pre>
136
+ ```ruby
137
137
  Given!(:original_size) { stack.size }
138
- </pre>
138
+ ```
139
139
 
140
140
  The code block is run unconditionally once before each test and the
141
141
  value of the block is bound to 'original_size'. This form is useful
142
142
  when you want to record the value of something that might be affected
143
143
  by the When code.
144
144
 
145
- <pre>
145
+ ```ruby
146
146
  Given { stack.clear }
147
- </pre>
147
+ ```
148
148
 
149
- The given block is run unconditionally once before each test. This
150
- form of given is used for code that is executed for side effects.
149
+ The block for the given clause is run unconditionally once before each
150
+ test. This form of given is used for code that is executed for side
151
+ effects.
151
152
 
152
153
  ### When
153
154
 
154
- The _When_ block specifies the code to be tested ... oops, excuse me
155
+ The _When_ clause specifies the code to be tested ... oops, excuse me
155
156
  ... specified. After the preconditions in the given section are met,
156
157
  the when code block is run.
157
158
 
158
- There should only be one _When_ block for a given context. However, a
159
- _When_ in an outer context shoud be treated as a _Given_ in an inner
160
- context. E.g.
159
+ There should not be more than one _When_ clause for a given direct
160
+ context. However, a _When_ in an outer context shoud be treated as a
161
+ _Given_ in an inner context. E.g.
161
162
 
162
- <pre>
163
+ ```ruby
163
164
  context "outer context" do
164
165
  When { code specified in the outer context }
165
166
  Then { assert something about the outer context }
@@ -173,30 +174,31 @@ context. E.g.
173
174
  Then { assert something about the inner context }
174
175
  end
175
176
  end
176
- </pre>
177
+ ```
177
178
 
178
179
  #### When examples:
179
180
 
180
- <pre>
181
+ ```ruby
181
182
  When { stack.push(:item) }
182
- </pre>
183
+ ```
183
184
 
184
185
  The code block is executed once per test. The effect of the _When{}_
185
186
  block is very similar to _Given{}_. However, When is used to identify
186
187
  the particular code that is being specified in the current context or
187
188
  describe block.
188
189
 
189
- <pre>
190
+ ```ruby
190
191
  When(:result) { stack.pop }
191
- </pre>
192
+ ```
192
193
 
193
194
  The code block is executed once per test and the value of the code
194
195
  block is bound to 'result'. Use this form when the code under test
195
196
  returns a value that you wish to interrogate in the _Then_ code.
196
197
 
197
- If an exception occurs during the execution of the When block, the
198
- exception is caught and a failure object is bound to 'result'. The
199
- failure can be checked in a then block with the 'have_failed' matcher.
198
+ If an exception occurs during the execution of the block for the When
199
+ clause, the exception is caught and a failure object is bound to
200
+ 'result'. The failure can be checked in a then block with the
201
+ 'have_failed' matcher.
200
202
 
201
203
  The failure object will rethrow the captured exception if anything
202
204
  other than have_failed matcher is used on the failure object.
@@ -205,10 +207,10 @@ For example, if the stack is empty when it is popped, then it is
205
207
  reasonable for pop to raise an UnderflowError. This is how you might
206
208
  specify that behavior:
207
209
 
208
- <pre>
210
+ ```ruby
209
211
  When(:result) { stack.pop }
210
212
  Then { result.should have_failed(UnderflowError, /empty/) }
211
- </pre>
213
+ ```
212
214
 
213
215
  Note that the arguments to the 'have_failed' matcher are the same as
214
216
  those given to the standard RSpec matcher 'raise_error'.
@@ -220,7 +222,13 @@ then conditions must be true after the code under test (the _When_
220
222
  clause) is run.
221
223
 
222
224
  The code in the block of a _Then_ clause should be a single _should_
223
- assertion. Code in _Then_ blocks should not have any side effects.
225
+ assertion. Code in _Then_ clauses should not have any side effects.
226
+
227
+ Let me repeat that: <b>_Then_ clauses should not have any side
228
+ effects!</b> _Then_ clauses with side effects are erroneous. _Then_
229
+ clauses need to be idempotent, so that running them once, twice, a
230
+ hundred times, or never does not change the state of the program. (The
231
+ same is true of _And_ clauses).
224
232
 
225
233
  In RSpec terms, a _Then_ clause forms a RSpec Example that runs in the
226
234
  context of an Example Group (defined by a describe or context clause).
@@ -230,27 +238,28 @@ there will be no examples to be run for that group. If all the
230
238
  assertions in an example group are done via Invariants, then the group
231
239
  should use an empty _Then_ clause, like this:
232
240
 
233
- <pre>
241
+ ```ruby
234
242
  Then { }
235
- </pre>
243
+ ```
236
244
 
237
245
  #### Then examples:
238
246
 
239
- <pre>
247
+ ```ruby
240
248
  Then { stack.should be_empty }
241
- </pre>
249
+ ```
242
250
 
243
- After the related _When_ block is run, the stack should be empty. If
244
- it is not empty, the test will fail.
251
+ After the related block for the _When_ clause is run, the stack should
252
+ be empty. If it is not empty, the test will fail.
245
253
 
246
254
  ### And
247
255
 
248
- The _And_ clause is similar to _Then_, but do not form their own RSpec
249
- examples. This means that _And_ clauses reuse the setup from the
256
+ The _And_ clause is similar to _Then_, but does not form its own RSpec
257
+ example. This means that _And_ clauses reuse the setup from a sibling
250
258
  _Then_ clause. Using a single _Then_ an multiple _And_ clauses in an
251
259
  example group means the setup for that group is run only once (for the
252
- _Then_ clause). This can be a significant speed savings where the
253
- setup for an example group is expensive.
260
+ _Then_ clause) and reused for all the _And_s. This can be a
261
+ significant speed savings where the setup for an example group is
262
+ expensive.
254
263
 
255
264
  Some things to keep in mind about _And_ clauses:
256
265
 
@@ -259,7 +268,7 @@ Some things to keep in mind about _And_ clauses:
259
268
  is an error.
260
269
 
261
270
  1. The code in the _And_ clause is run immediately after the first
262
- _Then_ of an example group.
271
+ (executed) _Then_ of an example group.
263
272
 
264
273
  1. And assertion failures in a _Then_ clause or a _And_ clause will
265
274
  cause all the subsequent _And_ clauses to be skipped.
@@ -270,6 +279,10 @@ Some things to keep in mind about _And_ clauses:
270
279
  appear in the documentation, html or textmate formats (options
271
280
  -fhtml, -fdoc, or -ftextmate).
272
281
 
282
+ 1. Like _Then_ clauses, _And_ clauses must be idempotent. That means
283
+ they should not execute any code that changes global program state.
284
+ (See the section on the _Then_ clause).
285
+
273
286
  The choice to use an _And_ clause is primarily a speed consideration.
274
287
  If an example group has expensive setup and there are a lot of _Then_
275
288
  clauses, then choosing to make some of the _Then_ clauses into _And_
@@ -278,26 +291,27 @@ stick with _Then_ clauses.
278
291
 
279
292
  #### Then/And examples:
280
293
 
281
- <pre>
294
+ ```ruby
282
295
  Then { pop_result.should == :top_item } # Required
283
296
  And { stack.top.should == :second_item } # No Setup rerun
284
297
  And { stack.depth.should == original_depth - 1 } # ... for these
285
- </pre>
298
+ ```
286
299
 
287
300
  ### Invariant
288
301
 
289
- The _Invariant_ block is a new idea that doesn't have an analog in
290
- RSpec or Test::Unit. The invariant allows you specify things that
291
- must always be true. In the stack example, <tt>empty?</tt> is defined
292
- in term of <tt>size</tt>. Whenever <tt>size</tt> is 0,
293
- <tt>empty?</tt> should be true. Whenever <tt>size</tt> is non-zero,
294
- <tt>empty?</tt> should be false.
302
+ The _Invariant_ clause is a new idea that doesn't have an analog in
303
+ RSpec or Test::Unit. The invariant allows you specify things that must
304
+ always be true (or at least always be true in the scope of the
305
+ invariant). In the stack example, <tt>empty?</tt> is defined in term
306
+ of <tt>size</tt>. Whenever <tt>size</tt> is 0, <tt>empty?</tt> should
307
+ be true. Whenever <tt>size</tt> is non-zero, <tt>empty?</tt> should be
308
+ false.
295
309
 
296
- You can conceptually think of an _Invariant_ block as a _Then_ block
310
+ You can conceptually think of an _Invariant_ clause as a _Then_ block
297
311
  that automatically gets added to every _Then_ within its scope.
298
312
 
299
- Invariants nested within a context only apply to the _Then_ blocks in
300
- that context.
313
+ Invariants nested within a context only apply to the _Then_ clauses
314
+ that are in the scope of that context.
301
315
 
302
316
  Invariants that reference a _Given_ precondition accessor must only be
303
317
  used in contexts that define that accessor.
@@ -319,9 +333,9 @@ the examples to produce better looking output. If you don't care about
319
333
  the pretty output and wish to disable source code caching
320
334
  unconditionally, then add the following line to your spec helper file:
321
335
 
322
- <pre>
336
+ ```ruby
323
337
  RSpec::Given.source_caching_disabled = true
324
- </pre>
338
+ ```
325
339
 
326
340
  # Future Directions
327
341
 
@@ -329,14 +343,18 @@ I really like the way the Given framework is working out. I feel my
329
343
  tests are much more like specifications when I use it. However, I'm
330
344
  not entirely happy with it.
331
345
 
332
- I would like to remove the need for the ".should" in all the
333
- _Then_ blocks. In other words, instead of saying:
346
+ I would like to remove the need for the ".should" in all the _Then_
347
+ clauses. In other words, instead of saying:
334
348
 
349
+ ```ruby
335
350
  Then { x.should == y }
351
+ ```
336
352
 
337
353
  we could say:
338
354
 
355
+ ```ruby
339
356
  Then { x == y }
357
+ ```
340
358
 
341
359
  I think the [wrong assertion library](http://rubygems.org/gems/wrong)
342
360
  has laid some groundwork in this area.
data/Rakefile CHANGED
@@ -54,7 +54,6 @@ task :examples => [:specs, :examples1, :examples2]
54
54
  desc "Run the RSpec 2 specs and examples"
55
55
  task :ex2 => [:specs, :examples2]
56
56
 
57
-
58
57
  desc "Run the specs"
59
58
  task :specs do
60
59
  puts "Running specs"
@@ -1,6 +1,7 @@
1
- require 'rspec/given'
2
1
  $LOAD_PATH << './examples/stack'
3
2
 
4
- RSpec.configure do |c|
5
- c.mock_with :flexmock
3
+ require 'rspec/given'
4
+
5
+ RSpec.configure do |config|
6
+ # config.mock_with :flexmock
6
7
  end
@@ -1,16 +1,17 @@
1
1
  require 'rspec/given'
2
- require 'spec_helper'
2
+ require 'example_helper'
3
3
 
4
4
  describe "And" do
5
+
5
6
  Given(:info) { [] }
6
- Given(:mock) { flexmock("mock") }
7
7
 
8
8
  describe "And is called after Then" do
9
- Given { mock.should_receive(:and_ran).once }
9
+ Given(:m) { mock("mock") }
10
+ Given { m.should_receive(:and_ran) }
10
11
  Then { info << "T" }
11
12
  And {
12
13
  info.should == ["T"]
13
- mock.and_ran
14
+ m.and_ran
14
15
  }
15
16
  end
16
17
 
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'example_helper'
2
2
 
3
3
  describe "Focused Line" do
4
4
  it "runs only a single test" do
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'example_helper'
2
2
 
3
3
  describe "Line Spec" do
4
4
 
@@ -1,5 +1,5 @@
1
1
  require 'rspec/given'
2
- require 'spec_helper'
2
+ require 'example_helper'
3
3
  require 'stack'
4
4
 
5
5
  describe Stack do
data/lib/rspec/given.rb CHANGED
@@ -14,7 +14,8 @@ if RSpec::Given.using_old_rspec?
14
14
  else
15
15
  require 'rspec/given/version'
16
16
  require 'rspec/given/module_methods'
17
- require 'rspec/given/line_cache'
17
+ require 'rspec/given/file_cache'
18
+ require 'rspec/given/line_extractor'
18
19
  require 'rspec/given/extensions'
19
20
  require 'rspec/given/configure'
20
21
  require 'rspec/given/failure'
@@ -71,8 +71,8 @@ module RSpec
71
71
  @_rg_contet_info ||= {}
72
72
  end
73
73
 
74
- def _rg_cache
75
- @_rg_cache ||= LineCache.new
74
+ def _rg_lines
75
+ @_rg_lines ||= LineExtractor.new
76
76
  end
77
77
 
78
78
  # Trigger the evaluation of a Given! block by referencing its
@@ -166,7 +166,7 @@ module RSpec
166
166
  b = block.binding
167
167
  file = eval "__FILE__", b
168
168
  line = eval "__LINE__", b
169
- description = _rg_cache.line(file, line) unless RSpec::Given.source_caching_disabled
169
+ description = _rg_lines.line(file, line) unless RSpec::Given.source_caching_disabled
170
170
  if description
171
171
  cmd = "it(description)"
172
172
  else
@@ -0,0 +1,19 @@
1
+ module RSpec
2
+ module Given
3
+ class FileCache
4
+ def initialize
5
+ @lines = {}
6
+ end
7
+
8
+ def get(file_name)
9
+ @lines[file_name] ||= read_lines(file_name)
10
+ end
11
+
12
+ private
13
+
14
+ def read_lines(file_name)
15
+ open(file_name) { |f| f.readlines }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ require 'rspec/given/file_cache'
2
+
3
+ module RSpec
4
+ module Given
5
+ class LineExtractor
6
+ def initialize(file_cache=nil)
7
+ @files = file_cache || FileCache.new
8
+ end
9
+
10
+ def line(file_name, line)
11
+ lines = @files.get(file_name)
12
+ extract_lines_from(lines, line-1)
13
+ end
14
+
15
+ def to_s
16
+ "<LineExtractor>"
17
+ end
18
+
19
+ private
20
+
21
+ def extract_lines_from(lines, line_index)
22
+ result = lines[line_index]
23
+ if continued?(result)
24
+ level = indentation_level(result)
25
+ begin
26
+ line_index += 1
27
+ result << lines[line_index]
28
+ end while indentation_level(lines[line_index]) > level
29
+ end
30
+ result
31
+ end
32
+
33
+ def continued?(string)
34
+ string =~ /(\{|do) *$/
35
+ end
36
+
37
+ def indentation_level(string)
38
+ string =~ /^(\s*)\S/
39
+ $1.size
40
+ end
41
+ end
42
+ end
43
+ end