Rename Source to Location

This commit is contained in:
Michael Miller 2021-02-12 22:46:22 -07:00
parent 08451df643
commit 74b78b7ca8
No known key found for this signature in database
GPG key ID: FB9F12F7C646A4AD
38 changed files with 163 additions and 163 deletions

View file

@ -2,9 +2,9 @@ require "option_parser"
require "./config_source" require "./config_source"
require "./formatting" require "./formatting"
require "./line_example_filter" require "./line_example_filter"
require "./location"
require "./location_example_filter"
require "./name_example_filter" require "./name_example_filter"
require "./source"
require "./source_example_filter"
module Spectator module Spectator
# Generates configuration from the command-line arguments. # Generates configuration from the command-line arguments.
@ -130,8 +130,8 @@ module Spectator
private def location_option(parser, builder) private def location_option(parser, builder)
parser.on("--location FILE:LINE", "Run the example at line 'LINE' in the file 'FILE', multiple allowed") do |location| parser.on("--location FILE:LINE", "Run the example at line 'LINE' in the file 'FILE', multiple allowed") do |location|
Log.debug { "Filtering for examples at #{location} (--location '#{location}')" } Log.debug { "Filtering for examples at #{location} (--location '#{location}')" }
source = Source.parse(location) location = Location.parse(location)
filter = SourceExampleFilter.new(source) filter = LocationExampleFilter.new(location)
builder.add_example_filter(filter) builder.add_example_filter(filter)
end end
end end

View file

@ -38,32 +38,32 @@ module Spectator::DSL
end end
# Defines a block of code to execute before any and all examples in the current group. # Defines a block of code to execute before any and all examples in the current group.
def before_all(source = nil, label = "before_all", &block) def before_all(location = nil, label = "before_all", &block)
hook = ExampleGroupHook.new(source: source, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.before_all(hook) @@builder.before_all(hook)
end end
# Defines a block of code to execute before every example in the current group # Defines a block of code to execute before every example in the current group
def before_each(source = nil, label = "before_each", &block : Example -> _) def before_each(location = nil, label = "before_each", &block : Example -> _)
hook = ExampleHook.new(source: source, label: label, &block) hook = ExampleHook.new(location: location, label: label, &block)
@@builder.before_each(hook) @@builder.before_each(hook)
end end
# Defines a block of code to execute after any and all examples in the current group. # Defines a block of code to execute after any and all examples in the current group.
def after_all(source = nil, label = "after_all", &block) def after_all(location = nil, label = "after_all", &block)
hook = ExampleGroupHook.new(source: source, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.after_all(hook) @@builder.after_all(hook)
end end
# Defines a block of code to execute after every example in the current group. # Defines a block of code to execute after every example in the current group.
def after_each(source = nil, label = "after_each", &block : Example ->) def after_each(location = nil, label = "after_each", &block : Example ->)
hook = ExampleHook.new(source: source, label: label, &block) hook = ExampleHook.new(location: location, label: label, &block)
@@builder.after_each(hook) @@builder.after_each(hook)
end end
# Defines a block of code to execute around every example in the current group. # Defines a block of code to execute around every example in the current group.
def around_each(source = nil, label = "around_each", &block : Example::Procsy ->) def around_each(location = nil, label = "around_each", &block : Example::Procsy ->)
hook = ExampleProcsyHook.new(source: source, label: label, &block) hook = ExampleProcsyHook.new(location: location, label: label, &block)
@@builder.around_each(hook) @@builder.around_each(hook)
end end

View file

@ -1,5 +1,5 @@
require "../context" require "../context"
require "../source" require "../location"
require "./builder" require "./builder"
require "./tags" require "./tags"
@ -47,7 +47,7 @@ module Spectator::DSL
::Spectator::DSL::Builder.add_example( ::Spectator::DSL::Builder.add_example(
_spectator_example_name(\{{what}}), _spectator_example_name(\{{what}}),
::Spectator::Source.new(\{{block.filename}}, \{{block.line_number}}), ::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}}),
new.as(::Spectator::Context), new.as(::Spectator::Context),
\%tags \%tags
) do |example| ) do |example|

View file

@ -1,7 +1,7 @@
require "../block" require "../block"
require "../expectation" require "../expectation"
require "../expectation_failed" require "../expectation_failed"
require "../source" require "../location"
require "../value" require "../value"
module Spectator::DSL module Spectator::DSL
@ -10,7 +10,7 @@ module Spectator::DSL
# Immediately fail the current test. # Immediately fail the current test.
# A reason can be specified with *message*. # A reason can be specified with *message*.
def fail(message = "Example failed", *, _file = __FILE__, _line = __LINE__) def fail(message = "Example failed", *, _file = __FILE__, _line = __LINE__)
raise ExpectationFailed.new(Source.new(_file, _line), message) raise ExpectationFailed.new(Location.new(_file, _line), message)
end end
# Starts an expectation. # Starts an expectation.
@ -30,8 +30,8 @@ module Spectator::DSL
end end
%expression = ::Spectator::Value.new(%actual, {{actual.stringify}}) %expression = ::Spectator::Value.new(%actual, {{actual.stringify}})
%source = ::Spectator::Source.new({{actual.filename}}, {{actual.line_number}}) %location = ::Spectator::Location.new({{actual.filename}}, {{actual.line_number}})
::Spectator::Expectation::Target.new(%expression, %source) ::Spectator::Expectation::Target.new(%expression, %location)
end end
# Starts an expectation. # Starts an expectation.
@ -82,8 +82,8 @@ module Spectator::DSL
{% raise "Unexpected block arguments in 'expect' call" %} {% raise "Unexpected block arguments in 'expect' call" %}
{% end %} {% end %}
%source = ::Spectator::Source.new({{block.filename}}, {{block.line_number}}) %location = ::Spectator::Location.new({{block.filename}}, {{block.line_number}})
::Spectator::Expectation::Target.new(%block, %source) ::Spectator::Expectation::Target.new(%block, %location)
end end
# Short-hand for expecting something of the subject. # Short-hand for expecting something of the subject.

View file

@ -1,4 +1,4 @@
require "../source" require "../location"
require "./builder" require "./builder"
require "./tags" require "./tags"
require "./memoize" require "./memoize"
@ -41,7 +41,7 @@ module Spectator::DSL
::Spectator::DSL::Builder.start_group( ::Spectator::DSL::Builder.start_group(
_spectator_group_name(\{{what}}), _spectator_group_name(\{{what}}),
::Spectator::Source.new(\{{block.filename}}, \{{block.line_number}}), ::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}}),
tags tags
) )

View file

@ -1,4 +1,4 @@
require "../source" require "../location"
require "./builder" require "./builder"
module Spectator::DSL module Spectator::DSL
@ -16,7 +16,7 @@ module Spectator::DSL
end end
::Spectator::DSL::Builder.{{type.id}}( ::Spectator::DSL::Builder.{{type.id}}(
::Spectator::Source.new(\{{block.filename}}, \{{block.line_number}}) ::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}})
) { \%hook } ) { \%hook }
end end
end end
@ -34,7 +34,7 @@ module Spectator::DSL
end end
::Spectator::DSL::Builder.{{type.id}}( ::Spectator::DSL::Builder.{{type.id}}(
::Spectator::Source.new(\{{block.filename}}, \{{block.line_number}}) ::Spectator::Location.new(\{{block.filename}}, \{{block.line_number}})
) do |example| ) do |example|
example.with_context(\{{@type.name}}) do example.with_context(\{{@type.name}}) do
\{% if block.args.empty? %} \{% if block.args.empty? %}

View file

@ -150,24 +150,24 @@ module Spectator::DSL
end end
macro expect_any_instance_of(type, _source_file = __FILE__, _source_line = __LINE__) macro expect_any_instance_of(type, _source_file = __FILE__, _source_line = __LINE__)
%source = ::Spectator::Source.new({{_source_file}}, {{_source_line}}) %location = ::Spectator::Location.new({{_source_file}}, {{_source_line}})
::Spectator::Mocks::ExpectAnyInstance({{type}}).new(%source) ::Spectator::Mocks::ExpectAnyInstance({{type}}).new(%location)
end end
macro receive(method_name, _source_file = __FILE__, _source_line = __LINE__, &block) macro receive(method_name, _source_file = __FILE__, _source_line = __LINE__, &block)
%source = ::Spectator::Source.new({{_source_file}}, {{_source_line}}) %location = ::Spectator::Location.new({{_source_file}}, {{_source_line}})
{% if block.is_a?(Nop) %} {% if block.is_a?(Nop) %}
::Spectator::Mocks::NilMethodStub.new({{method_name.id.symbolize}}, %source) ::Spectator::Mocks::NilMethodStub.new({{method_name.id.symbolize}}, %location)
{% else %} {% else %}
::Spectator::Mocks::ProcMethodStub.create({{method_name.id.symbolize}}, %source) { {{block.body}} } ::Spectator::Mocks::ProcMethodStub.create({{method_name.id.symbolize}}, %location) { {{block.body}} }
{% end %} {% end %}
end end
macro receive_messages(_source_file = __FILE__, _source_line = __LINE__, **stubs) macro receive_messages(_source_file = __FILE__, _source_line = __LINE__, **stubs)
%source = ::Spectator::Source.new({{_source_file}}, {{_source_line}}) %location = ::Spectator::Location.new({{_source_file}}, {{_source_line}})
%stubs = [] of ::Spectator::Mocks::MethodStub %stubs = [] of ::Spectator::Mocks::MethodStub
{% for name, value in stubs %} {% for name, value in stubs %}
%stubs << ::Spectator::Mocks::ValueMethodStub.new({{name.id.symbolize}}, %source, {{value}}) %stubs << ::Spectator::Mocks::ValueMethodStub.new({{name.id.symbolize}}, %location, {{value}})
{% end %} {% end %}
%stubs %stubs
end end

View file

@ -1,9 +1,9 @@
require "./example_context_delegate" require "./example_context_delegate"
require "./example_group" require "./example_group"
require "./harness" require "./harness"
require "./location"
require "./pending_result" require "./pending_result"
require "./result" require "./result"
require "./source"
require "./spec/node" require "./spec/node"
require "./tags" require "./tags"
@ -27,14 +27,14 @@ module Spectator
# The *entrypoint* defines the test code (typically inside *context*). # The *entrypoint* defines the test code (typically inside *context*).
# The *name* describes the purpose of the example. # The *name* describes the purpose of the example.
# It can be a `Symbol` to describe a type. # It can be a `Symbol` to describe a type.
# The *source* tracks where the example exists in source code. # The *location* tracks where the example exists in source code.
# The example will be assigned to *group* if it is provided. # The example will be assigned to *group* if it is provided.
# A set of *tags* can be used for filtering and modifying example behavior. # A set of *tags* can be used for filtering and modifying example behavior.
# Note: The tags will not be merged with the parent tags. # Note: The tags will not be merged with the parent tags.
def initialize(@context : Context, @entrypoint : self ->, def initialize(@context : Context, @entrypoint : self ->,
name : String? = nil, source : Source? = nil, name : String? = nil, location : Location? = nil,
group : ExampleGroup? = nil, tags = Tags.new) group : ExampleGroup? = nil, tags = Tags.new)
super(name, source, group, tags) super(name, location, group, tags)
end end
# Creates a dynamic example. # Creates a dynamic example.
@ -42,13 +42,13 @@ module Spectator
# The block will be given this example instance as an argument. # The block will be given this example instance as an argument.
# The *name* describes the purpose of the example. # The *name* describes the purpose of the example.
# It can be a `Symbol` to describe a type. # It can be a `Symbol` to describe a type.
# The *source* tracks where the example exists in source code. # The *location* tracks where the example exists in source code.
# The example will be assigned to *group* if it is provided. # The example will be assigned to *group* if it is provided.
# A set of *tags* can be used for filtering and modifying example behavior. # A set of *tags* can be used for filtering and modifying example behavior.
# Note: The tags will not be merged with the parent tags. # Note: The tags will not be merged with the parent tags.
def initialize(name : String? = nil, source : Source? = nil, group : ExampleGroup? = nil, def initialize(name : String? = nil, location : Location? = nil, group : ExampleGroup? = nil,
tags = Tags.new, &block : self ->) tags = Tags.new, &block : self ->)
super(name, source, group, tags) super(name, location, group, tags)
@context = NullContext.new @context = NullContext.new
@entrypoint = block @entrypoint = block
end end
@ -140,10 +140,10 @@ module Spectator
to_s(io) to_s(io)
io << '"' io << '"'
# Add source if it's available. # Add location if it's available.
if (source = self.source) if (location = self.location)
io << " @ " io << " @ "
io << source io << location
end end
io << result io << result

View file

@ -1,11 +1,11 @@
require "./label" require "./label"
require "./source" require "./location"
module Spectator module Spectator
# Information about a hook tied to an example group and a proc to invoke it. # Information about a hook tied to an example group and a proc to invoke it.
class ExampleGroupHook class ExampleGroupHook
# Location of the hook in source code. # Location of the hook in source code.
getter! source : Source getter! location : Location
# User-defined description of the hook. # User-defined description of the hook.
getter! label : Label getter! label : Label
@ -14,14 +14,14 @@ module Spectator
# Creates the hook with a proc. # Creates the hook with a proc.
# The *proc* will be called when the hook is invoked. # The *proc* will be called when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(@proc : (->), *, @source : Source? = nil, @label : Label = nil) def initialize(@proc : (->), *, @location : Location? = nil, @label : Label = nil)
end end
# Creates the hook with a block. # Creates the hook with a block.
# The block will be executed when the hook is invoked. # The block will be executed when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(*, @source : Source? = nil, @label : Label = nil, &block : -> _) def initialize(*, @location : Location? = nil, @label : Label = nil, &block : -> _)
@proc = block @proc = block
end end
@ -31,7 +31,7 @@ module Spectator
end end
# Produces the string representation of the hook. # Produces the string representation of the hook.
# Includes the source and label if they're not nil. # Includes the location and label if they're not nil.
def to_s(io) def to_s(io)
io << "example group hook" io << "example group hook"
@ -40,9 +40,9 @@ module Spectator
io << label io << label
end end
if (source = @source) if (location = @location)
io << " @ " io << " @ "
io << source io << location
end end
end end
end end

View file

@ -1,11 +1,11 @@
require "./label" require "./label"
require "./source" require "./location"
module Spectator module Spectator
# Information about a hook tied to an example and a proc to invoke it. # Information about a hook tied to an example and a proc to invoke it.
class ExampleHook class ExampleHook
# Location of the hook in source code. # Location of the hook in source code.
getter! source : Source getter! location : Location
# User-defined description of the hook. # User-defined description of the hook.
getter! label : Label getter! label : Label
@ -14,15 +14,15 @@ module Spectator
# Creates the hook with a proc. # Creates the hook with a proc.
# The *proc* will be called when the hook is invoked. # The *proc* will be called when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(@proc : (Example ->), *, @source : Source? = nil, @label : Label = nil) def initialize(@proc : (Example ->), *, @location : Location? = nil, @label : Label = nil)
end end
# Creates the hook with a block. # Creates the hook with a block.
# The block must take a single argument - the current example. # The block must take a single argument - the current example.
# The block will be executed when the hook is invoked. # The block will be executed when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(*, @source : Source? = nil, @label : Label = nil, &block : Example -> _) def initialize(*, @location : Location? = nil, @label : Label = nil, &block : Example -> _)
@proc = block @proc = block
end end
@ -33,7 +33,7 @@ module Spectator
end end
# Produces the string representation of the hook. # Produces the string representation of the hook.
# Includes the source and label if they're not nil. # Includes the location and label if they're not nil.
def to_s(io) def to_s(io)
io << "example hook" io << "example hook"
@ -42,9 +42,9 @@ module Spectator
io << label io << label
end end
if (source = @source) if (location = @location)
io << " @ " io << " @ "
io << source io << location
end end
end end
end end

View file

@ -1,11 +1,11 @@
require "./label" require "./label"
require "./source" require "./location"
module Spectator module Spectator
# Information about a hook tied to an example and a proc to invoke it. # Information about a hook tied to an example and a proc to invoke it.
class ExampleProcsyHook class ExampleProcsyHook
# Location of the hook in source code. # Location of the hook in source code.
getter! source : Source getter! location : Location
# User-defined description of the hook. # User-defined description of the hook.
getter! label : Label getter! label : Label
@ -14,15 +14,15 @@ module Spectator
# Creates the hook with a proc. # Creates the hook with a proc.
# The *proc* will be called when the hook is invoked. # The *proc* will be called when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(@proc : (Example::Procsy ->), *, @source : Source? = nil, @label : Label = nil) def initialize(@proc : (Example::Procsy ->), *, @location : Location? = nil, @label : Label = nil)
end end
# Creates the hook with a block. # Creates the hook with a block.
# The block must take a single argument - the current example wrapped in a procsy. # The block must take a single argument - the current example wrapped in a procsy.
# The block will be executed when the hook is invoked. # The block will be executed when the hook is invoked.
# A *source* and *label* can be provided for debugging. # A *location* and *label* can be provided for debugging.
def initialize(*, @source : Source? = nil, @label : Label = nil, &block : Example::Procsy -> _) def initialize(*, @location : Location? = nil, @label : Label = nil, &block : Example::Procsy -> _)
@proc = block @proc = block
end end
@ -38,7 +38,7 @@ module Spectator
end end
# Produces the string representation of the hook. # Produces the string representation of the hook.
# Includes the source and label if they're not nil. # Includes the location and label if they're not nil.
def to_s(io) def to_s(io)
io << "example hook" io << "example hook"
@ -47,9 +47,9 @@ module Spectator
io << label io << label
end end
if (source = @source) if (location = @location)
io << " @ " io << " @ "
io << source io << location
end end
end end
end end

View file

@ -1,5 +1,5 @@
require "./expression" require "./expression"
require "./source" require "./location"
module Spectator module Spectator
# Result of evaluating a matcher on a target. # Result of evaluating a matcher on a target.
@ -7,9 +7,9 @@ module Spectator
# such as whether it was successful and a description of the operation. # such as whether it was successful and a description of the operation.
struct Expectation struct Expectation
# Location of the expectation in source code. # Location of the expectation in source code.
# This can be nil if the source isn't capturable, # This can be nil if the location isn't capturable,
# for instance using the *should* syntax or dynamically created expectations. # for instance using the *should* syntax or dynamically created expectations.
getter source : Source? getter location : Location?
# Indicates whether the expectation was met. # Indicates whether the expectation was met.
def satisfied? def satisfied?
@ -48,14 +48,14 @@ module Spectator
# Creates the expectation. # Creates the expectation.
# The *match_data* comes from the result of calling `Matcher#match`. # The *match_data* comes from the result of calling `Matcher#match`.
# The *source* is the location of the expectation in source code, if available. # The *location* is the location of the expectation in source code, if available.
def initialize(@match_data : Matchers::MatchData, @source : Source? = nil) def initialize(@match_data : Matchers::MatchData, @location : Location? = nil)
end end
# Creates the JSON representation of the expectation. # Creates the JSON representation of the expectation.
def to_json(json : ::JSON::Builder) def to_json(json : ::JSON::Builder)
json.object do json.object do
json.field("source") { @source.to_json(json) } json.field("location") { @location.to_json(json) }
json.field("satisfied", satisfied?) json.field("satisfied", satisfied?)
if (failed = @match_data.as?(Matchers::FailedMatchData)) if (failed = @match_data.as?(Matchers::FailedMatchData))
failed_to_json(failed, json) failed_to_json(failed, json)
@ -76,15 +76,15 @@ module Spectator
end end
# Stores part of an expectation. # Stores part of an expectation.
# This covers the actual value (or block) being inspected and its source. # This covers the actual value (or block) being inspected and its location.
# This is the type returned by an `expect` block in the DSL. # This is the type returned by an `expect` block in the DSL.
# It is not intended to be used directly, but instead by chaining methods. # It is not intended to be used directly, but instead by chaining methods.
# Typically `#to` and `#not_to` are used. # Typically `#to` and `#not_to` are used.
struct Target(T) struct Target(T)
# Creates the expectation target. # Creates the expectation target.
# The *expression* is the actual value being tested and its label. # The *expression* is the actual value being tested and its label.
# The *source* is the location of where this expectation was defined. # The *location* is the location of where this expectation was defined.
def initialize(@expression : Expression(T), @source : Source) def initialize(@expression : Expression(T), @location : Location)
end end
# Asserts that some criteria defined by the matcher is satisfied. # Asserts that some criteria defined by the matcher is satisfied.
@ -163,7 +163,7 @@ module Spectator
# Reports an expectation to the current harness. # Reports an expectation to the current harness.
private def report(match_data : Matchers::MatchData) private def report(match_data : Matchers::MatchData)
expectation = Expectation.new(match_data, @source) expectation = Expectation.new(match_data, @location)
Harness.current.report(expectation) Harness.current.report(expectation)
end end
end end

View file

@ -28,7 +28,7 @@ module Spectator::Formatting
title(indent) title(indent)
indent.increase(inner_indent) do indent.increase(inner_indent) do
content(indent) content(indent)
source(indent) location(indent)
end end
end end
end end
@ -103,9 +103,9 @@ module Spectator::Formatting
end end
end end
# Produces the source line of the failure block. # Produces the location line of the failure block.
private def source(indent) private def location(indent)
indent.line(Comment.color(@result.example.source)) indent.line(Comment.color(@result.example.location))
end end
# Gets the number of characters a positive integer spans in base 10. # Gets the number of characters a positive integer spans in base 10.

View file

@ -8,7 +8,7 @@ module Spectator::Formatting
# Appends the command to the output. # Appends the command to the output.
def to_s(io) def to_s(io)
io << "crystal spec " io << "crystal spec "
io << @example.source io << @example.location
end end
# Colorizes the command instance based on the result. # Colorizes the command instance based on the result.

View file

@ -88,7 +88,7 @@ module Spectator::Formatting
@json.object do @json.object do
@json.field("example", result.example) @json.field("example", result.example)
@json.field("time", result.elapsed.total_seconds) @json.field("time", result.elapsed.total_seconds)
@json.field("source", result.example.source) @json.field("location", result.example.location)
end end
end end
end end

View file

@ -55,7 +55,7 @@ module Spectator::Formatting
# Adds all of the individual test suite blocks. # Adds all of the individual test suite blocks.
private def add_test_suites(report) private def add_test_suites(report)
report.group_by(&.example.source.path).each do |path, results| report.group_by(&.example.location.path).each do |path, results|
JUnitTestSuite.new(path, results).to_xml(@xml) JUnitTestSuite.new(path, results).to_xml(@xml)
end end
end end

View file

@ -31,7 +31,7 @@ module Spectator::Formatting
# Java-ified class name created from the spec. # Java-ified class name created from the spec.
private def classname private def classname
path = result.example.source.path path = result.example.location.path
file = File.basename(path) file = File.basename(path)
ext = File.extname(file) ext = File.extname(file)
name = file[0...-(ext.size)] name = file[0...-(ext.size)]

View file

@ -0,0 +1,16 @@
module Spectator::Formatting
# Produces the timing line in a profile block.
# This contains the length of time, and the example's location.
private struct LocationTiming
# Creates the location timing line.
def initialize(@span : Time::Span, @location : Location)
end
# Appends the location timing information to the output.
def to_s(io)
io << HumanTime.new(@span).colorize.bold
io << ' '
io << @location
end
end
end

View file

@ -21,7 +21,7 @@ module Spectator::Formatting
private def entry(indent, result) private def entry(indent, result)
indent.line(result.example) indent.line(result.example)
indent.increase do indent.increase do
indent.line(SourceTiming.new(result.elapsed, result.example.source)) indent.line(LocationTiming.new(result.elapsed, result.example.location))
end end
end end
end end

View file

@ -1,16 +0,0 @@
module Spectator::Formatting
# Produces the timing line in a profile block.
# This contains the length of time, and the example's source.
private struct SourceTiming
# Creates the source timing line.
def initialize(@span : Time::Span, @source : Source)
end
# Appends the source timing information to the output.
def to_s(io)
io << HumanTime.new(@span).colorize.bold
io << ' '
io << @source
end
end
end

View file

@ -51,7 +51,7 @@ module Spectator::Formatting
indent.line(result.example) indent.line(result.example)
indent.increase do indent.increase do
@io << "# " @io << "# "
indent.line(SourceTiming.new(result.elapsed, result.example.source)) indent.line(LocationTiming.new(result.elapsed, result.example.location))
end end
end end
end end

View file

@ -37,6 +37,8 @@ require "./label"
require "./lazy" require "./lazy"
require "./lazy_wrapper" require "./lazy_wrapper"
require "./line_example_filter" require "./line_example_filter"
require "./location"
require "./location_example_filter"
require "./matchers" require "./matchers"
require "./mocks" require "./mocks"
require "./name_example_filter" require "./name_example_filter"
@ -47,8 +49,6 @@ require "./pending_result"
require "./profile" require "./profile"
require "./report" require "./report"
require "./result" require "./result"
require "./source"
require "./source_example_filter"
require "./spec" require "./spec"
require "./tags" require "./tags"
require "./test_context" require "./test_context"

View file

@ -7,7 +7,7 @@ module Spectator
# Checks whether the example satisfies the filter. # Checks whether the example satisfies the filter.
def includes?(example) : Bool def includes?(example) : Bool
@line == example.source.line @line == example.location.line
end end
end end
end end

View file

@ -1,19 +1,19 @@
require "json" require "json"
module Spectator module Spectator
# Define the file and line number something originated from. # Defines the file and line number a piece of code originated from.
struct Source struct Location
# Absolute file path. # Absolute file path.
getter file : String getter file : String
# Line number in the file. # Line number in the file.
getter line : Int32 getter line : Int32
# Creates the source. # Creates the location.
def initialize(@file, @line) def initialize(@file, @line)
end end
# Parses a source from a string. # Parses a location from a string.
# The *string* should be in the form: # The *string* should be in the form:
# ```text # ```text
# FILE:LINE # FILE:LINE
@ -50,7 +50,7 @@ module Spectator
end end
end end
# String representation of the source. # String representation of the location.
# This is formatted as: # This is formatted as:
# ```text # ```text
# FILE:LINE # FILE:LINE
@ -61,7 +61,7 @@ module Spectator
io << line io << line
end end
# Creates the JSON representation of the source. # Creates the JSON representation of the location.
def to_json(json : ::JSON::Builder) def to_json(json : ::JSON::Builder)
json.string(to_s) json.string(to_s)
end end

View file

@ -1,14 +1,14 @@
module Spectator module Spectator
# Filter that matches examples in a given file and line. # Filter that matches examples in a given file and line.
class SourceExampleFilter < ExampleFilter class LocationExampleFilter < ExampleFilter
# Creates the filter. # Creates the filter.
# The *source* indicates which file and line the example must be on. # The *location* indicates which file and line the example must be on.
def initialize(@source : Source) def initialize(@location : Location)
end end
# Checks whether the example satisfies the filter. # Checks whether the example satisfies the filter.
def includes?(example) : Bool def includes?(example) : Bool
@source === example.source @location === example.location
end end
end end
end end

View file

@ -3,8 +3,8 @@ require "./generic_method_stub"
module Spectator::Mocks module Spectator::Mocks
class ExceptionMethodStub(ExceptionType) < GenericMethodStub(Nil) class ExceptionMethodStub(ExceptionType) < GenericMethodStub(Nil)
def initialize(name, source, @exception : ExceptionType, args = nil) def initialize(name, location, @exception : ExceptionType, args = nil)
super(name, source, args) super(name, location, args)
end end
def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT

View file

@ -2,7 +2,7 @@ require "./registry"
module Spectator::Mocks module Spectator::Mocks
struct ExpectAnyInstance(T) struct ExpectAnyInstance(T)
def initialize(@source : Source) def initialize(@location : Location)
end end
def to(stub : MethodStub) : Nil def to(stub : MethodStub) : Nil
@ -10,7 +10,7 @@ module Spectator::Mocks
Harness.current.mocks.expect(T, stub) Harness.current.mocks.expect(T, stub)
value = Value.new(stub.name, stub.to_s) value = Value.new(stub.name, stub.to_s)
matcher = Matchers::ReceiveTypeMatcher.new(value, stub.arguments?) matcher = Matchers::ReceiveTypeMatcher.new(value, stub.arguments?)
partial = Expectations::ExpectationPartial.new(actual, @source) partial = Expectations::ExpectationPartial.new(actual, @location)
partial.to_eventually(matcher) partial.to_eventually(matcher)
end end

View file

@ -7,8 +7,8 @@ module Spectator::Mocks
abstract class GenericMethodStub(ReturnType) < MethodStub abstract class GenericMethodStub(ReturnType) < MethodStub
getter! arguments : Arguments getter! arguments : Arguments
def initialize(name, source, @args : Arguments? = nil) def initialize(name, location, @args : Arguments? = nil)
super(name, source) super(name, location)
end end
def callable?(call : MethodCall) : Bool def callable?(call : MethodCall) : Bool
@ -25,7 +25,7 @@ module Spectator::Mocks
io << " : " io << " : "
io << ReturnType io << ReturnType
io << " at " io << " at "
io << @source io << @location
end end
end end
end end

View file

@ -1,13 +1,13 @@
require "../source" require "../location"
require "./method_call" require "./method_call"
module Spectator::Mocks module Spectator::Mocks
abstract class MethodStub abstract class MethodStub
getter name : Symbol getter name : Symbol
getter source : Source getter location : Location
def initialize(@name, @source) def initialize(@name, @location)
end end
def callable?(call : MethodCall) : Bool def callable?(call : MethodCall) : Bool

View file

@ -5,8 +5,8 @@ module Spectator::Mocks
class MultiValueMethodStub(ReturnType) < GenericMethodStub(ReturnType) class MultiValueMethodStub(ReturnType) < GenericMethodStub(ReturnType)
@index = 0 @index = 0
def initialize(name, source, @values : ReturnType, args = nil) def initialize(name, location, @values : ReturnType, args = nil)
super(name, source, args) super(name, location, args)
raise ArgumentError.new("Values must have at least one item") if @values.size < 1 raise ArgumentError.new("Values must have at least one item") if @values.size < 1
end end

View file

@ -13,36 +13,36 @@ module Spectator::Mocks
end end
def and_return(value) def and_return(value)
ValueMethodStub.new(@name, @source, value, @args) ValueMethodStub.new(@name, @location, value, @args)
end end
def and_return(*values) def and_return(*values)
MultiValueMethodStub.new(@name, @source, values.to_a, @args) MultiValueMethodStub.new(@name, @location, values.to_a, @args)
end end
def and_raise(exception_type : Exception.class) def and_raise(exception_type : Exception.class)
ExceptionMethodStub.new(@name, @source, exception_type.new, @args) ExceptionMethodStub.new(@name, @location, exception_type.new, @args)
end end
def and_raise(exception : Exception) def and_raise(exception : Exception)
ExceptionMethodStub.new(@name, @source, exception, @args) ExceptionMethodStub.new(@name, @location, exception, @args)
end end
def and_raise(message : String) def and_raise(message : String)
ExceptionMethodStub.new(@name, @source, Exception.new(message), @args) ExceptionMethodStub.new(@name, @location, Exception.new(message), @args)
end end
def and_raise(exception_type : Exception.class, *args) forall T def and_raise(exception_type : Exception.class, *args) forall T
ExceptionMethodStub.new(@name, @source, exception_type.new(*args), @args) ExceptionMethodStub.new(@name, @location, exception_type.new(*args), @args)
end end
def with(*args : *T, **opts : **NT) forall T, NT def with(*args : *T, **opts : **NT) forall T, NT
args = GenericArguments.new(args, opts) args = GenericArguments.new(args, opts)
NilMethodStub.new(@name, @source, args) NilMethodStub.new(@name, @location, args)
end end
def and_call_original def and_call_original
OriginalMethodStub.new(@name, @source, @args) OriginalMethodStub.new(@name, @location, @args)
end end
end end
end end

View file

@ -3,12 +3,12 @@ require "./generic_method_stub"
module Spectator::Mocks module Spectator::Mocks
class ProcMethodStub(ReturnType) < GenericMethodStub(ReturnType) class ProcMethodStub(ReturnType) < GenericMethodStub(ReturnType)
def initialize(name, source, @proc : -> ReturnType, args = nil) def initialize(name, location, @proc : -> ReturnType, args = nil)
super(name, source, args) super(name, location, args)
end end
def self.create(name, source, args = nil, &block : -> T) forall T def self.create(name, location, args = nil, &block : -> T) forall T
ProcMethodStub.new(name, source, block, args) ProcMethodStub.new(name, location, block, args)
end end
def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT

View file

@ -4,7 +4,7 @@ module Spectator::Mocks
module Reflection module Reflection
private macro _spectator_reflect private macro _spectator_reflect
{% for meth in @type.methods %} {% for meth in @type.methods %}
%source = ::Spectator::Source.new({{meth.filename}}, {{meth.line_number}}) %location = ::Spectator::Location.new({{meth.filename}}, {{meth.line_number}})
%args = ::Spectator::Mocks::GenericArguments.create( %args = ::Spectator::Mocks::GenericArguments.create(
{% for arg, i in meth.args %} {% for arg, i in meth.args %}
{% matcher = if arg.restriction {% matcher = if arg.restriction
@ -19,7 +19,7 @@ module Spectator::Mocks
{{matcher}}{% if i < meth.args.size %},{% end %} {{matcher}}{% if i < meth.args.size %},{% end %}
{% end %} {% end %}
) )
::Spectator::Mocks::TypeRegistry.add({{@type.id.stringify}}, {{meth.name.symbolize}}, %source, %args) ::Spectator::Mocks::TypeRegistry.add({{@type.id.stringify}}, {{meth.name.symbolize}}, %location, %args)
{% end %} {% end %}
end end
end end

View file

@ -6,14 +6,14 @@ module Spectator::Mocks
@@entries = {} of Key => Deque(MethodStub) @@entries = {} of Key => Deque(MethodStub)
def add(type_name : String, method_name : Symbol, source : Source, args : Arguments) : Nil def add(type_name : String, method_name : Symbol, location : Location, args : Arguments) : Nil
key = {type_name, method_name} key = {type_name, method_name}
list = if @@entries.has_key?(key) list = if @@entries.has_key?(key)
@@entries[key] @@entries[key]
else else
@@entries[key] = Deque(MethodStub).new @@entries[key] = Deque(MethodStub).new
end end
list << NilMethodStub.new(method_name, source, args) list << NilMethodStub.new(method_name, location, args)
end end
def exists?(type_name : String, call : MethodCall) : Bool def exists?(type_name : String, call : MethodCall) : Bool

View file

@ -3,8 +3,8 @@ require "./generic_method_stub"
module Spectator::Mocks module Spectator::Mocks
class ValueMethodStub(ReturnType) < GenericMethodStub(ReturnType) class ValueMethodStub(ReturnType) < GenericMethodStub(ReturnType)
def initialize(name, source, @value : ReturnType, args = nil) def initialize(name, location, @value : ReturnType, args = nil)
super(name, source, args) super(name, location, args)
end end
def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT def call(_args : GenericArguments(T, NT), &_original : -> RT) forall T, NT, RT

View file

@ -31,7 +31,7 @@ module Spectator
# Adds the common fields for a result to a JSON builder. # Adds the common fields for a result to a JSON builder.
private def add_json_fields(json : ::JSON::Builder) private def add_json_fields(json : ::JSON::Builder)
json.field("name", example) json.field("name", example)
json.field("location", example.source) json.field("location", example.location)
json.field("result", to_s) json.field("result", to_s)
json.field("time", elapsed.total_seconds) json.field("time", elapsed.total_seconds)
json.field("expectations", expectations) json.field("expectations", expectations)

View file

@ -52,16 +52,16 @@ module Spectator
# This should be a symbol when describing a type - the type name is represented as a symbol. # This should be a symbol when describing a type - the type name is represented as a symbol.
# Otherwise, a string should be used. # Otherwise, a string should be used.
# #
# The *source* optionally defined where the group originates in source code. # The *location* optionally defined where the group originates in source code.
# #
# A set of *tags* can be used for filtering and modifying example behavior. # A set of *tags* can be used for filtering and modifying example behavior.
# For instance, adding a "pending" tag will mark tests as pending and skip execution. # For instance, adding a "pending" tag will mark tests as pending and skip execution.
# #
# The newly created group is returned. # The newly created group is returned.
# It shouldn't be used outside of this class until a matching `#end_group` is called. # It shouldn't be used outside of this class until a matching `#end_group` is called.
def start_group(name, source = nil, tags = Tags.new) : ExampleGroup def start_group(name, location = nil, tags = Tags.new) : ExampleGroup
Log.trace { "Start group: #{name.inspect} @ #{source}; tags: #{tags}" } Log.trace { "Start group: #{name.inspect} @ #{location}; tags: #{tags}" }
ExampleGroup.new(name, source, current_group, tags).tap do |group| ExampleGroup.new(name, location, current_group, tags).tap do |group|
@group_stack << group @group_stack << group
end end
end end
@ -86,7 +86,7 @@ module Spectator
# This should be a string or nil. # This should be a string or nil.
# When nil, the example's name will be populated by the first expectation run inside of the test code. # When nil, the example's name will be populated by the first expectation run inside of the test code.
# #
# The *source* optionally defined where the example originates in source code. # The *location* optionally defined where the example originates in source code.
# #
# The *context* is an instance of the context the test code should run in. # The *context* is an instance of the context the test code should run in.
# See `Context` for more information. # See `Context` for more information.
@ -100,9 +100,9 @@ module Spectator
# It is expected that the test code runs when the block is called. # It is expected that the test code runs when the block is called.
# #
# The newly created example is returned. # The newly created example is returned.
def add_example(name, source, context, tags = Tags.new, &block : Example -> _) : Example def add_example(name, location, context, tags = Tags.new, &block : Example -> _) : Example
Log.trace { "Add example: #{name} @ #{source}; tags: #{tags}" } Log.trace { "Add example: #{name} @ #{location}; tags: #{tags}" }
Example.new(context, block, name, source, current_group, tags) Example.new(context, block, name, location, current_group, tags)
# The example is added to the current group by `Example` initializer. # The example is added to the current group by `Example` initializer.
end end

View file

@ -1,5 +1,5 @@
require "../label" require "../label"
require "../source" require "../location"
require "../tags" require "../tags"
module Spectator module Spectator
@ -9,7 +9,7 @@ module Spectator
# but can be anything that should be iterated over when running the spec. # but can be anything that should be iterated over when running the spec.
abstract class Node abstract class Node
# Location of the node in source code. # Location of the node in source code.
getter! source : Source getter! location : Location
# User-provided name or description of the node. # User-provided name or description of the node.
# This does not include the group name or descriptions. # This does not include the group name or descriptions.
@ -41,10 +41,10 @@ module Spectator
# Creates the node. # Creates the node.
# The *name* describes the purpose of the node. # The *name* describes the purpose of the node.
# It can be a `Symbol` to describe a type. # It can be a `Symbol` to describe a type.
# The *source* tracks where the node exists in source code. # The *location* tracks where the node exists in source code.
# The node will be assigned to *group* if it is provided. # The node will be assigned to *group* if it is provided.
# A set of *tags* can be used for filtering and modifying example behavior. # A set of *tags* can be used for filtering and modifying example behavior.
def initialize(@name : Label = nil, @source : Source? = nil, def initialize(@name : Label = nil, @location : Location? = nil,
group : ExampleGroup? = nil, @tags : Tags = Tags.new) group : ExampleGroup? = nil, @tags : Tags = Tags.new)
# Ensure group is linked. # Ensure group is linked.
group << self if group group << self if group