Add pre- and post-conditions

This commit is contained in:
Michael Miller 2019-09-26 21:37:29 -06:00
parent 1eec9190dd
commit f47c48b483
9 changed files with 80 additions and 16 deletions

View File

@ -45,5 +45,35 @@ module Spectator
::Spectator::SpecBuilder.add_around_each_hook { |test, proc| test.as({{@type.id}}).%hook(proc) }
end
macro pre_condition(&block)
def %hook({{block.args.splat}}) : Nil
{{block.body}}
end
::Spectator::SpecBuilder.add_pre_condition do |test, example|
cast_test = test.as({{@type.id}})
{% if block.args.empty? %}
cast_test.%hook
{% else %}
cast_test.%hook(example)
{% end %}
end
end
macro post_condition(&block)
def %hook({{block.args.splat}}) : Nil
{{block.body}}
end
::Spectator::SpecBuilder.add_post_condition do |test, example|
cast_test = test.as({{@type.id}})
{% if block.args.empty? %}
cast_test.%hook
{% else %}
cast_test.%hook(example)
{% end %}
end
end
end
end

View File

@ -10,28 +10,32 @@ module Spectator
# This will effectively run nothing extra while running a test.
def self.empty
new(
[] of ->,
[] of ->
[] of TestMetaMethod,
[] of TestMetaMethod
)
end
# Creates a new set of conditions.
def initialize(
@pre_conditions : Array(->),
@post_conditions : Array(->)
@pre_conditions : Array(TestMetaMethod),
@post_conditions : Array(TestMetaMethod)
)
end
# Runs all pre-condition checks.
# These should be run before every test.
def run_pre_conditions
@pre_conditions.each &.call
def run_pre_conditions(wrapper : TestWrapper, example : Example)
@pre_conditions.each do |hook|
wrapper.call(hook, example)
end
end
# Runs all post-condition checks.
# These should be run after every test.
def run_post_conditions
@post_conditions.each &.call
def run_post_conditions(wrapper : TestWrapper, example : Example)
@post_conditions.each do |hook|
wrapper.call(hook, example)
end
end
end
end

View File

@ -25,12 +25,15 @@ module Spectator
# Runs the test code and captures the result.
private def run_example(result)
wrapper = test_wrapper.around_hook(group.context)
context = group.context
wrapper = test_wrapper.around_hook(context)
# Capture how long it takes to run the test code.
result.elapsed = Time.measure do
begin
context.run_pre_conditions(self)
wrapper.call
context.run_post_conditions(self)
rescue ex # Catch all errors and handle them later.
result.error = ex
end

View File

@ -87,12 +87,12 @@ module Spectator
end
# Adds a pre-condition to run at the start of every example in the current group.
def add_pre_condition(&block : ->) : Nil
def add_pre_condition(&block : TestMetaMethod) : Nil
@@stack.current.add_pre_condition(block)
end
# Adds a post-condition to run at the end of every example in the current group.
def add_post_condition(&block : ->) : Nil
def add_post_condition(&block : TestMetaMethod) : Nil
@@stack.current.add_post_condition(block)
end

View File

@ -12,6 +12,8 @@ module Spectator::SpecBuilder
@before_all_hooks = Deque(->).new
@after_all_hooks = Deque(->).new
@around_each_hooks = Deque(::SpectatorTest, Proc(Nil) ->).new
@pre_conditions = Deque(TestMetaMethod).new
@post_conditions = Deque(TestMetaMethod).new
def add_child(child : Child)
@children << child
@ -37,6 +39,14 @@ module Spectator::SpecBuilder
@around_each_hooks << hook
end
def add_pre_condition(hook : TestMetaMethod)
@pre_conditions << hook
end
def add_post_condition(hook : TestMetaMethod)
@post_conditions << hook
end
private def build_hooks
ExampleHooks.new(
@before_all_hooks.to_a,
@ -46,5 +56,12 @@ module Spectator::SpecBuilder
@around_each_hooks.to_a
)
end
private def build_conditions
ExampleConditions.new(
@pre_conditions.to_a,
@post_conditions.to_a
)
end
end
end

View File

@ -7,7 +7,7 @@ module Spectator::SpecBuilder
end
def build(parent_group)
context = TestContext.new(parent_group.context, build_hooks, parent_group.context.values)
context = TestContext.new(parent_group.context, build_hooks, build_conditions, parent_group.context.values)
NestedExampleGroup.new(@description, @source, parent_group, context).tap do |group|
group.children = children.map do |child|
child.build(group).as(ExampleComponent)

View File

@ -4,7 +4,7 @@ require "./example_group_builder"
module Spectator::SpecBuilder
class RootExampleGroupBuilder < ExampleGroupBuilder
def build
context = TestContext.new(nil, build_hooks, TestValues.empty)
context = TestContext.new(nil, build_hooks, build_conditions, TestValues.empty)
RootExampleGroup.new(context).tap do |group|
group.children = children.map do |child|
child.build(group).as(ExampleComponent)

View File

@ -9,7 +9,7 @@ module Spectator::SpecBuilder
def build(parent_group)
values = parent_group.context.values
collection = @collection_builder.call(values)
context = TestContext.new(parent_group.context, build_hooks, values)
context = TestContext.new(parent_group.context, build_hooks, build_conditions, values)
NestedExampleGroup.new(@description, @source, parent_group, context).tap do |group|
group.children = collection.map do |element|
build_sub_group(group, element).as(ExampleComponent)
@ -19,7 +19,7 @@ module Spectator::SpecBuilder
private def build_sub_group(parent_group, element)
values = parent_group.context.values.add(@id, @description.to_s, element)
context = TestContext.new(parent_group.context, ExampleHooks.empty, values)
context = TestContext.new(parent_group.context, ExampleHooks.empty, ExampleConditions.empty, values)
NestedExampleGroup.new("#{@label} = #{element.inspect}", @source, parent_group, context).tap do |group|
group.children = children.map do |child|
child.build(group).as(ExampleComponent)

View File

@ -5,7 +5,7 @@ module Spectator
class TestContext
getter values
def initialize(@parent : TestContext?, @hooks : ExampleHooks, @values : TestValues)
def initialize(@parent : TestContext?, @hooks : ExampleHooks, @conditions : ExampleConditions, @values : TestValues)
@before_all_hooks_run = false
@after_all_hooks_run = false
end
@ -56,5 +56,15 @@ module Spectator
wrapper
end
end
def run_pre_conditions(example)
@parent.try &.run_pre_conditions(example)
@conditions.run_pre_conditions(example.test_wrapper, example)
end
def run_post_conditions(example)
@conditions.run_post_conditions(example.test_wrapper, example)
@parent.try &.run_post_conditions(example)
end
end
end