rspec-given 2.3.0.beta.3 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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