mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
before_each and after_each hooks now run in example scope
The entire example hooks class hierarchy is no longer needed. This is an easier implementation than originally planned. However, this is probably slower than the other method because each hook has to cast and check the example instance.
This commit is contained in:
parent
aee3ead578
commit
050251b491
2 changed files with 30 additions and 71 deletions
|
@ -662,16 +662,11 @@ module Spectator::DSL
|
||||||
# end
|
# end
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# Currently, the hook cannot use values and methods in the group like examples can.
|
# The hook can use values and methods in the group like examples can.
|
||||||
# This is a planned feature.
|
# It is called in the same scope as the example code.
|
||||||
# ```
|
# ```
|
||||||
# let(array) { [1, 2, 3] }
|
# let(array) { [1, 2, 3] }
|
||||||
# before_each { array << 4 } # *DOES NOT WORK YET!*
|
# before_each { array << 4 }
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# This could also be used to verify pre-conditions:
|
|
||||||
# ```
|
|
||||||
# before_each { is_expected.to_not be_nil } # *DOES NOT WORK YET!*
|
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# If multiple `#before_each` blocks are specified,
|
# If multiple `#before_each` blocks are specified,
|
||||||
|
@ -698,7 +693,18 @@ module Spectator::DSL
|
||||||
#
|
#
|
||||||
# See also: `#before_all`, `#after_all`, `#after_each`, and `#around_each`.
|
# See also: `#before_all`, `#after_all`, `#after_each`, and `#around_each`.
|
||||||
macro before_each(&block)
|
macro before_each(&block)
|
||||||
::Spectator::DSL::Builder.add_before_each_hook {{block}}
|
# Before each hook.
|
||||||
|
# Defined as a method so that it can access the same scope as the example code.
|
||||||
|
def %hook : Nil
|
||||||
|
{{block.body}}
|
||||||
|
end
|
||||||
|
|
||||||
|
::Spectator::DSL::Builder.add_before_each_hook do
|
||||||
|
# Get the wrapper instance and cast to current group type.
|
||||||
|
example = ::Spectator::Internals::Harness.current.example
|
||||||
|
instance = example.instance.as({{@type.id}})
|
||||||
|
instance.%hook
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a hook that will run following all examples in the group.
|
# Creates a hook that will run following all examples in the group.
|
||||||
|
@ -767,16 +773,11 @@ module Spectator::DSL
|
||||||
# end
|
# end
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# Currently, the hook cannot use values and methods in the group like examples can.
|
# The hook can use values and methods in the group like examples can.
|
||||||
# This is a planned feature.
|
# It is called in the same scope as the example code.
|
||||||
# ```
|
# ```
|
||||||
# let(array) { [1, 2, 3] }
|
# let(array) { [1, 2, 3] }
|
||||||
# after_each { array << 4 } # *DOES NOT WORK YET!*
|
# after_each { array << 4 }
|
||||||
# ```
|
|
||||||
#
|
|
||||||
# This could also be used to verify post-conditions:
|
|
||||||
# ```
|
|
||||||
# after_each { is_expected.to_not be_nil } # *DOES NOT WORK YET!*
|
|
||||||
# ```
|
# ```
|
||||||
#
|
#
|
||||||
# If multiple `#after_each` blocks are specified,
|
# If multiple `#after_each` blocks are specified,
|
||||||
|
@ -803,7 +804,18 @@ module Spectator::DSL
|
||||||
#
|
#
|
||||||
# See also: `#before_all`, `#before_each`, `#after_all`, and `#around_each`.
|
# See also: `#before_all`, `#before_each`, `#after_all`, and `#around_each`.
|
||||||
macro after_each(&block)
|
macro after_each(&block)
|
||||||
::Spectator::DSL::Builder.add_after_each_hook {{block}}
|
# After each hook.
|
||||||
|
# Defined as a method so that it can access the same scope as the example code.
|
||||||
|
def %hook : Nil
|
||||||
|
{{block.body}}
|
||||||
|
end
|
||||||
|
|
||||||
|
::Spectator::DSL::Builder.add_after_each_hook do
|
||||||
|
# Get the wrapper instance and cast to current group type.
|
||||||
|
example = ::Spectator::Internals::Harness.current.example
|
||||||
|
instance = example.instance.as({{@type.id}})
|
||||||
|
instance.%hook
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a hook that will run for every example in the group.
|
# Creates a hook that will run for every example in the group.
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
module Spectator::Internals
|
|
||||||
# Abstract base class for all example hooks.
|
|
||||||
# This provides an untyped base for every generic type of `ExampleHooks`.
|
|
||||||
#
|
|
||||||
# A hook is defined as a `Proc` instance.
|
|
||||||
# This class stores any number of hooks for before, after, and "around" an example.
|
|
||||||
# The before and after hooks run before and after an example (obviously).
|
|
||||||
# These hooks are passed the `Example` instance of the example being run.
|
|
||||||
#
|
|
||||||
# The around hook is special, in that it does both.
|
|
||||||
# It is started before the example runs and finishes after the example has ran.
|
|
||||||
# This is suited for methods that use block syntax to wrap some action.
|
|
||||||
# For instance: `File#open`.
|
|
||||||
# A `Proc` instance is given to each around hook,
|
|
||||||
# and the hook is expected to call that proc.
|
|
||||||
# If it doesn't then the example won't run, among other things.
|
|
||||||
abstract class BaseExampleHooks
|
|
||||||
# Creates a new set of hooks for examples.
|
|
||||||
# An array of `Proc` instances for each type of hook must be specified.
|
|
||||||
def initialize(@before = [] of Example ->, @after = [] of Example ->, @around = [] of Example ->)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Runs all of the before hooks.
|
|
||||||
# The `example` argument should be the example about to be run.
|
|
||||||
abstract def run_before(example : Example)
|
|
||||||
|
|
||||||
# Runs all of the after hooks.
|
|
||||||
# The `example` argument should be the example that just ran.
|
|
||||||
abstract def run_after(example : Example)
|
|
||||||
|
|
||||||
# Creates a `Proc` that invokes all of the around hooks and a block of code.
|
|
||||||
# Invoking the returned proc will call each around hook
|
|
||||||
# and finally the block of code provided to this method.
|
|
||||||
def wrap_around(&block : ->)
|
|
||||||
# If there's no around hooks,
|
|
||||||
# the returned proc will just be the block.
|
|
||||||
wrapper = block
|
|
||||||
|
|
||||||
# Must wrap in reverse order,
|
|
||||||
# so that the first hooks are the outermost and run first.
|
|
||||||
@around.reverse_each do |hook|
|
|
||||||
wrapper = wrap_proc(hook, wrapper)
|
|
||||||
end
|
|
||||||
|
|
||||||
wrapper
|
|
||||||
end
|
|
||||||
|
|
||||||
# Utility method for wrapping one proc with another.
|
|
||||||
private def wrap_proc(inner : Proc(Nil) ->, wrapper : ->)
|
|
||||||
->{ inner.call(wrapper) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue