From c5e8669e9ccc655c2c2be70f09bf22d210d55ac7 Mon Sep 17 00:00:00 2001 From: Gerard Caulfield Date: Tue, 10 May 2016 00:04:42 +1000 Subject: [PATCH] Simplify matching logic in tests Simplify matching logic by adding a custom matcher which handles the task of normalisation of object IDs instead of calling gsub many times throughout the test code. This allows our tests to focus more on what needs to be tested instead obfuscating the tests with logic unrelated to what the test is trying to cover. It also allows making the normalisation code more robust so there is less chance of an accidental match or typo slipping in. The change also replaces the arbitary default object IDs with a string that makes it very obvious that it is just a placeholder. --- spec/ext/active_record_spec.rb | 342 ++++++++++++++++----------------- spec/ext/mongo_mapper_spec.rb | 43 ++--- spec/ext/mongoid_spec.rb | 5 +- spec/ext/ripple_spec.rb | 4 +- spec/objects_spec.rb | 20 +- spec/spec_helper.rb | 20 ++ 6 files changed, 223 insertions(+), 211 deletions(-) diff --git a/spec/ext/active_record_spec.rb b/spec/ext/active_record_spec.rb index 6b67ac3..be3aba2 100644 --- a/spec/ext/active_record_spec.rb +++ b/spec/ext/active_record_spec.rb @@ -17,9 +17,9 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. end it "display single record" do - out = @ap.send(:awesome, @diana) + out = @ap.awesome(@diana) str = <<-EOS.strip -# { +# { :admin => false, :created_at => ?, :id => nil, @@ -32,21 +32,21 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. else str.sub!('?', '1992-10-10 12:30:00 UTC') end - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) end it "display multiple records" do - out = @ap.send(:awesome, [ @diana, @laura ]) + out = @ap.awesome([ @diana, @laura ]) str = <<-EOS.strip [ - [0] # { + [0] # { :admin => false, :created_at => ??, :id => nil, :name => "Diana", :rank => 1 }, - [1] # { + [1] # { :admin => true, :created_at => ?!, :id => nil, @@ -62,23 +62,23 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. str.sub!('??', '1992-10-10 12:30:00 UTC') str.sub!('?!', '2003-05-26 14:15:00 UTC') end - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) end it "display multiple records on a relation" do @diana.save @laura.save - out = @ap.send(:awesome, User.all) + out = @ap.awesome(User.all) str = <<-EOS.strip [ - [0] # { + [0] # { :admin => false, :created_at => ??, :id => 1, :name => "Diana", :rank => 1 }, - [1] # { + [1] # { :admin => true, :created_at => ?!, :id => 2, @@ -94,7 +94,7 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. str.sub!('??', '1992-10-10 12:30:00 UTC') str.sub!('?!', '2003-05-26 14:15:00 UTC') end - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) end end @@ -108,12 +108,12 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. end it "display single record" do - out = @ap.send(:awesome, @diana) + out = @ap.awesome(@diana) if activerecord_4_2? if RUBY_VERSION > '1.9.3' str = <<-EOS.strip -#{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = false, attr_reader :value_before_type_cast = false >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 1992-10-10 12:30:00 UTC, attr_reader :value_before_type_cast = "1992-10-10 12:30:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Diana", attr_reader :value_before_type_cast = "Diana" >, - "rank" => # #{ !ExtVerifier.has_rails? }. }, @materialized = false, @types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. EOS else str = <<-EOS.strip -#{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = false, attr_reader :value_before_type_cast = false >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 1992-10-10 12:30:00 UTC, attr_reader :value_before_type_cast = "1992-10-10 12:30:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Diana", attr_reader :value_before_type_cast = "Diana" >, - "rank" => # #{ !ExtVerifier.has_rails? }. > }, attr_reader :types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. end elsif activerecord_4_1? str = <<-EOS.strip -# # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. EOS elsif activerecord_4_0? str = <<-EOS.strip - # # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. elsif activerecord_3_2? if RUBY_VERSION > '1.9.3' str = <<-EOS.strip -#{ !ExtVerifier.has_rails? }. EOS else str = <<-EOS.strip -#{ !ExtVerifier.has_rails? }. end end str.sub!('?', '1992-10-10 12:30:00') - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) end it "display multiple records" do - out = @ap.send(:awesome, [ @diana, @laura ]) + out = @ap.awesome([ @diana, @laura ]) if activerecord_4_2? if RUBY_VERSION > '1.9.3' str = <<-EOS.strip [ - [0] #{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = false, attr_reader :value_before_type_cast = false >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 1992-10-10 12:30:00 UTC, attr_reader :value_before_type_cast = "1992-10-10 12:30:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Diana", attr_reader :value_before_type_cast = "Diana" >, - "rank" => # #{ !ExtVerifier.has_rails? }. }, @materialized = false, @types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. "rank" => nil } >, - [1] #{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = true, attr_reader :value_before_type_cast = true >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 2003-05-26 14:15:00 UTC, attr_reader :value_before_type_cast = "2003-05-26 14:15:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Laura", attr_reader :value_before_type_cast = "Laura" >, - "rank" => # #{ !ExtVerifier.has_rails? }. }, @materialized = false, @types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. else str = <<-EOS.strip [ - [0] #{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = false, attr_reader :value_before_type_cast = false >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 1992-10-10 12:30:00 UTC, attr_reader :value_before_type_cast = "1992-10-10 12:30:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Diana", attr_reader :value_before_type_cast = "Diana" >, - "rank" => # #{ !ExtVerifier.has_rails? }. > }, attr_reader :types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. "rank" => nil } >, - [1] #{ !ExtVerifier.has_rails? }. ], @transaction_state = nil, @txn = nil, - attr_accessor :attributes = # # #{ !ExtVerifier.has_rails? }. attr_reader :value = true, attr_reader :value_before_type_cast = true >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = 2003-05-26 14:15:00 UTC, attr_reader :value_before_type_cast = "2003-05-26 14:15:00" >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = nil, attr_reader :value_before_type_cast = nil >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :value = "Laura", attr_reader :value_before_type_cast = "Laura" >, - "rank" => # #{ !ExtVerifier.has_rails? }. > }, attr_reader :types = { - "admin" => # #, - "created_at" => # #, - "id" => # #, - "name" => # #, - "rank" => # #{ !ExtVerifier.has_rails? }. elsif activerecord_4_1? str = <<-EOS.strip [ - [0] # # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. "rank" => nil } >, - [1] # # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. elsif activerecord_4_0? str = <<-EOS.strip [ - [0] # # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. "rank" => nil } >, - [1] # # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "boolean", attr_reader :type = :boolean >, - "created_at" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "datetime", attr_reader :type = :datetime >, - "id" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "INTEGER", attr_reader :type = :integer >, - "name" => # #{ !ExtVerifier.has_rails? }. attr_reader :sql_type = "varchar(255)", attr_reader :type = :string >, - "rank" => # #{ !ExtVerifier.has_rails? }. if RUBY_VERSION > '1.9.3' str = <<-EOS.strip [ - [0] #{ !ExtVerifier.has_rails? }. "rank" => nil } >, - [1] #{ !ExtVerifier.has_rails? }. else str = <<-EOS.strip [ - [0] #{ !ExtVerifier.has_rails? }. }, attr_reader :mass_assignment_options = nil >, - [1] #{ !ExtVerifier.has_rails? }. end str.sub!('?', '1992-10-10 12:30:00') str.sub!('?', '2003-05-26 14:15:00') - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) end end @@ -1655,7 +1655,7 @@ RSpec.describe "AwesomePrint/ActiveRecord", skip: ->{ !ExtVerifier.has_rails? }. end it "should print the class" do - expect(@ap.send(:awesome, User)).to eq <<-EOS.strip + expect(@ap.awesome(User)).to eq <<-EOS.strip class User < ActiveRecord::Base { :id => :integer, :name => :string, @@ -1667,7 +1667,7 @@ class User < ActiveRecord::Base { end it "should print the class for non-direct subclasses of ActiveRecord::Base" do - out = @ap.send(:awesome, SubUser) + out = @ap.awesome(SubUser) expect(out).to eq <<-EOS.strip class SubUser < User { :id => :integer, @@ -1680,7 +1680,7 @@ class SubUser < User { end it "should print ActiveRecord::Base objects (ex. ancestors)" do - expect { @ap.send(:awesome, User.ancestors) }.not_to raise_error + expect { @ap.awesome(User.ancestors) }.not_to raise_error end end @@ -1692,7 +1692,7 @@ class SubUser < User { it "should format class methods properly" do # spec 1 - out = @ap.send(:awesome, User.methods.grep(/first/)) + out = @ap.awesome(User.methods.grep(/first/)) if ActiveRecord::VERSION::STRING >= "3.2" if RUBY_VERSION >= "1.9" @@ -1705,11 +1705,11 @@ class SubUser < User { end # spec 2 - out = @ap.send(:awesome, User.methods.grep(/primary_key/)) + out = @ap.awesome(User.methods.grep(/primary_key/)) expect(out).to match(/\sprimary_key\(.*?\)\s+Class \(ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods\)/) # spec 3 - out = @ap.send(:awesome, User.methods.grep(/validate/)) + out = @ap.awesome(User.methods.grep(/validate/)) if ActiveRecord::VERSION::MAJOR < 3 expect(out).to match(/\svalidate\(\*arg.*?\)\s+User \(ActiveRecord::Base\)/) diff --git a/spec/ext/mongo_mapper_spec.rb b/spec/ext/mongo_mapper_spec.rb index 9c0872a..be0e430 100644 --- a/spec/ext/mongo_mapper_spec.rb +++ b/spec/ext/mongo_mapper_spec.rb @@ -36,9 +36,9 @@ RSpec.describe "AwesomePrint/MongoMapper", skip: ->{ !ExtVerifier.has_mongo_mapp if MongoMapper::Version >= "0.13" str = <<-EOS.strip -#{ !ExtVerifier.has_mongo_mapp > ], @__mm_keys = { - "_id" => # #{ !ExtVerifier.has_mongo_mapp }, attr_accessor :type = ObjectId < Object >, - "first_name" => # #{ !ExtVerifier.has_mongo_mapp attr_accessor :options = {}, attr_accessor :type = String < Object >, - "last_name" => # #{ !ExtVerifier.has_mongo_mapp EOS else str = <<-EOS.strip -#{ !ExtVerifier.has_mongo_mapp > EOS end - out.gsub!(/0x([a-f\d]+)/, "0x01234567") - expect(out).to eq(str) + expect(out).to be_similar_to(str) end it "should print the class" do @@ -193,14 +192,12 @@ class Parent < Object { parent = Parent.new(:name => 'test') out = @ap.send(:awesome, parent) str = <<-EOS.strip -# { - "_id" => BSON::ObjectId('4d9183739a546f6806000001'), +# { + "_id" => placeholder_bison_id, "name" => "test" } EOS - out.gsub!(/'([\w]+){23}'/, "'4d9183739a546f6806000001'") - out.gsub!(/0x([a-f\d]+)/, "0x01234567") - expect(out).to eq(str) + expect(out).to be_similar_to(str) end end @@ -224,16 +221,14 @@ class Parent < Object { parent = Parent.new(:name => 'test') out = @ap.send(:awesome, parent) str = <<-EOS.strip -# { - "_id" => BSON::ObjectId('4d9183739a546f6806000001'), +# { + "_id" => placeholder_bison_id, "name" => "test", "child" => embeds one Child, "sibling" => one Sibling } EOS - out.gsub!(/'([\w]+){23}'/, "'4d9183739a546f6806000001'") - out.gsub!(/0x([a-f\d]+)/, "0x01234567") - expect(out).to eq(str) + expect(out).to be_similar_to(str) end end @@ -251,19 +246,17 @@ class Parent < Object { parent = Parent.new(:name => 'test', :child => Child.new(:data => 5)) out = @ap.send(:awesome, parent) str = <<-EOS.strip -# { - "_id" => BSON::ObjectId('4d9183739a546f6806000001'), +# { + "_id" => placeholder_bison_id, "name" => "test", - "child" => embedded # { - "_id" => BSON::ObjectId('4d9183739a546f6806000001'), + "child" => embedded # { + "_id" => placeholder_bison_id, "data" => 5 }, "sibling" => one Sibling } EOS - out.gsub!(/'([\w]+){23}'/, "'4d9183739a546f6806000001'") - out.gsub!(/0x([a-f\d]+)/, "0x01234567") - expect(out).to eq(str) + expect(out).to be_similar_to(str) end end end diff --git a/spec/ext/mongoid_spec.rb b/spec/ext/mongoid_spec.rb index b241b1b..6591a43 100644 --- a/spec/ext/mongoid_spec.rb +++ b/spec/ext/mongoid_spec.rb @@ -29,14 +29,13 @@ RSpec.describe "AwesomePrint/Mongoid", skip: ->{ !ExtVerifier.has_mongoid? }.cal object_id = user.id.inspect str = <<-EOS.strip -# { +# { :_id => #{object_id}, :first_name => "Al", :last_name => "Capone" } EOS - out.gsub!(/0x([a-f\d]+)/, "0x01234567") - expect(out).to eq(str) + expect(out).to be_similar_to(str) end it "should print the class" do diff --git a/spec/ext/ripple_spec.rb b/spec/ext/ripple_spec.rb index 3f94aec..9c35372 100644 --- a/spec/ext/ripple_spec.rb +++ b/spec/ext/ripple_spec.rb @@ -28,8 +28,8 @@ RSpec.describe 'AwesomePrint/Ripple', skip: ->{ !ExtVerifier.has_ripple? }.call user = RippleUser.new :_id => "12345", :first_name => "Al", :last_name => "Capone" out = @ap.send :awesome, user - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq <<-EOS.strip -# { + expect(out).to be_similar_to <<-EOS.strip +# { :_id => "12345", :first_name => "Al", :last_name => "Capone" diff --git a/spec/objects_spec.rb b/spec/objects_spec.rb index cdbfa40..aa3f476 100644 --- a/spec/objects_spec.rb +++ b/spec/objects_spec.rb @@ -24,13 +24,13 @@ RSpec.describe "Objects" do hello = Hello.new out = hello.ai(:plain => true, :raw => true) str = <<-EOS.strip -# EOS - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect) end @@ -44,13 +44,13 @@ EOS hello = Hello.new out = hello.ai(:plain => true, :raw => true) str = <<-EOS.strip -# EOS - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect) end @@ -69,7 +69,7 @@ EOS hello = Hello.new out = hello.ai(:plain => true, :raw => true) str = <<-EOS.strip -# EOS - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect) end @@ -96,13 +96,13 @@ EOS hello = Hello.new out = hello.ai(:raw => true) str = <<-EOS.strip -# EOS - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect) end @@ -120,9 +120,9 @@ EOS hello = Hello.new out = hello.ai(:multiline => false, :plain => true, :raw => true) str = <<-EOS.strip -# +# EOS - expect(out.gsub(/0x([a-f\d]+)/, "0x01234567")).to eq(str) + expect(out).to be_similar_to(str) expect(hello.ai(:plain => true, :raw => false)).to eq(hello.inspect) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4d43a29..4de361d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -47,6 +47,26 @@ RSpec.configure do |config| end end +# This matcher handles the normalization of objects to replace non deterministic +# parts (such as object IDs) with simple placeholder strings before doing a +# comparison with a given string. It's important that this method only matches +# a string which strictly conforms to the expected object ID format. +RSpec::Matchers.define :be_similar_to do |expected| + match do |actual| + @actual = normalize_object_strings(actual) + values_match? expected, @actual + end + + diffable +end + +# Override the Object IDs with a placeholder so that we are only checking +# that an ID is present and not that it matches a certain value. This is +# necessary as the Object IDs are not deterministic. +def normalize_object_strings(str) + str.gsub(/#<(.*?):0x[a-f\d]+/, '#<\1:placeholder_id') +end + def stub_dotfile! dotfile = File.join(ENV["HOME"], ".aprc") expect(File).to receive(:readable?).at_least(:once).with(dotfile).and_return(false)