Lazily initialize global DSL spec builder

Require config to create a spec builder.
Config should be fully set up before any DSL is encountered.
This commit is contained in:
Michael Miller 2021-08-08 11:25:06 -06:00
parent 605b82c532
commit 91d21b38e2
No known key found for this signature in database
GPG key ID: FB9F12F7C646A4AD
3 changed files with 25 additions and 53 deletions

View file

@ -68,7 +68,6 @@ module Spectator
::Log.setup_from_env(default_level: :none) ::Log.setup_from_env(default_level: :none)
# Build the spec and run it. # Build the spec and run it.
DSL::Builder.config = config
spec = DSL::Builder.build spec = DSL::Builder.build
spec.run spec.run
rescue ex rescue ex
@ -84,10 +83,8 @@ module Spectator
false false
end end
# Processes and builds up a configuration to use for running tests. # Global configuration used by Spectator for running tests.
private def config class_getter(config) { build_config }
@@config ||= build_config
end
# Builds the configuration. # Builds the configuration.
private def build_config private def build_config

View file

@ -10,7 +10,7 @@ module Spectator::DSL
extend self extend self
# Underlying spec builder. # Underlying spec builder.
@@builder = SpecBuilder.new private class_getter(builder) { SpecBuilder.new(Spectator.config) }
# Defines a new example group and pushes it onto the group stack. # Defines a new example group and pushes it onto the group stack.
# Examples and groups defined after calling this method will be nested under the new group. # Examples and groups defined after calling this method will be nested under the new group.
@ -18,7 +18,7 @@ module Spectator::DSL
# #
# See `Spec::Builder#start_group` for usage details. # See `Spec::Builder#start_group` for usage details.
def start_group(*args) def start_group(*args)
@@builder.start_group(*args) builder.start_group(*args)
end end
# Defines a new iterative example group and pushes it onto the group stack. # Defines a new iterative example group and pushes it onto the group stack.
@ -27,7 +27,7 @@ module Spectator::DSL
# #
# See `Spec::Builder#start_iterative_group` for usage details. # See `Spec::Builder#start_iterative_group` for usage details.
def start_iterative_group(*args) def start_iterative_group(*args)
@@builder.start_iterative_group(*args) builder.start_iterative_group(*args)
end end
# Completes a previously defined example group and pops it off the group stack. # Completes a previously defined example group and pops it off the group stack.
@ -35,7 +35,7 @@ module Spectator::DSL
# #
# See `Spec::Builder#end_group` for usage details. # See `Spec::Builder#end_group` for usage details.
def end_group(*args) def end_group(*args)
@@builder.end_group(*args) builder.end_group(*args)
end end
# Defines a new example. # Defines a new example.
@ -43,7 +43,7 @@ module Spectator::DSL
# #
# See `Spec::Builder#add_example` for usage details. # See `Spec::Builder#add_example` for usage details.
def add_example(*args, &block : Example ->) def add_example(*args, &block : Example ->)
@@builder.add_example(*args, &block) builder.add_example(*args, &block)
end end
# Defines a new pending example. # Defines a new pending example.
@ -51,98 +51,91 @@ module Spectator::DSL
# #
# See `Spec::Builder#add_pending_example` for usage details. # See `Spec::Builder#add_pending_example` for usage details.
def add_pending_example(*args) def add_pending_example(*args)
@@builder.add_pending_example(*args) builder.add_pending_example(*args)
end end
# Defines a block of code to execute before any and all examples in the test suite. # Defines a block of code to execute before any and all examples in the test suite.
def before_suite(location = nil, label = "before_suite", &block) def before_suite(location = nil, label = "before_suite", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.before_suite(hook) builder.before_suite(hook)
end end
# Defines a block of code to execute before any and all examples in the test suite. # Defines a block of code to execute before any and all examples in the test suite.
def prepend_before_suite(location = nil, label = "before_suite", &block) def prepend_before_suite(location = nil, label = "before_suite", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.prepend_before_suite(hook) builder.prepend_before_suite(hook)
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(location = nil, label = "before_all", &block) def before_all(location = nil, label = "before_all", &block)
hook = ExampleGroupHook.new(location: location, 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 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 prepend_before_all(location = nil, label = "before_all", &block) def prepend_before_all(location = nil, label = "before_all", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.prepend_before_all(hook) builder.prepend_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(location = nil, label = "before_each", &block : Example -> _) def before_each(location = nil, label = "before_each", &block : Example -> _)
hook = ExampleHook.new(location: location, 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 before every example in the current group # Defines a block of code to execute before every example in the current group
def prepend_before_each(location = nil, label = "before_each", &block : Example -> _) def prepend_before_each(location = nil, label = "before_each", &block : Example -> _)
hook = ExampleHook.new(location: location, label: label, &block) hook = ExampleHook.new(location: location, label: label, &block)
@@builder.prepend_before_each(hook) builder.prepend_before_each(hook)
end end
# Defines a block of code to execute after any and all examples in the test suite. # Defines a block of code to execute after any and all examples in the test suite.
def after_suite(location = nil, label = "after_suite", &block) def after_suite(location = nil, label = "after_suite", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.after_suite(hook) builder.after_suite(hook)
end end
# Defines a block of code to execute after any and all examples in the test suite. # Defines a block of code to execute after any and all examples in the test suite.
def append_after_suite(location = nil, label = "after_suite", &block) def append_after_suite(location = nil, label = "after_suite", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.append_after_suite(hook) builder.append_after_suite(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(location = nil, label = "after_all", &block) def after_all(location = nil, label = "after_all", &block)
hook = ExampleGroupHook.new(location: location, 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 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 append_after_all(location = nil, label = "after_all", &block) def append_after_all(location = nil, label = "after_all", &block)
hook = ExampleGroupHook.new(location: location, label: label, &block) hook = ExampleGroupHook.new(location: location, label: label, &block)
@@builder.append_after_all(hook) builder.append_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(location = nil, label = "after_each", &block : Example ->) def after_each(location = nil, label = "after_each", &block : Example ->)
hook = ExampleHook.new(location: location, 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 after every example in the current group. # Defines a block of code to execute after every example in the current group.
def append_after_each(location = nil, label = "after_each", &block : Example ->) def append_after_each(location = nil, label = "after_each", &block : Example ->)
hook = ExampleHook.new(location: location, label: label, &block) hook = ExampleHook.new(location: location, label: label, &block)
@@builder.append_after_each(hook) builder.append_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(location = nil, label = "around_each", &block : Example::Procsy ->) def around_each(location = nil, label = "around_each", &block : Example::Procsy ->)
hook = ExampleProcsyHook.new(location: location, label: label, &block) hook = ExampleProcsyHook.new(location: location, label: label, &block)
@@builder.around_each(hook) builder.around_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 prepend_around_each(location = nil, label = "around_each", &block : Example::Procsy ->) def prepend_around_each(location = nil, label = "around_each", &block : Example::Procsy ->)
hook = ExampleProcsyHook.new(location: location, label: label, &block) hook = ExampleProcsyHook.new(location: location, label: label, &block)
@@builder.prepend_around_each(hook) builder.prepend_around_each(hook)
end
# Sets the configuration of the spec.
#
# See `Spec::Builder#config=` for usage details.
def config=(config)
@@builder.config = config
end end
# Constructs the test spec. # Constructs the test spec.
@ -151,7 +144,7 @@ module Spectator::DSL
# Raises an error if there were not symmetrical calls to `#start_group` and `#end_group`. # Raises an error if there were not symmetrical calls to `#start_group` and `#end_group`.
# This would indicate a logical error somewhere in Spectator or an extension of it. # This would indicate a logical error somewhere in Spectator or an extension of it.
def build : Spec def build : Spec
@@builder.build builder.build
end end
end end
end end

View file

@ -37,12 +37,9 @@ module Spectator
# New examples should be added to the current group. # New examples should be added to the current group.
@stack : Deque(ExampleGroupBuilder) @stack : Deque(ExampleGroupBuilder)
# Configuration for the spec.
@config : Config?
# Creates a new spec builder. # Creates a new spec builder.
# A root group is pushed onto the group stack. # A root group is pushed onto the group stack.
def initialize def initialize(@config : Config)
root = ExampleGroupBuilder.new root = ExampleGroupBuilder.new
@stack = Deque(ExampleGroupBuilder).new @stack = Deque(ExampleGroupBuilder).new
@stack.push(root) @stack.push(root)
@ -58,7 +55,7 @@ module Spectator
group = root.build group = root.build
apply_config_hooks(group) apply_config_hooks(group)
Spec.new(group, config) Spec.new(group, @config)
end end
# Defines a new example group and pushes it onto the group stack. # Defines a new example group and pushes it onto the group stack.
@ -206,21 +203,6 @@ module Spectator
root.append_after_all(*args, **kwargs, &block) root.append_after_all(*args, **kwargs, &block)
end end
# Builds the configuration to use for the spec.
# A `Config::Builder` is yielded to the block provided to this method.
# That builder will be used to create the configuration.
def configure(& : Config::Builder -> _) : Nil
builder = Config::Builder.new
yield builder
@config = builder.build
end
# Sets the configuration of the spec.
# This configuration controls how examples run.
def config=(config)
@config = config
end
# Checks if the current group is the root group. # Checks if the current group is the root group.
private def root? private def root?
@stack.size == 1 @stack.size == 1