Move sample values to group instance

The goal is to construct examples with a parameterless initializer.
This doesn't quite work, since the sample values are retrieved via the
harness, which doesn't have an active example when the sample values are
created.
This commit is contained in:
Michael Miller 2019-08-30 14:46:24 -06:00
parent 4ecc2c6004
commit bfe641e07e
10 changed files with 25 additions and 39 deletions

View File

@ -41,12 +41,6 @@ module Spectator
include ::Spectator::DSL::StructureDSL # Include the DSL for creating groups, example, and more.
include ::Spectator::DSL::ExampleDSL # Mix in methods and macros specifically for example DSL.
# Placeholder initializer.
# This is needed because examples and groups call super in their initializer.
# Those initializers pass the sample values upward through their hierarchy.
def initialize(_sample_values : ::Spectator::Internals::SampleValues)
end
# Pass off the "what" argument and block to `DSL::StructureDSL.describe`.
# That method will handle creating a new group for this spec.
describe({{what}}) {{block}}

View File

@ -7,9 +7,9 @@ module Spectator::DSL
end
# Constructs a new example instance and returns it.
# The *group* and *sample_values* are passed to `Example#initialize`.
def build(group : ExampleGroup, sample_values : Internals::SampleValues) : Example
@example_type.new(group, sample_values)
# The *group* is passed to `Example#initialize`.
def build(group : ExampleGroup, _sample_values : Internals::SampleValues) : Example
@example_type.new(group)
end
end
end

View File

@ -26,7 +26,7 @@ module Spectator::DSL
# The *parent* should be the group that contains this group.
# The *sample_values* will be given to all of the examples (and groups) nested in this group.
def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
NestedExampleGroup.new(@what, parent, hooks, conditions).tap do |group|
NestedExampleGroup.new(@what, parent, hooks, conditions, sample_values).tap do |group|
# Set the group's children to built versions of the children from this instance.
group.children = @children.map do |child|
# Build the child and up-cast to prevent type errors.

View File

@ -6,7 +6,7 @@ module Spectator::DSL
# Creates a `RootExampleGroup` which can have instances of `Example` and `ExampleGroup` nested in it.
# The *sample_values* will be given to all of the examples (and groups) nested in this group.
def build(sample_values : Internals::SampleValues) : RootExampleGroup
RootExampleGroup.new(hooks, conditions).tap do |group|
RootExampleGroup.new(hooks, conditions, sample_values).tap do |group|
# Set the group's children to built versions of the children from this instance.
group.children = @children.map do |child|
# Build the child and up-cast to prevent type errors.

View File

@ -39,11 +39,11 @@ module Spectator::DSL
# The *parent* should be the group that contains this group.
# The *sample_values* will be given to all of the examples (and groups) nested in this group.
def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
collection = @collection_builder.call(@collection_type.new(sample_values))
collection = @collection_builder.call(@collection_type.new)
# This creates the container for the sub-groups.
# The hooks are defined here, instead of repeating for each sub-group.
NestedExampleGroup.new(@what, parent, hooks, conditions).tap do |group|
NestedExampleGroup.new(@what, parent, hooks, conditions, sample_values).tap do |group|
# Set the container group's children to be sub-groups for each item in the collection.
group.children = collection.map do |value|
# Create a sub-group for each item in the collection.
@ -61,7 +61,7 @@ module Spectator::DSL
private def build_sub_group(parent : ExampleGroup, sample_values : Internals::SampleValues, value : T) : NestedExampleGroup
# Add the value to sample values for this sub-group.
sub_values = sample_values.add(@symbol, @name, value)
NestedExampleGroup.new(value.to_s, parent, ExampleHooks.empty, ExampleConditions.empty).tap do |group|
NestedExampleGroup.new(value.to_s, parent, ExampleHooks.empty, ExampleConditions.empty, sub_values).tap do |group|
# Set the sub-group's children to built versions of the children from this instance.
group.children = @children.map do |child|
# Build the child and up-cast to prevent type errors.

View File

@ -503,13 +503,6 @@ module Spectator::DSL
# The collection could reference a helper method
# or anything else in the parent scope.
class Sample%sample < {{@type.id}}
# Placeholder initializer.
# This is needed because examples and groups call super in their initializer.
# Those initializers pass the sample values upward through their hierarchy.
def initialize(_sample_values : ::Spectator::Internals::SampleValues)
super
end
# Method that returns an array containing the collection.
# This method should be called only once.
# The framework stores the collection as an array for a couple of reasons.
@ -543,9 +536,9 @@ module Spectator::DSL
end
# Initializer to extract current element of the collection from sample values.
def initialize(sample_values : ::Spectator::Internals::SampleValues)
def initialize
super
@%wrapper = sample_values.get_wrapper(:%sample)
@%wrapper = ::Spectator::Internals::Harness.current.group.sample_values.get_wrapper(:%sample)
end
# Start a new example group.
@ -656,9 +649,9 @@ module Spectator::DSL
end
# Initializer to extract current element of the collection from sample values.
def initialize(sample_values : ::Spectator::Internals::SampleValues)
def initialize
super
@%wrapper = sample_values.get_wrapper(:%sample)
@%wrapper = ::Spectator::Internals::Harness.current.group.sample_values.get_wrapper(:%sample)
end
# Start a new example group.
@ -1576,13 +1569,6 @@ module Spectator::DSL
private macro _spectator_test(class_name, run_method_name)
# Wrapper class for isolating the test code.
class {{class_name.id}} < {{@type.id}}
# Initializer that accepts sample values.
# The sample values are passed upward to the group modules.
# Any module that adds sample values can pull their values from this instance.
def initialize(sample_values : ::Spectator::Internals::SampleValues)
super
end
# Generated method for actually running the test code.
def {{run_method_name.id}}
{{yield}}
@ -1614,9 +1600,9 @@ module Spectator::DSL
# Stores the group the example belongs to
# and sample values specific to this instance of the test.
# This method's signature must match the one used in `ExampleFactory#build`.
def initialize(group : ::Spectator::ExampleGroup, sample_values : ::Spectator::Internals::SampleValues)
def initialize(group : ::Spectator::ExampleGroup)
super
@instance = {{test_class_name.id}}.new(sample_values)
@instance = {{test_class_name.id}}.new
end
# Retrieves the underlying, wrapped test code.

View File

@ -31,8 +31,7 @@ module Spectator
# Creates the base of the example.
# The group should be the example group the example belongs to.
# The *sample_values* are passed to the example code.
def initialize(@group, sample_values : Internals::SampleValues)
def initialize(@group)
end
# Indicates there is only one example to run.

View File

@ -15,9 +15,11 @@ module Spectator
include Enumerable(ExampleComponent)
include Iterable(ExampleComponent)
getter sample_values : Internals::SampleValues
# Creates the example group.
# The hooks are stored to be triggered later.
def initialize(@hooks : ExampleHooks, @conditions : ExampleConditions)
def initialize(@hooks : ExampleHooks, @conditions : ExampleConditions, @sample_values)
@before_all_hooks_run = false
@after_all_hooks_run = false
end

View File

@ -34,6 +34,11 @@ module Spectator::Internals
# Retrieves the current running example.
getter example : Example
# Retrieves the group for the current running example.
def group
example.group
end
# Reports the outcome of an expectation.
# An exception will be raised when a failing result is given.
def report_expectation(expectation : Expectations::Expectation) : Nil

View File

@ -18,8 +18,8 @@ module Spectator
# The parent's children must contain this group,
# otherwise there may be unexpected behavior.
# The *hooks* are stored to be triggered later.
def initialize(@what, @parent, hooks : ExampleHooks, conditions : ExampleConditions)
super(hooks, conditions)
def initialize(@what, @parent, hooks : ExampleHooks, conditions : ExampleConditions, sample_values)
super(hooks, conditions, sample_values)
end
# Indicates wheter the group references a type.