rspec-given 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fc78c2338f9f6cb33f6f9e1d52410ded37c86fb6
4
- data.tar.gz: 796e3a8e856caf2db72f095ed75c5c3ac82eb55e
3
+ metadata.gz: 51d4d0b65e5c61f3e4477ba071cbb662baf9a641
4
+ data.tar.gz: 025e3eca40c723c210f09afa21a05a5bc36af8a2
5
5
  SHA512:
6
- metadata.gz: c609d57feba6ca8ad85ea6ceb3132bcf275a9758a84519a9454a9cd471eb2378739b753be3e73ebd89fc272cee803d2b3bce50f71a7768e5dea8e2560d149b8b
7
- data.tar.gz: 38b365c32c2a57dd23979ea9755edc955dab45a0f91fb27ffbad5f82e980132aeedf29f5ac3fe2cae7c9025da9e682561461d0aa9f071cda8702449c9a7f6cf6
6
+ metadata.gz: 4a72c0d1a81c7a4c232ff99ba00409fd5511a9b43522292b62c3c891075592e21323083db75312c0ebd05ef11409f172b76af0e69245b984baae2c77d8e3fdf0
7
+ data.tar.gz: fd9dfa5be45391c50a84b6ddccc3d9455a15f312dbe3733a4731d12164e3ae0cceeea0184803eb6134056a5076e1f80e26f41911394ceccdce85b1b1e701c46e
data/README.md CHANGED
@@ -4,7 +4,7 @@
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, minitest-given, and given-core, version 3.1.0.
7
+ Covering rspec-given, minitest-given, and given-core, version 3.1.1.
8
8
 
9
9
  rspec-given and minitest-given are extensions to your favorite testing
10
10
  framework to allow Given/When/Then notation when writing specs.
@@ -738,11 +738,9 @@ _expect_.
738
738
 
739
739
  Natural assertions use the Ripper library to parse the failing
740
740
  condition and find all the sub-expression values upon a failure.
741
- Currently Ripper is not fully supported on JRuby 1.7.4. Charles Nutter
742
- has said that Ripper support is coming soon and may arrive soon. Until
743
- then, natural assertions are disabled when running under JRuby. Never
744
- fear, JRuby supports all the other features of rspec-given and will
745
- work just fine.
741
+ Currently Ripper is not supported on Rubinius and versions of JRuby
742
+ prior to JRuby-1.7.5. Natural assertions are disabled in that case.
743
+ However, all other features of Given are supported.
746
744
 
747
745
  ### Non-Spec Assertions
748
746
 
@@ -0,0 +1,902 @@
1
+ # Given/When/Then for RSpec and Minitest
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, minitest-given, and given-core, version 3.1.0.
8
+
9
+ rspec-given and minitest-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 minitest-given) allows a simple given/when/then
18
+ structure RSpec specifications.
19
+
20
+ ## Status
21
+
22
+ * rspec-given is ready for production use.
23
+ * minitest-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 requires RSpec version 2.12 or better.
32
+
33
+ ### Minitest/Given
34
+
35
+ A new minitest-given gem allows Given/When/Then notation directly in
36
+ Minitest::Spec specifications.
37
+
38
+ To use minitest-given, just place the following require at the top of
39
+ the file (or in a convenient spec_helper).
40
+
41
+ ```ruby
42
+ require 'minitest/given'
43
+ ```
44
+
45
+ All the features of rspec-given are available in minitest-given.
46
+
47
+ When switching from RSpec/Given to Minitest/Given, here are some
48
+ things to watch out for:
49
+
50
+ * You need to use Minitest version 4.3 or better (yes, Minitest 5.x
51
+ should work as well).
52
+
53
+ * Minitest/Given adds the missing "context" block to Minitest::Spec.
54
+
55
+ * Only one before block is allowed in any given Minitest::Spec
56
+ describe block. This doesn't effect the number of Givens you are
57
+ allowed to use, but it may surprise if you are use to RSpec.
58
+
59
+ ### Auto Selecting
60
+
61
+ If you use natural assertions exclusively in your specs, it's quite
62
+ possible to write specs that run under both RSpec and Minitest::Spec.
63
+
64
+ Use this at the start of your spec file:
65
+
66
+ ```ruby
67
+ if defined?(RSpec)
68
+ require 'rspec/given'
69
+ else
70
+ require 'minitest/autorun'
71
+ require 'minitest/given'
72
+ end
73
+ ```
74
+
75
+ See
76
+ [stack_spec.rb](https://github.com/jimweirich/rspec-given/blob/minispec/examples/stack/stack_spec.rb)
77
+ and
78
+ [example_helper.rb](https://github.com/jimweirich/rspec-given/blob/minispec/examples/example_helper.rb)
79
+
80
+ ## Installation
81
+
82
+ ### If you are using bundler
83
+
84
+ Add `rspec-given` (or `minitest-given`) to the `:test` group in the `Gemfile`:
85
+
86
+ ```ruby
87
+ group :test do
88
+ gem 'rspec-given'
89
+ end
90
+ ```
91
+
92
+ ```ruby
93
+ group :test do
94
+ gem 'minitest-given'
95
+ end
96
+ ```
97
+
98
+ Download and install:
99
+
100
+ `$ bundle`
101
+
102
+ Then just require `rspec/given` (or `minitest/given`) in the
103
+ `spec_helper` of your project and it is ready to go.
104
+
105
+ ### If you are not using bundler
106
+
107
+ Install the gem:
108
+
109
+ `$ gem install rspec-given`
110
+
111
+ or
112
+
113
+ `$ gem install minitest-given`
114
+
115
+ Then just require `rspec/given` (or `minitest/given`) in the
116
+ `spec_helper` of your project and it is ready to go.
117
+
118
+ ## Example
119
+
120
+ Here is a specification written in the rspec-given framework:
121
+
122
+ ```ruby
123
+ require 'rspec/given'
124
+ require 'spec_helper'
125
+ require 'stack'
126
+
127
+ describe Stack do
128
+ def stack_with(initial_contents)
129
+ stack = Stack.new
130
+ initial_contents.each do |item| stack.push(item) end
131
+ stack
132
+ end
133
+
134
+ Given(:stack) { stack_with(initial_contents) }
135
+ Invariant { stack.empty? == (stack.depth == 0) }
136
+
137
+ context "with no items" do
138
+ Given(:initial_contents) { [] }
139
+ Then { stack.depth == 0 }
140
+
141
+ context "when pushing" do
142
+ When { stack.push(:an_item) }
143
+
144
+ Then { stack.depth == 1 }
145
+ Then { stack.top == :an_item }
146
+ end
147
+
148
+ context "when popping" do
149
+ When(:result) { stack.pop }
150
+ Then { result == Failure(Stack::UnderflowError, /empty/) }
151
+ end
152
+ end
153
+
154
+ context "with one item" do
155
+ Given(:initial_contents) { [:an_item] }
156
+
157
+ context "when popping" do
158
+ When(:pop_result) { stack.pop }
159
+
160
+ Then { pop_result == :an_item }
161
+ Then { stack.depth == 0 }
162
+ end
163
+ end
164
+
165
+ context "with several items" do
166
+ Given(:initial_contents) { [:second_item, :top_item] }
167
+ Given!(:original_depth) { stack.depth }
168
+
169
+ context "when pushing" do
170
+ When { stack.push(:new_item) }
171
+
172
+ Then { stack.top == :new_item }
173
+ Then { stack.depth == original_depth + 1 }
174
+ end
175
+
176
+ context "when popping" do
177
+ When(:pop_result) { stack.pop }
178
+
179
+ Then { pop_result == :top_item }
180
+ Then { stack.top == :second_item }
181
+ Then { stack.depth == original_depth - 1 }
182
+ end
183
+ end
184
+ end
185
+ ```
186
+
187
+ Let's talk about the individual statements used in the Given
188
+ framework.
189
+
190
+ ### Given
191
+
192
+ The _Given_ section specifies a starting point, a set of preconditions
193
+ that must be true before the code under test is allowed to be run. In
194
+ standard test frameworks the preconditions are established with a
195
+ combination of setup methods (or :before actions in RSpec) and code in
196
+ the test.
197
+
198
+ In the example code above the preconditions are started with _Given_
199
+ statements. A top level _Given_ (that applies to the entire describe
200
+ block) says that one of the preconditions is that there is a stack
201
+ with some initial contents.
202
+
203
+ Note that initial contents are not specified in the top level describe
204
+ block, but are given in each of the nested contexts. By pushing the
205
+ definition of "initial_contents" into the nested contexts, we can vary
206
+ them as needed for that particular context.
207
+
208
+ A precondition in the form "Given(:var) {...}" creates an accessor
209
+ method named "var". The accessor is lazily initialized by the code
210
+ block. If you want a non-lazy given, use "Given!(:var) {...}".
211
+
212
+ A precondition in the form "Given {...}" just executes the code block
213
+ for side effects. Since there is no accessor, the code block is
214
+ executed immediately (i.e. no lazy evaluation).
215
+
216
+ The preconditions are run in order of definition. Nested contexts
217
+ will inherit the preconditions from the enclosing context, with outer
218
+ preconditions running before inner preconditions.
219
+
220
+ #### Given examples:
221
+
222
+ ```ruby
223
+ Given(:stack) { Stack.new }
224
+ ```
225
+
226
+ The block for the given clause is lazily run and its value bound to
227
+ 'stack' if 'stack' is ever referenced in the test.
228
+ The first reference to 'stack' in the specification will cause the
229
+ code block to execute. Futher references to 'stack' will reuse the
230
+ previously generated value.
231
+
232
+ ```ruby
233
+ Given!(:original_size) { stack.size }
234
+ ```
235
+
236
+ The code block is run unconditionally once before each test and the
237
+ value of the block is bound to 'original_size'. This form is useful
238
+ when you want to record the value of something that might be affected
239
+ by the When code.
240
+
241
+ ```ruby
242
+ Given { stack.clear }
243
+ ```
244
+
245
+ The block for the given clause is run unconditionally once before each
246
+ test. This form of given is used for code that is executed for side
247
+ effects.
248
+
249
+ ### When
250
+
251
+ The _When_ clause specifies the code to be tested ... oops, excuse me
252
+ ... specified. After the preconditions in the given section are met,
253
+ the when code block is run.
254
+
255
+ In general there should not be more than one _When_ clause for a given
256
+ direct context. However, a _When_ in an outer context will be run
257
+ after all the _Givens_ but before the inner _When_. You can think of
258
+ an outer _When_ as setting up additional given state for the inner
259
+ _When_.
260
+
261
+ E.g.
262
+
263
+ ```ruby
264
+ context "outer context" do
265
+ When { code specified in the outer context }
266
+ Then { assert something about the outer context }
267
+
268
+ context "inner context" do
269
+
270
+ # At this point, the _When_ of the outer context
271
+ # should be treated as a _Given_ of the inner context
272
+
273
+ When { code specified in the inner context }
274
+ Then { assert something about the inner context }
275
+ end
276
+ end
277
+ ```
278
+
279
+ #### When examples:
280
+
281
+ ```ruby
282
+ When { stack.push(:item) }
283
+ ```
284
+
285
+ The code block is executed once per test. The effect of the _When{}_
286
+ block is very similar to _Given{}_. However, When is used to identify
287
+ the particular code that is being specified in the current context or
288
+ describe block.
289
+
290
+ ```ruby
291
+ When(:result) { stack.pop }
292
+ ```
293
+
294
+ The code block is executed once per test and the value of the code
295
+ block is bound to 'result'. Use this form when the code under test
296
+ returns a value that you wish to interrogate in the _Then_ code.
297
+
298
+ If an exception occurs during the execution of the block for the When
299
+ clause, the exception is caught and a failure object is bound to
300
+ 'result'. The failure can be checked in a then block with the
301
+ 'have_failed' matcher.
302
+
303
+ The failure object will rethrow the captured exception if anything
304
+ other than have_failed matcher is used on the failure object.
305
+
306
+ For example, if the stack is empty when it is popped, then it is
307
+ reasonable for pop to raise an UnderflowError. This is how you might
308
+ specify that behavior:
309
+
310
+ ```ruby
311
+ When(:result) { stack.pop }
312
+ Then { result.should have_failed(UnderflowError, /empty/) }
313
+ ```
314
+
315
+ Note that the arguments to the 'have_failed' matcher are the same as
316
+ those given to the standard RSpec matcher 'raise_error'.
317
+
318
+ ### Then
319
+
320
+ The _Then_ clauses are the postconditions of the specification. These
321
+ then conditions must be true after the code under test (the _When_
322
+ clause) is run.
323
+
324
+ The code in the block of a _Then_ clause should be a single _should_
325
+ assertion. Code in _Then_ clauses should not have any side effects.
326
+
327
+ Let me repeat that: <b>_Then_ clauses should not have any side
328
+ effects!</b> _Then_ clauses with side effects are erroneous. _Then_
329
+ clauses need to be idempotent, so that running them once, twice, a
330
+ hundred times, or never does not change the state of the program. (The
331
+ same is true of _And_ and _Invariant_ clauses).
332
+
333
+ In RSpec terms, a _Then_ clause forms a RSpec Example that runs in the
334
+ context of an Example Group (defined by a describe or context clause).
335
+
336
+ Each Example Group must have at least one _Then_ clause, otherwise
337
+ there will be no examples to be run for that group. If all the
338
+ assertions in an example group are done via Invariants, then the group
339
+ should use an empty _Then_ clause, like this:
340
+
341
+ ```ruby
342
+ Then { }
343
+ ```
344
+
345
+ #### Then examples:
346
+
347
+ ```ruby
348
+ Then { stack.empty? }
349
+ ```
350
+
351
+ After the related block for the _When_ clause is run, the stack should
352
+ be empty. If it is not empty, the test will fail.
353
+
354
+ ### And
355
+
356
+ The _And_ clause is similar to _Then_, but does not form its own RSpec
357
+ example. This means that _And_ clauses reuse the setup from a sibling
358
+ _Then_ clause. Using a single _Then_ and multiple _And_ clauses in an
359
+ example group means the setup for that group is run only once (for the
360
+ _Then_ clause) and reused for all the _And_ clauses. This can be a
361
+ significant speed savings where the setup for an example group is
362
+ expensive.
363
+
364
+ Some things to keep in mind about _And_ clauses:
365
+
366
+ * There must be at least one _Then_ in the example group and it must
367
+ be declared before the _And_ clauses. Forgetting the _Then_ clause
368
+ is an error.
369
+
370
+ * The code in the _And_ clause is run immediately after the first
371
+ (executed) _Then_ of an example group.
372
+
373
+ * An assertion failure in a _Then_ clause or an _And_ clause will
374
+ cause all the subsequent _And_ clauses to be skipped.
375
+
376
+ * Since _And_ clauses do not form their own RSpec examples, they are
377
+ not represented in the formatted output of RSpec. That means _And_
378
+ clauses do not produce dots in the Progress format, nor do they
379
+ appear in the documentation, html or textmate formats (options
380
+ -fhtml, -fdoc, or -ftextmate).
381
+
382
+ * Like _Then_ clauses, _And_ clauses must be idempotent. That means
383
+ they should not execute any code that changes global program state.
384
+ (See the section on the _Then_ clause).
385
+
386
+ The choice to use an _And_ clause is primarily a speed consideration.
387
+ If an example group has expensive setup and there are a lot of _Then_
388
+ clauses, then choosing to make some of the _Then_ clauses into _And_
389
+ clauses will speed up the spec. Otherwise it is probably better to
390
+ stick with _Then_ clauses.
391
+
392
+ #### Then/And examples:
393
+
394
+ ```ruby
395
+ Then { pop_result == :top_item } # Required
396
+ And { stack.top == :second_item } # No Setup rerun
397
+ And { stack.depth == original_depth - 1 } # ... for these
398
+ ```
399
+
400
+ ### Invariant
401
+
402
+ The _Invariant_ clause is a new idea that doesn't have an analog in
403
+ RSpec or Test::Unit. The invariant allows you specify things that must
404
+ always be true in the scope of the invariant. In the stack example, the method
405
+ <tt>empty?</tt> is defined in term of <tt>size</tt>.
406
+
407
+ ```ruby
408
+ Invariant { stack.empty? == (stack.depth == 0) }
409
+ ```
410
+
411
+ This invariant states that <code>empty?</code> is true if and only if
412
+ the stack depth is zero, and that assertion is checked at every _Then_
413
+ clause that is in the same scope.
414
+
415
+ You can conceptually think of an _Invariant_ clause as a _Then_ block
416
+ that automatically gets added to every _Then_ within its scope.
417
+ Invariants nested within a context only apply to the _Then_ clauses
418
+ that are in the scope of that context.
419
+
420
+ Invariants that reference a _Given_ precondition accessor must only be
421
+ used in contexts that define that accessor.
422
+
423
+ Notes:
424
+
425
+ * Since Invariants do not form their own RSpec example, they are not
426
+ represented in the RSpec formatted output (e.g. the '--format html'
427
+ option).
428
+
429
+ ## Execution Ordering
430
+
431
+ When running the test for a specific _Then_ clause, the following will
432
+ be true:
433
+
434
+ * The non-lazy _Given_ clauses will be run in the order that they are
435
+ specified, from the outermost scope to the innermost scope
436
+ containing the _Then_. (The lazy _Given_ clauses will be run upon
437
+ demand).
438
+
439
+ * All of the _Given_ clauses in all of the relevant scopes will run
440
+ before the first (outermost) _When_ clause in those same scopes.
441
+ That means that the _When_ code can assume that the givens have been
442
+ established, even if the givens are in a more nested scope than the
443
+ When.
444
+
445
+ * _When_ clauses and RSpec _before_ blocks will be executed in the
446
+ order that they are specified, from the outermost block to the
447
+ innermost block. This makes _before_ blocks an excellent choice when
448
+ writing narrative tests to specify actions that happen between the
449
+ "whens" of a narrative-style test.
450
+
451
+ Note that the ordering between _Given_ clauses and _before_ blocks are
452
+ not strongly specified. Hoisting a _When_ clause out of an inner scope
453
+ to an outer scope may change the order of execution between related
454
+ _Given_ clauses and any _before_ blocks (hoisting the _When_ clause
455
+ might cause the related _Given_ clauses to possibly run earlier).
456
+ Because of this, do not split order dependent code between _Given_
457
+ clauses and _before_ blocks.
458
+
459
+ ## Natural Assertions
460
+
461
+ RSpec/Given now supports the use of "natural assertions" in _Then_,
462
+ _And_, and _Invariant_ blocks. Natural assertions are just Ruby
463
+ conditionals, without the _should_ or _expect_ methods that RSpec
464
+ provides. Here are the Then/And examples showing natural assertions:
465
+
466
+ ### Using Natural Assertions
467
+
468
+ ```ruby
469
+ Then { stack.top == :second_item }
470
+ Then { stack.depth == original_depth - 1 }
471
+ Then { result == Failure(Stack::UnderflowError, /empty/) }
472
+ ```
473
+
474
+ ### Using RSpec expect().to
475
+
476
+ ```ruby
477
+ Then { expect(stack.top).to eq(:second_item) }
478
+ Then { expect(stack.depth).to eq(original_depth - 1) }
479
+ Then { expect(result).to have_failed(Stack::UnderflowError, /empty/) }
480
+ ```
481
+
482
+ ### Using Minitest asserts
483
+
484
+ ```ruby
485
+ Then { assert_equal :second_item, stack.top }
486
+ Then { assert_equal original_depth - 1, stack.depth }
487
+ Then {
488
+ assert_raises(Stack::UnderflowError, /empty/) do
489
+ result.call()
490
+ end
491
+ }
492
+ ```
493
+
494
+ ### Using Minitest expectations
495
+
496
+ ```ruby
497
+ Then { stack.top.must_equal :second_item }
498
+ Then { stack.depth.must_equal original_depth - 1}
499
+ Then { result.must_raise(Stack::UnderflowError, /empty/) }
500
+ ```
501
+
502
+ ### Disabling Natural Assertions
503
+
504
+ Natural assertions may be disabled, either globally or on a per
505
+ context basis. See the **configuration** section below to see how to
506
+ disable natural assertions project wide.
507
+
508
+ Here's a heads up: If you use natural assertions, but configure Given
509
+ to disable them, then all your specs will mysteriously pass. This is
510
+ why the **red** part of _Red/Green/Refactor_ is so important.
511
+
512
+ ### Failure Messages with Natural Assertions
513
+
514
+ Since natural assertions do not depend upon matchers, you don't get
515
+ customized error messages from them. What you _do_ get is a complete
516
+ analsysis of the expression that failed.
517
+
518
+ For example, given the following failing specification:
519
+
520
+ ```ruby
521
+ Given.use_natural_assertions
522
+
523
+ describe "Natural Assertions" do
524
+ Given(:foo) { 1 }
525
+ Given(:bar) { 2 }
526
+ Then { foo + bar == 2 }
527
+ end
528
+ ```
529
+
530
+ You would get:
531
+
532
+ ```
533
+ 1) Natural Assertions
534
+ Failure/Error: Then { foo + bar == 2 }
535
+ Then expression failed at /Users/jim/working/git/rspec-given/examples/failing/sample_spec.rb:6
536
+ expected: 3
537
+ to equal: 2
538
+ false <- foo + bar == 2
539
+ 3 <- foo + bar
540
+ 1 <- foo
541
+ 2 <- bar
542
+ # ./examples/failing/sample_spec.rb:6:in `block in Then'
543
+ ```
544
+
545
+ Notice how the failing expression "<code>foo+bar == 2</code>" was
546
+ broken down into subexpressions and values for each subexpression.
547
+ This gives you all the information you need to figure out exactly what
548
+ part of the expression is causing the failure.
549
+
550
+ Natural assertions will give additional information (e.g. "expected:
551
+ 3 to equal: 2") for top level expressions involving any of the
552
+ comparison operators (==, !=, <, <=, >, >=) or matching operators (=~,
553
+ !~).
554
+
555
+ ### Checking for exceptions with Natural Assertions
556
+
557
+ If you wish to see if the result of a _When_ clause is an exception,
558
+ you can use the following:
559
+
560
+ ```ruby
561
+ When(:result) { stack.pop }
562
+ Then { result == Failure(UnderflowError, /empty/) }
563
+ ```
564
+
565
+ The <code>Failure()</code> method accepts the same arguments as
566
+ <code>have_failed</code> and <code>raise_error</code>.
567
+
568
+ ### Caveats on Natural Assertions
569
+
570
+ Keep the following in mind when using natural assertions.
571
+
572
+ * Only a single expression/assertion per _Then_. The single expression
573
+ of the _Then_ block will be considered when determining pass/fail
574
+ for the assertion. If you _want_ to express a complex condition for
575
+ the _Then_, you need to use ||, && or some other logical operation
576
+ to join the conditions into a single expression (and the failure
577
+ message will break down the values for each part).
578
+
579
+ * Then clauses need be **idempotent**. This is true in general, but it
580
+ is particularly important for natural assertions to obey this
581
+ restriction. This means that assertions in a Then clause should not
582
+ change anything. Since the Natural Assertion error message contains
583
+ the values of all the subexpressions, the expression and its
584
+ subexpressions will be evaluated multiple times. If the Then clause
585
+ is not idempotent, you will get changing answers as the
586
+ subexpressions are evaluated.
587
+
588
+ That last point is important. If you write code like this:
589
+
590
+ ```ruby
591
+ # DO NOT WRITE CODE LIKE THIS
592
+ context "Incorrect non-idempotent conditions" do
593
+ Given(:ary) { [1, 2, 3] }
594
+ Then { ary.delete(1) == nil }
595
+ end
596
+ ```
597
+
598
+ Then the assertion will fail (because <code>ary.delete(1)</code> will
599
+ initially return 1). But when the error message is formated, the
600
+ system reports that <code>ary.delete(1)</code> returns nil. You will
601
+ scratch your head over that for a good while.
602
+
603
+ Instead, move the state changing code into a _When(:result)_ block, then
604
+ assert what you need to about :result. Something
605
+ like this is good:
606
+
607
+ ```ruby
608
+ context "Correct idempotent conditions" do
609
+ Given(:ary) { [1, 2, 3] }
610
+ When(:result) { ary.delete(1) }
611
+ Then { result == nil }
612
+ end
613
+ ```
614
+
615
+ It is good to note that non-idempotent assertions will also cause
616
+ problems with And and Invariant clauses.
617
+
618
+ ### Mixing Natural Assertions and RSpec Assertions
619
+
620
+ Natural assertions, RSpec should assertions and Minitest assertions
621
+ can be intermixed in a single test suite, even within a single
622
+ context.
623
+
624
+ ```ruby
625
+ context "Outer" do
626
+ context "Inner" do
627
+ Then { a == b } # Natural Assertions
628
+ Then { a.should == b } # RSpec style
629
+ Then { expect(a).to eq(b) } # RSpec style
630
+ Then { assert_equal b, a } # Minitest style
631
+ Then { a.must_equal b } # Minitest style
632
+ end
633
+
634
+ context "Disabled" do
635
+ use_natural_assertions false
636
+ end
637
+ end
638
+ ```
639
+
640
+ Both the _Outer_ and _Inner_ contexts will use natural assertions. The
641
+ _Disabled_ context overrides the setting inherited from _Outer_ and
642
+ will not process natural assertions.
643
+
644
+ See the **configuration** section below to see how to disable natural
645
+ assertions project wide.
646
+
647
+ ### Matchers and Natural Assertions
648
+
649
+ In RSpec, matchers are used to provide nice, readable error messages
650
+ when an assertion is not met. Natural assertions provide
651
+ self-explanatory failure messages for most things without requiring
652
+ any special matchers from the programmer.
653
+
654
+ In the rare case that some extra information would be helpful, it is
655
+ useful to create special objects that respond to the == operator.
656
+
657
+ #### Asserting Nearly Equal with Fuzzy Numbers
658
+
659
+ Operations on floating point numbers rarely create numbers that are
660
+ exactly equal, therefore it is useful to assert that two floating
661
+ point numbers are nearly equal. We do that by creating a fuzzy number
662
+ that has a looser interpretation of what it means to be equal.
663
+
664
+ For example, the following asserts that the square root of 10 is about
665
+ 3.1523 with an accuracy of 1 percent.
666
+
667
+ ```ruby
668
+ Then { Math.sqrt(10) == about(3.1623).percent(1) }
669
+ ```
670
+
671
+ As long as the real value of <code>Math.sqrt(10)</code> is within plus
672
+ or minus 1% of 3.1623 (i.e. 3.1623 +/- 0.031623), then the assertion
673
+ will pass.
674
+
675
+ There are several ways of creating fuzzy numbers:
676
+
677
+ * <code>about(n).delta(d)</code> -- A fuzzy number matching the range
678
+ (n-d)..(n+d)
679
+
680
+ * <code>about(n).percent(p)</code> -- A fuzzy number matching the
681
+ range (n-(n*p/100)) .. (n+(n*p/100))
682
+
683
+ * <code>about(n).epsilon(neps)</code> -- A fuzzy number matching the
684
+ range (n-(neps*e)) .. (n+(neps*e)), where e is the difference
685
+ between 1.0 and the next smallest floating point number.
686
+
687
+ * <code>about(n)</code> -- Same as <code>about(n).epsilon(10)</code>.
688
+
689
+ When the file <code>given/fuzzy_shortcuts</code> is required,
690
+ the following unicode shortcut methods are added to Numeric to create
691
+ fuzzy numbers.
692
+
693
+ * <code>n.±(del)</code> is the same as <code>about(n).delta(del)</code>
694
+
695
+ * <code>n.‰(percentage)</code> is the same as <code>about(n).percent(percentage)</code>
696
+
697
+ * <code>n.€(neps)</code> is the same as <code>about(n).epsilon(neps)</code>
698
+
699
+ * <code>n.±</code>, <code>n.‰</code>, and <code>n.€</code> are all
700
+ the same as <code>about(n)</code>
701
+
702
+ #### Detecting Exceptions
703
+
704
+ The RSpec matcher used for detecting exceptions will work with natural
705
+ assertions out of the box. Just check for equality against the
706
+ <code>Failure()</code> method return value.
707
+
708
+ For example, the following two Then clauses are equivalent:
709
+
710
+ ```ruby
711
+ # Using an RSpec matcher
712
+ Then { result.should have_failed(StandardError, /message/) }
713
+
714
+ # Using natural assertions
715
+ Then { result == Failure(StandardError, /message/) }
716
+ ```
717
+
718
+ ### Processing Natural Assertions
719
+
720
+ When natural assertions are enabled, they are only used if all of the
721
+ following are true:
722
+
723
+ 1. The block does not throw an RSpec assertion failure (or any other
724
+ exception for that matter).
725
+
726
+ 1. The block returns false (blocks that return true pass the
727
+ assertion and don't need a failure message).
728
+
729
+ 1. The block does not use the native frameworks assertions or
730
+ expectations (e.g. RSpec's _should_ or _expect_ methods, or
731
+ Minitest's _assert\_xxx_ or _must\_xxx_ methods).
732
+
733
+ Detecting that last point (the use of _should_ and _expect_) is done
734
+ by modifying the RSpec runtime to report uses of _should_ and
735
+ _expect_.
736
+
737
+ ### Platform Support
738
+
739
+ Natural assertions use the Ripper library to parse the failing
740
+ condition and find all the sub-expression values upon a failure.
741
+ Currently Ripper is not fully supported on JRuby 1.7.4. Charles Nutter
742
+ has said that Ripper support is coming soon and may arrive soon. Until
743
+ then, natural assertions are disabled when running under JRuby. Never
744
+ fear, JRuby supports all the other features of rspec-given and will
745
+ work just fine.
746
+
747
+ ### Non-Spec Assertions
748
+
749
+ Given also provides three assertions meant to be used in
750
+ non-test/non-spec code. For example, here is a square root function
751
+ decked out with pre and post-condition assertions.
752
+
753
+ ```ruby
754
+ require 'given/assertions'
755
+ require 'given/fuzzy_number'
756
+
757
+ include Given::Assertions
758
+ include Given::Fuzzy
759
+
760
+ def sqrt(n)
761
+ Precondition { n >= 0 }
762
+ result = Math.sqrt(n)
763
+ Postcondition { result ** 2 == about(n) }
764
+ result
765
+ end
766
+ ```
767
+
768
+ To use the non-testing assertions, you need to require the
769
+ 'given/assertions' file and then include the
770
+ <code>Given::Assertions</code> module into what ever class is using
771
+ the
772
+ <code>Precondition</code>/<code>Postcondition</code>/<code>Assert</code>
773
+ methods. The code block for these assertions should always be a
774
+ regular Ruby true/false value (the <code>should</code> and
775
+ <code>expect</code> methods from RSpec are not available).
776
+
777
+ Note that this example also uses the fuzzy number matching, but that
778
+ is not required for the assertions themselves.
779
+
780
+ The assertion methods are:
781
+
782
+ * <code>Precondition { bool }</code> -- If the block evaluates to
783
+ false (or nil), throw a Given::Assertions::PreconditionError.
784
+
785
+ * <code>Postcondition { bool }</code> -- If the block evaluates to
786
+ false (or nil), throw a Given::Assertions::PostconditionError.
787
+
788
+ * <code>Assert { bool }</code> -- If the block evaluates to
789
+ false (or nil), throw a Given::Assertions::AssertError.
790
+
791
+ Both PreconditionError and PostconditionError are subclasses of
792
+ AssertError.
793
+
794
+ You can disable assertion checking with one of the following commands:
795
+
796
+ * <code>Given::Assertions.enable_preconditions bool</code> --
797
+ Enable/Disable precondition assertions.
798
+ (default to enable)
799
+
800
+ * <code>Given::Assertions.enable_postconditions bool</code> --
801
+ Enable/Disable postcondition assertions.
802
+ (default to enable)
803
+
804
+ * <code>Given::Assertions.enable_asserts bool</code> --
805
+ Enable/Disable assert assertions. (default to enable)
806
+
807
+ * <code>Given::Assertions.enable_all bool</code> --
808
+ Enable/Disable all assertions with a single command.
809
+ (default to enable)
810
+
811
+ ### Further Reading
812
+
813
+ Natural assertions were inspired by the [wrong assertion
814
+ library](http://rubygems.org/gems/wrong) by [Alex
815
+ Chaffee](http://rubygems.org/profiles/alexch) and [Steve
816
+ Conover](http://rubygems.org/profiles/sconoversf).
817
+
818
+ ## Configuration
819
+
820
+ If the RSpec format option document, html or textmate is chosen,
821
+ RSpec/Given will automatically add additional source code information to
822
+ the examples to produce better looking output. If you don't care about
823
+ the pretty output and wish to disable source code caching
824
+ unconditionally, then add the following line to your spec helper file:
825
+
826
+ ```ruby
827
+ Given.source_caching_disabled = true
828
+ ```
829
+
830
+ Natural assertions are disabled by default. To globally configure
831
+ natural assertions, add one of the following lines to your spec_helper
832
+ file:
833
+
834
+ ```ruby
835
+ Given.use_natural_assertions # Enable natural assertions
836
+ Given.use_natural_assertions true # Same as above
837
+ Given.use_natural_assertions false # Disable natural assertions
838
+ Given.use_natural_assertions :always # Always process natural assertions
839
+ # ... even when should/expect are detected
840
+ ```
841
+
842
+ # License
843
+
844
+ rspec-given, minitest-given and given_core are available under the MIT
845
+ License. See the MIT-LICENSE file in the source distribution.
846
+
847
+ # History
848
+
849
+ * Version 3.1.0
850
+
851
+ * Add support for Precondition/Postcondition/Assert in non-spec
852
+ code.
853
+
854
+ * Version 3.0.1
855
+
856
+ * Add support for the === operation in natural assertions.
857
+
858
+ * Version 3.0.0
859
+
860
+ * Support for minitest added.
861
+
862
+ * Introduced gem given\_core to contain the common logic between the
863
+ RSpec and Minitest versions. Both the rspec-given gem and the
864
+ minitest-given gem have a dependency on given\_core.
865
+
866
+ * Natural assertions are now enabled by default.
867
+
868
+ * Version 2.4.4
869
+
870
+ * Support for RSpec 2.13 added.
871
+
872
+ * Version 2.4.3
873
+
874
+ * Better natural assertion messages when dealing with multi-line
875
+ output.
876
+
877
+ * Version 2.4.2
878
+
879
+ * Minor adjustment to natural assertion error messages to better
880
+ handle multi-line values.
881
+
882
+ * Remove flog, flay and other development tools from the bundle and
883
+ gemspec. The Rakefile was updated to suggest installing them if
884
+ they are not there.
885
+
886
+ * Version 2.4.1
887
+
888
+ * Fix bug where constants from nested modules were not properly
889
+ accessed.
890
+
891
+ * Version 2.4.0
892
+
893
+ * Add fuzzy number helper methods (with unicode method shortcuts).
894
+
895
+ * Fix bug caused by blank lines in Thens.
896
+
897
+ # Links
898
+
899
+ * Github: [https://github.com/jimweirich/rspec-given](https://github.com/jimweirich/rspec-given)
900
+ * Clone URL: git://github.com/jimweirich/rspec-given.git
901
+ * Bug/Issue Reporting: [https://github.com/jimweirich/rspec-given/issues](https://github.com/jimweirich/rspec-given/issues)
902
+ * Continuous Integration: [http://travis-ci.org/#!/jimweirich/rspec-given](http://travis-ci.org/#!/jimweirich/rspec-given)
data/Rakefile CHANGED
@@ -128,7 +128,7 @@ file "README.md" => ["examples/stack/stack_spec.rb", "lib/given/version.rb"] do
128
128
  while line = ins.gets
129
129
  case state
130
130
  when :copy
131
- if line =~ /rspec-given, version +\d+(\.(\d+|beta))+/i
131
+ if line =~ /rspec-given, minitest-given, and given-core, version +\d+(\.(\d+|beta))+/i
132
132
  line.gsub!(/version +\d+(\.(\d+|beta))+/i, "version #{Given::VERSION}")
133
133
  outs.puts line
134
134
  elsif line =~ /^<pre>/
@@ -1,42 +1,47 @@
1
- require 'given/assertions'
2
- require 'given/fuzzy_number'
1
+ require 'given/module_methods'
3
2
 
4
- include Given::Assertions
5
- include Given::Fuzzy
3
+ if Given::NATURAL_ASSERTIONS_SUPPORTED
6
4
 
7
- def sqrt(n)
8
- Precondition { n >= 0 }
9
- result = Math.sqrt(n)
10
- Postcondition { result ** 2 == about(n) }
11
- result
12
- end
5
+ require 'given/assertions'
6
+ require 'given/fuzzy_number'
13
7
 
14
- def sqrt_bad_postcondition(n)
15
- Precondition { n >= 0 }
16
- result = Math.sqrt(n)
17
- Postcondition { result ** 2 == about(n+1) }
18
- result
19
- end
8
+ include Given::Assertions
9
+ include Given::Fuzzy
20
10
 
21
- def use_assert(n)
22
- Assert { n == 1 }
23
- end
11
+ def sqrt(n)
12
+ Precondition { n >= 0 }
13
+ result = Math.sqrt(n)
14
+ Postcondition { result ** 2 == about(n) }
15
+ result
16
+ end
24
17
 
25
- def should_fail
26
- begin
27
- yield
28
- fail "Expected error"
29
- rescue Given::Assertions::AssertError => ex
30
- true
18
+ def sqrt_bad_postcondition(n)
19
+ Precondition { n >= 0 }
20
+ result = Math.sqrt(n)
21
+ Postcondition { result ** 2 == about(n+1) }
22
+ result
31
23
  end
32
- end
33
24
 
34
- sqrt(1)
35
- sqrt(2)
36
- sqrt(0)
25
+ def use_assert(n)
26
+ Assert { n == 1 }
27
+ end
28
+
29
+ def should_fail
30
+ begin
31
+ yield
32
+ fail "Expected error"
33
+ rescue Given::Assertions::AssertError => ex
34
+ true
35
+ end
36
+ end
37
37
 
38
- should_fail { sqrt(-1) }
39
- should_fail { sqrt_bad_postcondition(1) }
38
+ sqrt(1)
39
+ sqrt(2)
40
+ sqrt(0)
40
41
 
41
- use_assert(1)
42
- should_fail { use_assert(0) }
42
+ should_fail { sqrt(-1) }
43
+ should_fail { sqrt_bad_postcondition(1) }
44
+
45
+ use_assert(1)
46
+ should_fail { use_assert(0) }
47
+ end
@@ -1,7 +1,10 @@
1
+ require 'spec_helper'
1
2
  require 'rspec/given'
2
3
  require 'given/assertions'
3
4
 
4
5
  describe Given::Assertions do
6
+ use_natural_assertions_if_supported
7
+
5
8
  Given { extend Given::Assertions }
6
9
 
7
10
  describe "Assert { }" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-given
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Weirich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-30 00:00:00.000000000 Z
11
+ date: 2013-08-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: given_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.1.0
19
+ version: 3.1.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 3.1.0
26
+ version: 3.1.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -50,6 +50,7 @@ files:
50
50
  - Gemfile.lock
51
51
  - MIT-LICENSE
52
52
  - README.md
53
+ - README.old
53
54
  - Rakefile
54
55
  - TODO
55
56
  - lib/given.rb