ensure_it 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,243 @@
1
+ require 'benchmark'
2
+
3
+ if ENV['USE_REFINES'] == 'true'
4
+ ENSURE_IT_REFINED = true
5
+ end
6
+
7
+ module EnsureIt
8
+ class Benchmark < Thor
9
+ OBJECTS = [
10
+ nil, true, false, 0, 0.1, '1/3'.to_r, 'test', :test, Object, Class, ->{}
11
+ ]
12
+
13
+ class_option :smart, aliases: '-s', desc: 'use smart errors'
14
+ class_option :count, aliases: '-n', desc: 'number of tests', default: 10000
15
+ class_option :profile, aliases: '-p', desc: 'profile'
16
+
17
+ desc 'symbol', 'runs benchmarks for ensure_symbol'
18
+ def symbol
19
+ run_benchmark :symbol, ensure_proc: ->(x) { x.ensure_symbol } do |x|
20
+ x = x.to_sym if x.is_a?(String)
21
+ x.is_a?(Symbol) ? x : nil
22
+ end
23
+ end
24
+
25
+ desc 'symbol!', 'runs benchmarks for ensure_symbol!'
26
+ def symbol!
27
+ run_benchmark :symbol!, ensure_proc: ->(x) { x.ensure_symbol! } do |x|
28
+ x = x.to_sym if x.is_a?(String)
29
+ raise ArgumentError unless x.is_a?(Symbol)
30
+ end
31
+ end
32
+
33
+ desc 'string', 'runs benchmarks for ensure_string'
34
+ def string
35
+ run_benchmark :string, ensure_proc: ->(x) { x.ensure_string } do |x|
36
+ x = x.to_s if x.is_a?(Symbol)
37
+ x.is_a?(String) ? x : nil
38
+ end
39
+ end
40
+
41
+ desc 'string!', 'runs benchmarks for ensure_string!'
42
+ def string!
43
+ run_benchmark :string!, ensure_proc: ->(x) { x.ensure_string! } do |x|
44
+ x = x.to_s if x.is_a?(Symbol)
45
+ raise ArgumentError unless x.is_a?(String)
46
+ end
47
+ end
48
+
49
+ desc 'integer', 'runs benchmarks for ensure_integer'
50
+ def integer
51
+ run_benchmark :integer, ensure_proc: ->(x) { x.ensure_integer } do |x|
52
+ if x.is_a?(Integer)
53
+ x
54
+ elsif x.is_a?(Float) || x.is_a?(Rational)
55
+ x.round
56
+ elsif x.is_a?(String)
57
+ case x
58
+ when ::EnsureIt::INT_REGEXP then x.to_i
59
+ when ::EnsureIt::HEX_REGEXP then x[2..-1].to_i(16)
60
+ when ::EnsureIt::BIN_REGEXP then x[2..-1].to_i(2)
61
+ else nil
62
+ end
63
+ else
64
+ nil
65
+ end
66
+ end
67
+ end
68
+
69
+ desc 'integer!', 'runs benchmarks for ensure_integer!'
70
+ def integer!
71
+ run_benchmark :integer!, ensure_proc: ->(x) { x.ensure_integer! } do |x|
72
+ if x.is_a?(Integer)
73
+ x
74
+ elsif x.is_a?(Float) || x.is_a?(Rational)
75
+ x.round
76
+ elsif x.is_a?(String)
77
+ case x
78
+ when ::EnsureIt::INT_REGEXP then x.to_i
79
+ when ::EnsureIt::HEX_REGEXP then x[2..-1].to_i(16)
80
+ when ::EnsureIt::BIN_REGEXP then x[2..-1].to_i(2)
81
+ else raise ArgumentError
82
+ end
83
+ else
84
+ raise ArgumentError
85
+ end
86
+ end
87
+ end
88
+
89
+ desc 'float', 'runs benchmarks for ensure_float'
90
+ def float
91
+ run_benchmark :float, ensure_proc: ->(x) { x.ensure_float } do |x|
92
+ if x.is_a?(Float)
93
+ x
94
+ elsif x.is_a?(Numeric) ||
95
+ x.is_a?(String) && ::EnsureIt::FLOAT_REGEXP =~ x
96
+ x.to_f
97
+ else
98
+ nil
99
+ end
100
+ end
101
+ end
102
+
103
+ desc 'float!', 'runs benchmarks for ensure_float!'
104
+ def float!
105
+ run_benchmark :float!, ensure_proc: ->(x) { x.ensure_float! } do |x|
106
+ if x.is_a?(Float)
107
+ x
108
+ elsif x.is_a?(Numeric) ||
109
+ x.is_a?(String) && ::EnsureIt::FLOAT_REGEXP =~ x
110
+ x.to_f
111
+ else
112
+ raise ArgumentError
113
+ end
114
+ end
115
+ end
116
+
117
+ desc 'non_bang', 'runs all non-bang benchmarks'
118
+ def non_bang
119
+ invoke(:symbol)
120
+ invoke(:string)
121
+ invoke(:integer)
122
+ invoke(:float)
123
+ end
124
+
125
+ desc 'bang', 'runs all bang benchmarks'
126
+ def bang
127
+ invoke(:symbol!)
128
+ invoke(:string!)
129
+ invoke(:integer!)
130
+ invoke(:float!)
131
+ end
132
+
133
+ desc 'all', 'runs all benchmarks'
134
+ def all
135
+ invoke(:non_bang)
136
+ invoke(:bang)
137
+ end
138
+
139
+ no_commands do
140
+ protected
141
+
142
+ def run_benchmark(task_name, ensure_proc: proc {}, &standard_proc)
143
+ load_ensure_it
144
+ ensure_it, standard = [], []
145
+ start_task(task_name)
146
+ ::Benchmark.benchmark do |x|
147
+ start_profile(task_name)
148
+ ensure_it = x.report('ensure_it: ') do
149
+ OBJECTS.each do |obj|
150
+ count.times { ensure_proc.call(obj) rescue ::EnsureIt::Error }
151
+ end
152
+ end
153
+ standard = x.report('standard way: ') do
154
+ OBJECTS.each do |obj|
155
+ count.times { standard_proc.call(obj) rescue ArgumentError }
156
+ end
157
+ end
158
+ end_profile(task_name)
159
+ end
160
+ end_task(task_name)
161
+ [ensure_it, standard]
162
+ end
163
+
164
+ def start_task(task_name)
165
+ text = "Starting benchmarks for #ensure_#{task_name} "
166
+ if ENSURE_IT_REFINED == true
167
+ text << ' with refined version of EnsureIt.'
168
+ else
169
+ text << ' with monkey-patched version of EnsureIt.'
170
+ end
171
+ text << " Errors: #{::EnsureIt.config.errors}."
172
+ text << " Ruby version: #{RUBY_VERSION}"
173
+ say text, :green
174
+ end
175
+
176
+ def end_task(task_name); end
177
+
178
+ def start_profile(task_name)
179
+ RubyProf.start if profile?
180
+ end
181
+
182
+ def end_profile(task_name)
183
+ if profile?
184
+ result = RubyProf.stop
185
+ result.eliminate_methods!([
186
+ /\ABenchmark/,
187
+ /Thor::(?!Sandbox::EnsureIt::Benchmark#run_benchmark)/,
188
+ /Integer#times/, /Struct::Tms/, /<Module::Process>/,
189
+ /<Class::Time>/, /Time/
190
+ ])
191
+ file = File.join(profile_path, "ensure_#{task_name}.dot")
192
+ unless Dir.exist?(File.dirname(file))
193
+ FileUtils.mkpath File.dirname(file)
194
+ end
195
+ printer = RubyProf::DotPrinter.new(result)
196
+ File.open(file, 'w') { |f| printer.print(f, min_percent: 0) }
197
+ file = File.join(profile_path, "ensure_#{task_name}.txt")
198
+ printer = RubyProf::GraphPrinter.new(result)
199
+ File.open(file, 'w') { |f| printer.print(f, min_percent: 0) }
200
+ end
201
+ end
202
+
203
+ def count
204
+ n = options['count'].to_i
205
+ n <= 0 ? 10000 : n
206
+ end
207
+
208
+ def refined?
209
+ options['refined'] == 'refined' || options['refined'] == 'true'
210
+ end
211
+
212
+ def profile?
213
+ options.key?('profile')
214
+ end
215
+
216
+ def profile_path
217
+ if options['profile'] == 'profile' || options['profile'] == 'true'
218
+ File.join(Dir.pwd, 'tmp')
219
+ else
220
+ File.expand_path(File.join('..', 'tmp'), __FILE__)
221
+ end
222
+ end
223
+
224
+ def errors
225
+ if options['smart'] == 'smart' || options['smart'] == true
226
+ :smart
227
+ else
228
+ :standard
229
+ end
230
+ end
231
+
232
+ def load_ensure_it
233
+ lib = File.expand_path(File.join('..', '..'), __FILE__)
234
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
235
+ require(refined? ? 'ensure_it_refined' : 'ensure_it')
236
+ ::EnsureIt.configure do |config|
237
+ config.errors = errors
238
+ end
239
+ require 'ruby-prof' if profile?
240
+ end
241
+ end
242
+ end
243
+ end
@@ -2,35 +2,35 @@ require 'spec_helper'
2
2
 
3
3
  describe EnsureIt do
4
4
  describe 'refines requirement' do
5
- before { @backup = ENSURE_IT_REFINES }
5
+ before { @backup = ENSURE_IT_REFINED }
6
6
 
7
7
  after do
8
- if defined? ENSURE_IT_REFINES
9
- Object.instance_eval { remove_const(:ENSURE_IT_REFINES) }
8
+ if defined? ENSURE_IT_REFINED
9
+ Object.instance_eval { remove_const(:ENSURE_IT_REFINED) }
10
10
  end
11
- ENSURE_IT_REFINES = @backup
11
+ ENSURE_IT_REFINED = @backup
12
12
  end
13
13
 
14
14
  def load_refines
15
- if defined? ENSURE_IT_REFINES
16
- Object.instance_eval { remove_const(:ENSURE_IT_REFINES) }
15
+ if defined? ENSURE_IT_REFINED
16
+ Object.instance_eval { remove_const(:ENSURE_IT_REFINED) }
17
17
  end
18
18
  load(File.expand_path(
19
- File.join(%w(.. .. .. lib ensure_it_refines.rb)), __FILE__
19
+ File.join(%w(.. .. .. lib ensure_it_refined.rb)), __FILE__
20
20
  ))
21
21
  end
22
22
 
23
23
  if RUBY_VERSION >= '2.1'
24
- it 'defines ENSURE_IT_REFINES' do
24
+ it 'defines ENSURE_IT_REFINED' do
25
25
  load_refines
26
- expect(ENSURE_IT_REFINES).to be_true
26
+ expect(ENSURE_IT_REFINED).to be_true
27
27
  end
28
28
  else
29
- it %q{warns with ruby < 2.1 and doesn't defines ENSURE_IT_REFINES} do
29
+ it %q{warns with ruby < 2.1 and doesn't defines ENSURE_IT_REFINED} do
30
30
  expect {
31
31
  load_refines
32
32
  }.to warn('EsureIt: refines supported only for ruby >= 2.1')
33
- expect(ENSURE_IT_REFINES).to be_false
33
+ expect(ENSURE_IT_REFINED).to be_false
34
34
  end
35
35
  end
36
36
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_array(*args)
7
7
  obj.ensure_array(*args)
@@ -59,9 +59,9 @@ describe EnsureIt do
59
59
  it_behaves_like 'array parser'
60
60
  it_behaves_like 'empty array creator for unmet objects', except: Array
61
61
 
62
- it 'and returns nil with wrong: nil option' do
63
- expect(call_for(true, wrong: nil)).to be_nil
64
- expect(call_for(true, wrong: 1)).to eq 1
62
+ it 'and returns nil with default: nil option' do
63
+ expect(call_for(true, default: nil)).to be_nil
64
+ expect(call_for(true, default: 1)).to eq 1
65
65
  end
66
66
  end
67
67
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_class(*args)
7
7
  obj.ensure_class(*args)
@@ -25,14 +25,15 @@ describe EnsureIt do
25
25
 
26
26
  describe '#ensure_class' do
27
27
  it_behaves_like 'class selector'
28
+ it_behaves_like 'values checker', Array, Integer, values: [Array]
28
29
 
29
30
  it 'returns nil for wrong classes' do
30
31
  expect(call_for(10)).to be_nil
31
32
  expect(call_for(Float, Integer)).to be_nil
32
33
  end
33
34
 
34
- it 'returns wrong option for wrong classs' do
35
- expect(call_for(10, wrong: true)).to be_true
35
+ it 'returns default option for wrong classs' do
36
+ expect(call_for(10, default: true)).to be_true
36
37
  end
37
38
  end
38
39
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_float(*args)
7
7
  obj.ensure_float(*args)
@@ -51,6 +51,8 @@ describe EnsureIt do
51
51
  '123test', :test123, :'0.1',
52
52
  except: [String, Integer, Float, Rational]
53
53
  )
54
+ it_behaves_like 'values checker', 10.0, 23.5, values: [10.0, 11.0, 12.0]
55
+ it_behaves_like 'values checker', 10, 23, values: [10.0, 11.0, 12.0]
54
56
  end
55
57
 
56
58
  describe '#ensure_float!' do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_hash(*args)
7
7
  obj.ensure_hash(*args)
@@ -29,9 +29,9 @@ describe EnsureIt do
29
29
  it_behaves_like 'hash parser'
30
30
  it_behaves_like 'empty hash creator for unmet objects', except: Hash
31
31
 
32
- it 'and returns nil with wrong: nil option' do
33
- expect(call_for(true, wrong: nil)).to be_nil
34
- expect(call_for(true, wrong: 1)).to eq 1
32
+ it 'and returns nil with default: nil option' do
33
+ expect(call_for(true, default: nil)).to be_nil
34
+ expect(call_for(true, default: 1)).to eq 1
35
35
  end
36
36
  end
37
37
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_instance_of(*args)
7
7
  obj.ensure_instance_of(*args)
@@ -32,8 +32,8 @@ describe EnsureIt do
32
32
  expect(call_for('test', Symbol)).to be_nil
33
33
  end
34
34
 
35
- it 'returns wrong option for wrong instances' do
36
- expect(call_for(:test, String, wrong: 1)).to eq 1
35
+ it 'returns default option for wrong instances' do
36
+ expect(call_for(:test, String, default: 1)).to eq 1
37
37
  end
38
38
  end
39
39
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_integer(*args)
7
7
  obj.ensure_integer(*args)
@@ -75,6 +75,8 @@ describe EnsureIt do
75
75
  '123test', :test123, :'100',
76
76
  except: [String, Symbol, Integer, Float, Rational]
77
77
  )
78
+ it_behaves_like 'values checker', 10, 23, values: [10, 11, 12]
79
+ it_behaves_like 'values checker', 10.3, 12.6, values: [10, 11, 12]
78
80
  end
79
81
 
80
82
  describe '#ensure_integer!' do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_string(*args)
7
7
  obj.ensure_string(*args)
@@ -33,6 +33,8 @@ describe EnsureIt do
33
33
  describe '#ensure_string' do
34
34
  it_behaves_like 'stringifier'
35
35
  it_behaves_like 'niller for unmet objects', except: [String, Symbol]
36
+ it_behaves_like 'values checker', :one, :test, values: %w(one two)
37
+ it_behaves_like 'values checker', 'one', 'test', values: %w(one two)
36
38
  end
37
39
 
38
40
  describe '#ensure_string!' do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  class Tester
4
- using EnsureIt if ENSURE_IT_REFINES
4
+ using EnsureIt if ENSURE_IT_REFINED
5
5
 
6
6
  def ensure_symbol(*args)
7
7
  obj.ensure_symbol(*args)
@@ -21,11 +21,22 @@ describe EnsureIt do
21
21
  it 'and converts string to symbol' do
22
22
  expect(call_for('test')).to eq :test
23
23
  end
24
+
25
+ it 'and returns symbol if it in values' do
26
+ expect(call_for(:test, values: %i(test me))).to eq :test
27
+ expect(call_for('me', values: %i(test me))).to eq :me
28
+ end
24
29
  end
25
30
 
26
31
  describe '#ensure_symbol' do
27
32
  it_behaves_like 'symbolizer'
28
33
  it_behaves_like 'niller for unmet objects', except: [String, Symbol]
34
+ it_behaves_like 'values checker', :one, :test, values: %i(one two)
35
+ it_behaves_like 'values checker', 'one', 'test', values: %i(one two)
36
+
37
+ it 'returns nil if value not in values option' do
38
+ expect(call_for(:val, values: %i(test me))).to be_nil
39
+ end
29
40
  end
30
41
 
31
42
  describe '#ensure_symbol!' do
@@ -35,5 +46,11 @@ describe EnsureIt do
35
46
  except: [String, Symbol],
36
47
  message: /should be a Symbol or a String/
37
48
  )
49
+
50
+ it 'raises error if value not in values option' do
51
+ expect {
52
+ call_for(:val, values: %i(test me))
53
+ }.to raise_error EnsureIt::Error
54
+ end
38
55
  end
39
56
  end
@@ -6,17 +6,25 @@ describe EnsureIt::Error do
6
6
  end
7
7
  end
8
8
 
9
+
9
10
  describe EnsureIt do
10
- describe '.raise_error' do
11
- after { EnsureIt::Config.instance_variable_set(:@errors, nil) }
11
+ before do
12
+ @errors = EnsureIt.config.errors
13
+ EnsureIt::Config.instance_variable_set(:@errors, nil)
14
+ end
12
15
 
16
+ after do
17
+ EnsureIt::Config.instance_variable_set(:@errors, @errors)
18
+ end
19
+
20
+ describe '.raise_error' do
13
21
  it 'raises EnsureIt::Error by default' do
14
22
  expect {
15
23
  call_error(:test_method)
16
24
  }.to raise_error EnsureIt::Error
17
25
  end
18
26
 
19
- it 'raisesspecified error and message' do
27
+ it 'raises specified error and message' do
20
28
  expect {
21
29
  call_error(:test_method, error: ArgumentError, message: 'test')
22
30
  }.to raise_error ArgumentError, 'test'
@@ -115,7 +123,12 @@ describe EnsureIt do
115
123
  it "finds #{var} name" do
116
124
  m = method("test_#{var}_caller")
117
125
  args = [true] * (m.arity < 0 ? -m.arity - 1 : m.arity)
118
- error = get_error { m.call(*args) }
126
+ error = nil
127
+ begin
128
+ m.call(*args)
129
+ rescue EnsureIt::Error => err
130
+ error = err
131
+ end
119
132
  expect(error.message).to eq message
120
133
  end
121
134
  end
@@ -17,7 +17,7 @@ describe EnsureIt do
17
17
  end
18
18
  end)
19
19
  result =
20
- if ENSURE_IT_REFINES
20
+ if ENSURE_IT_REFINED
21
21
  PatchTestWrapper.module_eval do
22
22
  using EnsureIt
23
23
  PatchTestClass.new.test_method
data/spec/spec_helper.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  if ENV['USE_REFINES'] == 'true'
2
- require 'ensure_it_refines'
2
+ require 'ensure_it_refined'
3
3
  else
4
4
  require 'ensure_it'
5
5
  end
6
6
 
7
- if ENV['USE_COVERALLS'] == 'true'
8
- # coveralls.io gem breaks build with our smart errors due to TracePoint
9
- # conflicts, so build it separetly
10
- # TODO: find better way to resolve this issue
11
-
12
- EnsureIt.configure do |config|
13
- config.errors = :standard
14
- end
15
-
16
- require 'coveralls'
17
- Coveralls.wear!
18
- end
7
+ #if ENV['USE_COVERALLS'] == 'true'
8
+ # # coveralls.io gem breaks build with our smart errors due to TracePoint
9
+ # # conflicts, so build it separetly
10
+ # # TODO: find better way to resolve this issue
11
+ #
12
+ # EnsureIt.configure do |config|
13
+ # config.errors = :standard
14
+ # end
15
+ #
16
+ require 'coveralls'
17
+ Coveralls.wear!
18
+ #end
19
19
 
20
20
 
21
21
  Dir[File.join(File.dirname(__FILE__), 'support', '**', '*.rb')].each do |file|
@@ -13,23 +13,12 @@ class Tester
13
13
  end
14
14
 
15
15
  module EnsureItExampleGroup
16
- def self.fake_method; end
17
-
18
16
  def self.included(base)
19
17
  base.instance_eval do
20
18
  metadata[:type] = :ensure_it
21
19
  end
22
20
  end
23
21
 
24
- def general_objects(&block)
25
- enum = GENERAL_OBJECTS.each
26
- enum.define_singleton_method :except do |*classes|
27
- classes = classes.flatten.select { |x| x.is_a?(Class) }
28
- reject { |obj| classes.any? { |c| obj.is_a?(c) } }
29
- end
30
- block_given? ? enum.each(&block) : enum
31
- end
32
-
33
22
  def described_method
34
23
  group = example.metadata[:example_group]
35
24
  while group do
@@ -50,12 +39,6 @@ module EnsureItExampleGroup
50
39
  EnsureIt.raise_error(method_name, **opts)
51
40
  end
52
41
 
53
- def get_error
54
- yield
55
- rescue EnsureIt::Error => e
56
- e
57
- end
58
-
59
42
  RSpec.configure do |config|
60
43
  config.include(
61
44
  self,
@@ -1,5 +1,3 @@
1
- #using EnsureIt if ENSURE_IT_REFINES
2
-
3
1
  def fake_method; end
4
2
 
5
3
  FIXNUM_MAX = (2 ** (0.size * 8 - 2) - 1)
@@ -26,6 +24,14 @@ shared_examples 'niller for unmet objects' do |*add, except: []|
26
24
  compose_objects(add, except).map { |x| call_for(x) }.compact
27
25
  ).to be_empty
28
26
  end
27
+
28
+ it 'returns default value' do
29
+ objects = compose_objects(add, except)
30
+ default = Object.new
31
+ expect(
32
+ objects.map { |x| call_for(x, default: default) }
33
+ ).to match_array [default] * objects.size
34
+ end
29
35
  end
30
36
 
31
37
  shared_examples 'empty array creator for unmet objects' do |*add, except: []|
@@ -58,3 +64,15 @@ shared_examples 'banger for unmet objects' do |*add, except: [], **opts|
58
64
  end
59
65
  end
60
66
  end
67
+
68
+ shared_examples 'values checker' do |obj, unmet, values: []|
69
+ it 'returns value if it in values option' do
70
+ default = Object.new
71
+ expect(call_for(obj, values: values, default: default)).to_not eq default
72
+ end
73
+
74
+ it 'returns default if it not in values option' do
75
+ default = Object.new
76
+ expect(call_for(unmet, values: values, default: default)).to eq default
77
+ end
78
+ end