From 3c7274a3fcbe5f7b82d5d8bfe3937d86b4d68ebd Mon Sep 17 00:00:00 2001 From: Andrew Nordman Date: Sat, 30 Dec 2017 22:57:29 -0600 Subject: [PATCH 1/3] Moves KeyError into Shared spec This refactors my work on KeyError features into a shared spec to reduce the duplication. --- core/env/fetch_spec.rb | 27 ++-------------------- core/hash/fetch_spec.rb | 36 ++++------------------------- core/hash/fetch_values_spec.rb | 11 ++------- core/kernel/shared/sprintf.rb | 42 ++++++++++------------------------ core/string/modulo_spec.rb | 33 ++++---------------------- optional/capi/hash_spec.rb | 21 ++++------------- shared/hash/key_error.rb | 25 ++++++++++++++++++++ 7 files changed, 55 insertions(+), 140 deletions(-) create mode 100644 shared/hash/key_error.rb diff --git a/core/env/fetch_spec.rb b/core/env/fetch_spec.rb index a9c136986e..cc74e32da3 100644 --- a/core/env/fetch_spec.rb +++ b/core/env/fetch_spec.rb @@ -1,4 +1,5 @@ require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../../../shared/hash/key_error', __FILE__) describe "ENV.fetch" do it "returns a value" do @@ -12,31 +13,7 @@ end context "when the key is not found" do - before :each do - @key = "should_never_be_set" - end - - it "raises a KeyError" do - lambda { ENV.fetch @key }.should raise_error(KeyError) - end - - ruby_version_is "2.5" do - it "sets the ENV as the receiver of KeyError" do - -> { - ENV.fetch @key - }.should raise_error(KeyError) { |err| - err.receiver.should == ENV - } - end - - it "sets the non-existent key as the key of KeyError" do - -> { - ENV.fetch @key - }.should raise_error(KeyError) { |err| - err.key.should == @key - } - end - end + it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, ENV end it "provides the given default parameter" do diff --git a/core/hash/fetch_spec.rb b/core/hash/fetch_spec.rb index 38f1a873a0..3914f7e300 100644 --- a/core/hash/fetch_spec.rb +++ b/core/hash/fetch_spec.rb @@ -1,40 +1,14 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../../../shared/hash/key_error', __FILE__) describe "Hash#fetch" do - it "returns the value for key" do - { a: 1, b: -1 }.fetch(:b).should == -1 - end - context "when the key is not found" do - it "raises a KeyError" do - lambda { {}.fetch(:a) }.should raise_error(KeyError) - lambda { Hash.new(5).fetch(:a) }.should raise_error(KeyError) - lambda { Hash.new { 5 }.fetch(:a) }.should raise_error(KeyError) - end - - ruby_version_is "2.5" do - before :each do - @hsh = { } - @key = :a - end - - it "sets the Hash as the receiver of KeyError" do - -> { - @hsh.fetch(@key) - }.should raise_error(KeyError) { |err| - err.receiver.should == @hsh - } - end + it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new(a: 5) + end - it "sets the not-found key as key of KeyError" do - -> { - @hsh.fetch(@key) - }.should raise_error(KeyError) { |err| - err.key.should == @key - } - end - end + it "returns the value for key" do + { a: 1, b: -1 }.fetch(:b).should == -1 end it "returns default if key is not found when passed a default" do diff --git a/core/hash/fetch_values_spec.rb b/core/hash/fetch_values_spec.rb index 1c84697b33..e4bbd2a66f 100644 --- a/core/hash/fetch_values_spec.rb +++ b/core/hash/fetch_values_spec.rb @@ -1,5 +1,6 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes', __FILE__) +require File.expand_path('../../../shared/hash/key_error', __FILE__) ruby_version_is "2.3" do describe "Hash#fetch_values" do @@ -15,15 +16,7 @@ end describe "with unmatched keys" do - it "raises a KeyError" do - ->{ @hash.fetch_values :z }.should raise_error(KeyError) - ->{ @hash.fetch_values :a, :z }.should raise_error(KeyError) - end - - it "returns the default value from block" do - @hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"] - @hash.fetch_values(:a, :z) { |key| "`#{key}' is not found" }.should == [1, "`z' is not found"] - end + it_behaves_like :key_error, ->(obj, key) { obj.fetch_values(key) }, Hash.new(a: 5) end describe "without keys" do diff --git a/core/kernel/shared/sprintf.rb b/core/kernel/shared/sprintf.rb index 1eacf52485..9935d27db9 100644 --- a/core/kernel/shared/sprintf.rb +++ b/core/kernel/shared/sprintf.rb @@ -1,3 +1,5 @@ +require File.expand_path('../../../../shared/hash/key_error', __FILE__) + describe :kernel_sprintf, shared: true do def format(*args) @method.call(*args) @@ -823,36 +825,6 @@ def obj.to_str format("%d %d", 1, foo: "123") }.should raise_error(ArgumentError) end - - context "when there is no matching key" do - it "raises KeyError" do - -> () { - format("%s", {}) - }.should raise_error(KeyError) - end - - ruby_version_is "2.5" do - before :each do - @hash = { fooo: 1 } - end - - it "sets the Hash attempting to format on as receiver of KeyError" do - -> () { - format("%s", @hash) - }.should raise_error(KeyError) { |err| - err.receiver.should == @hash - } - end - - it "sets the faulty key in the formatter as key of KeyError" do - -> () { - format("%s", @hash) - }.should raise_error(KeyError) { |err| - err.key.should == :foo - } - end - end - end end describe "%{name} style" do @@ -892,4 +864,14 @@ def obj.to_str; end end end end + + describe "faulty key" do + before :all do + @base_method = @method + end + + it_behaves_like :key_error, -> (obj, key) { + @base_method.call("%<#{key}>s", obj) + }, { foooo: 1 } + end end diff --git a/core/string/modulo_spec.rb b/core/string/modulo_spec.rb index b6a6918880..7cb3561b17 100644 --- a/core/string/modulo_spec.rb +++ b/core/string/modulo_spec.rb @@ -1,7 +1,12 @@ require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../fixtures/classes.rb', __FILE__) +require File.expand_path('../../../shared/hash/key_error', __FILE__) describe "String#%" do + context "when key is missing from passed-in hash" do + it_behaves_like :key_error, -> (obj, key) { "%{#{key}}" % obj }, { a: 5 } + end + it "formats multiple expressions" do ("%b %x %d %s" % [10, 10, 10, 10]).should == "1010 a 10 10" end @@ -764,34 +769,6 @@ def obj.to_s() "obj" end ("%{foo}bar" % {foo: 'oof'}).should == "oofbar" end - context "when key is missing from passed-in hash" do - it "raises KeyError" do - lambda {"%{foo}" % {}}.should raise_error(KeyError) - end - - ruby_version_is "2.5" do - before :each do - @hash = { fooo: 1 } - end - - it "sets the passed-in hash as receiver for KeyError" do - -> { - "%{foo}" % @hash - }.should raise_error(KeyError) { |err| - err.receiver.should == @hash - } - end - - it "sets the missing key as key in KeyError" do - -> { - "%{foo}" % @hash - }.should raise_error(KeyError) { |err| - err.key.should == :foo - } - end - end - end - it "should raise ArgumentError if no hash given" do lambda {"%{foo}" % []}.should raise_error(ArgumentError) end diff --git a/optional/capi/hash_spec.rb b/optional/capi/hash_spec.rb index 4d818bb9ec..1a117bfbf8 100644 --- a/optional/capi/hash_spec.rb +++ b/optional/capi/hash_spec.rb @@ -1,4 +1,5 @@ require File.expand_path('../spec_helper', __FILE__) +require File.expand_path('../../../shared/hash/key_error', __FILE__) load_extension("hash") @@ -138,23 +139,9 @@ end context "when key is not found" do - ruby_version_is "2.5" do - it "sets the hash as receiver for KeyError" do - -> { - @s.rb_hash_fetch(@hsh, :c) - }.should raise_error(KeyError) { |err| - err.receiver.should == @hsh - } - end - - it "sets the key as key for KeyError" do - -> { - @s.rb_hash_fetch(@hsh, :c) - }.should raise_error(KeyError) { |err| - err.key.should == :c - } - end - end + it_behaves_like :key_error, -> (obj, key) { + @s.rb_hash_fetch(obj, key) + }, { a: 1 } end end diff --git a/shared/hash/key_error.rb b/shared/hash/key_error.rb new file mode 100644 index 0000000000..cb7a7089f0 --- /dev/null +++ b/shared/hash/key_error.rb @@ -0,0 +1,25 @@ +describe :key_error, shared: true do + it "raises a KeyError" do + -> { + @method.call(@object, 'foo') + }.should raise_error(KeyError) + end + + ruby_version_is "2.5" do + it "sets the Hash as the receiver of KeyError" do + -> { + @method.call(@object, 'foo') + }.should raise_error(KeyError) { |err| + err.receiver.should == @object + } + end + + it "sets the unmatched key as the key of KeyError" do + -> { + @method.call(@object, 'foo') + }.should raise_error(KeyError) { |err| + err.key.to_s.should == 'foo' + } + end + end +end From 1320550a24d3a8e1af628526e6c5d07090a81ad4 Mon Sep 17 00:00:00 2001 From: Andrew Nordman Date: Tue, 2 Jan 2018 13:20:28 -0600 Subject: [PATCH 2/3] Makes corrections to shared specs per review --- core/hash/fetch_spec.rb | 2 ++ core/hash/fetch_values_spec.rb | 33 +++++---------------------------- shared/hash/key_error.rb | 2 +- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/core/hash/fetch_spec.rb b/core/hash/fetch_spec.rb index 3914f7e300..e3f97dc901 100644 --- a/core/hash/fetch_spec.rb +++ b/core/hash/fetch_spec.rb @@ -5,6 +5,8 @@ describe "Hash#fetch" do context "when the key is not found" do it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new(a: 5) + it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, {} + it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new { 5 } end it "returns the value for key" do diff --git a/core/hash/fetch_values_spec.rb b/core/hash/fetch_values_spec.rb index e4bbd2a66f..0d7c9599e7 100644 --- a/core/hash/fetch_values_spec.rb +++ b/core/hash/fetch_values_spec.rb @@ -17,6 +17,11 @@ describe "with unmatched keys" do it_behaves_like :key_error, ->(obj, key) { obj.fetch_values(key) }, Hash.new(a: 5) + + it "returns the default value from block" do + @hash.fetch_values(:z) { |key| "`#{key}' is not found" }.should == ["`z' is not found"] + @hash.fetch_values(:a, :z) { |key| "`#{key}' is not found" }.should == [1, "`z' is not found"] + end end describe "without keys" do @@ -26,31 +31,3 @@ end end end - -ruby_version_is "2.5" do - describe "Hash#fetch_values" do - before :each do - @hash = { a: 1, b: 2, c: 3 } - end - - describe "with unmatched keys" do - before :each do - end - it "sets the Hash as the receiver of KeyError" do - -> { - @hash.fetch_values :a, :z - }.should raise_error(KeyError) { |err| - err.receiver.should == @hash - } - end - - it "sets the unmatched key as the key of KeyError" do - -> { - @hash.fetch_values :a, :z - }.should raise_error(KeyError) { |err| - err.key.should == :z - } - end - end - end -end diff --git a/shared/hash/key_error.rb b/shared/hash/key_error.rb index cb7a7089f0..061c88c483 100644 --- a/shared/hash/key_error.rb +++ b/shared/hash/key_error.rb @@ -10,7 +10,7 @@ -> { @method.call(@object, 'foo') }.should raise_error(KeyError) { |err| - err.receiver.should == @object + err.receiver.should equal(@object) } end From 17a642990b093f6ce2530bc3bfb418145880055a Mon Sep 17 00:00:00 2001 From: Andrew Nordman Date: Tue, 2 Jan 2018 13:22:24 -0600 Subject: [PATCH 3/3] Adds missing example to Hash#fetch for various Hash creations --- core/hash/fetch_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/core/hash/fetch_spec.rb b/core/hash/fetch_spec.rb index e3f97dc901..24662c2b0e 100644 --- a/core/hash/fetch_spec.rb +++ b/core/hash/fetch_spec.rb @@ -7,6 +7,7 @@ it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new(a: 5) it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, {} it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new { 5 } + it_behaves_like :key_error, ->(obj, key) { obj.fetch(key) }, Hash.new(5) end it "returns the value for key" do