rspec-given 2.4.5 → 3.0.0.beta.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -2
  3. data/Gemfile.lock +8 -10
  4. data/README.md +50 -34
  5. data/README.old +720 -0
  6. data/Rakefile +23 -17
  7. data/TODO +13 -0
  8. data/examples/example_helper.rb +8 -1
  9. data/examples/integration/and_spec.rb +6 -11
  10. data/examples/integration/focused_line_spec.rb +2 -1
  11. data/examples/integration/given_spec.rb +19 -9
  12. data/examples/integration/invariant_spec.rb +6 -6
  13. data/examples/integration/then_spec.rb +0 -1
  14. data/examples/loader.rb +4 -0
  15. data/examples/minitest_helper.rb +38 -0
  16. data/examples/stack/stack_spec.rb +2 -3
  17. data/lib/given.rb +2 -0
  18. data/lib/rspec/given.rb +1 -19
  19. data/rakelib/bundler_fix.rb +17 -0
  20. data/rakelib/gemspec.rake +161 -0
  21. data/rakelib/metrics.rake +30 -0
  22. data/rakelib/preview.rake +14 -0
  23. data/spec/lib/{rspec/given → given}/evaluator_spec.rb +1 -1
  24. data/spec/lib/{rspec/given → given}/ext/numeric_spec.rb +2 -2
  25. data/spec/lib/{rspec/given → given}/ext/numeric_specifications.rb +0 -0
  26. data/spec/lib/{rspec/given → given}/extensions_spec.rb +2 -2
  27. data/spec/lib/given/failure_matcher_spec.rb +77 -0
  28. data/spec/lib/given/failure_spec.rb +49 -0
  29. data/spec/lib/given/file_cache_spec.rb +26 -0
  30. data/spec/lib/{rspec/given → given}/fuzzy_number_spec.rb +2 -2
  31. data/spec/lib/{rspec/given → given}/have_failed_spec.rb +5 -4
  32. data/spec/lib/{rspec/given → given}/lexical_purity_spec.rb +0 -0
  33. data/spec/lib/given/line_extractor_spec.rb +84 -0
  34. data/spec/lib/{rspec/given → given}/module_methods_spec.rb +2 -2
  35. data/spec/lib/{rspec/given → given}/natural_assertion_spec.rb +4 -36
  36. data/spec/lib/{rspec/given → given}/options_spec.rb +33 -33
  37. data/spec/spec_helper.rb +20 -0
  38. data/spec/support/faux_then.rb +2 -2
  39. data/spec/support/natural_assertion_control.rb +1 -1
  40. metadata +35 -42
  41. data/examples/integration/failing_spec.rb +0 -5
  42. data/lib/rspec/given/configure.rb +0 -20
  43. data/lib/rspec/given/core.rb +0 -9
  44. data/lib/rspec/given/evaluator.rb +0 -39
  45. data/lib/rspec/given/ext/numeric.rb +0 -32
  46. data/lib/rspec/given/extensions.rb +0 -262
  47. data/lib/rspec/given/failure.rb +0 -53
  48. data/lib/rspec/given/file_cache.rb +0 -19
  49. data/lib/rspec/given/fuzzy_number.rb +0 -70
  50. data/lib/rspec/given/fuzzy_shortcuts.rb +0 -1
  51. data/lib/rspec/given/have_failed.rb +0 -77
  52. data/lib/rspec/given/line_extractor.rb +0 -43
  53. data/lib/rspec/given/module_methods.rb +0 -70
  54. data/lib/rspec/given/monkey.rb +0 -42
  55. data/lib/rspec/given/natural_assertion.rb +0 -193
  56. data/lib/rspec/given/rspec1_given.rb +0 -11
  57. data/lib/rspec/given/version.rb +0 -10
  58. data/spec/lib/rspec/given/failure_spec.rb +0 -17
  59. data/spec/lib/rspec/given/file_cache_spec.rb +0 -28
  60. data/spec/lib/rspec/given/line_extractor_spec.rb +0 -86
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6cf182dad94e38e77794cb12c33a5bddaeccab0
4
- data.tar.gz: 93d31454b226d0c89dbeafe2d61bce6f04dff699
3
+ metadata.gz: dead0bb84656fafdece7e640e5a0c7657feac258
4
+ data.tar.gz: 1b3f63bd32ebc338ebd8d2935dc4714ef4104861
5
5
  SHA512:
6
- metadata.gz: 0a2b452eb0ede60422e610aa87d73772b603c1f2a859596576046b9e13d18547a6f4df63dd8aa5c36d52e563745217e59fb0757663a1d3e77868e71d4999b201
7
- data.tar.gz: 357c72ac9ce1d2cd26bdc492852de9f22e62afab93a570f97f1211778f58be5f229ca2c1552950df502d1f5f11e5af725167d48b86327fef1ffda7388b708ac2
6
+ metadata.gz: e8ef2be0daac6d78e728925c9c3e9bbfe056169fa0edc46db5a14690bf4c819d08fd63d0fc2c2c9c2a34cb680422d485d6f4a8e052520903c7024cd668aad5c4
7
+ data.tar.gz: dffd7d53104c93141e17d43bf98b989a6540e4ebbe08f5c20a421e23233362587069a228ad570ed461f14ed924a4785a3c56b4e26e41075f45494931a400b62b
data/Gemfile CHANGED
@@ -1,3 +1,7 @@
1
1
  source 'https://rubygems.org'
2
- gemspec
3
- gem 'rake'
2
+
3
+ gem 'rake'
4
+ gem 'rspec', '>= 2.12'
5
+ gem 'minitest', '>= 4.3'
6
+ gem 'sorcerer', '>= 0.3.7'
7
+ gem 'flexmock'
data/Gemfile.lock CHANGED
@@ -1,20 +1,15 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rspec-given (2.4.4)
5
- rspec (>= 2.12)
6
- sorcerer (>= 0.3.7)
7
-
8
1
  GEM
9
2
  remote: https://rubygems.org/
10
3
  specs:
11
4
  diff-lcs (1.2.4)
5
+ flexmock (1.3.2)
6
+ minitest (5.0.6)
12
7
  rake (10.0.4)
13
- rspec (2.14.1)
8
+ rspec (2.14.0)
14
9
  rspec-core (~> 2.14.0)
15
10
  rspec-expectations (~> 2.14.0)
16
11
  rspec-mocks (~> 2.14.0)
17
- rspec-core (2.14.1)
12
+ rspec-core (2.14.0)
18
13
  rspec-expectations (2.14.0)
19
14
  diff-lcs (>= 1.1.3, < 2.0)
20
15
  rspec-mocks (2.14.1)
@@ -25,5 +20,8 @@ PLATFORMS
25
20
  ruby
26
21
 
27
22
  DEPENDENCIES
23
+ flexmock
24
+ minitest (>= 4.3)
28
25
  rake
29
- rspec-given!
26
+ rspec (>= 2.12)
27
+ sorcerer (>= 0.3.7)
data/README.md CHANGED
@@ -4,51 +4,48 @@
4
4
  | :----: |
5
5
  | [![Master Build Status](https://secure.travis-ci.org/jimweirich/rspec-given.png?branch=master)](https://travis-ci.org/jimweirich/rspec-given) |
6
6
 
7
- Covering rspec-given, version 2.4.5.
7
+ Covering rspec-given, minispec-given, and given-core, version 3.0.0.beta.1.
8
8
 
9
- rspec-given is an RSpec extension to allow Given/When/Then notation in
10
- RSpec specifications. It is a natural extension of the experimental
11
- work done on the Given framework.
9
+ rspec-given and minispec-given are extensions to your favorite testing
10
+ framework to allow Given/When/Then notation when writing specs.
12
11
 
13
12
  # Why Given/When/Then
14
13
 
15
14
  RSpec has done a great job of making specifications more readable for
16
- humans. However, I really like the given / when / then nature of
17
- Cucumber stories and would like to follow the same structure in my
18
- unit tests. rspec-given allows a simple given/when/then structure
19
- RSpec specifications.
15
+ humans. However, I really like the given/when/then nature of Cucumber
16
+ stories and would like to follow the same structure in my unit tests.
17
+ rspec-given (and now minispec-given) allows a simple given/when/then
18
+ structure RSpec specifications.
20
19
 
21
20
  ## Status
22
21
 
23
- rspec-given is ready for production use.
22
+ * rspec-given is ready for production use.
23
+ * minispec-given is experimental.
24
24
 
25
- ## Installation
25
+ ### RSpec/Given
26
26
 
27
- ### If you are using bundler
27
+ The rspec-given gem is the original given/when/then extension for
28
+ RSpec. It now depends on a given_core gem for the basic functionality
29
+ and then adds the RSpec specific code.
28
30
 
29
- Add `rspec-given` to the `:test` group in the `Gemfile`:
31
+ * rspec-given now require RSpec version 2.12 or better.
30
32
 
31
- ```ruby
32
- group :test do
33
- gem 'rspec-given'
34
- end
35
- ```
36
-
37
- Download and install:
33
+ ### Minitest/Given
38
34
 
39
- `$ bundle`
35
+ A new minispec-given gem allows Given/When/Then notation directly in
36
+ Minitest::Spec specifications.
40
37
 
41
- Then just require `rspec/given` in the `spec_helper` of your project and it is
42
- ready to go.
38
+ When switching from RSpec/Given to Minitest/Given, here are some
39
+ things to watch out for:
43
40
 
44
- ### If you are not using bundler
41
+ * You need to use Minitest version 4.3 or better (yes, Minitest 5.x
42
+ should work as well).
45
43
 
46
- Install the gem:
44
+ * Minitest/Given adds the missing "context" block to Minitest::Spec.
47
45
 
48
- `$ gem install rspec-given`
49
-
50
- Then just require `rspec/given` in the `spec_helper` of your project and it is
51
- ready to go.
46
+ * Only one before block is allowed in any given Minitest::Spec
47
+ describe block. This doesn't effect the number of Givens you are
48
+ allowed to use, but it may surprise if you are use to RSpec.
52
49
 
53
50
  ## Example
54
51
 
@@ -426,7 +423,7 @@ analsysis of the expression that failed.
426
423
  For example, given the following failing specification:
427
424
 
428
425
  ```ruby
429
- RSpec::Given.use_natural_assertions
426
+ Given.use_natural_assertions
430
427
 
431
428
  describe "Natural Assertions" do
432
429
  Given(:foo) { 1 }
@@ -647,6 +644,9 @@ Conover](http://rubygems.org/profiles/sconoversf).
647
644
 
648
645
  ## Configuration
649
646
 
647
+ Just require 'rspec/given' in the spec helper of your project and it
648
+ is ready to go.
649
+
650
650
  If the RSpec format option document, html or textmate is chosen,
651
651
  RSpec/Given will automatically add additional source code information to
652
652
  the examples to produce better looking output. If you don't care about
@@ -662,11 +662,11 @@ natural assertions, add one of the following lines to your spec_helper
662
662
  file:
663
663
 
664
664
  ```ruby
665
- RSpec::Given.use_natural_assertions # Enable natural assertions
666
- RSpec::Given.use_natural_assertions true # Same as above
667
- RSpec::Given.use_natural_assertions false # Disable natural assertions
668
- RSpec::Given.use_natural_assertions :always # Always process natural assertions
669
- # ... even when should/expect are detected
665
+ Given.use_natural_assertions # Enable natural assertions
666
+ Given.use_natural_assertions true # Same as above
667
+ Given.use_natural_assertions false # Disable natural assertions
668
+ Given.use_natural_assertions :always # Always process natural assertions
669
+ # ... even when should/expect are detected
670
670
  ```
671
671
 
672
672
  # License
@@ -676,6 +676,22 @@ file in the source distribution.
676
676
 
677
677
  # History
678
678
 
679
+ * Version 3.0.0
680
+
681
+ * Support for minitest added.
682
+
683
+ * Gems rspec-given and minispec-given both use the core
684
+ functionality of gem given_core.
685
+
686
+ * Version 2.4.4
687
+
688
+ * Support for RSpec 2.13 added.
689
+
690
+ * Version 2.4.3
691
+
692
+ * Better natural assertion messages when dealing with multi-line
693
+ output.
694
+
679
695
  * Version 2.4.2
680
696
 
681
697
  * Minor adjustment to natural assertion error messages to better
data/README.old ADDED
@@ -0,0 +1,720 @@
1
+ # rspec-given
2
+
3
+ | Master |
4
+ | :----: |
5
+ | [![Master Build Status](https://secure.travis-ci.org/jimweirich/rspec-given.png?branch=master)](https://travis-ci.org/jimweirich/rspec-given) |
6
+
7
+ Covering rspec-given, minispec-given, and given-core, version 3.0.0.beta.1.
8
+
9
+ rspec-given and minispec-given are extensions to your favorite testing
10
+ framework to allow Given/When/Then notation when writing specs.
11
+
12
+ # Why Given/When/Then
13
+
14
+ RSpec has done a great job of making specifications more readable for
15
+ humans. However, I really like the given/when/then nature of Cucumber
16
+ stories and would like to follow the same structure in my unit tests.
17
+ rspec-given (and now minispec-given) allows a simple given/when/then
18
+ structure RSpec specifications.
19
+
20
+ ## Status
21
+
22
+ * rspec-given is ready for production use.
23
+ * minispec-given is experimental.
24
+
25
+ ### RSpec/Given
26
+
27
+ The rspec-given gem is the original given/when/then extension for
28
+ RSpec. It now depends on a given_core gem for the basic functionality
29
+ and then adds the RSpec specific code.
30
+
31
+ * rspec-given now require RSpec version 2.12 or better.
32
+
33
+ ### Minitest/Given
34
+
35
+ A new minispec-given gem allows Given/When/Then notation directly in
36
+ Minitest::Spec specifications.
37
+
38
+ When switching from RSpec/Given to Minitest/Given, here are some
39
+ things to watch out for:
40
+
41
+ * You need to use Minitest version 4.3 or better (yes, Minitest 5.x
42
+ should work as well).
43
+
44
+ * Minitest/Given adds the missing "context" block to Minitest::Spec.
45
+
46
+ * Only one before block is allowed in any given Minitest::Spec
47
+ describe block. This doesn't effect the number of Givens you are
48
+ allowed to use, but it may surprise if you are use to RSpec.
49
+
50
+ ## Example
51
+
52
+ Here is a specification written in the rspec-given framework:
53
+
54
+ ```ruby
55
+ require 'rspec/given'
56
+ require 'spec_helper'
57
+ require 'stack'
58
+
59
+ describe Stack do
60
+ def stack_with(initial_contents)
61
+ stack = Stack.new
62
+ initial_contents.each do |item| stack.push(item) end
63
+ stack
64
+ end
65
+
66
+ Given(:stack) { stack_with(initial_contents) }
67
+ Invariant { stack.empty?.should == (stack.depth == 0) }
68
+
69
+ context "with no items" do
70
+ Given(:initial_contents) { [] }
71
+ Then { stack.depth.should == 0 }
72
+
73
+ context "when pushing" do
74
+ When { stack.push(:an_item) }
75
+
76
+ Then { stack.depth.should == 1 }
77
+ Then { stack.top.should == :an_item }
78
+ end
79
+
80
+ context "when popping" do
81
+ When(:result) { stack.pop }
82
+ Then { result.should have_failed(Stack::UnderflowError, /empty/) }
83
+ end
84
+ end
85
+
86
+ context "with one item" do
87
+ Given(:initial_contents) { [:an_item] }
88
+
89
+ context "when popping" do
90
+ When(:pop_result) { stack.pop }
91
+
92
+ Then { pop_result.should == :an_item }
93
+ Then { stack.depth.should == 0 }
94
+ end
95
+ end
96
+
97
+ context "with several items" do
98
+ Given(:initial_contents) { [:second_item, :top_item] }
99
+ Given!(:original_depth) { stack.depth }
100
+
101
+ context "when pushing" do
102
+ When { stack.push(:new_item) }
103
+
104
+ Then { stack.top.should == :new_item }
105
+ Then { stack.depth.should == original_depth + 1 }
106
+ end
107
+
108
+ context "when popping" do
109
+ When(:pop_result) { stack.pop }
110
+
111
+ Then { pop_result.should == :top_item }
112
+ Then { stack.top.should == :second_item }
113
+ Then { stack.depth.should == original_depth - 1 }
114
+ end
115
+ end
116
+ end
117
+ ```
118
+
119
+ Let's talk about the individual statements used in the Given
120
+ framework.
121
+
122
+ ### Given
123
+
124
+ The _Given_ section specifies a starting point, a set of preconditions
125
+ that must be true before the code under test is allowed to be run. In
126
+ standard test frameworks the preconditions are established with a
127
+ combination of setup methods (or :before actions in RSpec) and code in
128
+ the test.
129
+
130
+ In the example code above the preconditions are started with _Given_
131
+ statements. A top level _Given_ (that applies to the entire describe
132
+ block) says that one of the preconditions is that there is a stack
133
+ with some initial contents.
134
+
135
+ Note that initial contents are not specified in the top level describe
136
+ block, but are given in each of the nested contexts. By pushing the
137
+ definition of "initial_contents" into the nested contexts, we can vary
138
+ them as needed for that particular context.
139
+
140
+ A precondition in the form "Given(:var) {...}" creates an accessor
141
+ method named "var". The accessor is lazily initialized by the code
142
+ block. If you want a non-lazy given, use "Given!(:var) {...}".
143
+
144
+ A precondition in the form "Given {...}" just executes the code block
145
+ for side effects. Since there is no accessor, the code block is
146
+ executed immediately (i.e. no lazy evaluation).
147
+
148
+ The preconditions are run in order of definition. Nested contexts
149
+ will inherit the preconditions from the enclosing context, with outer
150
+ preconditions running before inner preconditions.
151
+
152
+ #### Given examples:
153
+
154
+ ```ruby
155
+ Given(:stack) { Stack.new }
156
+ ```
157
+
158
+ The block for the given clause is lazily run and its value bound to
159
+ 'stack' if 'stack' is ever referenced in the test.
160
+ The first reference to 'stack' in the specification will cause the
161
+ code block to execute. Futher references to 'stack' will reuse the
162
+ previously generated value.
163
+
164
+ ```ruby
165
+ Given!(:original_size) { stack.size }
166
+ ```
167
+
168
+ The code block is run unconditionally once before each test and the
169
+ value of the block is bound to 'original_size'. This form is useful
170
+ when you want to record the value of something that might be affected
171
+ by the When code.
172
+
173
+ ```ruby
174
+ Given { stack.clear }
175
+ ```
176
+
177
+ The block for the given clause is run unconditionally once before each
178
+ test. This form of given is used for code that is executed for side
179
+ effects.
180
+
181
+ ### When
182
+
183
+ The _When_ clause specifies the code to be tested ... oops, excuse me
184
+ ... specified. After the preconditions in the given section are met,
185
+ the when code block is run.
186
+
187
+ In general there should not be more than one _When_ clause for a given
188
+ direct context. However, a _When_ in an outer context will be run
189
+ after all the _Givens_ but before the inner _When_. You can think of
190
+ an outer _When_ as setting up additional given state for the inner
191
+ _When_.
192
+
193
+ E.g.
194
+
195
+ ```ruby
196
+ context "outer context" do
197
+ When { code specified in the outer context }
198
+ Then { assert something about the outer context }
199
+
200
+ context "inner context" do
201
+
202
+ # At this point, the _When_ of the outer context
203
+ # should be treated as a _Given_ of the inner context
204
+
205
+ When { code specified in the inner context }
206
+ Then { assert something about the inner context }
207
+ end
208
+ end
209
+ ```
210
+
211
+ #### When examples:
212
+
213
+ ```ruby
214
+ When { stack.push(:item) }
215
+ ```
216
+
217
+ The code block is executed once per test. The effect of the _When{}_
218
+ block is very similar to _Given{}_. However, When is used to identify
219
+ the particular code that is being specified in the current context or
220
+ describe block.
221
+
222
+ ```ruby
223
+ When(:result) { stack.pop }
224
+ ```
225
+
226
+ The code block is executed once per test and the value of the code
227
+ block is bound to 'result'. Use this form when the code under test
228
+ returns a value that you wish to interrogate in the _Then_ code.
229
+
230
+ If an exception occurs during the execution of the block for the When
231
+ clause, the exception is caught and a failure object is bound to
232
+ 'result'. The failure can be checked in a then block with the
233
+ 'have_failed' matcher.
234
+
235
+ The failure object will rethrow the captured exception if anything
236
+ other than have_failed matcher is used on the failure object.
237
+
238
+ For example, if the stack is empty when it is popped, then it is
239
+ reasonable for pop to raise an UnderflowError. This is how you might
240
+ specify that behavior:
241
+
242
+ ```ruby
243
+ When(:result) { stack.pop }
244
+ Then { result.should have_failed(UnderflowError, /empty/) }
245
+ ```
246
+
247
+ Note that the arguments to the 'have_failed' matcher are the same as
248
+ those given to the standard RSpec matcher 'raise_error'.
249
+
250
+ ### Then
251
+
252
+ The _Then_ clauses are the postconditions of the specification. These
253
+ then conditions must be true after the code under test (the _When_
254
+ clause) is run.
255
+
256
+ The code in the block of a _Then_ clause should be a single _should_
257
+ assertion. Code in _Then_ clauses should not have any side effects.
258
+
259
+ Let me repeat that: <b>_Then_ clauses should not have any side
260
+ effects!</b> _Then_ clauses with side effects are erroneous. _Then_
261
+ clauses need to be idempotent, so that running them once, twice, a
262
+ hundred times, or never does not change the state of the program. (The
263
+ same is true of _And_ and _Invariant_ clauses).
264
+
265
+ In RSpec terms, a _Then_ clause forms a RSpec Example that runs in the
266
+ context of an Example Group (defined by a describe or context clause).
267
+
268
+ Each Example Group must have at least one _Then_ clause, otherwise
269
+ there will be no examples to be run for that group. If all the
270
+ assertions in an example group are done via Invariants, then the group
271
+ should use an empty _Then_ clause, like this:
272
+
273
+ ```ruby
274
+ Then { }
275
+ ```
276
+
277
+ #### Then examples:
278
+
279
+ ```ruby
280
+ Then { stack.should be_empty }
281
+ ```
282
+
283
+ After the related block for the _When_ clause is run, the stack should
284
+ be empty. If it is not empty, the test will fail.
285
+
286
+ ### And
287
+
288
+ The _And_ clause is similar to _Then_, but does not form its own RSpec
289
+ example. This means that _And_ clauses reuse the setup from a sibling
290
+ _Then_ clause. Using a single _Then_ and multiple _And_ clauses in an
291
+ example group means the setup for that group is run only once (for the
292
+ _Then_ clause) and reused for all the _And_ clauses. This can be a
293
+ significant speed savings where the setup for an example group is
294
+ expensive.
295
+
296
+ Some things to keep in mind about _And_ clauses:
297
+
298
+ * There must be at least one _Then_ in the example group and it must
299
+ be declared before the _And_ clauses. Forgetting the _Then_ clause
300
+ is an error.
301
+
302
+ * The code in the _And_ clause is run immediately after the first
303
+ (executed) _Then_ of an example group.
304
+
305
+ * An assertion failure in a _Then_ clause or an _And_ clause will
306
+ cause all the subsequent _And_ clauses to be skipped.
307
+
308
+ * Since _And_ clauses do not form their own RSpec examples, they are
309
+ not represented in the formatted output of RSpec. That means _And_
310
+ clauses do not produce dots in the Progress format, nor do they
311
+ appear in the documentation, html or textmate formats (options
312
+ -fhtml, -fdoc, or -ftextmate).
313
+
314
+ * Like _Then_ clauses, _And_ clauses must be idempotent. That means
315
+ they should not execute any code that changes global program state.
316
+ (See the section on the _Then_ clause).
317
+
318
+ The choice to use an _And_ clause is primarily a speed consideration.
319
+ If an example group has expensive setup and there are a lot of _Then_
320
+ clauses, then choosing to make some of the _Then_ clauses into _And_
321
+ clauses will speed up the spec. Otherwise it is probably better to
322
+ stick with _Then_ clauses.
323
+
324
+ #### Then/And examples:
325
+
326
+ ```ruby
327
+ Then { pop_result.should == :top_item } # Required
328
+ And { stack.top.should == :second_item } # No Setup rerun
329
+ And { stack.depth.should == original_depth - 1 } # ... for these
330
+ ```
331
+
332
+ ### Invariant
333
+
334
+ The _Invariant_ clause is a new idea that doesn't have an analog in
335
+ RSpec or Test::Unit. The invariant allows you specify things that must
336
+ always be true in the scope of the invariant. In the stack example, the method
337
+ <tt>empty?</tt> is defined in term of <tt>size</tt>.
338
+
339
+ ```ruby
340
+ Invariant { stack.empty? == (stack.depth == 0) }
341
+ ```
342
+
343
+ This invariant states that <code>empty?</code> is true if and only if
344
+ the stack depth is zero, and that assertion is checked at every _Then_
345
+ clause that is in the same scope.
346
+
347
+ You can conceptually think of an _Invariant_ clause as a _Then_ block
348
+ that automatically gets added to every _Then_ within its scope.
349
+ Invariants nested within a context only apply to the _Then_ clauses
350
+ that are in the scope of that context.
351
+
352
+ Invariants that reference a _Given_ precondition accessor must only be
353
+ used in contexts that define that accessor.
354
+
355
+ Notes:
356
+
357
+ * Since Invariants do not form their own RSpec example, they are not
358
+ represented in the RSpec formatted output (e.g. the '--format html'
359
+ option).
360
+
361
+ ## Execution Ordering
362
+
363
+ When running the test for a specific _Then_ clause, the following will
364
+ be true:
365
+
366
+ * The non-lazy _Given_ clauses will be run in the order that they are
367
+ specified, from the outermost scope to the innermost scope
368
+ containing the _Then_. (The lazy _Given_ clauses will be run upon
369
+ demand).
370
+
371
+ * All of the _Given_ clauses in all of the relevant scopes will run
372
+ before the first (outermost) _When_ clause in those same scopes.
373
+ That means that the _When_ code can assume that the givens have been
374
+ established, even if the givens are in a more nested scope than the
375
+ When.
376
+
377
+ * _When_ clauses and RSpec _before_ blocks will be executed in the
378
+ order that they are specified, from the outermost block to the
379
+ innermost block. This makes _before_ blocks an excellent choice when
380
+ writing narrative tests to specify actions that happen between the
381
+ "whens" of a narrative-style test.
382
+
383
+ Note that the ordering between _Given_ clauses and _before_ blocks are
384
+ not strongly specified. Hoisting a _When_ clause out of an inner scope
385
+ to an outer scope may change the order of execution between related
386
+ _Given_ clauses and any _before_ blocks (hoisting the _When_ clause
387
+ might cause the related _Given_ clauses to possibly run earlier).
388
+ Because of this, do not split order dependent code between _Given_
389
+ clauses and _before_ blocks.
390
+
391
+ ## Natural Assertions
392
+
393
+ **NOTE:** <em>Natural assertions are currently an experimental feature
394
+ of RSpec/Given. They are currently disabled by default, but can be
395
+ enabled by a simple configuration option (see "use_natural_assertions"
396
+ below).</em>
397
+
398
+ RSpec/Given now supports the use of "natural assertions" in _Then_,
399
+ _And_, and _Invariant_ blocks. Natural assertions are just Ruby
400
+ conditionals, without the _should_ or _expect_ methods that RSpec
401
+ provides. Here are the Then/And examples from above, but written using
402
+ natural assertions:
403
+
404
+ ```ruby
405
+ Then { pop_result == :top_item }
406
+ And { stack.top == :second_item }
407
+ And { stack.depth == original_depth - 1 }
408
+ ```
409
+
410
+ Natural assertions must be enabled, either globally or on a per
411
+ context basis, to be recognized.
412
+
413
+ Here's a heads up: If you use natural assertions, but fail to enable
414
+ them, all your specs will mysteriously pass. This is why the **red**
415
+ part of _Red/Green/Refactor_ is so important.
416
+
417
+ ### Failure Messages with Natural Assertions
418
+
419
+ Since natural assertions do not depend upon matchers, you don't get
420
+ customized error messages from them. What you _do_ get is a complete
421
+ analsysis of the expression that failed.
422
+
423
+ For example, given the following failing specification:
424
+
425
+ ```ruby
426
+ Given.use_natural_assertions
427
+
428
+ describe "Natural Assertions" do
429
+ Given(:foo) { 1 }
430
+ Given(:bar) { 2 }
431
+ Then { foo + bar == 2 }
432
+ end
433
+ ```
434
+
435
+ You would get:
436
+
437
+ ```
438
+ 1) Natural Assertions
439
+ Failure/Error: Then { foo + bar == 2 }
440
+ Then expression failed at /Users/jim/working/git/rspec-given/examples/failing/sample_spec.rb:6
441
+ expected: 3
442
+ to equal: 2
443
+ false <- foo + bar == 2
444
+ 3 <- foo + bar
445
+ 1 <- foo
446
+ 2 <- bar
447
+ # ./examples/failing/sample_spec.rb:6:in `block in Then'
448
+ ```
449
+
450
+ Notice how the failing expression "<code>foo+bar == 2</code>" was
451
+ broken down into subexpressions and values for each subexpression.
452
+ This gives you all the information you need to figure out exactly what
453
+ part of the expression is causing the failure.
454
+
455
+ Natural assertions will give additional information (e.g. "expected:
456
+ 3 to equal: 2") for top level expressions involving any of the
457
+ comparison operators (==, !=, <, <=, >, >=) or matching operators (=~,
458
+ !~).
459
+
460
+ ### Caveats on Natural Assertions
461
+
462
+ Keep the following in mind when using natural assertions.
463
+
464
+ * Only a single expression/assertion per _Then_. The single expression
465
+ of the _Then_ block will be considered when determining pass/fail
466
+ for the assertion. If you _want_ to express a complex condition for
467
+ the _Then_, you need to use ||, && or some other logical operation
468
+ to join the conditions into a single expression (and the failure
469
+ message will break down the values for each part).
470
+
471
+ * Then clauses need be **idempotent**. This is true in general, but it
472
+ is particularly important for natural assertions to obey this
473
+ restriction. This means that assertions in a Then clause should not
474
+ change anything. Since the Natural Assertion error message contains
475
+ the values of all the subexpressions, the expression and its
476
+ subexpressions will be evaluated multiple times. If the Then clause
477
+ is not idempotent, you will get changing answers as the
478
+ subexpressions are evaluated.
479
+
480
+ That last point is important. If you write code like this:
481
+
482
+ ```ruby
483
+ # DO NOT WRITE CODE LIKE THIS
484
+ context "Incorrect non-idempotent conditions" do
485
+ Given(:ary) { [1, 2, 3] }
486
+ Then { ary.delete(1) == nil }
487
+ end
488
+ ```
489
+
490
+ Then the assertion will fail (because <code>ary.delete(1)</code> will
491
+ initially return 1). But when the error message is formated, the
492
+ system reports that <code>ary.delete(1)</code> returns nil. You will
493
+ scratch your head over that for a good while.
494
+
495
+ Instead, move the state changing code into a _When(:result)_ block, then
496
+ assert what you need to about :result. Something
497
+ like this is good:
498
+
499
+ ```ruby
500
+ context "Correct idempotent conditions" do
501
+ Given(:ary) { [1, 2, 3] }
502
+ When(:result) { ary.delete(1) }
503
+ Then { result == nil }
504
+ end
505
+ ```
506
+
507
+ It is good to note that non-idempotent assertions will also cause
508
+ problems with And clauses.
509
+
510
+ ### Mixing Natural Assertions and RSpec Assertions
511
+
512
+ Natural assertions and RSpec assertions for the most part can be
513
+ intermixed in a single test suite, even within a single context.
514
+ Because there are a few corner cases that might cause problems, they
515
+ must be explicitly enabled before they will be considered.
516
+
517
+ To enable natural assertions in a context, call the
518
+ _use_natural_assertions_ method in that context. For example:
519
+
520
+ ```ruby
521
+ context "Outer" do
522
+ use_natural_assertions
523
+
524
+ context "Inner" do
525
+ end
526
+
527
+ context "Disabled" do
528
+ use_natural_assertions false
529
+ end
530
+ end
531
+ ```
532
+
533
+ Both the _Outer_ and _Inner_ contexts will use natural assertions. The
534
+ _Disabled_ context overrides the setting inherited from _Outer_ and
535
+ will not process natural assertions.
536
+
537
+ See the **configuration** section below to see how to enable natural
538
+ assertions project wide.
539
+
540
+ ### Matchers and Natural Assertions
541
+
542
+ In RSpec, matchers are used to provide nice, readable error messages
543
+ when an assertion is not met. Natural assertions provide
544
+ self-explanatory failure messages for most things without requiring
545
+ any special matchers from the programmer.
546
+
547
+ In the rare case that some extra information would be helpful, it is
548
+ useful to create special objects that respond to the == operator.
549
+
550
+ #### Asserting Nearly Equal with Fuzzy Numbers
551
+
552
+ Operations on floating point numbers rarely create numbers that are
553
+ exactly equal, therefore it is useful to assert that two floating
554
+ point numbers are nearly equal. We do that by creating a fuzzy number
555
+ that has a looser interpretation of what it means to be equal.
556
+
557
+ For example, the following asserts that the square root of 10 is about
558
+ 3.1523 with an accuracy of 1 percent.
559
+
560
+ ```ruby
561
+ Then { Math.sqrt(10) == about(3.1623).percent(1) }
562
+ ```
563
+
564
+ As long as the real value of <code>Math.sqrt(10)</code> is within plus
565
+ or minus 1% of 3.1623 (i.e. 3.1623 +/- 0.031623), then the assertion
566
+ will pass.
567
+
568
+ There are several ways of creating fuzzy numbers:
569
+
570
+ * <code>about(n).delta(d)</code> -- A fuzzy number matching the range
571
+ (n-d)..(n+d)
572
+
573
+ * <code>about(n).percent(p)</code> -- A fuzzy number matching the
574
+ range (n-(n*p/100)) .. (n+(n*p/100))
575
+
576
+ * <code>about(n).epsilon(neps)</code> -- A fuzzy number matching the
577
+ range (n-(neps*e)) .. (n+(neps*e)), where e is the difference
578
+ between 1.0 and the next smallest floating point number.
579
+
580
+ * <code>about(n)</code> -- Same as <code>about(n).epsilon(10)</code>.
581
+
582
+ When the file <code>rspec/given/fuzzy_shortcuts</code> is required,
583
+ the following unicode shortcut methods are added to Numeric to create
584
+ fuzzy numbers.
585
+
586
+ * <code>n.±(del)</code> is the same as <code>about(n).delta(del)</code>
587
+
588
+ * <code>n.‰(percentage)</code> is the same as <code>about(n).percent(percentage)</code>
589
+
590
+ * <code>n.€(neps)</code> is the same as <code>about(n).epsilon(neps)</code>
591
+
592
+ * <code>n.±</code>, <code>n.‰</code>, and <code>n.€</code> are all
593
+ the same as <code>about(n)</code>
594
+
595
+ #### Detecting Exceptions
596
+
597
+ The RSpec matcher used for detecting exceptions will work with natural
598
+ assertions out of the box. Just check for equality against the
599
+ <code>have_failed</code> return value.
600
+
601
+ For example, the following two Then clauses are equivalent:
602
+
603
+ ```ruby
604
+ # Using an RSpec matcher
605
+ Then { result.should have_failed(StandardError, /message/) }
606
+
607
+ # Using natural assertions
608
+ Then { result == have_failed(StandardError, /message/) }
609
+ ```
610
+
611
+ ### Processing Natural Assertions
612
+
613
+ When natural assertions are enabled, they are only used if all of the
614
+ following are true:
615
+
616
+ 1. The block does not throw an RSpec assertion failure (or any other
617
+ exception for that matter).
618
+
619
+ 1. The block returns false (blocks that return true pass the
620
+ assertion and don't need a failure message).
621
+
622
+ 1. The block does not use RSpec's _should_ or _expect_ methods.
623
+
624
+ Detecting that last point (the use of _should_ and _expect_) is done
625
+ by modifying the RSpec runtime to report uses of _should_ and
626
+ _expect_.
627
+
628
+ ### Platform Support
629
+
630
+ Natural assertions use the Ripper library to parse the failing
631
+ condition and find all the sub-expression values upon a failure.
632
+ Currently Ripper is not supported on JRuby 1.7.2. Charles Nutter has
633
+ said that Ripper support is coming soon and may arrive as early as
634
+ version 1.7.3. Until then, natural assertions are disabled when
635
+ running under JRuby. Never fear, JRuby supports all the other features
636
+ of rspec-given and will work just fine.
637
+
638
+ ### Further Reading
639
+
640
+ Natural assertions were inspired by the [wrong assertion
641
+ library](http://rubygems.org/gems/wrong) by [Alex
642
+ Chaffee](http://rubygems.org/profiles/alexch) and [Steve
643
+ Conover](http://rubygems.org/profiles/sconoversf).
644
+
645
+ ## Configuration
646
+
647
+ Just require 'rspec/given' in the spec helper of your project and it
648
+ is ready to go.
649
+
650
+ If the RSpec format option document, html or textmate is chosen,
651
+ RSpec/Given will automatically add additional source code information to
652
+ the examples to produce better looking output. If you don't care about
653
+ the pretty output and wish to disable source code caching
654
+ unconditionally, then add the following line to your spec helper file:
655
+
656
+ ```ruby
657
+ RSpec::Given.source_caching_disabled = true
658
+ ```
659
+
660
+ Natural assertions are disabled by default. To globally configure
661
+ natural assertions, add one of the following lines to your spec_helper
662
+ file:
663
+
664
+ ```ruby
665
+ Given.use_natural_assertions # Enable natural assertions
666
+ Given.use_natural_assertions true # Same as above
667
+ Given.use_natural_assertions false # Disable natural assertions
668
+ Given.use_natural_assertions :always # Always process natural assertions
669
+ # ... even when should/expect are detected
670
+ ```
671
+
672
+ # License
673
+
674
+ RSpec-Given is available under the MIT License. See the MIT-LICENSE
675
+ file in the source distribution.
676
+
677
+ # History
678
+
679
+ * Version 3.0.0
680
+
681
+ * Support for minitest added.
682
+
683
+ * Gems rspec-given and minispec-given both use the core
684
+ functionality of gem given_core.
685
+
686
+ * Version 2.4.4
687
+
688
+ * Support for RSpec 2.13 added.
689
+
690
+ * Version 2.4.3
691
+
692
+ * Better natural assertion messages when dealing with multi-line
693
+ output.
694
+
695
+ * Version 2.4.2
696
+
697
+ * Minor adjustment to natural assertion error messages to better
698
+ handle multi-line values.
699
+
700
+ * Remove flog, flay and other development tools from the bundle and
701
+ gemspec. The Rakefile was updated to suggest installing them if
702
+ they are not there.
703
+
704
+ * Version 2.4.1
705
+
706
+ * Fix bug where constants from nested modules were not properly
707
+ accessed.
708
+
709
+ * Version 2.4.0
710
+
711
+ * Add fuzzy number helper methods (with unicode method shortcuts).
712
+
713
+ * Fix bug caused by blank lines in Thens.
714
+
715
+ # Links
716
+
717
+ * Github: [https://github.com/jimweirich/rspec-given](https://github.com/jimweirich/rspec-given)
718
+ * Clone URL: git://github.com/jimweirich/rspec-given.git
719
+ * Bug/Issue Reporting: [https://github.com/jimweirich/rspec-given/issues](https://github.com/jimweirich/rspec-given/issues)
720
+ * Continuous Integration: [http://travis-ci.org/#!/jimweirich/rspec-given](http://travis-ci.org/#!/jimweirich/rspec-given)