mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Reduce nesting by collapsing modules with ::
This commit is contained in:
parent
0d282d3d50
commit
77b4c71c2a
14 changed files with 440 additions and 468 deletions
|
@ -1,65 +1,63 @@
|
|||
module Spectator
|
||||
module DSL
|
||||
module Builder
|
||||
extend self
|
||||
module Spectator::DSL
|
||||
module Builder
|
||||
extend self
|
||||
|
||||
@@group_stack = [::Spectator::DSL::ExampleGroupBuilder.new("ROOT")]
|
||||
@@group_stack = [::Spectator::DSL::ExampleGroupBuilder.new("ROOT")]
|
||||
|
||||
private def root_group
|
||||
@@group_stack.first
|
||||
end
|
||||
private def root_group
|
||||
@@group_stack.first
|
||||
end
|
||||
|
||||
private def current_group
|
||||
@@group_stack.last
|
||||
end
|
||||
private def current_group
|
||||
@@group_stack.last
|
||||
end
|
||||
|
||||
private def push_group(group : ExampleGroupBuilder)
|
||||
current_group.add_child(group)
|
||||
@@group_stack.push(group)
|
||||
end
|
||||
private def push_group(group : ExampleGroupBuilder)
|
||||
current_group.add_child(group)
|
||||
@@group_stack.push(group)
|
||||
end
|
||||
|
||||
def start_group(*args) : Nil
|
||||
group = ::Spectator::DSL::ExampleGroupBuilder.new(*args)
|
||||
push_group(group)
|
||||
end
|
||||
def start_group(*args) : Nil
|
||||
group = ::Spectator::DSL::ExampleGroupBuilder.new(*args)
|
||||
push_group(group)
|
||||
end
|
||||
|
||||
def start_given_group(*args) : Nil
|
||||
group = ::Spectator::DSL::GivenExampleGroupBuilder.new(*args)
|
||||
push_group(group)
|
||||
end
|
||||
def start_given_group(*args) : Nil
|
||||
group = ::Spectator::DSL::GivenExampleGroupBuilder.new(*args)
|
||||
push_group(group)
|
||||
end
|
||||
|
||||
def end_group : Nil
|
||||
@@group_stack.pop
|
||||
end
|
||||
def end_group : Nil
|
||||
@@group_stack.pop
|
||||
end
|
||||
|
||||
def add_example(example_type : Example.class) : Nil
|
||||
factory = ::Spectator::DSL::ExampleFactory.new(example_type)
|
||||
current_group.add_child(factory)
|
||||
end
|
||||
def add_example(example_type : Example.class) : Nil
|
||||
factory = ::Spectator::DSL::ExampleFactory.new(example_type)
|
||||
current_group.add_child(factory)
|
||||
end
|
||||
|
||||
def add_before_all_hook(&block : ->) : Nil
|
||||
current_group.add_before_all_hook(block)
|
||||
end
|
||||
def add_before_all_hook(&block : ->) : Nil
|
||||
current_group.add_before_all_hook(block)
|
||||
end
|
||||
|
||||
def add_before_each_hook(&block : ->) : Nil
|
||||
current_group.add_before_each_hook(block)
|
||||
end
|
||||
def add_before_each_hook(&block : ->) : Nil
|
||||
current_group.add_before_each_hook(block)
|
||||
end
|
||||
|
||||
def add_after_all_hook(&block : ->) : Nil
|
||||
current_group.add_after_all_hook(block)
|
||||
end
|
||||
def add_after_all_hook(&block : ->) : Nil
|
||||
current_group.add_after_all_hook(block)
|
||||
end
|
||||
|
||||
def add_after_each_hook(&block : ->) : Nil
|
||||
current_group.add_after_each_hook(block)
|
||||
end
|
||||
def add_after_each_hook(&block : ->) : Nil
|
||||
current_group.add_after_each_hook(block)
|
||||
end
|
||||
|
||||
def add_around_each_hook(&block : Proc(Nil) ->) : Nil
|
||||
current_group.add_around_each_hook(block)
|
||||
end
|
||||
def add_around_each_hook(&block : Proc(Nil) ->) : Nil
|
||||
current_group.add_around_each_hook(block)
|
||||
end
|
||||
|
||||
protected def build : ExampleGroup
|
||||
root_group.build(nil, Internals::SampleValues.empty)
|
||||
end
|
||||
protected def build : ExampleGroup
|
||||
root_group.build(nil, Internals::SampleValues.empty)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
require "./matcher_dsl"
|
||||
|
||||
module Spectator
|
||||
module DSL
|
||||
module ExampleDSL
|
||||
include MatcherDSL
|
||||
module Spectator::DSL
|
||||
module ExampleDSL
|
||||
include MatcherDSL
|
||||
|
||||
macro is_expected
|
||||
expect(subject)
|
||||
end
|
||||
macro is_expected
|
||||
expect(subject)
|
||||
end
|
||||
|
||||
macro expect(actual)
|
||||
::Spectator::Expectation.new({{actual.stringify}}, {{actual}})
|
||||
end
|
||||
macro expect(actual)
|
||||
::Spectator::Expectation.new({{actual.stringify}}, {{actual}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
module Spectator
|
||||
module DSL
|
||||
class ExampleFactory
|
||||
def initialize(@example_type : Example.class)
|
||||
end
|
||||
module Spectator::DSL
|
||||
class ExampleFactory
|
||||
def initialize(@example_type : Example.class)
|
||||
end
|
||||
|
||||
def build(group : ExampleGroup, sample_values : Internals::SampleValues) : Example
|
||||
@example_type.new(group, sample_values)
|
||||
end
|
||||
def build(group : ExampleGroup, sample_values : Internals::SampleValues) : Example
|
||||
@example_type.new(group, sample_values)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,60 +1,58 @@
|
|||
module Spectator
|
||||
module DSL
|
||||
class ExampleGroupBuilder
|
||||
alias Child = ExampleFactory | ExampleGroupBuilder
|
||||
module Spectator::DSL
|
||||
class ExampleGroupBuilder
|
||||
alias Child = ExampleFactory | ExampleGroupBuilder
|
||||
|
||||
@children = [] of Child
|
||||
@before_all_hooks = [] of ->
|
||||
@before_each_hooks = [] of ->
|
||||
@after_all_hooks = [] of ->
|
||||
@after_each_hooks = [] of ->
|
||||
@around_each_hooks = [] of Proc(Nil) ->
|
||||
@children = [] of Child
|
||||
@before_all_hooks = [] of ->
|
||||
@before_each_hooks = [] of ->
|
||||
@after_all_hooks = [] of ->
|
||||
@after_each_hooks = [] of ->
|
||||
@around_each_hooks = [] of Proc(Nil) ->
|
||||
|
||||
def initialize(@what : String)
|
||||
end
|
||||
def initialize(@what : String)
|
||||
end
|
||||
|
||||
def add_child(child : Child) : Nil
|
||||
@children << child
|
||||
end
|
||||
def add_child(child : Child) : Nil
|
||||
@children << child
|
||||
end
|
||||
|
||||
def add_before_all_hook(block : ->) : Nil
|
||||
@before_all_hooks << block
|
||||
end
|
||||
def add_before_all_hook(block : ->) : Nil
|
||||
@before_all_hooks << block
|
||||
end
|
||||
|
||||
def add_before_each_hook(block : ->) : Nil
|
||||
@before_each_hooks << block
|
||||
end
|
||||
def add_before_each_hook(block : ->) : Nil
|
||||
@before_each_hooks << block
|
||||
end
|
||||
|
||||
def add_after_all_hook(block : ->) : Nil
|
||||
@after_all_hooks << block
|
||||
end
|
||||
def add_after_all_hook(block : ->) : Nil
|
||||
@after_all_hooks << block
|
||||
end
|
||||
|
||||
def add_after_each_hook(block : ->) : Nil
|
||||
@after_each_hooks << block
|
||||
end
|
||||
def add_after_each_hook(block : ->) : Nil
|
||||
@after_each_hooks << block
|
||||
end
|
||||
|
||||
def add_around_each_hook(block : Proc(Nil) ->) : Nil
|
||||
@around_each_hooks << block
|
||||
end
|
||||
def add_around_each_hook(block : Proc(Nil) ->) : Nil
|
||||
@around_each_hooks << block
|
||||
end
|
||||
|
||||
def build(parent : ExampleGroup?, sample_values : Internals::SampleValues) : ExampleGroup
|
||||
ExampleGroup.new(@what, parent, build_hooks).tap do |group|
|
||||
children = @children.map do |child|
|
||||
child.build(group, sample_values).as(ExampleGroup::Child)
|
||||
end
|
||||
group.children = children
|
||||
def build(parent : ExampleGroup?, sample_values : Internals::SampleValues) : ExampleGroup
|
||||
ExampleGroup.new(@what, parent, build_hooks).tap do |group|
|
||||
children = @children.map do |child|
|
||||
child.build(group, sample_values).as(ExampleGroup::Child)
|
||||
end
|
||||
group.children = children
|
||||
end
|
||||
end
|
||||
|
||||
private def build_hooks
|
||||
ExampleHooks.new(
|
||||
@before_all_hooks,
|
||||
@before_each_hooks,
|
||||
@after_all_hooks,
|
||||
@after_each_hooks,
|
||||
@around_each_hooks
|
||||
)
|
||||
end
|
||||
private def build_hooks
|
||||
ExampleHooks.new(
|
||||
@before_all_hooks,
|
||||
@before_each_hooks,
|
||||
@after_all_hooks,
|
||||
@after_each_hooks,
|
||||
@around_each_hooks
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
require "./example_group_builder"
|
||||
|
||||
module Spectator
|
||||
module DSL
|
||||
class GivenExampleGroupBuilder(T) < ExampleGroupBuilder
|
||||
module Spectator::DSL
|
||||
class GivenExampleGroupBuilder(T) < ExampleGroupBuilder
|
||||
|
||||
def initialize(what : String, @collection : Array(T), @symbol : Symbol)
|
||||
super(what)
|
||||
end
|
||||
def initialize(what : String, @collection : Array(T), @symbol : Symbol)
|
||||
super(what)
|
||||
end
|
||||
|
||||
def build(parent : ExampleGroup?, sample_values : Internals::SampleValues) : ExampleGroup
|
||||
ExampleGroup.new(@what, parent, build_hooks).tap do |group|
|
||||
group.children = @collection.map do |value|
|
||||
build_sub_group(group, sample_values, value).as(ExampleGroup::Child)
|
||||
end
|
||||
def build(parent : ExampleGroup?, sample_values : Internals::SampleValues) : ExampleGroup
|
||||
ExampleGroup.new(@what, parent, build_hooks).tap do |group|
|
||||
group.children = @collection.map do |value|
|
||||
build_sub_group(group, sample_values, value).as(ExampleGroup::Child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private def build_sub_group(parent : ExampleGroup, sample_values : Internals::SampleValues, value : T) : ExampleGroup
|
||||
sub_values = sample_values.add(@symbol, @symbol.to_s, value)
|
||||
ExampleGroup.new(value.to_s, parent, ExampleHooks.empty).tap do |group|
|
||||
group.children = @children.map do |child|
|
||||
child.build(group, sub_values).as(ExampleGroup::Child)
|
||||
end
|
||||
private def build_sub_group(parent : ExampleGroup, sample_values : Internals::SampleValues, value : T) : ExampleGroup
|
||||
sub_values = sample_values.add(@symbol, @symbol.to_s, value)
|
||||
ExampleGroup.new(value.to_s, parent, ExampleHooks.empty).tap do |group|
|
||||
group.children = @children.map do |child|
|
||||
child.build(group, sub_values).as(ExampleGroup::Child)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
require "../matchers"
|
||||
|
||||
module Spectator
|
||||
module DSL
|
||||
module MatcherDSL
|
||||
macro eq(expected)
|
||||
::Spectator::Matchers::EqualityMatcher.new({{expected.stringify}}, {{expected}})
|
||||
end
|
||||
module Spectator::DSL
|
||||
module MatcherDSL
|
||||
macro eq(expected)
|
||||
::Spectator::Matchers::EqualityMatcher.new({{expected.stringify}}, {{expected}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,198 +1,196 @@
|
|||
require "../example_group"
|
||||
|
||||
module Spectator
|
||||
module DSL
|
||||
module StructureDSL
|
||||
module Spectator::DSL
|
||||
module StructureDSL
|
||||
|
||||
def initialize(sample_values : Internals::SampleValues)
|
||||
def initialize(sample_values : Internals::SampleValues)
|
||||
end
|
||||
|
||||
macro describe(what, &block)
|
||||
context({{what}}) {{block}}
|
||||
end
|
||||
|
||||
macro context(what, &block)
|
||||
module Group%group
|
||||
include {{@type.id}}
|
||||
|
||||
{% if what.is_a?(Path) || what.is_a?(Generic) %}
|
||||
_spectator_described_class {{what}}
|
||||
{% end %}
|
||||
|
||||
::Spectator::DSL::Builder.start_group(
|
||||
{{what.is_a?(StringLiteral) ? what : what.stringify}}
|
||||
)
|
||||
|
||||
{{block.body}}
|
||||
|
||||
::Spectator::DSL::Builder.end_group
|
||||
end
|
||||
end
|
||||
|
||||
macro describe(what, &block)
|
||||
context({{what}}) {{block}}
|
||||
end
|
||||
macro given(collection, &block)
|
||||
module Group%group
|
||||
include {{@type.id}}
|
||||
|
||||
macro context(what, &block)
|
||||
module Group%group
|
||||
include {{@type.id}}
|
||||
|
||||
{% if what.is_a?(Path) || what.is_a?(Generic) %}
|
||||
_spectator_described_class {{what}}
|
||||
{% end %}
|
||||
|
||||
::Spectator::DSL::Builder.start_group(
|
||||
{{what.is_a?(StringLiteral) ? what : what.stringify}}
|
||||
)
|
||||
|
||||
{{block.body}}
|
||||
|
||||
::Spectator::DSL::Builder.end_group
|
||||
def %collection
|
||||
{{collection}}
|
||||
end
|
||||
end
|
||||
|
||||
macro given(collection, &block)
|
||||
module Group%group
|
||||
include {{@type.id}}
|
||||
@%wrapper : ::Spectator::Internals::ValueWrapper
|
||||
|
||||
def %collection
|
||||
{{collection}}
|
||||
end
|
||||
|
||||
@%wrapper : ::Spectator::Internals::ValueWrapper
|
||||
|
||||
def {{block.args.empty? ? "value".id : block.args.first}}
|
||||
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%collection.first))).value
|
||||
end
|
||||
|
||||
def initialize(sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
@%wrapper = sample_values.get_wrapper(:%group)
|
||||
end
|
||||
|
||||
_spectator_given_collection Collection%collection, %to_a, %collection
|
||||
%to_a = Collection%collection.new.%to_a
|
||||
|
||||
::Spectator::DSL::Builder.start_given_group(
|
||||
{{collection.stringify}},
|
||||
%to_a,
|
||||
:%group
|
||||
)
|
||||
|
||||
{{block.body}}
|
||||
|
||||
::Spectator::DSL::Builder.end_group
|
||||
def {{block.args.empty? ? "value".id : block.args.first}}
|
||||
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%collection.first))).value
|
||||
end
|
||||
|
||||
def initialize(sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
@%wrapper = sample_values.get_wrapper(:%group)
|
||||
end
|
||||
|
||||
_spectator_given_collection Collection%collection, %to_a, %collection
|
||||
%to_a = Collection%collection.new.%to_a
|
||||
|
||||
::Spectator::DSL::Builder.start_given_group(
|
||||
{{collection.stringify}},
|
||||
%to_a,
|
||||
:%group
|
||||
)
|
||||
|
||||
{{block.body}}
|
||||
|
||||
::Spectator::DSL::Builder.end_group
|
||||
end
|
||||
end
|
||||
|
||||
macro subject(&block)
|
||||
let(:subject) {{block}}
|
||||
end
|
||||
macro subject(&block)
|
||||
let(:subject) {{block}}
|
||||
end
|
||||
|
||||
macro let(name, &block)
|
||||
let!(%value) {{block}}
|
||||
macro let(name, &block)
|
||||
let!(%value) {{block}}
|
||||
|
||||
@%wrapper : ::Spectator::Internals::ValueWrapper?
|
||||
@%wrapper : ::Spectator::Internals::ValueWrapper?
|
||||
|
||||
def {{name.id}}
|
||||
if (wrapper = @%wrapper)
|
||||
wrapper.unsafe_as(::Spectator::Internals::TypedValueWrapper(typeof(%value))).value
|
||||
else
|
||||
%value.tap do |value|
|
||||
@%wrapper = ::Spectator::Internals::TypedValueWrapper(typeof(%value)).new(value)
|
||||
end
|
||||
def {{name.id}}
|
||||
if (wrapper = @%wrapper)
|
||||
wrapper.unsafe_as(::Spectator::Internals::TypedValueWrapper(typeof(%value))).value
|
||||
else
|
||||
%value.tap do |value|
|
||||
@%wrapper = ::Spectator::Internals::TypedValueWrapper(typeof(%value)).new(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
macro let!(name, &block)
|
||||
def {{name.id}}
|
||||
macro let!(name, &block)
|
||||
def {{name.id}}
|
||||
{{block.body}}
|
||||
end
|
||||
end
|
||||
|
||||
macro before_all(&block)
|
||||
::Spectator::DSL::Builder.add_before_all_hook {{block}}
|
||||
end
|
||||
|
||||
macro before_each(&block)
|
||||
::Spectator::DSL::Builder.add_before_each_hook {{block}}
|
||||
end
|
||||
|
||||
macro after_all(&block)
|
||||
::Spectator::DSL::Builder.add_after_all_hook {{block}}
|
||||
end
|
||||
|
||||
macro after_each(&block)
|
||||
::Spectator::DSL::Builder.add_after_each_hook {{block}}
|
||||
end
|
||||
|
||||
macro around_each(&block)
|
||||
::Spectator::DSL::Builder.add_around_each_hook {{block}}
|
||||
end
|
||||
|
||||
def include_examples
|
||||
raise NotImplementedError.new("Spectator::DSL#include_examples")
|
||||
end
|
||||
|
||||
macro it(description, &block)
|
||||
_spectator_example_wrapper(Wrapper%example, %run) {{block}}
|
||||
|
||||
_spectator_example(Example%example, Wrapper%example, ::Spectator::RunnableExample, {{description}}) do
|
||||
protected def run_instance
|
||||
@instance.%run
|
||||
end
|
||||
end
|
||||
|
||||
::Spectator::DSL::Builder.add_example(Example%example)
|
||||
end
|
||||
|
||||
macro pending(description, &block)
|
||||
_spectator_example_wrapper(Wrapper%example, %run) {{block}}
|
||||
|
||||
_spectator_example(Example%example, Wrapper%example, ::Spectator::PendingExample, {{description}})
|
||||
|
||||
::Spectator::DSL::Builder.add_example(Example%example)
|
||||
end
|
||||
|
||||
macro it_behaves_like
|
||||
{% raise NotImplementedError.new("it_behaves_like functionality is not implemented") %}
|
||||
end
|
||||
|
||||
private macro _spectator_described_class(what)
|
||||
def described_class
|
||||
{{what}}.tap do |thing|
|
||||
raise "#{thing} must be a type name to use #described_class or #subject,\
|
||||
but it is a #{typeof(thing)}" unless thing.is_a?(Class)
|
||||
end
|
||||
end
|
||||
|
||||
_spectator_implicit_subject
|
||||
end
|
||||
|
||||
private macro _spectator_implicit_subject
|
||||
def subject
|
||||
described_class.new
|
||||
end
|
||||
end
|
||||
|
||||
private macro _spectator_given_collection(class_name, to_a_method_name, collection_method_name)
|
||||
class {{class_name.id}}
|
||||
include {{@type.id}}
|
||||
|
||||
def {{to_a_method_name.id}}
|
||||
{{collection_method_name.id}}.to_a
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private macro _spectator_example_wrapper(class_name, run_method_name, &block)
|
||||
class {{class_name.id}}
|
||||
include ::Spectator::DSL::ExampleDSL
|
||||
include {{@type.id}}
|
||||
|
||||
def initialize(sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
end
|
||||
|
||||
def {{run_method_name.id}}
|
||||
{{block.body}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
macro before_all(&block)
|
||||
::Spectator::DSL::Builder.add_before_all_hook {{block}}
|
||||
end
|
||||
|
||||
macro before_each(&block)
|
||||
::Spectator::DSL::Builder.add_before_each_hook {{block}}
|
||||
end
|
||||
|
||||
macro after_all(&block)
|
||||
::Spectator::DSL::Builder.add_after_all_hook {{block}}
|
||||
end
|
||||
|
||||
macro after_each(&block)
|
||||
::Spectator::DSL::Builder.add_after_each_hook {{block}}
|
||||
end
|
||||
|
||||
macro around_each(&block)
|
||||
::Spectator::DSL::Builder.add_around_each_hook {{block}}
|
||||
end
|
||||
|
||||
def include_examples
|
||||
raise NotImplementedError.new("Spectator::DSL#include_examples")
|
||||
end
|
||||
|
||||
macro it(description, &block)
|
||||
_spectator_example_wrapper(Wrapper%example, %run) {{block}}
|
||||
|
||||
_spectator_example(Example%example, Wrapper%example, ::Spectator::RunnableExample, {{description}}) do
|
||||
protected def run_instance
|
||||
@instance.%run
|
||||
end
|
||||
private macro _spectator_example(example_class_name, wrapper_class_name, base_class, description, &block)
|
||||
class {{example_class_name.id}} < {{base_class.id}}
|
||||
def initialize(group : ::Spectator::ExampleGroup, sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
@instance = {{wrapper_class_name.id}}.new(sample_values)
|
||||
end
|
||||
|
||||
::Spectator::DSL::Builder.add_example(Example%example)
|
||||
end
|
||||
{% if block.is_a?(Block) %}
|
||||
{{block.body}}
|
||||
{% end %}
|
||||
|
||||
macro pending(description, &block)
|
||||
_spectator_example_wrapper(Wrapper%example, %run) {{block}}
|
||||
|
||||
_spectator_example(Example%example, Wrapper%example, ::Spectator::PendingExample, {{description}})
|
||||
|
||||
::Spectator::DSL::Builder.add_example(Example%example)
|
||||
end
|
||||
|
||||
macro it_behaves_like
|
||||
{% raise NotImplementedError.new("it_behaves_like functionality is not implemented") %}
|
||||
end
|
||||
|
||||
private macro _spectator_described_class(what)
|
||||
def described_class
|
||||
{{what}}.tap do |thing|
|
||||
raise "#{thing} must be a type name to use #described_class or #subject,\
|
||||
but it is a #{typeof(thing)}" unless thing.is_a?(Class)
|
||||
end
|
||||
end
|
||||
|
||||
_spectator_implicit_subject
|
||||
end
|
||||
|
||||
private macro _spectator_implicit_subject
|
||||
def subject
|
||||
described_class.new
|
||||
end
|
||||
end
|
||||
|
||||
private macro _spectator_given_collection(class_name, to_a_method_name, collection_method_name)
|
||||
class {{class_name.id}}
|
||||
include {{@type.id}}
|
||||
|
||||
def {{to_a_method_name.id}}
|
||||
{{collection_method_name.id}}.to_a
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private macro _spectator_example_wrapper(class_name, run_method_name, &block)
|
||||
class {{class_name.id}}
|
||||
include ::Spectator::DSL::ExampleDSL
|
||||
include {{@type.id}}
|
||||
|
||||
def initialize(sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
end
|
||||
|
||||
def {{run_method_name.id}}
|
||||
{{block.body}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private macro _spectator_example(example_class_name, wrapper_class_name, base_class, description, &block)
|
||||
class {{example_class_name.id}} < {{base_class.id}}
|
||||
def initialize(group : ::Spectator::ExampleGroup, sample_values : ::Spectator::Internals::SampleValues)
|
||||
super
|
||||
@instance = {{wrapper_class_name.id}}.new(sample_values)
|
||||
end
|
||||
|
||||
{% if block.is_a?(Block) %}
|
||||
{{block.body}}
|
||||
{% end %}
|
||||
|
||||
def description
|
||||
{{description.is_a?(StringLiteral) ? description : description.stringify}}
|
||||
end
|
||||
def description
|
||||
{{description.is_a?(StringLiteral) ? description : description.stringify}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,120 +1,118 @@
|
|||
require "./formatter"
|
||||
require "colorize"
|
||||
|
||||
module Spectator
|
||||
module Formatters
|
||||
class DefaultFormatter < Formatter
|
||||
SUCCESS_COLOR = :green
|
||||
FAILURE_COLOR = :red
|
||||
ERROR_COLOR = :magenta
|
||||
PENDING_COLOR = :yellow
|
||||
module Spectator::Formatters
|
||||
class DefaultFormatter < Formatter
|
||||
SUCCESS_COLOR = :green
|
||||
FAILURE_COLOR = :red
|
||||
ERROR_COLOR = :magenta
|
||||
PENDING_COLOR = :yellow
|
||||
|
||||
SUCCESS_CHAR = '.'.colorize(SUCCESS_COLOR)
|
||||
FAILURE_CHAR = 'F'.colorize(FAILURE_COLOR)
|
||||
ERROR_CHAR = 'E'.colorize(ERROR_COLOR)
|
||||
PENDING_CHAR = '*'.colorize(PENDING_COLOR)
|
||||
SUCCESS_CHAR = '.'.colorize(SUCCESS_COLOR)
|
||||
FAILURE_CHAR = 'F'.colorize(FAILURE_COLOR)
|
||||
ERROR_CHAR = 'E'.colorize(ERROR_COLOR)
|
||||
PENDING_CHAR = '*'.colorize(PENDING_COLOR)
|
||||
|
||||
def start_suite
|
||||
end
|
||||
def start_suite
|
||||
end
|
||||
|
||||
def end_suite(results : TestResults)
|
||||
def end_suite(results : TestResults)
|
||||
puts
|
||||
puts
|
||||
display_failures(results)
|
||||
display_errors(results)
|
||||
display_summary(results)
|
||||
end
|
||||
|
||||
private def display_failures(results)
|
||||
failures = results.failures
|
||||
if failures.any?
|
||||
puts "Failures:"
|
||||
puts
|
||||
puts
|
||||
display_failures(results)
|
||||
display_errors(results)
|
||||
display_summary(results)
|
||||
end
|
||||
|
||||
private def display_failures(results)
|
||||
failures = results.failures
|
||||
if failures.any?
|
||||
puts "Failures:"
|
||||
puts
|
||||
failures.each_with_index do |failure, index|
|
||||
display_failure(failure.as(FailedResult), index + 1)
|
||||
end
|
||||
failures.each_with_index do |failure, index|
|
||||
display_failure(failure.as(FailedResult), index + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private def display_failure(failure, number)
|
||||
expected = "TODO"
|
||||
actual = "TODO"
|
||||
puts " #{number}) #{failure.example}"
|
||||
puts " Failure: #{failure.error.message}"
|
||||
puts
|
||||
puts " Expected: #{expected}"
|
||||
puts " got: #{actual}"
|
||||
puts
|
||||
private def display_failure(failure, number)
|
||||
expected = "TODO"
|
||||
actual = "TODO"
|
||||
puts " #{number}) #{failure.example}"
|
||||
puts " Failure: #{failure.error.message}"
|
||||
puts
|
||||
puts " Expected: #{expected}"
|
||||
puts " got: #{actual}"
|
||||
puts
|
||||
end
|
||||
|
||||
private def display_errors(results)
|
||||
end
|
||||
|
||||
private def display_summary(results)
|
||||
puts finish_time_string(results)
|
||||
puts result_string(results)
|
||||
end
|
||||
|
||||
def start_example(example : Example)
|
||||
end
|
||||
|
||||
def end_example(result : Result)
|
||||
print result_char(result)
|
||||
end
|
||||
|
||||
private def result_char(result : Result)
|
||||
case result
|
||||
when SuccessfulResult
|
||||
SUCCESS_CHAR
|
||||
when PendingResult
|
||||
PENDING_CHAR
|
||||
when ErroredResult
|
||||
ERROR_CHAR
|
||||
when FailedResult
|
||||
FAILURE_CHAR
|
||||
end
|
||||
end
|
||||
|
||||
private def display_errors(results)
|
||||
private def finish_time_string(results)
|
||||
"Finished in #{human_time(results.runtime)}"
|
||||
end
|
||||
|
||||
private def result_string(results)
|
||||
examples = results.examples
|
||||
failures = results.failed_examples
|
||||
errors = results.errored_examples
|
||||
pending = results.pending_examples
|
||||
string = "#{examples} examples, #{failures} failures, #{errors} errors, #{pending} pending"
|
||||
if failures > 0 || errors > 0
|
||||
string.colorize(FAILURE_COLOR)
|
||||
elsif pending != examples
|
||||
string.colorize(PENDING_COLOR)
|
||||
else
|
||||
string.colorize(SUCCESS_COLOR)
|
||||
end
|
||||
end
|
||||
|
||||
private def display_summary(results)
|
||||
puts finish_time_string(results)
|
||||
puts result_string(results)
|
||||
end
|
||||
private def human_time(span : Time::Span)
|
||||
millis = span.total_milliseconds
|
||||
return "#{(millis * 1000).round.to_i} microseconds" if millis < 1
|
||||
|
||||
def start_example(example : Example)
|
||||
end
|
||||
seconds = span.total_seconds
|
||||
return "#{millis.round(2)} milliseconds" if seconds < 1
|
||||
return "#{seconds.round(2)} seconds" if seconds < 60
|
||||
|
||||
def end_example(result : Result)
|
||||
print result_char(result)
|
||||
end
|
||||
int_seconds = seconds.to_i
|
||||
minutes = int_seconds / 60
|
||||
int_seconds %= 60
|
||||
return sprintf("%i:%02i", minutes, int_seconds) if minutes < 60
|
||||
|
||||
private def result_char(result : Result)
|
||||
case result
|
||||
when SuccessfulResult
|
||||
SUCCESS_CHAR
|
||||
when PendingResult
|
||||
PENDING_CHAR
|
||||
when ErroredResult
|
||||
ERROR_CHAR
|
||||
when FailedResult
|
||||
FAILURE_CHAR
|
||||
end
|
||||
end
|
||||
hours = minutes / 60
|
||||
minutes %= 60
|
||||
return sprintf("%i:%02i:%02i", hours, minutes, int_seconds) if hours < 24
|
||||
|
||||
private def finish_time_string(results)
|
||||
"Finished in #{human_time(results.runtime)}"
|
||||
end
|
||||
|
||||
private def result_string(results)
|
||||
examples = results.examples
|
||||
failures = results.failed_examples
|
||||
errors = results.errored_examples
|
||||
pending = results.pending_examples
|
||||
string = "#{examples} examples, #{failures} failures, #{errors} errors, #{pending} pending"
|
||||
if failures > 0 || errors > 0
|
||||
string.colorize(FAILURE_COLOR)
|
||||
elsif pending != examples
|
||||
string.colorize(PENDING_COLOR)
|
||||
else
|
||||
string.colorize(SUCCESS_COLOR)
|
||||
end
|
||||
end
|
||||
|
||||
private def human_time(span : Time::Span)
|
||||
millis = span.total_milliseconds
|
||||
return "#{(millis * 1000).round.to_i} microseconds" if millis < 1
|
||||
|
||||
seconds = span.total_seconds
|
||||
return "#{millis.round(2)} milliseconds" if seconds < 1
|
||||
return "#{seconds.round(2)} seconds" if seconds < 60
|
||||
|
||||
int_seconds = seconds.to_i
|
||||
minutes = int_seconds / 60
|
||||
int_seconds %= 60
|
||||
return sprintf("%i:%02i", minutes, int_seconds) if minutes < 60
|
||||
|
||||
hours = minutes / 60
|
||||
minutes %= 60
|
||||
return sprintf("%i:%02i:%02i", hours, minutes, int_seconds) if hours < 24
|
||||
|
||||
days = hours / 24
|
||||
hours %= 24
|
||||
return sprintf("%i days %i:%02i:%02i", days, hours, minutes, int_seconds)
|
||||
end
|
||||
days = hours / 24
|
||||
hours %= 24
|
||||
return sprintf("%i days %i:%02i:%02i", days, hours, minutes, int_seconds)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
module Spectator
|
||||
module Formatters
|
||||
abstract class Formatter
|
||||
abstract def start_suite
|
||||
abstract def end_suite(results : TestResults)
|
||||
abstract def start_example(example : Example)
|
||||
abstract def end_example(result : Result)
|
||||
end
|
||||
module Spectator::Formatters
|
||||
abstract class Formatter
|
||||
abstract def start_suite
|
||||
abstract def end_suite(results : TestResults)
|
||||
abstract def start_example(example : Example)
|
||||
abstract def end_example(result : Result)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
require "./value_wrapper"
|
||||
|
||||
module Spectator
|
||||
module Internals
|
||||
struct SampleValues
|
||||
private record Entry, name : String, wrapper : ValueWrapper
|
||||
module Spectator::Internals
|
||||
struct SampleValues
|
||||
private record Entry, name : String, wrapper : ValueWrapper
|
||||
|
||||
def self.empty
|
||||
new({} of Symbol => Entry)
|
||||
end
|
||||
def self.empty
|
||||
new({} of Symbol => Entry)
|
||||
end
|
||||
|
||||
protected def initialize(@values = {} of Symbol => Entry)
|
||||
end
|
||||
protected def initialize(@values = {} of Symbol => Entry)
|
||||
end
|
||||
|
||||
def add(id : Symbol, name : String, value : T) : SampleValues forall T
|
||||
wrapper = TypedValueWrapper(T).new(value)
|
||||
SampleValues.new(@values.merge({
|
||||
id => Entry.new(name, wrapper)
|
||||
}))
|
||||
end
|
||||
def add(id : Symbol, name : String, value : T) : SampleValues forall T
|
||||
wrapper = TypedValueWrapper(T).new(value)
|
||||
SampleValues.new(@values.merge({
|
||||
id => Entry.new(name, wrapper)
|
||||
}))
|
||||
end
|
||||
|
||||
def get_wrapper(id : Symbol)
|
||||
@values[id].wrapper
|
||||
end
|
||||
def get_wrapper(id : Symbol)
|
||||
@values[id].wrapper
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
require "./value_wrapper"
|
||||
|
||||
module Spectator
|
||||
module Internals
|
||||
class TypedValueWrapper(T) < ValueWrapper
|
||||
getter value : T
|
||||
module Spectator::Internals
|
||||
class TypedValueWrapper(T) < ValueWrapper
|
||||
getter value : T
|
||||
|
||||
def initialize(@value : T)
|
||||
end
|
||||
def initialize(@value : T)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
module Spectator
|
||||
module Internals
|
||||
# Base class for proxying test values to examples.
|
||||
# This abstraction is required for inferring types.
|
||||
# The `DSL#let` macro makes heavy use of this.
|
||||
abstract class ValueWrapper
|
||||
# Retrieves the underlying value.
|
||||
abstract def value
|
||||
end
|
||||
module Spectator::Internals
|
||||
# Base class for proxying test values to examples.
|
||||
# This abstraction is required for inferring types.
|
||||
# The `DSL#let` macro makes heavy use of this.
|
||||
abstract class ValueWrapper
|
||||
# Retrieves the underlying value.
|
||||
abstract def value
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
require "./matcher"
|
||||
|
||||
module Spectator
|
||||
module Matchers
|
||||
class EqualityMatcher(T) < Matcher
|
||||
def initialize(label, @expected : T)
|
||||
super(label)
|
||||
end
|
||||
module Spectator::Matchers
|
||||
class EqualityMatcher(T) < Matcher
|
||||
def initialize(label, @expected : T)
|
||||
super(label)
|
||||
end
|
||||
|
||||
def match?(expectation : Expectation)
|
||||
expectation.actual == @expected
|
||||
end
|
||||
def match?(expectation : Expectation)
|
||||
expectation.actual == @expected
|
||||
end
|
||||
|
||||
def message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to equal #{label} (using ==)"
|
||||
end
|
||||
def message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to equal #{label} (using ==)"
|
||||
end
|
||||
|
||||
def negated_message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to not equal #{label} (using ==)"
|
||||
end
|
||||
def negated_message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to not equal #{label} (using ==)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
module Spectator
|
||||
module Matchers
|
||||
abstract class Matcher
|
||||
private getter label : String
|
||||
module Spectator::Matchers
|
||||
abstract class Matcher
|
||||
private getter label : String
|
||||
|
||||
private def initialize(@label : String)
|
||||
end
|
||||
|
||||
abstract def match?(expectation : Expectation)
|
||||
abstract def message(expectation : Expectation) : String
|
||||
abstract def negated_message(expectation : Expectation) : String
|
||||
private def initialize(@label : String)
|
||||
end
|
||||
|
||||
abstract def match?(expectation : Expectation)
|
||||
abstract def message(expectation : Expectation) : String
|
||||
abstract def negated_message(expectation : Expectation) : String
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue