rspec-given 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,34 +1,71 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ activesupport (3.2.12)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ blankslate (3.1.2)
4
8
  bluecloth (2.2.0)
5
- diff-lcs (1.1.3)
6
- flay (2.0.1)
9
+ charlock_holmes (0.6.9.1)
10
+ diff-lcs (1.2.1)
11
+ escape_utils (0.2.4)
12
+ ffi (1.0.11)
13
+ flay (2.1.0)
7
14
  ruby_parser (~> 3.0)
8
15
  sexp_processor (~> 4.0)
9
- flog (3.2.1)
16
+ flog (3.2.2)
10
17
  ruby_parser (~> 3.1, > 3.1.0)
11
18
  sexp_processor (~> 4.0)
12
- ghpreview (0.0.2)
19
+ gemoji (1.4.0)
20
+ ghpreview (0.0.6)
21
+ github-linguist (= 2.1)
22
+ html-pipeline (= 0.0.6)
13
23
  httpclient
14
24
  listen
15
25
  rb-fsevent
16
- httpclient (2.3.0.1)
17
- listen (0.6.0)
18
- rake (0.9.2.2)
19
- rb-fsevent (0.9.2)
20
- rspec (2.12.0)
21
- rspec-core (~> 2.12.0)
22
- rspec-expectations (~> 2.12.0)
23
- rspec-mocks (~> 2.12.0)
24
- rspec-core (2.12.0)
25
- rspec-expectations (2.12.0)
26
- diff-lcs (~> 1.1.3)
27
- rspec-mocks (2.12.0)
26
+ github-linguist (2.1.0)
27
+ charlock_holmes (~> 0.6.6)
28
+ escape_utils (~> 0.2.3)
29
+ mime-types (~> 1.18)
30
+ pygments.rb (~> 0.2.13)
31
+ github-markdown (0.5.3)
32
+ html-pipeline (0.0.6)
33
+ activesupport (>= 2)
34
+ escape_utils (~> 0.2)
35
+ gemoji (~> 1.0)
36
+ github-linguist (~> 2.1)
37
+ github-markdown (~> 0.5)
38
+ nokogiri (~> 1.4)
39
+ rinku (~> 1.7)
40
+ sanitize (~> 2.0)
41
+ httpclient (2.3.3)
42
+ i18n (0.6.4)
43
+ listen (0.7.3)
44
+ mime-types (1.21)
45
+ multi_json (1.6.1)
46
+ nokogiri (1.5.6)
47
+ pygments.rb (0.2.13)
48
+ rubypython (~> 0.5.3)
49
+ rake (10.0.3)
50
+ rb-fsevent (0.9.3)
51
+ rinku (1.7.2)
52
+ rspec (2.13.0)
53
+ rspec-core (~> 2.13.0)
54
+ rspec-expectations (~> 2.13.0)
55
+ rspec-mocks (~> 2.13.0)
56
+ rspec-core (2.13.1)
57
+ rspec-expectations (2.13.0)
58
+ diff-lcs (>= 1.1.3, < 2.0)
59
+ rspec-mocks (2.13.0)
28
60
  ruby_parser (3.1.1)
29
61
  sexp_processor (~> 4.1)
30
- sexp_processor (4.1.3)
31
- sorcerer (0.3.7)
62
+ rubypython (0.5.3)
63
+ blankslate (>= 2.1.2.3)
64
+ ffi (~> 1.0.7)
65
+ sanitize (2.0.3)
66
+ nokogiri (>= 1.4.4, < 1.6)
67
+ sexp_processor (4.1.5)
68
+ sorcerer (0.3.10)
32
69
 
33
70
  PLATFORMS
34
71
  ruby
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # rspec-given
2
2
 
3
- Covering rspec-given, version 2.4.0.
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, version 2.4.1.
4
8
 
5
9
  rspec-given is an RSpec extension to allow Given/When/Then notation in
6
10
  RSpec specifications. It is a natural extension of the experimental
@@ -38,7 +42,7 @@ describe Stack do
38
42
  Given(:stack) { stack_with(initial_contents) }
39
43
  Invariant { stack.empty?.should == (stack.depth == 0) }
40
44
 
41
- context "when empty" do
45
+ context "with no items" do
42
46
  Given(:initial_contents) { [] }
43
47
  Then { stack.depth.should == 0 }
44
48
 
@@ -641,6 +645,19 @@ file:
641
645
  # ... even when should/expect are detected
642
646
  ```
643
647
 
648
+ # History
649
+
650
+ * Version 2.4.1
651
+
652
+ * Fix bug where constants from nested modules were not properly
653
+ accessed.
654
+
655
+ * Version 2.4.0
656
+
657
+ * Add fuzzy number helper methods (with unicode method shortcuts).
658
+
659
+ * Fix bug caused by blank lines in Thens.
660
+
644
661
  # Links
645
662
 
646
663
  * Github: [https://github.com/jimweirich/rspec-given](https://github.com/jimweirich/rspec-given)
data/Rakefile CHANGED
@@ -66,7 +66,9 @@ task :examples1 => [:verify_rspec1] do
66
66
  sh "spec examples/stack/stack_spec1.rb"
67
67
  end
68
68
 
69
- EXAMPLES = FileList['examples/**/*_spec.rb'].exclude('examples/failing/*.rb')
69
+ EXAMPLES = FileList['examples/**/*_spec.rb'].
70
+ exclude('examples/failing/*.rb').
71
+ exclude('examples/integration/failing/*.rb')
70
72
  FAILING_EXAMPLES = FileList['examples/failing/**/*_spec.rb']
71
73
 
72
74
  desc "Run the examples in RSpec 2"
@@ -0,0 +1,9 @@
1
+ require 'rspec/given'
2
+
3
+ describe "Then with nesting" do
4
+ use_natural_assertions
5
+ Given(:index) { 1 }
6
+ Given(:value) { "X" }
7
+ Given(:array) { ["a", "b", "c"] }
8
+ Then { array[index].upcase == value }
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'rspec/given'
2
+
3
+ module Nesting
4
+ X = 1
5
+ end
6
+
7
+ module Nesting
8
+ describe "Then with nesting" do
9
+ use_natural_assertions
10
+ Given(:z) { 2 }
11
+ Then { X == z }
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require 'rspec/given'
2
+
3
+ describe "Then with nesting" do
4
+ use_natural_assertions
5
+ def self.xyz
6
+ nil
7
+ end
8
+ Then { xyz }
9
+ end
@@ -0,0 +1,38 @@
1
+ require 'example_helper'
2
+ require 'open3'
3
+
4
+ describe "Failing Messages" do
5
+ use_natural_assertions_if_supported
6
+
7
+ IOS = Struct.new(:out, :err)
8
+
9
+ def run_spec(filename)
10
+ inn, out, err, wait = Open3.popen3("rspec", "examples/integration/failing/#{filename}")
11
+ IOS.new(out.read, err.read)
12
+ end
13
+
14
+ When(:ios) { run_spec(failing_test) }
15
+
16
+ context "when referencing constants from nested modules" do
17
+ Given(:failing_test) { "module_nesting_spec.rb" }
18
+ Then { ios.err == "" }
19
+ And { ios.out !~ /uninitialized constant RSpec::Given::InstanceExtensions::X/ }
20
+ end
21
+
22
+ context "when referencing undefined methods" do
23
+ Given(:failing_test) { "undefined_method_spec.rb" }
24
+ Then { ios.err == "" }
25
+ And { ios.out =~ /undefined local variable or method `xyz'/ }
26
+ end
27
+
28
+ context "when breaking down expressions" do
29
+ Given(:failing_test) { "eval_subexpression_spec.rb" }
30
+ Then { ios.err == "" }
31
+ And { ios.out =~ /false *<- array\[index\]\.upcase == value$/ }
32
+ And { ios.out =~ /"B" *<- array\[index\].upcase$/ }
33
+ And { ios.out =~ /"b" *<- array\[index\]$/ }
34
+ And { ios.out =~ /\["a", "b", "c"\] *<- array$/ }
35
+ And { ios.out =~ /1 *<- index$/ }
36
+ And { ios.out =~ /"X" *<- value$/ }
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ require 'example_helper'
2
+
3
+ describe "Failing Messages" do
4
+
5
+ end
@@ -78,7 +78,7 @@ module RSpec
78
78
  def _rg_check_invariants # :nodoc:
79
79
  _rg_contexts.each do |context|
80
80
  context._rgc_invariants.each do |block|
81
- _rg_evaluate(block)
81
+ _rg_evaluate("Invariant", block)
82
82
  end
83
83
  end
84
84
  end
@@ -86,7 +86,7 @@ module RSpec
86
86
  def _rg_check_ands # :nodoc:
87
87
  return if self.class._rgc_context_info[:and_ran]
88
88
  self.class._rgc_and_blocks.each do |block|
89
- _rg_evaluate(block)
89
+ _rg_evaluate("And", block)
90
90
  end
91
91
  self.class._rgc_context_info[:and_ran] = true
92
92
  end
@@ -95,16 +95,16 @@ module RSpec
95
95
  def _rg_then(&block) # :nodoc:
96
96
  _rg_establish_givens
97
97
  _rg_check_invariants
98
- _rg_evaluate(block)
98
+ _rg_evaluate("Then", block)
99
99
  _rg_check_ands
100
100
  end
101
101
 
102
102
  # Evaluate a Then, And, or Invariant assertion.
103
- def _rg_evaluate(block) # :nodoc:
103
+ def _rg_evaluate(clause_type, block) # :nodoc:
104
104
  RSpec::Given.matcher_called = false
105
105
  passed = instance_eval(&block)
106
106
  if ! passed && _rg_na_configured? && ! RSpec::Given.matcher_called
107
- nassert = NaturalAssertion.new(block, binding, self.class._rgc_lines)
107
+ nassert = NaturalAssertion.new(clause_type, block, self, self.class._rgc_lines)
108
108
  RSpec::Given.fail_with nassert.message if _rg_need_na_message?(nassert)
109
109
  end
110
110
  end
@@ -1,7 +1,8 @@
1
1
  module RSpec
2
2
  module Given
3
3
  # Does this platform support natural assertions?
4
- NATURAL_ASSERTIONS_SUPPORTED = ! defined?(JRUBY_VERSION)
4
+ RBX_IN_USE = (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx')
5
+ NATURAL_ASSERTIONS_SUPPORTED = ! defined?(JRUBY_VERSION) && ! RBX_IN_USE
5
6
 
6
7
  def self.matcher_called
7
8
  @_matcher_called
@@ -29,9 +29,10 @@ module RSpec
29
29
 
30
30
  class NaturalAssertion
31
31
 
32
- def initialize(block, env, line_extractor)
32
+ def initialize(clause_type, block, example, line_extractor)
33
+ @clause_type = clause_type
33
34
  @block = block
34
- @env = env
35
+ @example = example
35
36
  @line_extractor = line_extractor
36
37
  set_file_and_line
37
38
  end
@@ -47,13 +48,18 @@ module RSpec
47
48
  end
48
49
 
49
50
  def message
50
- @output = "Then expression failed at #{source_line}\n"
51
+ @output = "#{@clause_type} expression failed at #{source_line}\n"
52
+ @output << "Failing expression: #{source.strip}\n" if @clause_type != "Then"
51
53
  explain_failure
52
54
  display_pairs(expression_value_pairs)
53
55
  @output << "\n"
54
56
  @output
55
57
  end
56
58
 
59
+ def evaluate(expr_string)
60
+ eval_in_context(expr_string)
61
+ end
62
+
57
63
  private
58
64
 
59
65
  def using_should?
@@ -90,7 +96,7 @@ module RSpec
90
96
 
91
97
  def expression_value_pairs
92
98
  assertion_subexpressions.map { |exp|
93
- [exp, eval_in(exp, @env)]
99
+ [exp, eval_string(exp)]
94
100
  }
95
101
  end
96
102
 
@@ -125,40 +131,59 @@ module RSpec
125
131
  end
126
132
 
127
133
  def then_block?(sexp)
128
- sexp.first == :program &&
129
- sexp[1].first == :stmts_add &&
130
- sexp[1][2].first == :method_add_block &&
131
- (sexp[1][2][2].first == :brace_block || sexp[1][2][2].first == :do_block)
134
+ delve(sexp,0) == :program &&
135
+ delve(sexp,1,0) == :stmts_add &&
136
+ delve(sexp,1,2,0) == :method_add_block &&
137
+ (delve(sexp,1,2,2,0) == :brace_block || delve(sexp,1,2,2,0) == :do_block)
132
138
  end
133
139
 
134
140
  def extract_first_statement(block_sexp)
135
- unless contains_one_statement?(block_sexp)
141
+ if contains_multiple_statements?(block_sexp)
136
142
  source = Sorcerer.source(block_sexp)
137
143
  fail InvalidThenError, "Multiple statements in Then block at #{source_line}\n#{source}"
138
144
  end
139
145
  extract_statement_from_block(block_sexp)
140
146
  end
141
147
 
142
- def contains_one_statement?(block_sexp)
143
- block_sexp[2].first == :stmts_add &&
144
- block_sexp[2][1].first == :stmts_new
148
+ def contains_multiple_statements?(block_sexp)
149
+ !(delve(block_sexp,2,0) == :stmts_add &&
150
+ delve(block_sexp,2,1,0) == :stmts_new)
145
151
  end
146
152
 
147
153
  def extract_statement_from_block(block_sexp)
148
- block_sexp[2][2]
154
+ delve(block_sexp,2,2)
155
+ end
156
+
157
+ # Safely dive into an array with a list of indicies. Return nil
158
+ # if the element doesn't exist, or if the intermediate result is
159
+ # not indexable.
160
+ def delve(ary, *indicies)
161
+ result = ary
162
+ while !indicies.empty? && result
163
+ return nil unless result.respond_to?(:[])
164
+ i = indicies.shift
165
+ result = result[i]
166
+ end
167
+ result
149
168
  end
150
169
 
151
170
  def eval_sexp(sexp)
152
171
  expr = Sorcerer.source(sexp)
153
- eval_in(expr, @env)
172
+ eval_string(expr)
154
173
  end
155
174
 
156
- def eval_in(exp, binding)
157
- eval(exp, binding).inspect
175
+ def eval_string(exp_string)
176
+ eval_in_context(exp_string).inspect
158
177
  rescue StandardError => ex
159
178
  EvalErr.new("#{ex.class}: #{ex.message}")
160
179
  end
161
180
 
181
+ def eval_in_context(exp_string)
182
+ exp_proc = "proc { #{exp_string} }"
183
+ blk = eval(exp_proc, @block.binding)
184
+ @example.instance_eval(&blk)
185
+ end
186
+
162
187
  WRAP_WIDTH = 20
163
188
 
164
189
  def display_pairs(pairs)
@@ -3,7 +3,7 @@ module RSpec
3
3
  VERSION_NUMBERS = [
4
4
  VERSION_MAJOR = 2,
5
5
  VERSION_MINOR = 4,
6
- VERSION_BUILD = 0,
6
+ VERSION_BUILD = 1,
7
7
  ]
8
8
  VERSION = VERSION_NUMBERS.join(".")
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-given
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-03 00:00:00.000000000 Z
12
+ date: 2013-03-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -104,10 +104,10 @@ files:
104
104
  - Gemfile
105
105
  - Gemfile.lock
106
106
  - MIT-LICENSE
107
- - Rakefile
108
107
  - README.md
109
- - README.old
108
+ - Rakefile
110
109
  - lib/rspec-given.rb
110
+ - lib/rspec/given.rb
111
111
  - lib/rspec/given/configure.rb
112
112
  - lib/rspec/given/core.rb
113
113
  - lib/rspec/given/ext/numeric.rb
@@ -123,11 +123,15 @@ files:
123
123
  - lib/rspec/given/natural_assertion.rb
124
124
  - lib/rspec/given/rspec1_given.rb
125
125
  - lib/rspec/given/version.rb
126
- - lib/rspec/given.rb
127
126
  - examples/example_helper.rb
128
127
  - examples/failing/natural_failing_spec.rb
129
128
  - examples/failing/sample_spec.rb
130
129
  - examples/integration/and_spec.rb
130
+ - examples/integration/failing/eval_subexpression_spec.rb
131
+ - examples/integration/failing/module_nesting_spec.rb
132
+ - examples/integration/failing/undefined_method_spec.rb
133
+ - examples/integration/failing_messages_spec.rb
134
+ - examples/integration/failing_spec.rb
131
135
  - examples/integration/focused_line_spec.rb
132
136
  - examples/integration/given_spec.rb
133
137
  - examples/integration/invariant_spec.rb
data/README.old DELETED
@@ -1,649 +0,0 @@
1
- # rspec-given
2
-
3
- Covering rspec-given, version 2.3.2.
4
-
5
- rspec-given is an RSpec extension to allow Given/When/Then notation in
6
- RSpec specifications. It is a natural extension of the experimental
7
- work done on the Given framework. It turns out that 90% of the Given
8
- framework can be trivially implemented on top of RSpec.
9
-
10
- # Why Given/When/Then
11
-
12
- RSpec has done a great job of making specifications more readable for
13
- humans. However, I really like the given / when / then nature of
14
- Cucumber stories and would like to follow the same structure in my
15
- unit tests. rspec-given allows a simple given/when/then structure
16
- RSpec specifications.
17
-
18
- ## Status
19
-
20
- rspec-given is ready for production use.
21
-
22
- ## Example
23
-
24
- Here is a specification written in the rspec-given framework:
25
-
26
- ```ruby
27
- require 'rspec/given'
28
- require 'spec_helper'
29
- require 'stack'
30
-
31
- describe Stack do
32
- def stack_with(initial_contents)
33
- stack = Stack.new
34
- initial_contents.each do |item| stack.push(item) end
35
- stack
36
- end
37
-
38
- Given(:stack) { stack_with(initial_contents) }
39
- Invariant { stack.empty?.should == (stack.depth == 0) }
40
-
41
- context "when empty" do
42
- Given(:initial_contents) { [] }
43
- Then { stack.depth.should == 0 }
44
-
45
- context "when pushing" do
46
- When { stack.push(:an_item) }
47
-
48
- Then { stack.depth.should == 1 }
49
- Then { stack.top.should == :an_item }
50
- end
51
-
52
- context "when popping" do
53
- When(:result) { stack.pop }
54
- Then { result.should have_failed(Stack::UnderflowError, /empty/) }
55
- end
56
- end
57
-
58
- context "with one item" do
59
- Given(:initial_contents) { [:an_item] }
60
-
61
- context "when popping" do
62
- When(:pop_result) { stack.pop }
63
-
64
- Then { pop_result.should == :an_item }
65
- Then { stack.depth.should == 0 }
66
- end
67
- end
68
-
69
- context "with several items" do
70
- Given(:initial_contents) { [:second_item, :top_item] }
71
- Given!(:original_depth) { stack.depth }
72
-
73
- context "when pushing" do
74
- When { stack.push(:new_item) }
75
-
76
- Then { stack.top.should == :new_item }
77
- Then { stack.depth.should == original_depth + 1 }
78
- end
79
-
80
- context "when popping" do
81
- When(:pop_result) { stack.pop }
82
-
83
- Then { pop_result.should == :top_item }
84
- Then { stack.top.should == :second_item }
85
- Then { stack.depth.should == original_depth - 1 }
86
- end
87
- end
88
- end
89
- ```
90
-
91
- Let's talk about the individual statements used in the Given
92
- framework.
93
-
94
- ### Given
95
-
96
- The _Given_ section specifies a starting point, a set of preconditions
97
- that must be true before the code under test is allowed to be run. In
98
- standard test frameworks the preconditions are established with a
99
- combination of setup methods (or :before actions in RSpec) and code in
100
- the test.
101
-
102
- In the example code above the preconditions are started with _Given_
103
- statements. A top level _Given_ (that applies to the entire describe
104
- block) says that one of the preconditions is that there is a stack
105
- with some initial contents.
106
-
107
- Note that initial contents are not specified in the top level describe
108
- block, but are given in each of the nested contexts. By pushing the
109
- definition of "initial_contents" into the nested contexts, we can vary
110
- them as needed for that particular context.
111
-
112
- A precondition in the form "Given(:var) {...}" creates an accessor
113
- method named "var". The accessor is lazily initialized by the code
114
- block. If you want a non-lazy given, use "Given!(:var) {...}".
115
-
116
- A precondition in the form "Given {...}" just executes the code block
117
- for side effects. Since there is no accessor, the code block is
118
- executed immediately (i.e. no lazy evaluation).
119
-
120
- The preconditions are run in order of definition. Nested contexts
121
- will inherit the preconditions from the enclosing context, with outer
122
- preconditions running before inner preconditions.
123
-
124
- #### Given examples:
125
-
126
- ```ruby
127
- Given(:stack) { Stack.new }
128
- ```
129
-
130
- The block for the given clause is lazily run and its value bound to
131
- 'stack' if 'stack' is ever referenced in the test.
132
- The first reference to 'stack' in the specification will cause the
133
- code block to execute. Futher references to 'stack' will reuse the
134
- previously generated value.
135
-
136
- ```ruby
137
- Given!(:original_size) { stack.size }
138
- ```
139
-
140
- The code block is run unconditionally once before each test and the
141
- value of the block is bound to 'original_size'. This form is useful
142
- when you want to record the value of something that might be affected
143
- by the When code.
144
-
145
- ```ruby
146
- Given { stack.clear }
147
- ```
148
-
149
- The block for the given clause is run unconditionally once before each
150
- test. This form of given is used for code that is executed for side
151
- effects.
152
-
153
- ### When
154
-
155
- The _When_ clause specifies the code to be tested ... oops, excuse me
156
- ... specified. After the preconditions in the given section are met,
157
- the when code block is run.
158
-
159
- In general there should not be more than one _When_ clause for a given
160
- direct context. However, a _When_ in an outer context will be run
161
- after all the _Givens_ but before the inner _When_. You can think of
162
- an outer _When_ as setting up additional given state for the inner
163
- _When_.
164
-
165
- E.g.
166
-
167
- ```ruby
168
- context "outer context" do
169
- When { code specified in the outer context }
170
- Then { assert something about the outer context }
171
-
172
- context "inner context" do
173
-
174
- # At this point, the _When_ of the outer context
175
- # should be treated as a _Given_ of the inner context
176
-
177
- When { code specified in the inner context }
178
- Then { assert something about the inner context }
179
- end
180
- end
181
- ```
182
-
183
- #### When examples:
184
-
185
- ```ruby
186
- When { stack.push(:item) }
187
- ```
188
-
189
- The code block is executed once per test. The effect of the _When{}_
190
- block is very similar to _Given{}_. However, When is used to identify
191
- the particular code that is being specified in the current context or
192
- describe block.
193
-
194
- ```ruby
195
- When(:result) { stack.pop }
196
- ```
197
-
198
- The code block is executed once per test and the value of the code
199
- block is bound to 'result'. Use this form when the code under test
200
- returns a value that you wish to interrogate in the _Then_ code.
201
-
202
- If an exception occurs during the execution of the block for the When
203
- clause, the exception is caught and a failure object is bound to
204
- 'result'. The failure can be checked in a then block with the
205
- 'have_failed' matcher.
206
-
207
- The failure object will rethrow the captured exception if anything
208
- other than have_failed matcher is used on the failure object.
209
-
210
- For example, if the stack is empty when it is popped, then it is
211
- reasonable for pop to raise an UnderflowError. This is how you might
212
- specify that behavior:
213
-
214
- ```ruby
215
- When(:result) { stack.pop }
216
- Then { result.should have_failed(UnderflowError, /empty/) }
217
- ```
218
-
219
- Note that the arguments to the 'have_failed' matcher are the same as
220
- those given to the standard RSpec matcher 'raise_error'.
221
-
222
- ### Then
223
-
224
- The _Then_ clauses are the postconditions of the specification. These
225
- then conditions must be true after the code under test (the _When_
226
- clause) is run.
227
-
228
- The code in the block of a _Then_ clause should be a single _should_
229
- assertion. Code in _Then_ clauses should not have any side effects.
230
-
231
- Let me repeat that: <b>_Then_ clauses should not have any side
232
- effects!</b> _Then_ clauses with side effects are erroneous. _Then_
233
- clauses need to be idempotent, so that running them once, twice, a
234
- hundred times, or never does not change the state of the program. (The
235
- same is true of _And_ and _Invariant_ clauses).
236
-
237
- In RSpec terms, a _Then_ clause forms a RSpec Example that runs in the
238
- context of an Example Group (defined by a describe or context clause).
239
-
240
- Each Example Group must have at least one _Then_ clause, otherwise
241
- there will be no examples to be run for that group. If all the
242
- assertions in an example group are done via Invariants, then the group
243
- should use an empty _Then_ clause, like this:
244
-
245
- ```ruby
246
- Then { }
247
- ```
248
-
249
- #### Then examples:
250
-
251
- ```ruby
252
- Then { stack.should be_empty }
253
- ```
254
-
255
- After the related block for the _When_ clause is run, the stack should
256
- be empty. If it is not empty, the test will fail.
257
-
258
- ### And
259
-
260
- The _And_ clause is similar to _Then_, but does not form its own RSpec
261
- example. This means that _And_ clauses reuse the setup from a sibling
262
- _Then_ clause. Using a single _Then_ and multiple _And_ clauses in an
263
- example group means the setup for that group is run only once (for the
264
- _Then_ clause) and reused for all the _And_ clauses. This can be a
265
- significant speed savings where the setup for an example group is
266
- expensive.
267
-
268
- Some things to keep in mind about _And_ clauses:
269
-
270
- * There must be at least one _Then_ in the example group and it must
271
- be declared before the _And_ clauses. Forgetting the _Then_ clause
272
- is an error.
273
-
274
- * The code in the _And_ clause is run immediately after the first
275
- (executed) _Then_ of an example group.
276
-
277
- * An assertion failure in a _Then_ clause or an _And_ clause will
278
- cause all the subsequent _And_ clauses to be skipped.
279
-
280
- * Since _And_ clauses do not form their own RSpec examples, they are
281
- not represented in the formatted output of RSpec. That means _And_
282
- clauses do not produce dots in the Progress format, nor do they
283
- appear in the documentation, html or textmate formats (options
284
- -fhtml, -fdoc, or -ftextmate).
285
-
286
- * Like _Then_ clauses, _And_ clauses must be idempotent. That means
287
- they should not execute any code that changes global program state.
288
- (See the section on the _Then_ clause).
289
-
290
- The choice to use an _And_ clause is primarily a speed consideration.
291
- If an example group has expensive setup and there are a lot of _Then_
292
- clauses, then choosing to make some of the _Then_ clauses into _And_
293
- clauses will speed up the spec. Otherwise it is probably better to
294
- stick with _Then_ clauses.
295
-
296
- #### Then/And examples:
297
-
298
- ```ruby
299
- Then { pop_result.should == :top_item } # Required
300
- And { stack.top.should == :second_item } # No Setup rerun
301
- And { stack.depth.should == original_depth - 1 } # ... for these
302
- ```
303
-
304
- ### Invariant
305
-
306
- The _Invariant_ clause is a new idea that doesn't have an analog in
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, 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.
318
-
319
- You can conceptually think of an _Invariant_ clause as a _Then_ block
320
- that automatically gets added to every _Then_ within its scope.
321
- Invariants nested within a context only apply to the _Then_ clauses
322
- that are in the scope of that context.
323
-
324
- Invariants that reference a _Given_ precondition accessor must only be
325
- used in contexts that define that accessor.
326
-
327
- Notes:
328
-
329
- * Since Invariants do not form their own RSpec example, they are not
330
- represented in the RSpec formatted output (e.g. the '--format html'
331
- option).
332
-
333
- ## Execution Ordering
334
-
335
- When running the test for a specific _Then_ clause, the following will
336
- be true:
337
-
338
- * The non-lazy _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_. (The lazy _Given_ clauses will be run upon
341
- demand).
342
-
343
- * All of the _Given_ clauses in all of the relevant scopes will run
344
- before the first (outermost) _When_ clause in those same scopes.
345
- That means that the _When_ code can assume that the givens have been
346
- established, even if the givens are in a more nested scope than the
347
- When.
348
-
349
- * _When_ clauses and RSpec _before_ blocks will be executed in the
350
- order that they are specified, from the outermost block to the
351
- innermost block. This makes _before_ blocks an excellent choice when
352
- writing narrative tests to specify actions that happen between the
353
- "whens" of a narrative-style test.
354
-
355
- Note that the ordering between _Given_ clauses and _before_ blocks are
356
- not strongly specified. Hoisting a _When_ clause out of an inner scope
357
- to an outer scope may change the order of execution between related
358
- _Given_ clauses and any _before_ blocks (hoisting the _When_ clause
359
- might cause the related _Given_ clauses to possibly run earlier).
360
- Because of this, do not split order dependent code between _Given_
361
- clauses and _before_ blocks.
362
-
363
- ## Natural Assertions
364
-
365
- **NOTE:** <em>Natural assertions are currently an experimental feature
366
- of RSpec/Given. They are currently disabled by default, but can be
367
- enabled by a simple configuration option (see "use_natural_assertions"
368
- below).</em>
369
-
370
- RSpec/Given now supports the use of "natural assertions" in _Then_,
371
- _And_, and _Invariant_ blocks. Natural assertions are just Ruby
372
- conditionals, without the _should_ or _expect_ methods that RSpec
373
- provides. Here are the Then/And examples from above, but written using
374
- natural assertions:
375
-
376
- ```ruby
377
- Then { pop_result == :top_item }
378
- And { stack.top == :second_item }
379
- And { stack.depth == original_depth - 1 }
380
- ```
381
-
382
- Natural assertions must be enabled, either globally or on a per
383
- context basis, to be recognized.
384
-
385
- Here's a heads up: If you use natural assertions, but fail to enable
386
- them, all your specs will mysteriously pass. This is why the **red**
387
- part of _Red/Green/Refactor_ is so important.
388
-
389
- ### Failure Messages with Natural Assertions
390
-
391
- Since natural assertions do not depend upon matchers, you don't get
392
- customized error messages from them. What you _do_ get is a complete
393
- analsysis of the expression that failed.
394
-
395
- For example, given the following failing specification:
396
-
397
- ```ruby
398
- RSpec::Given.use_natural_assertions
399
-
400
- describe "Natural Assertions" do
401
- Given(:foo) { 1 }
402
- Given(:bar) { 2 }
403
- Then { foo + bar == 2 }
404
- end
405
- ```
406
-
407
- You would get:
408
-
409
- ```
410
- 1) Natural Assertions
411
- Failure/Error: Then { foo + bar == 2 }
412
- Then expression failed at /Users/jim/working/git/rspec-given/examples/failing/sample_spec.rb:6
413
- expected: 3
414
- to equal: 2
415
- false <- foo + bar == 2
416
- 3 <- foo + bar
417
- 1 <- foo
418
- 2 <- bar
419
- # ./examples/failing/sample_spec.rb:6:in `block in Then'
420
- ```
421
-
422
- Notice how the failing expression "<code>foo+bar == 2</code>" was
423
- broken down into subexpressions and values for each subexpression.
424
- This gives you all the information you need to figure out exactly what
425
- part of the expression is causing the failure.
426
-
427
- Natural assertions will give additional information (e.g. "expected:
428
- 3 to equal: 2") for top level expressions involving any of the
429
- comparison operators (==, !=, <, <=, >, >=) or matching operators (=~,
430
- !~).
431
-
432
- ### Caveats on Natural Assertions
433
-
434
- Keep the following in mind when using natural assertions.
435
-
436
- * Only a single expression/assertion per _Then_. The single expression
437
- of the _Then_ block will be considered when determining pass/fail
438
- for the assertion. If you _want_ to express a complex condition for
439
- the _Then_, you need to use ||, && or some other logical operation
440
- to join the conditions into a single expression (and the failure
441
- message will break down the values for each part).
442
-
443
- * Then clauses need be **idempotent**. This is true in general, but it
444
- is particularly important for natural assertions to obey this
445
- restriction. This means that assertions in a Then clause should not
446
- change anything. Since the Natural Assertion error message contains
447
- the values of all the subexpressions, the expression and its
448
- subexpressions will be evaluated multiple times. If the Then clause
449
- is not idempotent, you will get changing answers as the
450
- subexpressions are evaluated.
451
-
452
- That last point is important. If you write code like this:
453
-
454
- ```ruby
455
- # DO NOT WRITE CODE LIKE THIS
456
- context "Incorrect non-idempotent conditions" do
457
- Given(:ary) { [1, 2, 3] }
458
- Then { ary.delete(1) == nil }
459
- end
460
- ```
461
-
462
- Then the assertion will fail (because <code>ary.delete(1)</code> will
463
- initially return 1). But when the error message is formated, the
464
- system reports that <code>ary.delete(1)</code> returns nil. You will
465
- scratch your head over that for a good while.
466
-
467
- Instead, move the state changing code into a _When(:result)_ block, then
468
- assert what you need to about :result. Something
469
- like this is good:
470
-
471
- ```ruby
472
- context "Correct idempotent conditions" do
473
- Given(:ary) { [1, 2, 3] }
474
- When(:result) { ary.delete(1) }
475
- Then { result == nil }
476
- end
477
- ```
478
-
479
- It is good to note that non-idempotent assertions will also cause
480
- problems with And clauses.
481
-
482
- ### Mixing Natural Assertions and RSpec Assertions
483
-
484
- Natural assertions and RSpec assertions for the most part can be
485
- intermixed in a single test suite, even within a single context.
486
- Because there are a few corner cases that might cause problems, they
487
- must be explicitly enabled before they will be considered.
488
-
489
- To enable natural assertions in a context, call the
490
- _use_natural_assertions_ method in that context. For example:
491
-
492
- ```ruby
493
- context "Outer" do
494
- use_natural_assertions
495
-
496
- context "Inner" do
497
- end
498
-
499
- context "Disabled" do
500
- use_natural_assertions false
501
- end
502
- end
503
- ```
504
-
505
- Both the _Outer_ and _Inner_ contexts will use natural assertions. The
506
- _Disabled_ context overrides the setting inherited from _Outer_ and
507
- will not process natural assertions.
508
-
509
- See the **configuration** section below to see how to enable natural
510
- assertions project wide.
511
-
512
- ### Matchers and Natural Assertions
513
-
514
- In RSpec, matchers are used to provide nice, readable error messages
515
- when an assertion is not met. Natural assertions provide
516
- self-explanatory failure messages for most things without requiring
517
- any special matchers from the programmer.
518
-
519
- In the rare case that some extra information would be helpful, it is
520
- useful to create special objects that respond to the == operator.
521
-
522
- #### Asserting Nearly Equal with Fuzzy Numbers
523
-
524
- Operations on floating point numbers rarely create numbers that are
525
- exactly equal, therefore it is useful to assert that two floating
526
- point numbers are nearly equal. We do that by creating a fuzzy number
527
- that has a looser interpretation of what it means to be equal.
528
-
529
- For example, the following asserts that the square root of 10 is about
530
- 3.1523 with an accuracy of 1 percent.
531
-
532
- ```ruby
533
- Then { Math.sqrt(10) == about(3.1623).percent(1) }
534
- ```
535
-
536
- As long as the real value of <code>Math.sqrt(10)</code> is within plus
537
- or minus 1% of 3.1623 (i.e. 3.1623 +/- 0.031623), then the assertion
538
- will pass.
539
-
540
- There are several ways of creating fuzzy numbers:
541
-
542
- * <code>about(n).delta(d)</code> -- A fuzzy number matching the range
543
- (n-d)..(n+d)
544
-
545
- * <code>about(n).percent(p)</code> -- A fuzzy number matching the
546
- range (n-(n*p/100)) .. (n+(n*p/100))
547
-
548
- * <code>about(n).epsilon(neps)</code> -- A fuzzy number matching the
549
- range (n-(neps*e)) .. (n+(neps*e)), where e is the difference
550
- between 1.0 and the next smallest floating point number.
551
-
552
- * <code>about(n)</code> -- Same as <code>about(n).epsilon(10)</code>.
553
-
554
- When the file <code>rspec/given/fuzzy_shortcuts</code> is required,
555
- the following unicode shortcut methods are added to Numeric to create
556
- fuzzy numbers.
557
-
558
- * <code>n.±(del)</code> is the same as <code>about(n).delta(del)</code>
559
-
560
- * <code>n.‰(percentage)</code> is the same as <code>about(n).percent(percentage)</code>
561
-
562
- * <code>n.€(neps)</code> is the same as <code>about(n).epsilon(neps)</code>
563
-
564
- * <code>n.±</code>, <code>n.‰</code>, and <code>n.€</code> are all
565
- the same as <code>about(n)</code>
566
-
567
- #### Detecting Exceptions
568
-
569
- The RSpec matcher used for detecting exceptions will work with natural
570
- assertions out of the box. Just check for equality against the
571
- <code>have_failed</code> return value.
572
-
573
- For example, the following two Then clauses are equivalent:
574
-
575
- ```ruby
576
- # Using an RSpec matcher
577
- Then { result.should have_failed(StandardError, /message/) }
578
-
579
- # Using natural assertions
580
- Then { result == have_failed(StandardError, /message/) }
581
- ```
582
-
583
- ### Processing Natural Assertions
584
-
585
- When natural assertions are enabled, they are only used if all of the
586
- following are true:
587
-
588
- 1. The block does not throw an RSpec assertion failure (or any other
589
- exception for that matter).
590
-
591
- 1. The block returns false (blocks that return true pass the
592
- assertion and don't need a failure message).
593
-
594
- 1. The block does not use RSpec's _should_ or _expect_ methods.
595
-
596
- Detecting that last point (the use of _should_ and _expect_) is done
597
- by modifying the RSpec runtime to report uses of _should_ and
598
- _expect_.
599
-
600
- ### Platform Support
601
-
602
- Natural assertions use the Ripper library to parse the failing
603
- condition and find all the sub-expression values upon a failure.
604
- Currently Ripper is not supported on JRuby 1.7.2. Charles Nutter has
605
- said that Ripper support is coming soon and may arrive as early as
606
- version 1.7.3. Until then, natural assertions are disabled when
607
- running under JRuby. Never fear, JRuby supports all the other features
608
- of rspec-given and will work just fine.
609
-
610
- ### Further Reading
611
-
612
- Natural assertions were inspired by the [wrong assertion
613
- library](http://rubygems.org/gems/wrong) by [Alex
614
- Chaffee](http://rubygems.org/profiles/alexch) and [Steve
615
- Conover](http://rubygems.org/profiles/sconoversf).
616
-
617
- ## Configuration
618
-
619
- Just require 'rspec/given' in the spec helper of your project and it
620
- is ready to go.
621
-
622
- If the RSpec format option document, html or textmate is chosen,
623
- RSpec/Given will automatically add additional source code information to
624
- the examples to produce better looking output. If you don't care about
625
- the pretty output and wish to disable source code caching
626
- unconditionally, then add the following line to your spec helper file:
627
-
628
- ```ruby
629
- RSpec::Given.source_caching_disabled = true
630
- ```
631
-
632
- Natural assertions are disabled by default. To globally configure
633
- natural assertions, add one of the following lines to your spec_helper
634
- file:
635
-
636
- ```ruby
637
- RSpec::Given.use_natural_assertions # Enable natural assertions
638
- RSpec::Given.use_natural_assertions true # Same as above
639
- RSpec::Given.use_natural_assertions false # Disable natural assertions
640
- RSpec::Given.use_natural_assertions :always # Always process natural assertions
641
- # ... even when should/expect are detected
642
- ```
643
-
644
- # Links
645
-
646
- * Github: [https://github.com/jimweirich/rspec-given](https://github.com/jimweirich/rspec-given)
647
- * Clone URL: git://github.com/jimweirich/rspec-given.git
648
- * Bug/Issue Reporting: [https://github.com/jimweirich/rspec-given/issues](https://github.com/jimweirich/rspec-given/issues)
649
- * Continuous Integration: [http://travis-ci.org/#!/jimweirich/rspec-given](http://travis-ci.org/#!/jimweirich/rspec-given)