diff --git a/CHANGELOG.md b/CHANGELOG.md index dfbe8c2..fb7b645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Expectations using 'should' syntax report file and line where the 'should' keyword is instead of the test start. -- String interpolation for example names/labels uses a separate context than the one used by the test. ## [0.11.5] - 2022-12-18 ### Added diff --git a/src/spectator/dsl/examples.cr b/src/spectator/dsl/examples.cr index 8a08116..703f2d3 100644 --- a/src/spectator/dsl/examples.cr +++ b/src/spectator/dsl/examples.cr @@ -125,10 +125,8 @@ module Spectator::DSL {% if what.is_a?(StringLiteral) || what.is_a?(NilLiteral) %} {{what}} {% elsif what.is_a?(StringInterpolation) %} - {{@type.name}}.new.eval do - {{what}} - rescue e - "" + ->(example : ::Spectator::Example) do + example.with_context(\{{@type.name}}) { {{what}} } end {% else %} {{what.stringify}} diff --git a/src/spectator/example.cr b/src/spectator/example.cr index 0c20ccb..04d69c9 100644 --- a/src/spectator/example.cr +++ b/src/spectator/example.cr @@ -28,6 +28,8 @@ 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*). @@ -45,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 = nil) + 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 +118,10 @@ module Spectator begin @result = Harness.run do + if proc = @name_proc + self.name = proc.call(self) + end + @group.try(&.call_before_all) if (parent = @group) parent.call_around_each(procsy).call diff --git a/src/spectator/example_builder.cr b/src/spectator/example_builder.cr index ae5866a..23398d2 100644 --- a/src/spectator/example_builder.cr +++ b/src/spectator/example_builder.cr @@ -8,7 +8,7 @@ module Spectator # Constructs examples. # Call `#build` to produce an `Example`. class ExampleBuilder < NodeBuilder - @name : String? + @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`. @@ -18,6 +18,15 @@ module Spectator @name : String? = nil, @location : Location? = nil, @metadata : Metadata? = nil) 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? = nil) + 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.