rspec-collection 2.0.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.
@@ -0,0 +1,61 @@
1
+ # rspec-collection
2
+
3
+ Allow RSpec assertions over the elements of a collection.
4
+
5
+ ## Usage
6
+
7
+ Allow RSpec assertions over the elements of a collection. For example:
8
+
9
+ collection.should all\_be > 0
10
+
11
+ will specify that each element of the collection should be greater
12
+ than zero. Each element of the collection that fails the test will
13
+ be reported in the error message.
14
+
15
+ Examples:
16
+
17
+ [1,1,1].should all\_be eq(1)
18
+ [2,4,6].should all\_be\_even
19
+ [3,6,9].should all\_be\_divisible_by(3)
20
+ [1,1,1].should all\_be == 1
21
+ [2,3,5].should all\_be { |n| prime?(n) }
22
+
23
+ (for appropriate definitions of prime? and divisible_by?)
24
+
25
+ ### Requirements
26
+
27
+ * RSpec 2.0.0
28
+
29
+ ## Todo
30
+
31
+ * Other means of navigation besides left/right keys
32
+ * Vertical view of all slides in a row
33
+ * Generate PDFs (maybe via cucumber)
34
+ * Stop making Nokogiri sad when parsing out snippets
35
+
36
+ ## Contributors
37
+
38
+ * Jim Weirich
39
+
40
+ (c) Copyright 2010 Jim Weirich
41
+
42
+ Permission is hereby granted, free of charge, to any person
43
+ obtaining a copy of this software and associated documentation
44
+ files (the "Software"), to deal in the Software without
45
+ restriction, including without limitation the rights to use,
46
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
47
+ copies of the Software, and to permit persons to whom the
48
+ Software is furnished to do so, subject to the following
49
+ conditions:
50
+
51
+ The above copyright notice and this permission notice shall be
52
+ included in all copies or substantial portions of the Software.
53
+
54
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
55
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
56
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
57
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
58
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
59
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
60
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
61
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/ruby -wKU
2
+
3
+ require 'rake/clean'
4
+ require './lib/rspec-collection/version'
5
+
6
+ CLOBBER.include('*.gemspec')
7
+
8
+ Project = OpenStruct.new(
9
+ :name => "rspec-collection",
10
+ :version => RSpecCollection::VERSION,
11
+ :author => "Jim Weirich",
12
+ :author_email => "jim@edgecase.com",
13
+ :home_page => "http://github.com/jimweirich/rspec-collection")
14
+
15
+ task :default => :spec
16
+
17
+ task :spec do
18
+ sh "rspec -Ilib spec"
19
+ end
@@ -0,0 +1,3 @@
1
+ # Require the package files.
2
+ require 'rspec-collection/all_be.rb'
3
+
@@ -0,0 +1,127 @@
1
+ # Allow RSpec assertions over the elements of a collection. For example:
2
+ #
3
+ # collection.should all_be > 0
4
+ #
5
+ # will specify that each element of the collection should be greater
6
+ # than zero. Each element of the collection that fails the test will
7
+ # be reported in the error message.
8
+ #
9
+ # Examples:
10
+ # [1,1,1].should all_be eq(1)
11
+ # [2,4,6].should all_be_even
12
+ # [3,6,9].should all_be_divisible_by(3)
13
+ # [1,1,1].should all_be == 1
14
+ # [2,3,5].should all_be { |n| prime?(n) }
15
+ #
16
+ # (for appropriate definitions of prime? and divisible_by?)
17
+ #
18
+ module RSpec
19
+ module Matchers
20
+
21
+ # Helper functions gathered here to avoid global name space
22
+ # pollution.
23
+ module AllBe
24
+ module_function
25
+
26
+ # Format a predicate function (with option arguments) for human
27
+ # readability.
28
+ def format_predicate(pred, *args)
29
+ message_elements =
30
+ ["be #{pred.gsub(/_/, ' ')}"] +
31
+ args.map { |a| a.inspect }
32
+ message_elements.join(' ')
33
+ end
34
+
35
+ # Create a collection matcher using +block+ as the matching
36
+ # condition. Block should take one or two arguments:
37
+ #
38
+ # lambda { |element| ... }
39
+ # lambda { |element, messages| ... }
40
+ #
41
+ # If a block wishes to use custom failure messages, it should
42
+ # append the message to the +messages+ array. Otherwise we will
43
+ # format an appropriate error message for each failing element.
44
+ #
45
+ def make_matcher(condition_string, &block)
46
+ Matcher.new :all_be, block do |_block_|
47
+ @failing_messages = []
48
+ @broken = []
49
+ match do |actual|
50
+ actual.each do |element|
51
+ unless _block_.call(element, @failing_messages)
52
+ @broken << element
53
+ end
54
+ end
55
+ @broken.empty?
56
+ end
57
+
58
+ failure_message_for_should do |actual|
59
+ messages = ["in #{actual.inspect}:"]
60
+ if @failing_messages.empty?
61
+ messages += @broken.map { |element| "expected #{element.inspect} to #{condition_string}" }
62
+ else
63
+ messages += @failing_messages
64
+ end
65
+ messages.join("\n")
66
+ end
67
+
68
+ failure_message_for_should_not do |actual|
69
+ "expected #{actual.inspect} to not all #{condition_string}"
70
+ end
71
+
72
+ description do
73
+ "all be"
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ # Handle mapping operators to appropriate collection mappers.
80
+ class AllBeOperatorMatcher
81
+ [:==, :!=, :>, :<, :<=, :>=, :=~].each do |op|
82
+ define_method(op) do |value|
83
+ AllBe.make_matcher("be #{op} #{value}") { |element|
84
+ element.send(op, value)
85
+ }
86
+ end
87
+ end
88
+ end
89
+
90
+ alias method_missing_without_all_be method_missing
91
+
92
+ # Handle all_be_XXX predicates. If it doesn't match the
93
+ # all_be_XXX pattern, delegate to the existing method missing
94
+ # handler.
95
+ def method_missing(sym, *args, &block)
96
+ if sym.to_s =~ /^all_be_(\w+)$/
97
+ pred = $1
98
+ pred_method = "#{pred}?"
99
+ pred_string = AllBe.format_predicate(pred, *args)
100
+ AllBe.make_matcher(pred_string) { |element|
101
+ element.send(pred_method, *args, &block)
102
+ }
103
+ else
104
+ method_missing_without_all_be(sym, *args, &block)
105
+ end
106
+ end
107
+
108
+ # Return a matcher appropriate for matching across elements of a
109
+ # collection.
110
+ def all_be(matcher=nil, &block)
111
+ if matcher
112
+ AllBe.make_matcher("pass") { |element, messages|
113
+ if matcher.matches?(element)
114
+ true
115
+ else
116
+ messages << matcher.failure_message_for_should
117
+ false
118
+ end
119
+ }
120
+ elsif block_given?
121
+ AllBe.make_matcher("satisfy the block", &block)
122
+ else
123
+ AllBeOperatorMatcher.new
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,13 @@
1
+ module RSpecCollection
2
+ module Version
3
+ COMPONENTS = [
4
+ Major = 2,
5
+ Minor = 0,
6
+ Build = 0,
7
+ ]
8
+
9
+ STRING = COMPONENTS.join(".")
10
+ end
11
+
12
+ VERSION = Version::STRING
13
+ end
@@ -0,0 +1,64 @@
1
+ begin
2
+ require 'rubygems'
3
+ require 'rake/gempackagetask'
4
+ rescue Exception
5
+ nil
6
+ end
7
+
8
+ PKG_FILES = FileList['**/*.rb', 'Rakefile', '**/*.rake', 'README.md']
9
+
10
+ if ! defined?(Gem)
11
+ puts "Package Target requires RubyGEMs"
12
+ else
13
+ SPEC = Gem::Specification.new do |s|
14
+
15
+ #### Basic information.
16
+
17
+ s.name = Project.name
18
+ s.version = Project.version
19
+ s.summary = "Allow RSpec assertions over the elements of a collection."
20
+ s.description = <<-EOF
21
+ For example:
22
+
23
+ collection.should all_be > 0
24
+
25
+ will specify that each element of the collection should be greater
26
+ than zero. Each element of the collection that fails the test will
27
+ be reported in the error message.
28
+ EOF
29
+
30
+ #### Dependencies and requirements.
31
+
32
+ s.add_dependency('rspec-core', '>= 2.0.0')
33
+ #s.requirements << ""
34
+
35
+ s.files = PKG_FILES.to_a
36
+ s.require_path = 'lib' # Use these for libraries.
37
+
38
+ #### Documentation and testing.
39
+
40
+ s.has_rdoc = true
41
+ s.extra_rdoc_files = ["README.md"]
42
+ s.rdoc_options = ""
43
+
44
+ #### Author and project details.
45
+
46
+ s.author = Project.author
47
+ s.email = Project.author_email
48
+ s.homepage = Project.home_page
49
+ s.rubyforge_project = "n/a"
50
+ end
51
+
52
+ Rake::GemPackageTask.new(SPEC) do |pkg|
53
+ pkg.need_zip = false
54
+ pkg.need_tar = false
55
+ end
56
+
57
+ file "#{Project.name}.gemspec" => ["Rakefile", "rakelib/gem.rake"] do |t|
58
+ require 'yaml'
59
+ open(t.name, "w") { |f| f.puts SPEC.to_yaml }
60
+ end
61
+
62
+ desc "Create a stand-alone gemspec"
63
+ task :gemspec => "#{Project.name}.gemspec"
64
+ end
@@ -0,0 +1,272 @@
1
+ require 'spec_helper'
2
+ require 'rspec-collection'
3
+
4
+ class Integer
5
+ def divisible_by?(n)
6
+ (self % n) == 0
7
+ end
8
+ end
9
+
10
+ describe "Collection Matchers" do
11
+
12
+ # matcher ----------------------------------------------------------
13
+
14
+ context "using matchers" do
15
+ it "matcher passes" do
16
+ [1,1,1].should all_be eq(1)
17
+ end
18
+
19
+ it "NOT matcher passes" do
20
+ [1,2,1].should_not all_be eq(1)
21
+ end
22
+
23
+ it "matcher fails correctly" do
24
+ should_fail([1,2,3]) { |obj|
25
+ obj.should all_be eq(1)
26
+ }
27
+ end
28
+
29
+ it "NOT matcher fails correctly" do
30
+ should_fail([1,1,1]) { |obj|
31
+ obj.should_not all_be eq(1)
32
+ }
33
+ end
34
+ end
35
+
36
+ # block ------------------------------------------------------------
37
+
38
+ context "using blocks" do
39
+ it "block passes" do
40
+ [0,2,4].should all_be { |item| item.even? }
41
+ end
42
+
43
+ it "NOT block passes" do
44
+ [0,2,5].should_not all_be { |item| item.even? }
45
+ end
46
+
47
+ it "NOT block fails correctly" do
48
+ should_fail([0,2,4]) { |obj|
49
+ obj.should_not all_be { |item| item.even? }
50
+ }
51
+ end
52
+
53
+ it "NOT block fails correctly" do
54
+ should_fail([0,2,4]) { |obj|
55
+ obj.should_not all_be { |item| item.even? }
56
+ }
57
+ end
58
+ end
59
+
60
+ # predicates -------------------------------------------------------
61
+
62
+ context "using predicates" do
63
+ it "predicate passes" do
64
+ [0,2,4].should all_be_even
65
+ end
66
+
67
+ it "NOT predicate passes" do
68
+ [0,2,5].should_not all_be_even
69
+ end
70
+
71
+ it "predicate fails correctly" do
72
+ should_fail([0,2,5]) { |obj|
73
+ obj.should all_be_even
74
+ }
75
+ end
76
+
77
+ it "NOT predicate fails correctly" do
78
+ should_fail([0,2,4]) { |obj|
79
+ obj.should_not all_be_even
80
+ }
81
+ end
82
+ end
83
+
84
+ # predicates with args ---------------------------------------------
85
+
86
+ context "using predicates with arguments" do
87
+ it "predicate passes" do
88
+ [3,6,9].should all_be_divisible_by(3)
89
+ end
90
+
91
+ it "NOT predicate passes" do
92
+ [3,6,8].should_not all_be_divisible_by(3)
93
+ end
94
+
95
+ it "predicate fails correctly" do
96
+ should_fail([3,6,8]) { |obj|
97
+ obj.should all_be_divisible_by(3)
98
+ }
99
+ end
100
+
101
+ it "NOT predicate fails correctly" do
102
+ should_fail([3,6,9]) { |obj|
103
+ obj.should_not all_be_divisible_by(3)
104
+ }
105
+ end
106
+ end
107
+
108
+ # operator ---------------------------------------------------------
109
+
110
+ context "using operators" do
111
+ it "operator passes" do
112
+ [1,1,1].should all_be == 1
113
+ end
114
+
115
+ it "NOT operator passes" do
116
+ [1,1,2].should_not all_be == 1
117
+ end
118
+
119
+ it "operator fails correctly" do
120
+ should_fail([1,2,3]) { |obj|
121
+ obj.should all_be < 3
122
+ }
123
+ end
124
+
125
+ it "NOT operator fails correctly" do
126
+ should_fail([1,2,1]) { |obj|
127
+ obj.should_not all_be < 3
128
+ }
129
+ end
130
+
131
+ it "=~ operator passes" do
132
+ ["a", "b", "c"].should all_be =~ /^.$/
133
+ end
134
+
135
+ it "NOT =~ operator passes" do
136
+ ["a", "b", "c"].should_not all_be =~ /^..$/
137
+ end
138
+
139
+ it "=~ operator fails correctly" do
140
+ should_fail(["a", "b", "cc"]) { |obj|
141
+ obj.should all_be =~ /^.$/
142
+ }
143
+ end
144
+
145
+ it "NOT =~ operator fails correctly" do
146
+ should_fail(["a", "b", "c"]) { |obj|
147
+ obj.should_not all_be =~ /^.$/
148
+ }
149
+ end
150
+ end
151
+
152
+ private # ----------------------------------------------------------
153
+
154
+ def should_fail(obj, &block)
155
+ lambda {
156
+ yield(obj)
157
+ }.should raise_error(RSpec::Expectations::ExpectationNotMetError)
158
+ end
159
+ end
160
+
161
+ describe "Error Messages" do
162
+
163
+ # matcher ----------------------------------------------------------
164
+
165
+ context "when matchers fail" do
166
+ it "contains multiple items" do
167
+ lambda {
168
+ [1,2,3].should all_be eq(1)
169
+ }.should raise_error(
170
+ RSpec::Expectations::ExpectationNotMetError,
171
+ /expected 1.*got 2.*expected 1.*got 3/m)
172
+ end
173
+ end
174
+
175
+ context "when NOT matchers fail" do
176
+ it "contains single failure message" do
177
+ lambda {
178
+ [1,1,1].should_not all_be eq(1)
179
+ }.should raise_error(
180
+ RSpec::Expectations::ExpectationNotMetError,
181
+ /expected \[1, 1, 1\] to not all pass/m)
182
+ end
183
+ end
184
+
185
+ # block ------------------------------------------------------------
186
+
187
+ context "when blocks fail" do
188
+ it "contains multiple items" do
189
+ lambda {
190
+ [1,2,3].should all_be { |n| n == 1 }
191
+ }.should raise_error(
192
+ RSpec::Expectations::ExpectationNotMetError,
193
+ /expected 2 to satisfy the block.*expected 3 to satisfy the block/m)
194
+ end
195
+ end
196
+
197
+ context "when NOT matchers fail" do
198
+ it "contains single failure message" do
199
+ lambda {
200
+ [1,1,1].should_not all_be { |n| n == 1 }
201
+ }.should raise_error(
202
+ RSpec::Expectations::ExpectationNotMetError,
203
+ /expected \[1, 1, 1\] to not all satisfy the block/m)
204
+ end
205
+ end
206
+
207
+ # predicate --------------------------------------------------------
208
+
209
+ context "when predicates fail" do
210
+ it "contains multiple items" do
211
+ lambda {
212
+ [1,0,3].should all_be_zero
213
+ }.should raise_error(
214
+ RSpec::Expectations::ExpectationNotMetError,
215
+ /expected 1 to be zero.*expected 3 to be zero/m)
216
+ end
217
+ end
218
+
219
+ context "when NOT predicates fail" do
220
+ it "contains single failure message" do
221
+ lambda {
222
+ [0,0].should_not all_be_zero
223
+ }.should raise_error(
224
+ RSpec::Expectations::ExpectationNotMetError,
225
+ /expected \[0, 0\] to not all be zero/m)
226
+ end
227
+ end
228
+
229
+ # predicate with args ----------------------------------------------
230
+
231
+ context "when predicates fail" do
232
+ it "contains multiple items" do
233
+ lambda {
234
+ [3,4,5].should all_be_divisible_by(3)
235
+ }.should raise_error(
236
+ RSpec::Expectations::ExpectationNotMetError,
237
+ /expected 4 to be divisible by 3.*expected 5 to be divisible by 3/m)
238
+ end
239
+ end
240
+
241
+ context "when NOT predicates fail" do
242
+ it "contains single failure message" do
243
+ lambda {
244
+ [3,6,9].should_not all_be_divisible_by(3)
245
+ }.should raise_error(
246
+ RSpec::Expectations::ExpectationNotMetError,
247
+ /expected \[3, 6, 9\] to not all be divisible by 3/m)
248
+ end
249
+ end
250
+
251
+ # operators --------------------------------------------------------
252
+
253
+ context "when operators fail" do
254
+ it "contains multiple items" do
255
+ lambda {
256
+ [1,2,3].should all_be == 1
257
+ }.should raise_error(
258
+ RSpec::Expectations::ExpectationNotMetError,
259
+ /expected 2 to be == 1.*expected 3 to be == 1/m)
260
+ end
261
+ end
262
+
263
+ context "when NOT predicates fail" do
264
+ it "contains single failure message" do
265
+ lambda {
266
+ [1,1,1].should_not all_be == 1
267
+ }.should raise_error(
268
+ RSpec::Expectations::ExpectationNotMetError,
269
+ /expected \[1, 1, 1\] to not all be == 1/m)
270
+ end
271
+ end
272
+ end
@@ -0,0 +1,21 @@
1
+ # Requires supporting ruby files with custom matchers and macros, etc,
2
+ # in spec/support/ and its subdirectories.
3
+
4
+ RSpec.configure do |config|
5
+ # == Mock Framework
6
+ #
7
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
8
+ #
9
+ # config.mock_with :mocha
10
+ # config.mock_with :flexmock
11
+ # config.mock_with :rr
12
+ config.mock_with :rspec
13
+
14
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
15
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
16
+
17
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
18
+ # examples within a transaction, remove the following line or assign false
19
+ # instead of true.
20
+ # config.use_transactional_fixtures = true
21
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-collection
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 2
7
+ - 0
8
+ - 0
9
+ version: 2.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Jim Weirich
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-12 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec-core
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 2
30
+ - 0
31
+ - 0
32
+ version: 2.0.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: " For example:\n\n collection.should all_be > 0\n\n will specify that each element of the collection should be greater\n than zero. Each element of the collection that fails the test will\n be reported in the error message.\n"
36
+ email: jim@edgecase.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.md
43
+ files:
44
+ - lib/rspec-collection/all_be.rb
45
+ - lib/rspec-collection/version.rb
46
+ - lib/rspec-collection.rb
47
+ - spec/rspec-collection/all_be_spec.rb
48
+ - spec/spec_helper.rb
49
+ - Rakefile
50
+ - rakelib/gem.rake
51
+ - README.md
52
+ has_rdoc: true
53
+ homepage: http://github.com/jimweirich/rspec-collection
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options:
58
+ - ""
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project: n/a
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Allow RSpec assertions over the elements of a collection.
84
+ test_files: []
85
+