Support string interpolation for example names

This commit is contained in:
Michael Miller 2022-01-10 21:29:05 -07:00
parent aabec269cb
commit dd49fe3a67
No known key found for this signature in database
GPG key ID: AC78B32D30CE34A2
4 changed files with 49 additions and 4 deletions

View file

@ -0,0 +1,9 @@
require "../spec_helper"
Spectator.describe "Spec metadata" do
let(interpolation) { "string interpolation" }
it "supports #{interpolation}" do |example|
expect(example.name).to eq("supports string interpolation")
end
end

View file

@ -122,10 +122,12 @@ module Spectator::DSL
# For anything else, it is stringified.
# This is intended to be used to convert a description from the spec DSL to `Node#name`.
private macro _spectator_example_name(what)
{% if what.is_a?(StringLiteral) ||
what.is_a?(StringInterpolation) ||
what.is_a?(NilLiteral) %}
{% if what.is_a?(StringLiteral) || what.is_a?(NilLiteral) %}
{{what}}
{% elsif what.is_a?(StringInterpolation) %}
->(example : ::Spectator::Example) do
example.with_context(\{{@type.name}}) { {{what}} }
end
{% else %}
{{what.stringify}}
{% end %}

View file

@ -28,11 +28,12 @@ module Spectator
# Is pending if the example hasn't run.
getter result : Result = PendingResult.new("Example not run")
@name_proc : Proc(Example, String)?
# Creates the example.
# An instance to run the test code in is given by *context*.
# The *entrypoint* defines the test code (typically inside *context*).
# The *name* describes the purpose of the example.
# It can be a `Symbol` to describe a type.
# The *location* tracks where the example exists in source code.
# The example will be assigned to *group* if it is provided.
# A set of *metadata* can be used for filtering and modifying example behavior.
@ -46,6 +47,24 @@ module Spectator
group << self if group
end
# Creates the example.
# An instance to run the test code in is given by *context*.
# The *entrypoint* defines the test code (typically inside *context*).
# The *name* describes the purpose of the example.
# It can be a proc to be evaluated in the context of the example.
# The *location* tracks where the example exists in source code.
# The example will be assigned to *group* if it is provided.
# A set of *metadata* can be used for filtering and modifying example behavior.
# Note: The metadata will not be merged with the parent metadata.
def initialize(@context : Context, @entrypoint : self ->,
@name_proc : Example -> String, location : Location? = nil,
@group : ExampleGroup? = nil, metadata = Metadata.new)
super(nil, location, metadata)
# Ensure group is linked.
group << self if group
end
# Creates a dynamic example.
# A block provided to this method will be called as-if it were the test code for the example.
# The block will be given this example instance as an argument.
@ -98,6 +117,10 @@ module Spectator
begin
@result = Harness.run do
if proc = @name_proc.as?(Proc(Example, String))
self.name = proc.call(self)
end
@group.try(&.call_before_all)
if (parent = @group)
parent.call_around_each(procsy).call

View file

@ -8,6 +8,8 @@ module Spectator
# Constructs examples.
# Call `#build` to produce an `Example`.
class ExampleBuilder < NodeBuilder
@name : Proc(Example, String) | String?
# Creates the builder.
# A proc provided by *context_builder* is used to create a unique `Context` for each example produced by `#build`.
# The *entrypoint* indicates the proc used to invoke the test code in the example.
@ -16,6 +18,15 @@ module Spectator
@name : String? = nil, @location : Location? = nil, @metadata : Metadata = Metadata.new)
end
# Creates the builder.
# A proc provided by *context_builder* is used to create a unique `Context` for each example produced by `#build`.
# The *entrypoint* indicates the proc used to invoke the test code in the example.
# The *name* is an interpolated string that runs in the context of the example.
# *location*, and *metadata* will be applied to the `Example` produced by `#build`.
def initialize(@context_builder : -> Context, @entrypoint : Example ->,
@name : Example -> String, @location : Location? = nil, @metadata : Metadata = Metadata.new)
end
# Constructs an example with previously defined attributes and context.
# The *parent* is an already constructed example group to nest the new example under.
# It can be nil if the new example won't have a parent.