rspec-given 2.3.0.beta.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # rspec-given
2
2
 
3
- Covering rspec-given, version 2.3.0.beta.3.
3
+ Covering rspec-given, version 2.3.0.
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
@@ -305,14 +305,19 @@ stick with _Then_ clauses.
305
305
 
306
306
  The _Invariant_ clause is a new idea that doesn't have an analog in
307
307
  RSpec or Test::Unit. The invariant allows you specify things that must
308
- always be true in the scope of the invariant. In the stack example,
309
- <tt>empty?</tt> is defined in term of <tt>size</tt>. Whenever
310
- <tt>size</tt> is 0, <tt>empty?</tt> should be true. Whenever
311
- <tt>size</tt> is non-zero, <tt>empty?</tt> should be false.
308
+ always be true in the scope of the invariant. In the stack example, the method
309
+ <tt>empty?</tt> is defined in term of <tt>size</tt>.
310
+
311
+ ```ruby
312
+ Invariant { stack.empty? == (stack.depth == 0) }
313
+ ```
314
+
315
+ This invariant states that <code>empty?</code> is true if and only if
316
+ the stack depth is zero, and that assertion is checked at every _Then_
317
+ clause that is in the same scope.
312
318
 
313
319
  You can conceptually think of an _Invariant_ clause as a _Then_ block
314
320
  that automatically gets added to every _Then_ within its scope.
315
-
316
321
  Invariants nested within a context only apply to the _Then_ clauses
317
322
  that are in the scope of that context.
318
323
 
@@ -325,10 +330,40 @@ Notes:
325
330
  represented in the RSpec formatted output (e.g. the '--format html'
326
331
  option).
327
332
 
333
+ ## Execution Ordering
334
+
335
+ When running the test for a specific _Then_ clause, the following will
336
+ be true:
337
+
338
+ * The _Given_ clauses will be run in the order that they are
339
+ specified, from the outermost scope to the innermost scope
340
+ containing the _Then_.
341
+
342
+ * All of the _Given_ clauses in all of the relevant scopes will run
343
+ before the first (outermost) _When_ clause in those same scopes.
344
+ That means that the _When_ code can assume that the givens have been
345
+ established, even if the givens are in a more nested scope than the
346
+ When.
347
+
348
+ * _When_ clauses and RSpec _before_ blocks will be executed in the
349
+ order that they are specified, from the outermost block to the
350
+ innermost block. This makes _before_ blocks an excellent choice
351
+ when writing narrative tests to specify actions that happen between
352
+ the "whens" of a narrative.
353
+
354
+ Note that the ordering between _Given_ clauses and _before_ blocks are
355
+ a not strongly specified. Hoisting a _When_ clause out of an inner
356
+ scope to an outer scope may change the ordering of when the _Given_
357
+ clause runs in relation to a _before_ block (the hoisting will cause
358
+ the givens to possibly run earlier). Because of this, do not split
359
+ order dependent code between _Given_ clauses and _before_ blocks.
360
+
328
361
  ## Natural Assertions
329
362
 
330
363
  **NOTE:** <em>Natural assertions are an experimental feature of
331
- RSpec/Given. They are currently disabled by default.</em>
364
+ RSpec/Given. They are currently disabled by default. They can be
365
+ enabled by a simple configuration option (see "use_natural_assertions"
366
+ below).</em>
332
367
 
333
368
  RSpec/Given now supports the use of "natural assertions" in _Then_,
334
369
  _And_, and _Invariant_ blocks. Natural assertions are just Ruby
@@ -399,12 +434,14 @@ Keep the following in mind when using Natural Assertions.
399
434
  to join the conditions into a single expression (and the failure
400
435
  message will breakdown the values for each part).
401
436
 
402
- * Natural assertions must be **idempotent** (that means they don't
403
- change anything). Since the natural assertion error message contains
437
+ * Then clauses need be **idempotent**. This is true in general, but it
438
+ is particularly important for Natural assertions to obey this
439
+ restriction. This means that assertions in a Then clause should not
440
+ change anything. Since the natural assertion error message contains
404
441
  the values of all the subexpressions, the expression and its
405
- subexpressions will be evaluated multiple times. If the block is not
406
- idempotent, you will get changing answers as the subexpressions are
407
- evaluated.
442
+ subexpressions will be evaluated multiple times. If the Then clause
443
+ is not idempotent, you will get changing answers as the
444
+ subexpressions are evaluated.
408
445
 
409
446
  That last point is important. If you write code like this:
410
447
 
@@ -433,6 +470,9 @@ like this is good:
433
470
  end
434
471
  ```
435
472
 
473
+ It is good to note that non-idempotent assertions will also cause
474
+ problems with And clauses.
475
+
436
476
  ### Mixing Natural Assertions and RSpec Assertions
437
477
 
438
478
  Natural assertions and RSpec assertions for the most part can be
@@ -463,49 +503,79 @@ will not process natural assertions.
463
503
  See the **configuration** section below to see how to enable natural
464
504
  assertions project wide.
465
505
 
466
- ### Processing Natural Assertions
506
+ ### Matchers and Natural Assertions
467
507
 
468
- When natural assertions are enabled, they are only used if:
508
+ In RSpec, matchers are used to provide nice, readable error messages
509
+ when an assertion is not met. Natural assertions provide
510
+ self-explanatory failure messages for most things without requiring
511
+ any special matchers from the programmer.
469
512
 
470
- 1. The block does not throw an RSpec assertion failure (or any other
471
- exception for that matter).
513
+ In the rare case that some extra information would be hepful, it is
514
+ useful to create special objects that respond to the == operator.
472
515
 
473
- 1. The block returns false (blocks that return true pass the
474
- assertion and don't need a failure message).
516
+ #### Asserting Nearly Equal
475
517
 
476
- 1. The block does not directly use RSpec's _should_ or _expect_
477
- method.
518
+ Operations on floating point numbers rarely create numbers that are
519
+ exactly equal, therefore it is useful to assert that two floating
520
+ point numbers are nearly equal.
478
521
 
479
- Detecting that last point (the use of _should_ and _expect_) is done
480
- by examining the source of the block. However it is not always
481
- possible to correctly determine if _should_ and _expect_ are used
482
- merely from the source. Fortunately you can always override the
483
- automatic detection by either forcing natural assertions (with
484
- :always) or disabling them (with false).
522
+ For example, the following asserts that the square root of 10 is about
523
+ 3.1523 with an accuracy of 0.1 percent.
485
524
 
486
525
  ```ruby
487
- # Then uses a non-RSpec version of "should" on
488
- context "sample" do
489
- use_natural_assertions :always
490
- Then { obj.should } # Non-rspec should is called
491
- end
526
+ Then { Math.sqrt(10) == about(3.1623).percent(1) }
492
527
  ```
493
528
 
529
+ As long as the real value of <code>Math.sqrt(10)</code> is within plus
530
+ or minus 1% of 3.1623 (i.e. 3.1623 +/- 0.0031623), then the assertion
531
+ will pass.
532
+
533
+ There are several ways of creating approximate numbers:
534
+
535
+ * <code>about(n).delta(d)</code> -- A fuzzy number matching the range
536
+ (n-d)..(n+d)
537
+
538
+ * <code>about(n).percent(p)</code> -- A fuzzy number matching the
539
+ range (n-(n*p/100)) .. (n+(n*p/100))
540
+
541
+ * <code>about(n).epsilon(neps)</code> -- A fuzzy number matching the
542
+ range (n-(neps*e)) .. (n+(neps*e)), where e is the difference
543
+ between 1.0 and the next smallest floating point number.
544
+
545
+ * <code>about(n)</code> -- Same as <code>about(n).epsilon(10)</code>.
546
+
547
+ #### Detecting Exceptions
548
+
549
+ The RSpec matcher used for detecting exceptions will work with natural
550
+ assertions out of the box. Just check for equality against the
551
+ <code>have_failed</code> return value.
552
+
553
+ For example, the following two Then clauses are equivalent:
554
+
494
555
  ```ruby
495
- # Then does not call should directly, so disable natural assertions
496
- context "sample" do
497
- use_natural_assertions false
498
- Then { check_validations(obj) } # check_validations calls "should" internally
499
- end
556
+ # Using an RSpec matcher
557
+ Then { result.should have_failed(StandardError, /message/) }
500
558
 
501
- # You can also just not use a Then for that condition.
502
- context "another sample" do
503
- it "checks validations" do
504
- check_validations(obj)
505
- end
506
- end
559
+ # Using natural assertions
560
+ Then { result == have_failed(StandardError, /message/) }
507
561
  ```
508
562
 
563
+ ### Processing Natural Assertions
564
+
565
+ When natural assertions are enabled, they are only used if:
566
+
567
+ 1. The block does not throw an RSpec assertion failure (or any other
568
+ exception for that matter).
569
+
570
+ 1. The block returns false (blocks that return true pass the
571
+ assertion and don't need a failure message).
572
+
573
+ 1. The block does not use RSpec's _should_ or _expect_ methods.
574
+
575
+ Detecting that last point (the use of _should_ and _expect_) is done
576
+ by modifying the RSpec runtime to report uses of _should_ and
577
+ _expect_.
578
+
509
579
  ### Further Reading
510
580
 
511
581
  Natural assertions were inspired by the [wrong assertion
@@ -23,6 +23,18 @@ describe "Natural Assertions" do
23
23
  (puts "Ha ha world", ! true)
24
24
  }
25
25
 
26
+ Then { Math.sqrt(10) == about(3.1623).percent(0.0001) }
27
+
28
+ describe "Error Examples" do
29
+ When(:result) { fail "OUCH" }
30
+ Then { result == :ok }
31
+ end
32
+
33
+ describe "Non-Error Failures" do
34
+ When(:result) { :ok }
35
+ Then { result == have_failed(StandardError, /^O/) }
36
+ end
37
+
26
38
  context "Incorrect non-idempotent conditions" do
27
39
  Given(:ary) { [1, 2, 3] }
28
40
  Then { ary.delete(1) == nil }
@@ -1,5 +1,6 @@
1
1
  require 'rspec'
2
2
  require 'rspec/given/extensions'
3
+ require 'rspec/given/fuzzy_number'
3
4
  require 'rspec/given/have_failed'
4
5
  require 'rspec/given/module_methods'
5
6
 
@@ -7,6 +8,7 @@ RSpec.configure do |c|
7
8
  c.extend(RSpec::Given::ClassExtensions)
8
9
  c.include(RSpec::Given::InstanceExtensions)
9
10
  c.include(RSpec::Given::HaveFailed)
11
+ c.include(RSpec::Given::Fuzzy)
10
12
 
11
13
  c.backtrace_clean_patterns << /lib\/rspec\/given/
12
14
 
@@ -159,7 +159,7 @@ module RSpec
159
159
  # Scenario "a scenario description" do ... end
160
160
  #
161
161
  def Scenario(description, &block)
162
- file, line = eval("[__LINE__, __FILE__]", block.binding)
162
+ file, line = eval("[__FILE__, __LINE__]", block.binding)
163
163
  puts "WARNING: Scenario is deprecated, please use either describe or context (#{file}:#{line})"
164
164
  context(description, &block)
165
165
  end
@@ -190,7 +190,7 @@ module RSpec
190
190
  # Given!(:name) { ... code ... }
191
191
  #
192
192
  def Given!(name, &block)
193
- let!(name, &block)
193
+ let(name, &block)
194
194
  _rgc_givens << _rgc_trigger_given(name)
195
195
  end
196
196
 
@@ -14,9 +14,29 @@ module RSpec
14
14
  klass == Failure
15
15
  end
16
16
 
17
- def method_missing(sym, *args, &block)
17
+ def ==(other)
18
+ if other.is_a?(::RSpec::Given::HaveFailed::HaveFailedMatcher)
19
+ other.matches?(self)
20
+ else
21
+ die
22
+ end
23
+ end
24
+
25
+ def !=(other)
26
+ if other.is_a?(::RSpec::Given::HaveFailed::HaveFailedMatcher)
27
+ ! other.matches?(self)
28
+ else
29
+ die
30
+ end
31
+ end
32
+
33
+ def die
18
34
  ::Kernel.raise @exception
19
35
  end
36
+
37
+ def method_missing(sym, *args, &block)
38
+ die
39
+ end
20
40
  end
21
41
  end
22
42
  end
@@ -0,0 +1,64 @@
1
+
2
+ module RSpec
3
+ module Given
4
+ module Fuzzy
5
+ class FuzzyNumber
6
+
7
+ DEFAULT_EPSILON = 10 * Float::EPSILON
8
+
9
+ attr_reader :exact_value, :delta_amount
10
+
11
+ def initialize(exact_value)
12
+ @exact_value = exact_value
13
+ @delta_amount = exact_value * DEFAULT_EPSILON
14
+ end
15
+
16
+ # Low limit of the fuzzy number.
17
+ def low_limit
18
+ exact_value - delta_amount
19
+ end
20
+
21
+ # High limit of the fuzzy number.
22
+ def high_limit
23
+ exact_value + delta_amount
24
+ end
25
+
26
+ # True if the other number is in range of the fuzzy number.
27
+ def ==(other)
28
+ (other - exact_value).abs <= delta_amount
29
+ end
30
+
31
+ def to_s
32
+ "<Approximately #{exact_value} +/- #{delta_amount}>"
33
+ end
34
+
35
+ # Set the delta for a fuzzy number.
36
+ def delta(delta)
37
+ @delta_amount = delta.abs
38
+ self
39
+ end
40
+
41
+ # Specifying a percentage of the exact number to be used in
42
+ # setting the delta.
43
+ def percent(percentage)
44
+ delta(exact_value * (percentage / 100.0))
45
+ end
46
+
47
+ # Specifying the number of epsilons to be used in setting the
48
+ # delta.
49
+ def epsilon(neps)
50
+ delta(exact_value * (neps * Float::EPSILON))
51
+ end
52
+ end
53
+
54
+ # Create an approximate number that is approximately equal to
55
+ # the given number, plus or minus the delta value. If no
56
+ # explicit delta is given, then the default delta that is about
57
+ # 10X the size of the smallest possible change in the given
58
+ # number will be used.
59
+ def about(*args)
60
+ FuzzyNumber.new(*args)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -24,6 +24,10 @@ module RSpec
24
24
  super(lambda { })
25
25
  end
26
26
  end
27
+
28
+ def to_s
29
+ "<Failure matching #{@expected_error}: #{@expected_message.inspect}>"
30
+ end
27
31
  end
28
32
 
29
33
  else
@@ -36,6 +40,10 @@ module RSpec
36
40
  super(lambda { })
37
41
  end
38
42
  end
43
+
44
+ def to_s
45
+ "<FailureMatcher on #{@expected_error}: #{@expected_message.inspect}>"
46
+ end
39
47
  end
40
48
 
41
49
  end
@@ -58,6 +66,10 @@ module RSpec
58
66
  def have_failed(error=Exception, message=nil, &block)
59
67
  HaveFailedMatcher.new(error, message, &block)
60
68
  end
69
+ alias have_raised have_failed
70
+
71
+ def failure(error=Exception, message=nil, &block)
72
+ end
61
73
  end
62
74
  end
63
75
  end
@@ -4,8 +4,6 @@ module RSpec
4
4
  VERSION_MAJOR = 2,
5
5
  VERSION_MINOR = 3,
6
6
  VERSION_BUILD = 0,
7
- 'beta',
8
- VERSION_BETA = 3,
9
7
  ]
10
8
  VERSION = VERSION_NUMBERS.join(".")
11
9
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-given
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0.beta.3
5
- prerelease: 6
4
+ version: 2.3.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Jim Weirich
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-05 00:00:00.000000000 Z
12
+ date: 2013-01-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -112,6 +112,7 @@ files:
112
112
  - lib/rspec/given/extensions.rb
113
113
  - lib/rspec/given/failure.rb
114
114
  - lib/rspec/given/file_cache.rb
115
+ - lib/rspec/given/fuzzy_number.rb
115
116
  - lib/rspec/given/have_failed.rb
116
117
  - lib/rspec/given/line_extractor.rb
117
118
  - lib/rspec/given/module_methods.rb
@@ -153,9 +154,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
153
154
  required_rubygems_version: !ruby/object:Gem::Requirement
154
155
  none: false
155
156
  requirements:
156
- - - ! '>'
157
+ - - ! '>='
157
158
  - !ruby/object:Gem::Version
158
- version: 1.3.1
159
+ version: '0'
159
160
  requirements: []
160
161
  rubyforge_project: given
161
162
  rubygems_version: 1.8.24