must_be 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,194 @@
1
+ require 'spec_helper'
2
+
3
+ describe MustBe do
4
+ include MustBeExampleHelper
5
+
6
+ describe Proxy do
7
+ subject { Proxy.new(:moxie) }
8
+
9
+ context "when initialized with method other than :must or :must_not" do
10
+ it "should raise ArgumentError" do
11
+ expect do
12
+ Proxy.new(:moxie, :must_could)
13
+ end.should raise_error(ArgumentError,
14
+ "assertion (:must_could) must be :must or :must_not")
15
+ end
16
+ end
17
+
18
+ describe "it should not forward" do
19
+ example "#__id__" do
20
+ subject.__id__.should_not == :moxie.__id__
21
+ end
22
+
23
+ example "#object_id" do
24
+ subject.object_id.should_not == :moxie.object_id
25
+ end
26
+ end
27
+ end
28
+
29
+ module ItShouldNotifyExpectations
30
+ def it_should_notify(message, &implementation)
31
+ example "#{message} should notify" do
32
+ instance_eval &implementation
33
+ should notify(message)
34
+ end
35
+ end
36
+
37
+ def it_should_not_notify(message, &implementation)
38
+ example "#{message} should not notify" do
39
+ instance_eval &implementation
40
+ should_not notify
41
+ end
42
+ end
43
+ end
44
+
45
+ describe '#must' do
46
+ extend ItShouldNotifyExpectations
47
+
48
+ context "when called with a block" do
49
+ it "should return the receiver" do
50
+ 0xdad.must{}.object_id.should == 0xdad.object_id
51
+ end
52
+
53
+ it "should notify if block returns false" do
54
+ :helm.must{|receiver| receiver == :harm }.should == :helm
55
+ should notify(":helm.must {}")
56
+ end
57
+
58
+ it "should notify with message if provided" do
59
+ :ice.must("ice must be icy") do |receiver|
60
+ receiver == :icy
61
+ end.should == :ice
62
+ should notify("ice must be icy")
63
+ end
64
+
65
+ it "should not notify if block returns true" do
66
+ :jinn.must{|receiver| receiver == :jinn }.should == :jinn
67
+ should_not notify
68
+ end
69
+
70
+ it "should allow nested #must_notify" do
71
+ :keys.must("electrify kites") do |receiver, message|
72
+ must_notify("#{receiver} must #{message}")
73
+ true
74
+ end.should == :keys
75
+ should notify("keys must electrify kites")
76
+ end
77
+ end
78
+
79
+ context "when used to proxy" do
80
+ subject { 230579.must }
81
+
82
+ it_should_notify("230579.must.==(70581)") do
83
+ subject == 70581
84
+ end
85
+
86
+ it_should_not_notify("230579.must.>(411)") do
87
+ subject > 411
88
+ end
89
+
90
+ it_should_not_notify("230579.must.odd?") do
91
+ subject.odd?
92
+ end
93
+
94
+ it_should_notify("230579.must.between?(-4, 4)") do
95
+ subject.between?(-4, 4)
96
+ end
97
+
98
+ it_should_notify("230579.must.respond_to?(:finite?)") do
99
+ subject.respond_to? :finite?
100
+ end
101
+
102
+ it_should_not_notify("230579.must.instance_of?(Fixnum)") do
103
+ subject.instance_of? Fixnum
104
+ end
105
+
106
+ it_should_notify("230579.must.instance_of?(Integer)") do
107
+ subject.instance_of? Integer
108
+ end
109
+
110
+ it "should have a different #object_id" do
111
+ subject.should == 230579
112
+ subject.object_id.should_not == 230579.object_id
113
+ end
114
+
115
+ context "after MustBe.disable" do
116
+ before_disable_after_enable
117
+
118
+ it "should have the same #object_id" do
119
+ subject.object_id.should == 230579.object_id
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#must_not' do
126
+ extend ItShouldNotifyExpectations
127
+
128
+ context "when called with a block" do
129
+ it "should return the receiver" do
130
+ 0xdad.must_not{}.should == 0xdad
131
+ end
132
+
133
+ it "should notify if block returns true" do
134
+ :helm.must_not{|receiver| receiver == :helm }.should == :helm
135
+ should notify(":helm.must_not {}")
136
+ end
137
+
138
+ it "should notify with message if provided" do
139
+ :ice.must_not("ice must not be ice") do |receiver|
140
+ receiver == :ice
141
+ end.should == :ice
142
+ should notify("ice must not be ice")
143
+ end
144
+
145
+ it "should not notify if block returns false" do
146
+ :jinn.must_not{|receiver| receiver == :gem }.should == :jinn
147
+ should_not notify
148
+ end
149
+
150
+ it "should allow nested #must_notify" do
151
+ :keys.must_not("electrify kites") do |receiver, message|
152
+ must_notify("#{receiver} must not #{message}")
153
+ false
154
+ end.should == :keys
155
+ should notify("keys must not electrify kites")
156
+ end
157
+ end
158
+
159
+ context "when used to proxy" do
160
+ subject { 230579.must_not }
161
+
162
+ it_should_not_notify("230579.must_not.==(70581)") do
163
+ subject == 70581
164
+ end
165
+
166
+ it_should_notify("230579.must_not.>(411)") do
167
+ subject > 411
168
+ end
169
+
170
+ it_should_notify("230579.must_not.odd?") do
171
+ subject.odd?
172
+ end
173
+
174
+ it_should_not_notify("230579.must_not.between?(-4, 4)") do
175
+ subject.between?(-4, 4)
176
+ end
177
+
178
+ it_should_not_notify(
179
+ "230579.must_not.respond_to?(:finite?)") do
180
+ subject.respond_to? :finite?
181
+ end
182
+
183
+ it_should_notify("230579.must_not.instance_of?(Fixnum)") do
184
+ subject.instance_of? Fixnum
185
+ end
186
+
187
+ it_should_not_notify(
188
+ "230579.must_not.instance_of?(Integer)") do
189
+ subject.instance_of? Integer
190
+ end
191
+ end
192
+ end
193
+
194
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ # Since the notify matcher has lots of cases, we should spec out each
4
+ # possible combination to make sure it has the expected behavior.
5
+ #
6
+ # Patterns are built by choosing:
7
+ # Whether there is a note:
8
+ # :note
9
+ # :no_note
10
+ # Polarity of the expectation:
11
+ # :should
12
+ # :should_not
13
+ # Message argument of notify matcher:
14
+ # nil
15
+ # 'same'
16
+ # 'different'
17
+ #
18
+ describe "Notify Matcher" do
19
+ include MustBeExampleHelper
20
+
21
+ def self.it_should_follow_pattern(note, polarity, message, result)
22
+ context "when there is #{note == :note ? "a" : "no"} note" do
23
+ message_arg = message ? %{("#{message}")} : ""
24
+ call = "#{polarity} notify#{message_arg}"
25
+ it "should #{result ? "fail" : "succeed"} if expecting #{call}" do
26
+ pattern_notify = lambda do
27
+ must_notify("same") if note == :note
28
+ send(polarity, notify(message))
29
+ end
30
+
31
+ pattern_notify.send(result ? :should : :should_not, raise_error(
32
+ Spec::Expectations::ExpectationNotMetError, result))
33
+ end
34
+ end
35
+ end
36
+
37
+ it_should_follow_pattern :note, :should, nil, nil
38
+ it_should_follow_pattern :note, :should, 'same', nil
39
+ it_should_follow_pattern :note, :should, 'different',
40
+ 'expected note with message: "different"' "\n"\
41
+ ' got note with message: "same"'
42
+ it_should_follow_pattern :note, :should_not, nil,
43
+ 'expected no note' "\n"\
44
+ 'got note with message: "same"'
45
+ it_should_follow_pattern :note, :should_not, 'same',
46
+ 'did NOT expect note with message: "same"' "\n"\
47
+ ' got note with message: "same"'
48
+ it_should_follow_pattern :note, :should_not, 'different', nil
49
+
50
+ it_should_follow_pattern :no_note, :should, nil,
51
+ 'expected a note'
52
+ it_should_follow_pattern :no_note, :should, 'same',
53
+ 'expected a note with message: "same"'
54
+ it_should_follow_pattern :no_note, :should, 'different',
55
+ 'expected a note with message: "different"'
56
+ it_should_follow_pattern :no_note, :should_not, nil, nil
57
+ it_should_follow_pattern :no_note, :should_not, 'same', nil
58
+ it_should_follow_pattern :no_note, :should_not, 'different', nil
59
+ end
@@ -0,0 +1,180 @@
1
+ ### MUST_BE__DO_NOT_AUTOMATICALLY_INCLUDE_IN_OBJECT ###
2
+ #
3
+ # Hard to describe within normal RSpec control flow. Instead we raise a
4
+ # RuntimeError if MUST_BE__DO_NOT_AUTOMATICALLY_INCLUDE_IN_OBJECT doesn't
5
+ # behave as expected.
6
+ #
7
+
8
+ ENV['MUST_BE__NOTIFIER'] = nil # to make `rake spec` work.
9
+ ENV['MUST_BE__DO_NOT_AUTOMATICALLY_INCLUDE_IN_OBJECT'] = "" # any string.
10
+
11
+ require 'lib/must_be'
12
+
13
+ if Object.include? MustBe
14
+ raise "MustBe should not be automatically included in Object."
15
+ end
16
+
17
+ def expect_error(error_type)
18
+ begin
19
+ raised_error = false
20
+ yield
21
+ rescue error_type
22
+ raised_error = true
23
+ end
24
+ raise "expected #{error_type}" unless raised_error
25
+ end
26
+
27
+ # Show that MustBe does not need to be included in Object to be useful.
28
+ def example_of_must_be_inclusion
29
+ example = Object.new
30
+ example.extend(MustBe)
31
+ example.must == example
32
+ example.must_not_be_nil
33
+
34
+ # must_only_contain and must_not_contain require contents to also include
35
+ # MustBe.
36
+ contents = Object.new
37
+
38
+ container = [contents]
39
+ container.extend(MustBe)
40
+
41
+ expect_error(NoMethodError) do
42
+ container.must_only_contain
43
+ end
44
+
45
+ contents.extend(MustBe)
46
+ expect_error(MustBe::Note) do
47
+ container.must_not_contain
48
+ end
49
+ end
50
+ example_of_must_be_inclusion
51
+
52
+ class Object
53
+ include MustBe
54
+ end
55
+
56
+ ### MustBeExampleHelper ###
57
+
58
+ module MustBeExampleHelper
59
+
60
+ $default_must_be_notifier = MustBe.notifier
61
+
62
+ def self.included(example_group)
63
+ example_group.before do
64
+ MustBe.notifier = lambda do |note|
65
+ @note = note
66
+ false
67
+ end
68
+ end
69
+
70
+ class <<example_group
71
+
72
+ ### Value Assertion ###
73
+
74
+ def it_should_have_must_be_value_assertion(method, value, alt = 411)
75
+ describe '##{method}' do
76
+ it "should not notify if receiver is #{value.inspect}" do
77
+ value.send(method).should == value
78
+ should_not notify
79
+ end
80
+
81
+ it "should notify if receiver is not #{value.inspect}" do
82
+ alt.send(method).should == alt
83
+ should notify("#{alt.inspect}.#{method}")
84
+ end
85
+ end
86
+ end
87
+
88
+ def it_should_have_must_not_be_value_assertion(method, value, alt = 411)
89
+ describe '##{method}' do
90
+ it "should notify if receiver is #{value.inspect}" do
91
+ value.send(method)
92
+ should notify("#{value.inspect}.#{method}")
93
+ end
94
+
95
+ it "should not notify if receiver is not #{value.inspect}" do
96
+ alt.send(method)
97
+ should_not notify
98
+ end
99
+ end
100
+ end
101
+
102
+ ### Notify Example ###
103
+
104
+ def notify_example(expression, message = nil)
105
+ expression = expression.gsub(/\n\s*/, " ")
106
+ if message.is_a? Module
107
+ message = expression+", but matches #{message}"
108
+ end
109
+ example "#{expression} should #{message ? "" : "not "}notify" do
110
+ eval(expression)
111
+ if message == true
112
+ should notify
113
+ elsif message
114
+ should notify(message)
115
+ else
116
+ should_not notify
117
+ end
118
+ end
119
+ end
120
+
121
+ ### Enable ###
122
+
123
+ def before_disable_after_enable
124
+ before do
125
+ MustBe.disable
126
+ end
127
+
128
+ after do
129
+ MustBe.enable
130
+ end
131
+ end
132
+
133
+ def before_disable_and_reenable
134
+ before do
135
+ MustBe.disable
136
+ MustBe.enable
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ ### Notify Matcher ###
143
+
144
+ def notify(message = nil)
145
+ simple_matcher do |given, matcher|
146
+ result, message =
147
+ if @note
148
+ if message
149
+ if message === @note.message
150
+ [true,
151
+ "did NOT expect note with message: #{message.inspect}\n"\
152
+ " got note with message: #{@note.message.inspect}"]
153
+ else
154
+ [false,
155
+ "expected note with message: #{message.inspect}\n"\
156
+ " got note with message: #{@note.message.inspect}"]
157
+ end
158
+ else
159
+ [true,
160
+ "expected no note\n"\
161
+ "got note with message: #{@note.message.inspect}"]
162
+ end
163
+ else
164
+ [false, if message
165
+ "expected a note with message: #{message.inspect}"
166
+ else
167
+ "expected a note"
168
+ end]
169
+ end
170
+
171
+ if result
172
+ matcher.negative_failure_message = message
173
+ else
174
+ matcher.failure_message = message
175
+ end
176
+
177
+ result
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,176 @@
1
+ require 'spec_helper'
2
+
3
+ describe MustBe, " typical usage" do
4
+ include MustBeExampleHelper
5
+
6
+ describe '#must_be', " notifies when receiver doesn't case-equal (===) any"\
7
+ " of its arguments" do
8
+ context "when called with a Class, it notifies unless"\
9
+ " receiver.is_a? Class" do
10
+ notify_example %{4.must_be(Numeric)}
11
+ notify_example %{4.must_be(Float)}, Fixnum
12
+ end
13
+
14
+ context "when called with a regexp, it notifies unless"\
15
+ " regexp =~ receiver" do
16
+ notify_example %{"funny".must_be(/n{2}/)}
17
+ notify_example %{"funny".must_be(/\d/)}, String
18
+ end
19
+
20
+ context "when called with a range, it notifies unless"\
21
+ " range.include? receiver" do
22
+ notify_example %{5.must_be(1..5)}
23
+ notify_example %{5.must_be(1...5)}, Fixnum
24
+ end
25
+
26
+ context "when called with an array, it notifies unless"\
27
+ " array == receiver" do
28
+ notify_example %{[3, 5].must_be([3, 5])}
29
+ notify_example %{3.must_be([3, 5])}, Fixnum
30
+ end
31
+
32
+ context "when called with a proc, it notifies unless proc[receiver]" do
33
+ notify_example %{:anything.must_be(lambda {|v| true })}
34
+ notify_example %{:anything.must_be(lambda {|v| false })}, true
35
+ end
36
+
37
+ context "when called with most other objects, it notifies unless"\
38
+ " object == receiver" do
39
+ notify_example %{:yep.must_be(:yep)}
40
+ notify_example %{:yep.must_be(:nope)}, Symbol
41
+ end
42
+
43
+ context "when called without arguments, it notifies if receiver is"\
44
+ " false or nil" do
45
+ notify_example %{5.must_be}
46
+ notify_example %{nil.must_be}, NilClass
47
+ notify_example %{false.must_be}, FalseClass
48
+ end
49
+
50
+ context "when called with multiple arguments, it notifies unless"\
51
+ " receiver case-equals (===) one of them" do
52
+ notify_example %{:happy.must_be(String, Symbol)}
53
+ notify_example %{934.must_be(String, Symbol)}, Fixnum
54
+ end
55
+ end
56
+
57
+ describe '#must' do
58
+ context "when called with a block, it notifies if the result is"\
59
+ " false or nil" do
60
+ notify_example %{:helm.must("message") {|receiver, message| message ==
61
+ "mess" }}, "message"
62
+ notify_example %{:helm.must {|receiver| receiver == :helm }}
63
+ end
64
+
65
+ context "when called with no argument, it returns a proxy which notifies"\
66
+ " when a method returning false or nil is called" do
67
+ notify_example %{5.must == 4}, "5.must.==(4)"
68
+ notify_example %{5.must > 4}
69
+ end
70
+ end
71
+
72
+ describe '#must_only_contain' do
73
+ context "with Array receiver, it should notify unless each member in the"\
74
+ " array case-equals (===) one of the arguments" do
75
+ notify_example %{[1, :hi, "wow"].must_only_contain(Numeric, Symbol,
76
+ String)}
77
+ notify_example %{[1, :hi, "wow"].must_only_contain(Numeric, String)},
78
+ "must_only_contain: :hi.must_be(Numeric, String), but matches"\
79
+ " Symbol in container [1, :hi, \"wow\"]"
80
+ end
81
+
82
+ context "with Hash receiver, it should notify unless each pair"\
83
+ " case-equals (===) a pair in an argument hash" do
84
+ notify_example %{{:key => "value"}.must_only_contain({Symbol => [Symbol,
85
+ String]})}
86
+ notify_example %{{:key => "value"}.must_only_contain({Symbol => Symbol},
87
+ {Symbol => Numeric})}, "must_only_contain: pair {:key=>\"value\"}"\
88
+ " does not match [{Symbol=>Symbol}, {Symbol=>Numeric}] in"\
89
+ " container {:key=>\"value\"}"
90
+ end
91
+ end
92
+
93
+ describe '#must_only_ever_contain' do
94
+ context "like #must_only_contain, it notifies unless each member"\
95
+ " case-equals (===) one of the arguments" do
96
+ notify_example %{[1, :hi, "wow"].must_only_ever_contain(Numeric, Symbol,
97
+ String)}
98
+ notify_example %{[1, :hi, "wow"].must_only_ever_contain(Numeric,
99
+ String)},
100
+ "must_only_ever_contain: :hi.must_be(Numeric, String), but"\
101
+ " matches Symbol in container [1, :hi, \"wow\"]"
102
+ end
103
+
104
+ context "it notifies whenever the container is updated to hold an member"\
105
+ " which does not case-equal (===) one of the arguments" do
106
+ describe "[1, 2, 3].must_only_ever_contain(Numeric)" do
107
+ subject { [1, 2, 3].must_only_ever_contain(Numeric) }
108
+
109
+ notify_example %{subject << 3.14}
110
+ notify_example %{subject << nil}, "must_only_ever_contain:"\
111
+ " Array#<<(nil): nil.must_be(Numeric), but matches NilClass in"\
112
+ " container [1, 2, 3, nil]"
113
+ end
114
+ end
115
+ end
116
+
117
+ describe '#must_notify', " is a primitive used to define other must_be"\
118
+ " methods" do
119
+ context "when called with a string, it notifies with a string message" do
120
+ notify_example %{must_notify("message")}, "message"
121
+ end
122
+
123
+ context "when called with multiple arguments, it notifies with method"\
124
+ " invocation details" do
125
+ notify_example %{must_notify(:receiver, :method_name,
126
+ [:arg, :arg, :arg], lambda {}, " additional message")},
127
+ ":receiver.method_name(:arg, :arg, :arg) {} additional message"
128
+ end
129
+ end
130
+
131
+ describe '#must_check', " interrupts normal notification" do
132
+ context "when called with a block, it yields to the block" do
133
+ example "#must_check returns a note if the block calls #must_notify" do
134
+ note = must_check do
135
+ must_notify("message")
136
+ end
137
+ note.message.should == "message"
138
+ should_not notify
139
+ end
140
+
141
+ example "#must_check returns nil if the block does not call"\
142
+ " #must_notify" do
143
+ note = must_check do
144
+ :would_not_notify
145
+ end
146
+ note.should be_nil
147
+ should_not notify
148
+ end
149
+ end
150
+
151
+ context "when called with a proc and a block, #must_check calls the"\
152
+ " proc" do
153
+ example "#must_check passes the note to the block and notifies with"\
154
+ " the result of the block if the proc calls #must_notify" do
155
+ must_check(lambda do
156
+ must_notify("original message")
157
+ end) do |note|
158
+ note.message.should == "original message"
159
+ "new message"
160
+ end
161
+ should notify("new message")
162
+ end
163
+
164
+ example "the block is not called if the proc does not call"\
165
+ " #must_notify" do
166
+ did_call_block = false
167
+ must_check(lambda do
168
+ :would_not_notify
169
+ end) do |note|
170
+ did_call_block = true
171
+ end
172
+ did_call_block.should be_false
173
+ end
174
+ end
175
+ end
176
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: must_be
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - William Taysom
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-12 00:00:00 +08:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: must_be provides runtime assertions which can easily be disabled in production environments. Likewise, the notifier can be customized to raise errors, log failure, enter the debugger, or anything else.
23
+ email: wtaysom@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.md
30
+ files:
31
+ - .gitignore
32
+ - README.md
33
+ - Rakefile
34
+ - VERSION
35
+ - doc/readme/examples.rb
36
+ - doc/readme/run_examples.rb
37
+ - lib/must_be.rb
38
+ - lib/must_be/attr_typed.rb
39
+ - lib/must_be/basic.rb
40
+ - lib/must_be/containers.rb
41
+ - lib/must_be/containers_registered_classes.rb
42
+ - lib/must_be/core.rb
43
+ - lib/must_be/nonstandard_control_flow.rb
44
+ - lib/must_be/proxy.rb
45
+ - must_be.gemspec
46
+ - spec/must_be/attr_typed_spec.rb
47
+ - spec/must_be/basic_spec.rb
48
+ - spec/must_be/containers_spec.rb
49
+ - spec/must_be/core_spec.rb
50
+ - spec/must_be/nonstandard_control_flow_spec.rb
51
+ - spec/must_be/proxy_spec.rb
52
+ - spec/notify_matcher_spec.rb
53
+ - spec/spec_helper.rb
54
+ - spec/typical_usage_spec.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/wtaysom/must_be
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.7
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: must_be Runtime Assertions
89
+ test_files:
90
+ - spec/must_be/attr_typed_spec.rb
91
+ - spec/must_be/basic_spec.rb
92
+ - spec/must_be/containers_spec.rb
93
+ - spec/must_be/core_spec.rb
94
+ - spec/must_be/nonstandard_control_flow_spec.rb
95
+ - spec/must_be/proxy_spec.rb
96
+ - spec/notify_matcher_spec.rb
97
+ - spec/spec_helper.rb
98
+ - spec/typical_usage_spec.rb