minitest-given 3.3.0 → 3.4.0

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: 7f6ac78ebf0dcbd97a1c4507f2a003f6ec9003b3
4
- data.tar.gz: 5e7fcbba3bc694a5ac78cce67eb5f3454d52dfee
3
+ metadata.gz: c3769f9d39bd6466f993687a0f3df8c169b27118
4
+ data.tar.gz: b041cd8182ff4ac8044e2eedc914a0196a87066f
5
5
  SHA512:
6
- metadata.gz: 06b7d59ef0798b8d6283bdd0645e8fbde93b09f86bafbd21d04b6e67e540a7ff0a7b32cd4655a8e38687a14e573b629a5e3dcda7be31b1d7bfc1e6236a3095a7
7
- data.tar.gz: 27f9034b05e5bdf0e7904f2a93d809cf1f189017068fa61b0b8bdf915ad2ebb2ec9285ea0cea6ceedb3e714a902726f081a48fabfdf45320b74225526b883e6b
6
+ metadata.gz: bcce0e56e74705ad54cbee6edef23fd17fb9241ee2cb87efd047d043c2231231fa1ffebe756a62489dd35c1ccd8ff14b1e67004967bd6b72e429ffa12a19fb07
7
+ data.tar.gz: 1f6a19b866f2c00fa3016bdaec94d227ee23a27e6bf88bbd5ee867e61ed5f0e371b81fc178504ca677ab412c0a6c49f05a92da92ed01c95272c64e415eb62f45
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.3.0.beta21.
7
+ Covering rspec-given, minitest-given, and given-core, version 3.4.0.
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.
@@ -866,6 +866,11 @@ License. See the MIT-LICENSE file in the source distribution.
866
866
 
867
867
  # History
868
868
 
869
+ * Version 3.4.0
870
+
871
+ * Bare failure objects in Then clauses will now propagate their
872
+ captured failure (added <code>to_bool</code> to failure object).
873
+
869
874
  * Version 3.3.0
870
875
 
871
876
  * Add support for <code>to_bool</code>.
data/Rakefile CHANGED
@@ -42,7 +42,7 @@ task :tag do
42
42
  end
43
43
 
44
44
  desc "Publish the gems"
45
- task :publish => [:clobber, :gem] do
45
+ task :publish_gems => [:clobber, :gem] do
46
46
  FileList['pkg/*.gem'].each do |gemname|
47
47
  sh "gem push #{gemname}"
48
48
  end
@@ -0,0 +1,282 @@
1
+ ## Beautiful Failure Messages
2
+
3
+ The RSpec/Given library is an extension to the RSpec testing framework
4
+ that explicitly supports a Given/When/Then style for testing. It has
5
+ two goals:
6
+
7
+ * Encourage specification language when writing tests
8
+ * Allow beautiful failure messages without writing custom matchers
9
+
10
+ RSpec/Given has a been very successful in both these goals. Consider
11
+ the following spec snippet for a Page object in a Wiki Rails
12
+ application:
13
+
14
+ ```ruby
15
+ describe "content conversion to HTML" do
16
+ Given(:page) {
17
+ Page.new(
18
+ name: "HomePage",
19
+ content: "Have a _nice_ day.")
20
+ }
21
+ Then { page.html_content == "Have a <em>nice</em> day." }
22
+ end
23
+ ```
24
+
25
+ Assuming that the <code>html_content</code> method is incomplete and
26
+ not yet marking emphasized text, the failure message from the
27
+ specification will be:
28
+
29
+ 1) Page content conversion to HTML
30
+ Failure/Error: Then { page.html_content == "Have a <em>nice</em> day." }
31
+ Then expression failed at .../spec/models/page_spec.rb:38
32
+ expected: "Have a _nice_ day."
33
+ to equal: "Have a <em>nice</em> day."
34
+ false <- page.html_content == "Have a <em>nice</em> day."
35
+ "Have a _nice_ day."
36
+ <- page.html_content
37
+ #<Page name: "HomePage", content: "Have a _nice_ day." ...>
38
+ <- page
39
+ # ./spec/models/page_spec.rb:38:in `block in Then'
40
+
41
+ Let's break that down:
42
+
43
+ **It says what failed:**
44
+
45
+ Failure/Error: Then { page.html_content == "Have a <em>nice</em> day." }
46
+
47
+ **It says where it failed:**
48
+
49
+ Then expression failed at .../spec/models/page_spec.rb:38
50
+
51
+ **It says what was expected:**
52
+
53
+ expected: "Have a _nice_ day."
54
+ to equal: "Have a <em>nice</em> day."
55
+
56
+ **It then breaks down each subexpression and displays its value:**
57
+
58
+ false <- page.html_content == "Have a <em>nice</em> day."
59
+ "Have a _nice_ day."
60
+ <- page.html_content
61
+ #<Page name: "HomePage", content: "Have a _nice_ day." ...>
62
+ <- page
63
+
64
+ All of this happens without the developer needing to write any special
65
+ error matchers or custom output. Everything you need to debug a spec
66
+ failure is there in the output.
67
+
68
+ ## A More Complex Example
69
+
70
+ Let's look at a more complex example. Suppose we want to test
71
+ validations in the Page object. For example, we might want to make
72
+ sure that:
73
+
74
+ * The page has a name
75
+ * The name conforms to the standard wiki naming convention (i.e. WikiName).
76
+
77
+ Here's the beginning of that specification:
78
+
79
+ ```ruby
80
+ describe Page do
81
+ VALID_ATTRS = { name: "SomePage", content: "CONTENT" }
82
+ Given(:attrs) { VALID_ATTRS }
83
+ Given(:page) { Page.new(attrs) }
84
+
85
+ ...
86
+ end
87
+ ```
88
+
89
+ <code>VALID\_ATTRS</code> is a list of attributes that will construct a
90
+ valid page object. Normally I would put <code>VALID\_ATTRS</code> in something like
91
+ Factory Girl, but a simple constant is good enough this example.
92
+
93
+ I then declare a given that <code>attrs</code> is the valid
94
+ attributes, and that <code>Page</code> is constructed from these valid
95
+ attributes.
96
+
97
+ I can now describe a valid page object.
98
+
99
+ ```ruby
100
+ context "with valid attributes" do
101
+ Then { page.valid? }
102
+ end
103
+ ```
104
+
105
+ To describe a validation failure where the name is missing, I create a
106
+ context where I override the default <code>attrs</code> with a version
107
+ that omits the name.
108
+
109
+ ```ruby
110
+ context "with missing name" do
111
+ Given(:attrs) { VALID_ATTRS.merge(name: nil) }
112
+ Then { page.invalid? }
113
+ And { ! page.errors[:name].empty? }
114
+ And { page.errors[:name].any? { |msg| msg =~ /blank/ } }
115
+ end
116
+ ```
117
+
118
+ Why Then/And/And? Because there are three things that should be true
119
+ if a validation fails.
120
+
121
+ 1. The object must not be valid
122
+ 2. The field that has the error must have error messages
123
+ 3. At least one of the error messages should mention the word 'blank'
124
+
125
+ Suppose the Page object has a validation on name, but doesn't check
126
+ for presence. The failure message clearly tells you that the spec
127
+ failed because no error messages on the <code>name</code> field
128
+ mentioned 'blank'.
129
+
130
+ 1) Page validations with missing name
131
+ Failure/Error: Then { page.invalid? }
132
+ And expression failed at ./spec/models/page_spec.rb:27
133
+ Failing expression: And { page.errors[:name].any? { |msg| msg =~ /blank/ } }
134
+ false <- page.errors[:name].any? { |msg| msg =~ /blank/ }
135
+ ["is not a wiki name"]
136
+ <- page.errors[:name]
137
+ #<ActiveModel::Errors:... @messages={:name=>["is not a wiki name"]}>
138
+ <- page.errors
139
+ #<Page name: nil, content: "CONTENT", ...>
140
+ <- page
141
+ # ./spec/models/page_spec.rb:25:in `block in Then'
142
+
143
+ We get informative error messages, which is exactly what we want.
144
+
145
+ However, the spec itself is a little wordy, with repeating
146
+ Then/And/And. What if we wrote a simple query function that checked
147
+ for the three conditions and reported true/false accordingly.
148
+
149
+ ```ruby
150
+ def invalid?(page, field, pattern)
151
+ page.invalid? &&
152
+ ! page.errors[field].empty? &&
153
+ page.errors[field].any? { |msg| msg =~ pattern }
154
+ end
155
+ ```
156
+
157
+ Now we can use <code>invalid?</code> in all our validations
158
+ specifications:
159
+
160
+ ```ruby
161
+ context "with missing name" do
162
+ Given(:attrs) { VALID_ATTRS.merge(name: nil) }
163
+ Then { invalid?(page, :name, /blank/) }
164
+ end
165
+ ```
166
+
167
+ But there is a downside. Because <code>invalid?</code> only returns
168
+ true/false, and there are no mention of the <code>errors</code> object
169
+ in the Then clause, the failure message is really uninformative:
170
+
171
+ 1) Page validations with missing name
172
+ Failure/Error: Then { invalid_on(page, :name, /blank/) }
173
+ Then expression failed at ./spec/models/page_spec.rb:31
174
+ false <- invalid_on(page, :name, /blank/)
175
+ #<Page name: nil, content: "CONTENT", ...>
176
+ <- page
177
+ # ./spec/models/page_spec.rb:31:in `block in Then'
178
+
179
+ All we know is that the page is invalid. We get no indication of what
180
+ fields were actually in error and what the error messages actually
181
+ were.
182
+
183
+ ## Custom Failure Message
184
+
185
+ By abstracting away the details how to check for invalid models (which
186
+ is generally a good thing), RSpec/Given lost the ability to give us
187
+ the details of why it failed.
188
+
189
+ Fortunately, there is a simple fix. Instead of returning a simple
190
+ true/false value, the <code>invalid?</code> method should return an
191
+ object, that when inspected, tells why it failed.
192
+
193
+ If a _Then_ clause returns a value that supports a
194
+ <code>to_bool</code> method, then RSpec/Given will call that method
195
+ before checking for true/false (in rspec-given 3.3.0 or later). All we
196
+ need to do is arrange for that object to be returned.
197
+
198
+ ```ruby
199
+ def must_be_invalid(model, field, pattern=//)
200
+ MustBeInvalid.new(model, field, pattern)
201
+ end
202
+ ```
203
+
204
+ Since the method no longer returns a true/false value, I've changed
205
+ the name from <code>invalid?</code> to <code>must\_be\_invalid</code>.
206
+
207
+ The code for the <code>MustBeInvalid</code> class is a bit long, but
208
+ there is nothing complex in it. The <code>to_bool</code> method
209
+ carefully checks for each of our three conditions and records the
210
+ exact reason for failure in the @why instance variable. The
211
+ <code>inspect</code> method (called by RSpec/Given to display its
212
+ value) just returns the @why value with additional details about the
213
+ errors on the object.
214
+
215
+ ```ruby
216
+ class MustBeInvalid
217
+ def initialize(model, field, pattern)
218
+ @model = model
219
+ @field = field
220
+ @pattern = pattern
221
+ @why = nil
222
+ end
223
+
224
+ def to_bool
225
+ if @model.valid?
226
+ @why = "#{@model.class} was valid (expected invalid)"
227
+ false
228
+ elsif @model.errors[@field].empty?
229
+ @why = "#{@model.class} had no errors on field #{@field}" +
230
+ error_descriptions
231
+ false
232
+ elsif @model.errors[@field].none? { |msg| msg =~ @pattern }
233
+ @why = "#{@model.class} had no errors " +
234
+ "matching #{@pattern} on field #{@field}" +
235
+ error_descriptions
236
+ false
237
+ else
238
+ @why = "OK (expected invalid)"
239
+ true
240
+ end
241
+ end
242
+
243
+ def inspect
244
+ to_bool if @why.nil?
245
+ @why
246
+ end
247
+
248
+ private
249
+
250
+ def error_descriptions
251
+ if @model.errors.empty?
252
+ ""
253
+ else
254
+ "\n Errors were:\n * " +
255
+ @model.errors.full_messages.
256
+ map { |msg| msg }.join("\n * ")
257
+ end
258
+ end
259
+ end
260
+ ```
261
+
262
+ The failure message returned by <code>MustBeInvalid</code> is once
263
+ again clear and to the point. It contains all the information needed
264
+ for debugging.
265
+
266
+ 1) Page validations with missing name
267
+ Failure/Error: Then { must_be_invalid(page, :name, /blank/) }
268
+ Then expression failed at ./spec/models/page_spec.rb:31
269
+ Page had no errors matching (?-mix:blank) on field name
270
+ Errors were:
271
+ * Name is not a wiki name
272
+ <- must_be_invalid(page, :name, /blank/)
273
+ #<Page name: nil, content: "CONTENT", ...>
274
+ <- page
275
+ # ./spec/models/page_spec.rb:31:in `block in Then'
276
+
277
+ ## Summary
278
+
279
+ I've always felt that you can tell the maturity level of a piece of
280
+ software by the beauty of the error messages it produces. By
281
+ providing the ability to do custom messages where needed, RSpec/Given
282
+ takes a step in that direction.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitest-given
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.4.0
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-12-20 00:00:00.000000000 Z
11
+ date: 2013-12-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: given_core
@@ -16,26 +16,26 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.3.0
19
+ version: 3.4.0
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.3.0
26
+ version: 3.4.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>'
31
+ - - ">"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '4.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>'
38
+ - - ">"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '4.3'
41
41
  description: |
@@ -52,13 +52,8 @@ files:
52
52
  - README.md
53
53
  - Rakefile
54
54
  - TODO
55
- - lib/given.rb
56
- - lib/minitest-given.rb
57
- - lib/minitest/given.rb
58
- - rakelib/bundler_fix.rb
59
- - rakelib/gemspec.rake
60
- - rakelib/metrics.rake
61
- - rakelib/preview.rake
55
+ - doc/article/custom_error_messages.md
56
+ - doc/main.rdoc
62
57
  - examples/example_helper.rb
63
58
  - examples/failing/natural_failing_spec.rb
64
59
  - examples/failing/sample_spec.rb
@@ -80,34 +75,40 @@ files:
80
75
  - examples/stack/stack_spec.rb
81
76
  - examples/stack/stack_spec1.rb
82
77
  - examples/use_assertions.rb
83
- - doc/main.rdoc
78
+ - lib/given.rb
79
+ - lib/minitest-given.rb
80
+ - lib/minitest/given.rb
81
+ - rakelib/bundler_fix.rb
82
+ - rakelib/gemspec.rake
83
+ - rakelib/metrics.rake
84
+ - rakelib/preview.rake
84
85
  homepage: http://github.com/jimweirich/rspec-given
85
86
  licenses:
86
87
  - MIT
87
88
  metadata: {}
88
89
  post_install_message:
89
90
  rdoc_options:
90
- - --line-numbers
91
- - --inline-source
92
- - --main
91
+ - "--line-numbers"
92
+ - "--inline-source"
93
+ - "--main"
93
94
  - doc/main.rdoc
94
- - --title
95
+ - "--title"
95
96
  - Minitest::Spec Given Extensions
96
97
  require_paths:
97
98
  - lib
98
99
  required_ruby_version: !ruby/object:Gem::Requirement
99
100
  requirements:
100
- - - '>='
101
+ - - ">="
101
102
  - !ruby/object:Gem::Version
102
103
  version: 1.9.2
103
104
  required_rubygems_version: !ruby/object:Gem::Requirement
104
105
  requirements:
105
- - - '>='
106
+ - - ">="
106
107
  - !ruby/object:Gem::Version
107
108
  version: '0'
108
109
  requirements: []
109
110
  rubyforge_project: given
110
- rubygems_version: 2.1.11
111
+ rubygems_version: 2.2.0
111
112
  signing_key:
112
113
  specification_version: 4
113
114
  summary: Given/When/Then Specification Extensions for Minitest::Spec.