Adjust double string representation

to_s and inspect (with variants) are no longer "original implementation."
This commit is contained in:
Michael Miller 2022-11-29 21:24:31 -07:00
parent 1f98bf9ff1
commit a967dce241
No known key found for this signature in database
GPG key ID: 32B47AE8F388A1FF
6 changed files with 215 additions and 32 deletions

View file

@ -212,14 +212,10 @@ Spectator.describe Spectator::Double do
expect(dbl.hash).to be_a(UInt64) expect(dbl.hash).to be_a(UInt64)
expect(dbl.in?([42])).to be_false expect(dbl.in?([42])).to be_false
expect(dbl.in?(1, 2, 3)).to be_false expect(dbl.in?(1, 2, 3)).to be_false
expect(dbl.inspect).to contain("EmptyDouble")
expect(dbl.itself).to be(dbl) expect(dbl.itself).to be(dbl)
expect(dbl.not_nil!).to be(dbl) expect(dbl.not_nil!).to be(dbl)
expect(dbl.pretty_inspect).to contain("EmptyDouble")
expect(dbl.pretty_print(pp)).to be_nil expect(dbl.pretty_print(pp)).to be_nil
expect(dbl.tap { nil }).to be(dbl) expect(dbl.tap { nil }).to be(dbl)
expect(dbl.to_s).to contain("EmptyDouble")
expect(dbl.to_s(io)).to be_nil
expect(dbl.try { nil }).to be_nil expect(dbl.try { nil }).to be_nil
expect(dbl.object_id).to be_a(UInt64) expect(dbl.object_id).to be_a(UInt64)
expect(dbl.same?(dbl)).to be_true expect(dbl.same?(dbl)).to be_true
@ -469,7 +465,7 @@ Spectator.describe Spectator::Double do
it "stores calls to non-stubbed methods" do it "stores calls to non-stubbed methods" do
expect { dbl.baz }.to raise_error(Spectator::UnexpectedMessage, /baz/) expect { dbl.baz }.to raise_error(Spectator::UnexpectedMessage, /baz/)
expect(called_method_names(dbl)).to eq(%i[baz]) expect(called_method_names(dbl)).to contain(:baz)
end end
it "stores arguments for a call" do it "stores arguments for a call" do
@ -479,4 +475,68 @@ Spectator.describe Spectator::Double do
expect(call.arguments).to eq(args) expect(call.arguments).to eq(args)
end end
end end
describe "#to_s" do
subject(string) { dbl.to_s }
context "with a name" do
let(dbl) { FooBarDouble.new }
it "indicates it's a double" do
expect(string).to contain("Double")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
end
context "without a name" do
let(dbl) { EmptyDouble.new }
it "indicates it's a double" do
expect(string).to contain("Double")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
end
end
describe "#inspect" do
subject(string) { dbl.inspect }
context "with a name" do
let(dbl) { FooBarDouble.new }
it "indicates it's a double" do
expect(string).to contain("Double")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
context "without a name" do
let(dbl) { EmptyDouble.new }
it "indicates it's a double" do
expect(string).to contain("Double")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
end
end end

View file

@ -275,7 +275,7 @@ Spectator.describe Spectator::LazyDouble do
it "stores calls to non-stubbed methods" do it "stores calls to non-stubbed methods" do
expect { dbl.baz }.to raise_error(Spectator::UnexpectedMessage, /baz/) expect { dbl.baz }.to raise_error(Spectator::UnexpectedMessage, /baz/)
expect(called_method_names(dbl)).to eq(%i[baz]) expect(called_method_names(dbl)).to contain(:baz)
end end
it "stores arguments for a call" do it "stores arguments for a call" do
@ -285,4 +285,68 @@ Spectator.describe Spectator::LazyDouble do
expect(call.arguments).to eq(args) expect(call.arguments).to eq(args)
end end
end end
describe "#to_s" do
subject(string) { dbl.to_s }
context "with a name" do
let(dbl) { Spectator::LazyDouble.new("dbl-name") }
it "indicates it's a double" do
expect(string).to contain("LazyDouble")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
end
context "without a name" do
let(dbl) { Spectator::LazyDouble.new }
it "contains the double type" do
expect(string).to contain("LazyDouble")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
end
end
describe "#inspect" do
subject(string) { dbl.inspect }
context "with a name" do
let(dbl) { Spectator::LazyDouble.new("dbl-name") }
it "contains the double type" do
expect(string).to contain("LazyDouble")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
context "without a name" do
let(dbl) { Spectator::LazyDouble.new }
it "contains the double type" do
expect(string).to contain("LazyDouble")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
end
end end

View file

@ -186,12 +186,9 @@ Spectator.describe Spectator::NullDouble do
expect(dbl.hash).to be_a(UInt64) expect(dbl.hash).to be_a(UInt64)
expect(dbl.in?([42])).to be_false expect(dbl.in?([42])).to be_false
expect(dbl.in?(1, 2, 3)).to be_false expect(dbl.in?(1, 2, 3)).to be_false
expect(dbl.inspect).to contain("EmptyDouble")
expect(dbl.itself).to be(dbl) expect(dbl.itself).to be(dbl)
expect(dbl.not_nil!).to be(dbl) expect(dbl.not_nil!).to be(dbl)
expect(dbl.pretty_inspect).to contain("EmptyDouble")
expect(dbl.tap { nil }).to be(dbl) expect(dbl.tap { nil }).to be(dbl)
expect(dbl.to_s).to contain("EmptyDouble")
expect(dbl.try { nil }).to be_nil expect(dbl.try { nil }).to be_nil
expect(dbl.object_id).to be_a(UInt64) expect(dbl.object_id).to be_a(UInt64)
expect(dbl.same?(dbl)).to be_true expect(dbl.same?(dbl)).to be_true
@ -439,4 +436,68 @@ Spectator.describe Spectator::NullDouble do
expect(call.arguments).to eq(args) expect(call.arguments).to eq(args)
end end
end end
describe "#to_s" do
subject(string) { dbl.to_s }
context "with a name" do
let(dbl) { FooBarDouble.new }
it "indicates it's a double" do
expect(string).to contain("NullDouble")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
end
context "without a name" do
let(dbl) { EmptyDouble.new }
it "contains the double type" do
expect(string).to contain("NullDouble")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
end
end
describe "#inspect" do
subject(string) { dbl.inspect }
context "with a name" do
let(dbl) { FooBarDouble.new }
it "contains the double type" do
expect(string).to contain("NullDouble")
end
it "contains the double name" do
expect(string).to contain("dbl-name")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
context "without a name" do
let(dbl) { EmptyDouble.new }
it "contains the double type" do
expect(string).to contain("NullDouble")
end
it "contains \"Anonymous\"" do
expect(string).to contain("Anonymous")
end
it "contains the object ID" do
expect(string).to contain(dbl.object_id.to_s(16))
end
end
end
end end

View file

@ -98,16 +98,14 @@ module Spectator
# Simplified string representation of a double. # Simplified string representation of a double.
# Avoids displaying nested content and bloating method instantiation. # Avoids displaying nested content and bloating method instantiation.
def to_s(io : IO) : Nil def to_s(io : IO) : Nil
io << _spectator_stubbed_name io << "#<" + {{@type.name(generic_args: false).stringify}} + " "
io << _spectator_stubbed_name << '>'
end end
# :ditto: # :ditto:
def inspect(io : IO) : Nil def inspect(io : IO) : Nil
{% if anno = @type.annotation(::Spectator::StubbedName) %} io << "#<" + {{@type.name(generic_args: false).stringify}} + " "
io << "#<Double " << {{(anno[0] || :Anonymous.id).stringify}} io << _spectator_stubbed_name
{% else %}
io << "#<Double Anonymous"
{% end %}
io << ":0x" io << ":0x"
object_id.to_s(io, 16) object_id.to_s(io, 16)
@ -118,17 +116,17 @@ module Spectator
# #
# NOTE: Defining a stub for a method not defined in the double's type has no effect. # NOTE: Defining a stub for a method not defined in the double's type has no effect.
protected def _spectator_define_stub(stub : Stub) : Nil protected def _spectator_define_stub(stub : Stub) : Nil
Log.debug { "Defined stub for #{_spectator_stubbed_name} #{stub}" } Log.debug { "Defined stub for #{inspect} #{stub}" }
@stubs.unshift(stub) @stubs.unshift(stub)
end end
protected def _spectator_remove_stub(stub : Stub) : Nil protected def _spectator_remove_stub(stub : Stub) : Nil
Log.debug { "Removing stub #{stub} from #{_spectator_stubbed_name}" } Log.debug { "Removing stub #{stub} from #{inspect}" }
@stubs.delete(stub) @stubs.delete(stub)
end end
protected def _spectator_clear_stubs : Nil protected def _spectator_clear_stubs : Nil
Log.debug { "Clearing stubs for #{_spectator_stubbed_name}" } Log.debug { "Clearing stubs for #{inspect}" }
@stubs.clear @stubs.clear
end end
@ -158,17 +156,17 @@ module Spectator
# Returns the double's name formatted for user output. # Returns the double's name formatted for user output.
private def _spectator_stubbed_name : String private def _spectator_stubbed_name : String
{% if anno = @type.annotation(StubbedName) %} {% if anno = @type.annotation(StubbedName) %}
"#<Double " + {{(anno[0] || :Anonymous.id).stringify}} + ">" {{(anno[0] || :Anonymous.id).stringify}}
{% else %} {% else %}
"#<Double Anonymous>" "Anonymous"
{% end %} {% end %}
end end
private def self._spectator_stubbed_name : String private def self._spectator_stubbed_name : String
{% if anno = @type.annotation(StubbedName) %} {% if anno = @type.annotation(StubbedName) %}
"#<Class Double " + {{(anno[0] || :Anonymous.id).stringify}} + ">" {{(anno[0] || :Anonymous.id).stringify}}
{% else %} {% else %}
"#<Class Double Anonymous>" "Anonymous"
{% end %} {% end %}
end end
@ -188,7 +186,7 @@ module Spectator
"Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)."
end end
raise UnexpectedMessage.new("#{_spectator_stubbed_name} received unexpected message #{call}") raise UnexpectedMessage.new("#{inspect} received unexpected message #{call}")
end end
private def _spectator_abstract_stub_fallback(call : MethodCall, type) private def _spectator_abstract_stub_fallback(call : MethodCall, type)
@ -207,9 +205,9 @@ module Spectator
call = ::Spectator::MethodCall.new({{call.name.symbolize}}, args) call = ::Spectator::MethodCall.new({{call.name.symbolize}}, args)
_spectator_record_call(call) _spectator_record_call(call)
Log.trace { "#{_spectator_stubbed_name} got undefined method `#{call}{% if call.block %} { ... }{% end %}`" } Log.trace { "#{inspect} got undefined method `#{call}{% if call.block %} { ... }{% end %}`" }
raise ::Spectator::UnexpectedMessage.new("#{_spectator_stubbed_name} received unexpected message #{call}") raise ::Spectator::UnexpectedMessage.new("#{inspect} received unexpected message #{call}")
nil # Necessary for compiler to infer return type as nil. Avoids runtime "can't execute ... `x` has no type errors". nil # Necessary for compiler to infer return type as nil. Avoids runtime "can't execute ... `x` has no type errors".
end end
end end

View file

@ -37,13 +37,13 @@ module Spectator
# Returns the double's name formatted for user output. # Returns the double's name formatted for user output.
private def _spectator_stubbed_name : String private def _spectator_stubbed_name : String
"#<LazyDouble #{@name || "Anonymous"}>" @name || "Anonymous"
end end
private def _spectator_stub_fallback(call : MethodCall, &) private def _spectator_stub_fallback(call : MethodCall, &)
if _spectator_stub_for_method?(call.method) if _spectator_stub_for_method?(call.method)
Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." } Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." }
raise UnexpectedMessage.new("#{_spectator_stubbed_name} received unexpected message #{call}") raise UnexpectedMessage.new("#{inspect} received unexpected message #{call}")
else else
Log.trace { "Fallback for #{call} - call original" } Log.trace { "Fallback for #{call} - call original" }
yield yield
@ -57,7 +57,7 @@ module Spectator
%call = ::Spectator::MethodCall.new({{call.name.symbolize}}, %args) %call = ::Spectator::MethodCall.new({{call.name.symbolize}}, %args)
_spectator_record_call(%call) _spectator_record_call(%call)
Log.trace { "#{_spectator_stubbed_name} got undefined method `#{%call}{% if call.block %} { ... }{% end %}`" } Log.trace { "#{inspect} got undefined method `#{%call}{% if call.block %} { ... }{% end %}`" }
# Attempt to find a stub that satisfies the method call and arguments. # Attempt to find a stub that satisfies the method call and arguments.
if %stub = _spectator_find_stub(%call) if %stub = _spectator_find_stub(%call)

View file

@ -26,7 +26,7 @@ module Spectator
private def _spectator_abstract_stub_fallback(call : MethodCall) private def _spectator_abstract_stub_fallback(call : MethodCall)
if _spectator_stub_for_method?(call.method) if _spectator_stub_for_method?(call.method)
Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." } Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." }
raise UnexpectedMessage.new("#{_spectator_stubbed_name} received unexpected message #{call}") raise UnexpectedMessage.new("#{inspect} received unexpected message #{call}")
else else
Log.trace { "Fallback for #{call} - return self" } Log.trace { "Fallback for #{call} - return self" }
self self
@ -42,9 +42,9 @@ module Spectator
private def _spectator_abstract_stub_fallback(call : MethodCall, type) private def _spectator_abstract_stub_fallback(call : MethodCall, type)
if _spectator_stub_for_method?(call.method) if _spectator_stub_for_method?(call.method)
Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." } Log.info { "Stubs are defined for #{call.method.inspect}, but none matched (no argument constraints met)." }
raise UnexpectedMessage.new("#{_spectator_stubbed_name} received unexpected message #{call}") raise UnexpectedMessage.new("#{inspect} received unexpected message #{call}")
else else
raise TypeCastError.new("#{_spectator_stubbed_name} received message #{call} and is attempting to return `self`, but returned type must be `#{type}`.") raise TypeCastError.new("#{inspect} received message #{call} and is attempting to return `self`, but returned type must be `#{type}`.")
end end
end end
@ -56,7 +56,7 @@ module Spectator
%call = ::Spectator::MethodCall.new({{call.name.symbolize}}, %args) %call = ::Spectator::MethodCall.new({{call.name.symbolize}}, %args)
_spectator_record_call(%call) _spectator_record_call(%call)
Log.trace { "#{_spectator_stubbed_name} got undefined method `#{%call}{% if call.block %} { ... }{% end %}`" } Log.trace { "#{inspect} got undefined method `#{%call}{% if call.block %} { ... }{% end %}`" }
self self
end end