Update docs

Mostly fixes around symbols for syntax.
Added some missing docs and updated incorrect or vague ones.
This commit is contained in:
Michael Miller 2019-02-17 23:01:43 -07:00
parent 9c16a5a53e
commit 847cc662bd
51 changed files with 258 additions and 219 deletions

View file

@ -38,7 +38,7 @@ module Spectator::DSL
end end
# Begins a new sample group in the spec - # Begins a new sample group in the spec -
# that is, a group defined by the `sample` keyword in the DSL. # that is, a group defined by the `StructureDSL#sample` macro in the DSL.
# A corresponding `#end_group` call must be made # A corresponding `#end_group` call must be made
# when the group being started is finished. # when the group being started is finished.
# See `SampleExampleGroupBuilder#initialize` for the arguments # See `SampleExampleGroupBuilder#initialize` for the arguments
@ -91,10 +91,12 @@ module Spectator::DSL
current_group.add_around_each_hook(block) current_group.add_around_each_hook(block)
end 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 : ->) : Nil
current_group.add_pre_condition(block) current_group.add_pre_condition(block)
end 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 : ->) : Nil
current_group.add_post_condition(block) current_group.add_post_condition(block)
end end

View file

@ -1,12 +1,14 @@
require "./matcher_dsl" require "./matcher_dsl"
module Spectator::DSL module Spectator::DSL
# Methods that are available inside test code (an `it` block). # Methods that are available inside test code.
# Basically, inside an `StructureDSL#it` block.
module ExampleDSL module ExampleDSL
include MatcherDSL include MatcherDSL
# Starts an expectation. # Starts an expectation.
# This should be followed up with `to` or `to_not`. # This should be followed up with `Spectator::Expectations::ExpectationPartial#to`
# or `Spectator::Expectations::ExpectationPartial#to_not`.
# The value passed in will be checked # The value passed in will be checked
# to see if it satisfies the conditions specified. # to see if it satisfies the conditions specified.
# #
@ -21,7 +23,8 @@ module Spectator::DSL
end end
# Starts an expectation on a block of code. # Starts an expectation on a block of code.
# This should be followed up with `to` or `to_not`. # This should be followed up with `Spectator::Expectations::ExpectationPartial#to`
# or `Spectator::Expectations::ExpectationPartial#to_not`.
# The block passed in, or its return value, will be checked # The block passed in, or its return value, will be checked
# to see if it satisfies the conditions specified. # to see if it satisfies the conditions specified.
# #
@ -40,7 +43,7 @@ module Spectator::DSL
# ``` # ```
# expect(&.size).to eq(5) # expect(&.size).to eq(5)
# ``` # ```
# The method passed will always be evaluated on `#subject`. # The method passed will always be evaluated on the subject.
macro expect(_source_file = __FILE__, _source_line = __LINE__, &block) macro expect(_source_file = __FILE__, _source_line = __LINE__, &block)
{% if block.is_a?(Nop) %} {% if block.is_a?(Nop) %}
{% raise "Argument or block must be provided to expect" %} {% raise "Argument or block must be provided to expect" %}
@ -48,13 +51,20 @@ module Spectator::DSL
# Check if the short-hand method syntax is used. # Check if the short-hand method syntax is used.
# This is a hack, since macros don't get this as a "literal" or something similar. # This is a hack, since macros don't get this as a "literal" or something similar.
# The Crystal compiler will translate `&.foo` to `{ |__arg0| __arg0.foo }`. # The Crystal compiler will translate:
# ```
# &.foo
# ```
# to:
# ```
# { |__arg0| __arg0.foo }
# ```
# The hack used here is to check if it looks like a compiler-generated block. # The hack used here is to check if it looks like a compiler-generated block.
{% if block.args == ["__arg0".id] && block.body.is_a?(Call) && block.body.id =~ /^__arg0\./ %} {% if block.args == ["__arg0".id] && block.body.is_a?(Call) && block.body.id =~ /^__arg0\./ %}
# Extract the method name to make it clear to the user what is tested. # Extract the method name to make it clear to the user what is tested.
# The raw block can't be used because it's not clear to the user. # The raw block can't be used because it's not clear to the user.
{% method_name = block.body.id.split('.').last %} {% method_name = block.body.id.split('.').last %}
# TODO: Maybe pass the subject in as __arg0 instead of prefixing with `subject.`. # TODO: Maybe pass the subject in as __arg0 instead of prefixing the method name.
::Spectator::Expectations::ValueExpectationPartial.new(subject.{{method_name}}, {{"#" + method_name}}, {{_source_file}}, {{_source_line}}) ::Spectator::Expectations::ValueExpectationPartial.new(subject.{{method_name}}, {{"#" + method_name}}, {{_source_file}}, {{_source_line}})
{% else %} {% else %}
# In this case, it looks like the short-hand method syntax wasn't used. # In this case, it looks like the short-hand method syntax wasn't used.
@ -64,7 +74,8 @@ module Spectator::DSL
end end
# Starts an expectation. # Starts an expectation.
# This should be followed up with `to` or `to_not`. # This should be followed up with `Spectator::Expectations::ExpectationPartial#to`
# or `Spectator::Expectations::ExpectationPartial#to_not`.
# The value passed in will be checked # The value passed in will be checked
# to see if it satisfies the conditions specified. # to see if it satisfies the conditions specified.
# #
@ -81,7 +92,8 @@ module Spectator::DSL
end end
# Starts an expectation on a block of code. # Starts an expectation on a block of code.
# This should be followed up with `to` or `to_not`. # This should be followed up with `Spectator::Expectations::ExpectationPartial#to`
# or `Spectator::Expectations::ExpectationPartial#to_not`.
# The block passed in, or its return value, will be checked # The block passed in, or its return value, will be checked
# to see if it satisfies the conditions specified. # to see if it satisfies the conditions specified.
# #
@ -102,7 +114,7 @@ module Spectator::DSL
# ``` # ```
# it expects(&.size).to eq(5) # it expects(&.size).to eq(5)
# ``` # ```
# The method passed will always be evaluated on `#subject`. # The method passed will always be evaluated on the subject.
macro expects(&block) macro expects(&block)
expect {{block}} expect {{block}}
end end

View file

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

View file

@ -53,16 +53,18 @@ module Spectator::DSL
@around_each_hooks << block @around_each_hooks << block
end end
# Adds a pre-condition to run at the start of every example in this group.
def add_pre_condition(block : ->) : Nil def add_pre_condition(block : ->) : Nil
@pre_conditions << block @pre_conditions << block
end end
# Adds a post-condition to run at the end of every example in this group.
def add_post_condition(block : ->) : Nil def add_post_condition(block : ->) : Nil
@post_conditions << block @post_conditions << block
end end
# Constructs an `ExampleHooks` instance with all the hooks defined for this group. # Constructs an `ExampleHooks` instance with all the hooks defined for this group.
# This method should be only when the group is being built, # This method should be called only when the group is being built,
# otherwise some hooks may be missing. # otherwise some hooks may be missing.
private def hooks private def hooks
ExampleHooks.new( ExampleHooks.new(
@ -74,6 +76,10 @@ module Spectator::DSL
) )
end end
# Constructs an `ExampleConditions` instance
# with all the pre- and post-conditions defined for this group.
# This method should be called only when the group is being built,
# otherwise some conditions may be missing.
private def conditions private def conditions
ExampleConditions.new(@pre_conditions, @post_conditions) ExampleConditions.new(@pre_conditions, @post_conditions)
end end

View file

@ -4,7 +4,7 @@ module Spectator::DSL
# Methods for defining matchers for expectations. # Methods for defining matchers for expectations.
module MatcherDSL module MatcherDSL
# Indicates that some value should equal another. # Indicates that some value should equal another.
# The `==` operator is used for this check. # The == operator is used for this check.
# The value passed to this method is the expected value. # The value passed to this method is the expected value.
# #
# Example: # Example:
@ -16,7 +16,7 @@ module Spectator::DSL
end end
# Indicates that some value should not equal another. # Indicates that some value should not equal another.
# The `!=` operator is used for this check. # The != operator is used for this check.
# The value passed to this method is the unexpected value. # The value passed to this method is the unexpected value.
# #
# Example: # Example:
@ -28,7 +28,8 @@ module Spectator::DSL
end end
# Indicates that some value when compared to another satisfies an operator. # Indicates that some value when compared to another satisfies an operator.
# An operator can follow, such as: `<`, `<=`, `>`, or `>=`. # An operator can follow, such as: <, <=, >, or >=.
# See `Spectator::Matchers::TruthyMatcher` for a full list of operators.
# #
# Examples: # Examples:
# ``` # ```
@ -47,8 +48,8 @@ module Spectator::DSL
end end
# Indicates that some value should semantically equal another. # Indicates that some value should semantically equal another.
# The `===` operator is used for this check. # The === operator is used for this check.
# This has identical behavior as a `when` condition in a `case` block. # This has identical behavior as a "when" condition in a case block.
# #
# Examples: # Examples:
# ``` # ```
@ -61,8 +62,8 @@ module Spectator::DSL
end end
# Indicates that some value should be of a specified type. # Indicates that some value should be of a specified type.
# The `#is_a?` method is used for this check. # The `Object#is_a?` method is used for this check.
# A type name or type union should be used for `expected`. # A type name or type union should be used for *expected*.
# #
# Examples: # Examples:
# ``` # ```
@ -76,8 +77,8 @@ module Spectator::DSL
end end
# Indicates that some value should be of a specified type. # Indicates that some value should be of a specified type.
# The `#is_a?` method is used for this check. # The `Object#is_a?` method is used for this check.
# A type name or type union should be used for `expected`. # A type name or type union should be used for *expected*.
# This method is identical to `#be_a`, # This method is identical to `#be_a`,
# and exists just to improve grammar. # and exists just to improve grammar.
# #
@ -90,7 +91,7 @@ module Spectator::DSL
end end
# Indicates that some value should be less than another. # Indicates that some value should be less than another.
# The `<` operator is used for this check. # The < operator is used for this check.
# The value passed to this method is the value expected to be larger. # The value passed to this method is the value expected to be larger.
# #
# Example: # Example:
@ -102,7 +103,7 @@ module Spectator::DSL
end end
# Indicates that some value should be less than or equal to another. # Indicates that some value should be less than or equal to another.
# The `<=` operator is used for this check. # The <= operator is used for this check.
# The value passed to this method is the value expected to be larger or equal. # The value passed to this method is the value expected to be larger or equal.
# #
# Example: # Example:
@ -114,7 +115,7 @@ module Spectator::DSL
end end
# Indicates that some value should be greater than another. # Indicates that some value should be greater than another.
# The `>` operator is used for this check. # The > operator is used for this check.
# The value passed to this method is the value expected to be smaller. # The value passed to this method is the value expected to be smaller.
# #
# Example: # Example:
@ -126,7 +127,7 @@ module Spectator::DSL
end end
# Indicates that some value should be greater than or equal to another. # Indicates that some value should be greater than or equal to another.
# The `>=` operator is used for this check. # The >= operator is used for this check.
# The value passed to this method is the value expected to be smaller or equal. # The value passed to this method is the value expected to be smaller or equal.
# #
# Example: # Example:
@ -138,9 +139,9 @@ module Spectator::DSL
end end
# Indicates that some value should match another. # Indicates that some value should match another.
# The `=~` operator is used for this check. # The =~ operator is used for this check.
# Typically a regular expression is used, # Typically a regular expression is used,
# but any type that has the `=~` operator will work. # but any type that has the =~ operator will work.
# #
# Examples: # Examples:
# ``` # ```
@ -174,7 +175,7 @@ module Spectator::DSL
end end
# Indicates that some value should be truthy. # Indicates that some value should be truthy.
# This means that the value is not `false` and not `nil`. # This means that the value is not false and not nil.
# #
# Examples: # Examples:
# ``` # ```
@ -186,7 +187,7 @@ module Spectator::DSL
end end
# Indicates that some value should be falsey. # Indicates that some value should be falsey.
# This means that the value is either `false` or `nil`. # This means that the value is either false or nil.
# #
# Examples: # Examples:
# ``` # ```
@ -200,7 +201,8 @@ module Spectator::DSL
# Indicates that some value should be contained within another. # Indicates that some value should be contained within another.
# This checker can be used in one of two ways. # This checker can be used in one of two ways.
# #
# The first: the `expected` argument can be anything that implements `#includes?`. # The first: the *expected* argument can be anything
# that implements the `includes?` method.
# This is typically a `Range`, but can also be `Enumerable`. # This is typically a `Range`, but can also be `Enumerable`.
# #
# Examples: # Examples:
@ -209,9 +211,9 @@ module Spectator::DSL
# expect(7).to be_within(1..10) # expect(7).to be_within(1..10)
# ``` # ```
# #
# The other way is to use this in conjunction with `of`. # The other way is to use this is with the "of" keyword.
# This creates a lower and upper bound # This creates a lower and upper bound
# centered around the value of the `expected` argument. # centered around the value of the *expected* argument.
# This usage is helpful for comparisons on floating-point numbers. # This usage is helpful for comparisons on floating-point numbers.
# #
# Examples: # Examples:
@ -220,13 +222,13 @@ module Spectator::DSL
# expect(speed).to be_within(5).of(speed_limit) # expect(speed).to be_within(5).of(speed_limit)
# ``` # ```
# #
# NOTE: The `of` suffix must be used # NOTE: The of suffix must be used
# if the `expected` argument does not implement `#includes?` # if the *expected* argument does not implement an includes? method.
# #
# Additionally, for this second usage, # Additionally, for this second usage,
# an `inclusive` or `exclusive` suffix can be added. # an "inclusive" or "exclusive" suffix can be added.
# These modify the upper-bound on the range being checked against. # These modify the upper-bound on the range being checked against.
# By default, the range is *inclusive*. # By default, the range is inclusive.
# #
# Examples: # Examples:
# ``` # ```
@ -247,9 +249,9 @@ module Spectator::DSL
# expect(7).to be_within(1, 10) # expect(7).to be_within(1, 10)
# ``` # ```
# #
# Additionally, an `inclusive` or `exclusive` suffix can be added. # Additionally, an "inclusive" or "exclusive" suffix can be added.
# These modify the upper-bound on the range being checked against. # These modify the upper-bound on the range being checked against.
# By default, the range is *inclusive*. # By default, the range is inclusive.
# #
# Examples: # Examples:
# ``` # ```
@ -301,10 +303,10 @@ module Spectator::DSL
# Indicates that some value or set should start with another value. # Indicates that some value or set should start with another value.
# This is typically used on a `String` or `Array` (any `Enumerable` works). # This is typically used on a `String` or `Array` (any `Enumerable` works).
# The `expected` argument can be a `String`, `Char`, or `Regex` # The *expected* argument can be a `String`, `Char`, or `Regex`
# when the actual type (being comapred against) is a `String`. # when the actual type (being comapred against) is a `String`.
# For `Enumerable` types, only the first item is inspected. # For `Enumerable` types, only the first item is inspected.
# It is compared with the `===` operator, # It is compared with the === operator,
# so that values, types, regular expressions, and others can be tested. # so that values, types, regular expressions, and others can be tested.
# #
# Examples: # Examples:
@ -323,10 +325,10 @@ module Spectator::DSL
# Indicates that some value or set should end with another value. # Indicates that some value or set should end with another value.
# This is typically used on a `String` or `Array` (any `Indexable` works). # This is typically used on a `String` or `Array` (any `Indexable` works).
# The `expected` argument can be a `String`, `Char`, or `Regex` # The *expected* argument can be a `String`, `Char`, or `Regex`
# when the actual type (being comapred against) is a `String`. # when the actual type (being comapred against) is a `String`.
# For `Indexable` types, only the last item is inspected. # For `Indexable` types, only the last item is inspected.
# It is compared with the `===` operator, # It is compared with the === operator,
# so that values, types, regular expressions, and others can be tested. # so that values, types, regular expressions, and others can be tested.
# #
# Examples: # Examples:
@ -345,7 +347,7 @@ module Spectator::DSL
# Indicates that some value or set should contain another value. # Indicates that some value or set should contain another value.
# This is typically used on a `String` or `Array` (any `Enumerable` works). # This is typically used on a `String` or `Array` (any `Enumerable` works).
# The `expected` argument can be a `String` or `Char` # The *expected* argument can be a `String` or `Char`
# when the actual type (being comapred against) is a `String`. # when the actual type (being comapred against) is a `String`.
# For `Enumerable` types, items are compared using the underying implementation. # For `Enumerable` types, items are compared using the underying implementation.
# In both cases, the `includes?` method is used. # In both cases, the `includes?` method is used.
@ -369,11 +371,11 @@ module Spectator::DSL
# Indicates that some value or set should contain another value. # Indicates that some value or set should contain another value.
# This is similar to `#contain`, but uses a different method for matching. # This is similar to `#contain`, but uses a different method for matching.
# Typically a `String` or `Array` (any `Enumerable` works) is checked against. # Typically a `String` or `Array` (any `Enumerable` works) is checked against.
# The `expected` argument can be a `String` or `Char` # The *expected* argument can be a `String` or `Char`
# when the actual type (being comapred against) is a `String`. # when the actual type (being comapred against) is a `String`.
# The `includes?` method is used for this case. # The `includes?` method is used for this case.
# For `Enumerable` types, each item is inspected until one matches. # For `Enumerable` types, each item is inspected until one matches.
# The `===` operator is used for this case, which allows for equality, type, regex, and other matches. # The === operator is used for this case, which allows for equality, type, regex, and other matches.
# #
# Examples: # Examples:
# ``` # ```
@ -432,7 +434,7 @@ module Spectator::DSL
# Indicates that some value should have a set of attributes matching some conditions. # Indicates that some value should have a set of attributes matching some conditions.
# A list of named arguments are expected. # A list of named arguments are expected.
# The names correspond to the attributes in the instance to check. # The names correspond to the attributes in the instance to check.
# The values are conditions to check with the `===` operator against the attribute's value. # The values are conditions to check with the === operator against the attribute's value.
# #
# Examples: # Examples:
# ``` # ```
@ -444,10 +446,10 @@ module Spectator::DSL
end end
# Used to create predicate matchers. # Used to create predicate matchers.
# Any missing method that starts with `be_` will be handled. # Any missing method that starts with 'be_' will be handled.
# All other method names will be ignored and raise a compile-time error. # All other method names will be ignored and raise a compile-time error.
# #
# This can be used to simply check a predicate method that ends in `?`. # This can be used to simply check a predicate method that ends in '?'.
# For instance: # For instance:
# ``` # ```
# expect("foobar").to be_ascii_only # expect("foobar").to be_ascii_only
@ -456,7 +458,7 @@ module Spectator::DSL
# ``` # ```
macro method_missing(call) macro method_missing(call)
{% if call.name.starts_with?("be_") %} {% if call.name.starts_with?("be_") %}
{% method_name = call.name[3..-1] %} # Remove `be_` prefix. {% method_name = call.name[3..-1] %} # Remove be_ prefix.
::Spectator::Matchers::PredicateMatcher(NamedTuple({{method_name}}: Nil)).new ::Spectator::Matchers::PredicateMatcher(NamedTuple({{method_name}}: Nil)).new
{% else %} {% else %}
{% raise "Undefined local variable or method '#{call}'" %} {% raise "Undefined local variable or method '#{call}'" %}

View file

@ -3,7 +3,7 @@ module Spectator::DSL
# Creates groups of examples and nested groups. # Creates groups of examples and nested groups.
class NestedExampleGroupBuilder < ExampleGroupBuilder class NestedExampleGroupBuilder < ExampleGroupBuilder
# Creates a new group builder. # Creates a new group builder.
# The value for `what` should be the context for the group. # The value for *what* should be the context for the group.
# #
# For example, in these samples: # For example, in these samples:
# ``` # ```
@ -23,8 +23,8 @@ module Spectator::DSL
# Builds the example group. # Builds the example group.
# A new `NestedExampleGroup` will be returned # A new `NestedExampleGroup` will be returned
# which can have instances of `Example` and `ExampleGroup` nested in it. # which can have instances of `Example` and `ExampleGroup` nested in it.
# The `parent` should be the group that contains this group. # 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. # 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 def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
NestedExampleGroup.new(@what, parent, hooks, conditions).tap do |group| NestedExampleGroup.new(@what, parent, hooks, conditions).tap do |group|
# Set the group's children to built versions of the children from this instance. # Set the group's children to built versions of the children from this instance.

View file

@ -4,7 +4,7 @@ module Spectator::DSL
# and it should be at the top of the spec "tree". # and it should be at the top of the spec "tree".
class RootExampleGroupBuilder < ExampleGroupBuilder class RootExampleGroupBuilder < ExampleGroupBuilder
# Creates a `RootExampleGroup` which can have instances of `Example` and `ExampleGroup` nested in it. # 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. # The *sample_values* will be given to all of the examples (and groups) nested in this group.
def build(sample_values : Internals::SampleValues) : RootExampleGroup def build(sample_values : Internals::SampleValues) : RootExampleGroup
RootExampleGroup.new(hooks, conditions).tap do |group| RootExampleGroup.new(hooks, conditions).tap do |group|
# Set the group's children to built versions of the children from this instance. # Set the group's children to built versions of the children from this instance.

View file

@ -8,9 +8,9 @@ module Spectator::DSL
# By doing so, the hooks are defined once, are inherited, and use less memory. # By doing so, the hooks are defined once, are inherited, and use less memory.
class SampleExampleGroupBuilder(T) < NestedExampleGroupBuilder class SampleExampleGroupBuilder(T) < NestedExampleGroupBuilder
# Creates a new group builder. # Creates a new group builder.
# The value for `what` should be the text the user specified for the collection. # The value for *what* should be the text the user specified for the collection.
# The `collection` is the actual array of items to create examples for. # The *collection* is the actual array of items to create examples for.
# The `name` is the variable name that the user accesses the current collection item with. # The *name* is the variable name that the user accesses the current collection item with.
# #
# In this code: # In this code:
# ``` # ```
@ -18,11 +18,11 @@ module Spectator::DSL
# # ... # # ...
# end # end
# ``` # ```
# The `what` value would be "random_integers" # The *what* would be "random_integers"
# and the collection would contain the items returned by calling `random_integers`. # and the collection would contain the items returned by calling *random_integers*.
# The `name` would be "integer". # The *name* would be "integer".
# #
# The `symbol` is passed along to the sample values # The *symbol* is passed along to the sample values
# so that the example code can retrieve the current item from the collection. # so that the example code can retrieve the current item from the collection.
# The symbol should be unique. # The symbol should be unique.
def initialize(what : String, @collection : Array(T), @name : String, @symbol : Symbol) def initialize(what : String, @collection : Array(T), @name : String, @symbol : Symbol)
@ -32,8 +32,8 @@ module Spectator::DSL
# Builds the example group. # Builds the example group.
# A new `NestedExampleGroup` will be returned # A new `NestedExampleGroup` will be returned
# which can have instances of `Example` and `ExampleGroup` nested in it. # which can have instances of `Example` and `ExampleGroup` nested in it.
# The `parent` should be the group that contains this group. # 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. # 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 def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
# This creates the container for the sub-groups. # This creates the container for the sub-groups.
# The hooks are defined here, instead of repeating for each sub-group. # The hooks are defined here, instead of repeating for each sub-group.
@ -47,9 +47,9 @@ module Spectator::DSL
end end
# Builds a sub-group for one item in the collection. # Builds a sub-group for one item in the collection.
# The `parent` should be the container group currently being built by the `#build` call. # The *parent* should be the container group currently being built by the `#build` call.
# The `sample_values` should be the same as what was passed to the `#build` call. # The *sample_values* should be the same as what was passed to the `#build` call.
# The `value` is the current item in the collection. # The *value* is the current item in the collection.
# The value will be added to the sample values for the sub-group, # The value will be added to the sample values for the sub-group,
# so it shouldn't be added prior to calling this method. # so it shouldn't be added prior to calling this method.
private def build_sub_group(parent : ExampleGroup, sample_values : Internals::SampleValues, value : T) : NestedExampleGroup private def build_sub_group(parent : ExampleGroup, sample_values : Internals::SampleValues, value : T) : NestedExampleGroup

View file

@ -20,9 +20,11 @@ module Spectator::DSL
# it "does something" do # it "does something" do
# # Test code goes here... # # Test code goes here...
# end # end
# ```
# #
# # becomes... # becomes...
# #
# ```
# # Class describing the example # # Class describing the example
# # and provides a means of running the test. # # and provides a means of running the test.
# # Typically every class, module, and method # # Typically every class, module, and method
@ -85,9 +87,11 @@ module Spectator::DSL
# end # end
# end # end
# end # end
# ```
# #
# # becomes... # becomes...
# #
# ```
# # describe "#foo" # # describe "#foo"
# module Context123 # module Context123
# # Start a new group. # # Start a new group.
@ -148,13 +152,13 @@ module Spectator::DSL
# For more information, see `Internals::SampleValues`. # For more information, see `Internals::SampleValues`.
module StructureDSL module StructureDSL
# Placeholder initializer. # Placeholder initializer.
# This is needed because examples and groups call `super` in their initializer. # This is needed because examples and groups call super in their initializer.
# Those initializers pass the sample values upward through their hierarchy. # Those initializers pass the sample values upward through their hierarchy.
def initialize(sample_values : Internals::SampleValues) def initialize(sample_values : Internals::SampleValues)
end end
# Creates a new example group to describe a component. # Creates a new example group to describe a component.
# The `what` argument describes "what" is being tested. # The *what* argument describes "what" is being tested.
# Additional example groups and DSL may be nested in the block. # Additional example groups and DSL may be nested in the block.
# #
# Typically when testing a method, # Typically when testing a method,
@ -168,7 +172,7 @@ module Spectator::DSL
# ``` # ```
# #
# When describing a class (or any other type), # When describing a class (or any other type),
# the `what` parameter doesn't need to be quoted. # the *what* parameter doesn't need to be quoted.
# ``` # ```
# describe String do # describe String do
# it "does something" do # it "does something" do
@ -196,7 +200,7 @@ module Spectator::DSL
end end
# Creates a new example group to describe a situation. # Creates a new example group to describe a situation.
# The `what` argument describes the scenario or case being tested. # The *what* argument describes the scenario or case being tested.
# Additional example groups and DSL may be nested in the block. # Additional example groups and DSL may be nested in the block.
# #
# The `#describe` and `#context` are identical in terms of functionality. # The `#describe` and `#context` are identical in terms of functionality.
@ -352,12 +356,12 @@ module Spectator::DSL
# #
# given value = 5 do # given value = 5 do
# expect(&.odd?).to be_true # expect(&.odd?).to be_true
# expect(&.event?).to be_false # expect(&.even?).to be_false
# end # end
# #
# given value = 42 do # given value = 42 do
# expect(&.odd?).to be_false # expect(&.odd?).to be_false
# expect(&.event?).to be_true # expect(&.even?).to be_true
# end # end
# end # end
# ``` # ```
@ -438,18 +442,18 @@ module Spectator::DSL
# Creates a new example group to test multiple values with. # Creates a new example group to test multiple values with.
# This method takes a collection of values # This method takes a collection of values
# and repeats the contents of the block with each value. # and repeats the contents of the block with each value.
# The `collection` argument should be a literal collection, # The *collection* argument should be a literal collection,
# such as an array, or a function that returns an enumerable. # such as an array, or a function that returns an enumerable.
# Additionally, a count may be specified to limit the number of values tested. # Additionally, a count may be specified to limit the number of values tested.
# #
# NOTE: If an infinite enumerable is provided for the collection, # NOTE: If an infinite enumerable is provided for the collection,
# then a count must be specified. # then a count must be specified.
# Only the first `count` items will be used. # Only the first *count* items will be used.
# #
# The block can accept an argument. # The block can accept an argument.
# If it does, then the argument's name is used to reference # If it does, then the argument's name is used to reference
# the current item in the collection. # the current item in the collection.
# If an argument isn't provided, then `#value` can be used instead. # If an argument isn't provided, then *value* can be used instead.
# #
# Example with a block argument: # Example with a block argument:
# ``` # ```
@ -472,8 +476,8 @@ module Spectator::DSL
# ``` # ```
# #
# In the examples above, the test case (`#it` block) # In the examples above, the test case (`#it` block)
# is repeated for each element in `some_integers`. # is repeated for each element in *some_integers*.
# `some_integers` is a ficticous collection. # *some_integers* is a ficticous collection.
# The collection will be iterated once. # The collection will be iterated once.
# `#sample` and `#random_sample` blocks can be nested, # `#sample` and `#random_sample` blocks can be nested,
# and work similarly to loops. # and work similarly to loops.
@ -521,7 +525,7 @@ module Spectator::DSL
# Iterating multiple times would generate inconsistent values at runtime. # Iterating multiple times would generate inconsistent values at runtime.
def %to_a def %to_a
# If a count was provided, # If a count was provided,
# only select the first `count` items from the collection. # only select the first *count* items from the collection.
# Otherwise, select all of them. # Otherwise, select all of them.
{% if count %} {% if count %}
%sample.first({{count}}) %sample.first({{count}})
@ -535,7 +539,7 @@ module Spectator::DSL
# The module uses a generated unique name. # The module uses a generated unique name.
module Context%sample module Context%sample
# Include the parent module. # Include the parent module.
# Since `@type` resolves immediately, # Since @type resolves immediately,
# this will reference the parent type. # this will reference the parent type.
include {{@type.id}} include {{@type.id}}
@ -545,7 +549,7 @@ module Spectator::DSL
# Retrieves the current element from the collection. # Retrieves the current element from the collection.
def {{name}} def {{name}}
# Unwrap the value and return it. # Unwrap the value and return it.
# The `#first` method has a return type that matches the element type. # The `Enumerable#first` method has a return type that matches the element type.
# So it is used on the collection method proxy to resolve the type at compile-time. # So it is used on the collection method proxy to resolve the type at compile-time.
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value @%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value
end end
@ -576,8 +580,8 @@ module Spectator::DSL
# Creates a new example group to test multiple random values with. # Creates a new example group to test multiple random values with.
# This method takes a collection of values and count # This method takes a collection of values and count
# and repeats the contents of the block with each value. # and repeats the contents of the block with each value.
# This method randomly selects `count` items from the collection. # This method randomly selects *count* items from the collection.
# The `collection` argument should be a literal collection, # The *collection* argument should be a literal collection,
# such as an array, or a function that returns an enumerable. # such as an array, or a function that returns an enumerable.
# #
# NOTE: If an enumerable is used, it must be finite. # NOTE: If an enumerable is used, it must be finite.
@ -585,7 +589,7 @@ module Spectator::DSL
# The block can accept an argument. # The block can accept an argument.
# If it does, then the argument's name is used to reference # If it does, then the argument's name is used to reference
# the current item in the collection. # the current item in the collection.
# If an argument isn't provided, then `#value` can be used instead. # If an argument isn't provided, then *value* can be used instead.
# #
# Example with a block argument: # Example with a block argument:
# ``` # ```
@ -608,8 +612,8 @@ module Spectator::DSL
# ``` # ```
# #
# In the examples above, the test case (`#it` block) # In the examples above, the test case (`#it` block)
# is repeated for 5 random elements in `some_integers`. # is repeated for 5 random elements in *some_integers*.
# `some_integers` is a ficticous collection. # *some_integers* is a ficticous collection.
# The collection will be iterated once. # The collection will be iterated once.
# `#sample` and `#random_sample` blocks can be nested, # `#sample` and `#random_sample` blocks can be nested,
# and work similarly to loops. # and work similarly to loops.
@ -655,7 +659,7 @@ module Spectator::DSL
# The module uses a generated unique name. # The module uses a generated unique name.
module Context%sample module Context%sample
# Include the parent module. # Include the parent module.
# Since `@type` resolves immediately, # Since @type resolves immediately,
# this will reference the parent type. # this will reference the parent type.
include {{@type.id}} include {{@type.id}}
@ -665,7 +669,7 @@ module Spectator::DSL
# Retrieves the current element from the collection. # Retrieves the current element from the collection.
def {{name}} def {{name}}
# Unwrap the value and return it. # Unwrap the value and return it.
# The `#first` method has a return type that matches the element type. # The `Enumerable#first` method has a return type that matches the element type.
# So it is used on the collection method proxy to resolve the type at compile-time. # So it is used on the collection method proxy to resolve the type at compile-time.
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value @%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value
end end
@ -714,13 +718,13 @@ module Spectator::DSL
# ``` # ```
# #
# By using a subject, some of the DSL becomes simpler. # By using a subject, some of the DSL becomes simpler.
# For example, `ExampleDSL#is_expected` can be used # For example, `ExampleDSL#is_expected` can be used.
# as short-hand for `expect(subject)`.
# ``` # ```
# subject { "foobar" } # subject { "foobar" }
# #
# it "isn't empty" do # it "isn't empty" do
# is_expected.to_not be_empty # is_expected.to_not be_empty # is the same as:
# expect(subject).to_not be_empty
# end # end
# ``` # ```
# #
@ -807,18 +811,18 @@ module Spectator::DSL
let!(%value) {{block}} let!(%value) {{block}}
# Wrapper to hold the value. # Wrapper to hold the value.
# This will be `nil` if the value hasn't been referenced yet. # This will be nil if the value hasn't been referenced yet.
# After being referenced, the cached value will be stored in a wrapper. # After being referenced, the cached value will be stored in a wrapper.
@%wrapper : ::Spectator::Internals::ValueWrapper? @%wrapper : ::Spectator::Internals::ValueWrapper?
# Method for returning the value. # Method for returning the value.
def {{name.id}} def {{name.id}}
# Check if the value is cached. # Check if the value is cached.
# The wrapper will be `nil` if it isn't. # The wrapper will be nil if it isn't.
if (wrapper = @%wrapper) if (wrapper = @%wrapper)
# It is cached, return that value. # It is cached, return that value.
# Unwrap it from the wrapper variable. # Unwrap it from the wrapper variable.
# Here we use `typeof(METHOD)` to get around the issue # Here we use typeof to get around the issue
# that the macro has no idea what type the value is. # that the macro has no idea what type the value is.
wrapper.unsafe_as(::Spectator::Internals::TypedValueWrapper(typeof(%value))).value wrapper.unsafe_as(::Spectator::Internals::TypedValueWrapper(typeof(%value))).value
else else
@ -1326,7 +1330,7 @@ module Spectator::DSL
end end
# Creates an example, or a test case. # Creates an example, or a test case.
# The `what` argument describes "what" is being tested or asserted. # The *what* argument describes "what" is being tested or asserted.
# The block contains the code to run the test. # The block contains the code to run the test.
# One or more expectations should be in the block. # One or more expectations should be in the block.
# #
@ -1386,7 +1390,7 @@ module Spectator::DSL
# Creates an example, or a test case, that does not run. # Creates an example, or a test case, that does not run.
# This can be used to prototype functionality that isn't ready. # This can be used to prototype functionality that isn't ready.
# The `what` argument describes "what" is being tested or asserted. # The *what* argument describes "what" is being tested or asserted.
# The block contains the code to run the test. # The block contains the code to run the test.
# One or more expectations should be in the block. # One or more expectations should be in the block.
# #
@ -1422,7 +1426,7 @@ module Spectator::DSL
end end
# Same as `#pending`. # Same as `#pending`.
# Include for compatibility with RSpec. # Included for compatibility with RSpec.
macro xit(what, &block) macro xit(what, &block)
pending({{what}}) {{block}} pending({{what}}) {{block}}
end end
@ -1435,8 +1439,8 @@ module Spectator::DSL
# #
# Since the names are generated, and macros can't return values, # Since the names are generated, and macros can't return values,
# the names for everything must be passed in as arguments. # the names for everything must be passed in as arguments.
# The `class_name` argument is the name of the class to define. # The *class_name* argument is the name of the class to define.
# The `run_method_name` argument is the name of the method in the wrapper class # The *run_method_name* argument is the name of the method in the wrapper class
# that will actually run the test code. # that will actually run the test code.
# The block passed to this macro is the actual test code. # The block passed to this macro is the actual test code.
private macro _spectator_test(class_name, run_method_name, &block) private macro _spectator_test(class_name, run_method_name, &block)
@ -1465,12 +1469,12 @@ module Spectator::DSL
# Creates an example class. # Creates an example class.
# Since the names are generated, and macros can't return values, # Since the names are generated, and macros can't return values,
# the names for everything must be passed in as arguments. # the names for everything must be passed in as arguments.
# The `example_class_name` argument is the name of the class to define. # The *example_class_name* argument is the name of the class to define.
# The `test_class_name` argument is the name of the wrapper class to reference. # The *test_class_name* argument is the name of the wrapper class to reference.
# This must be the same as `class_name` for `#_spectator_example_wrapper`. # This must be the same as `class_name` for `#_spectator_example_wrapper`.
# The `base_class` argument specifies which type of example class the new class should derive from. # The *base_class* argument specifies which type of example class the new class should derive from.
# This should typically be `RunnableExample` or `PendingExample`. # This should typically be `RunnableExample` or `PendingExample`.
# The `what` argument is the description passed to the `#it` or `#pending` block. # The *what* argument is the description passed to the `#it` or `#pending` block.
# And lastly, the block specified is any additional content to put in the class. # And lastly, the block specified is any additional content to put in the class.
# For instance, to define a method in the class, do it in the block. # For instance, to define a method in the class, do it in the block.
# ``` # ```

View file

@ -6,7 +6,7 @@ module Spectator
# This is different from a "failed" result # This is different from a "failed" result
# in that the error was not from a failed expectation. # in that the error was not from a failed expectation.
class ErroredResult < FailedResult class ErroredResult < FailedResult
# Calls the `error` method on `interface` and passes `self`. # Calls the `error` method on *interface* and passes self.
def call(interface) def call(interface)
interface.error(self) interface.error(self)
end end

View file

@ -2,7 +2,7 @@ require "./example_component"
module Spectator module Spectator
# Base class for all types of examples. # Base class for all types of examples.
# Concrete types must implement the `#run_inner`, `#what`, and `#instance` methods. # Concrete types must implement the `#run_impl, `#what`, `#instance`, and `#source` methods.
abstract class Example < ExampleComponent abstract class Example < ExampleComponent
# Indicates whether the example has already been run. # Indicates whether the example has already been run.
getter? finished = false getter? finished = false
@ -31,7 +31,7 @@ module Spectator
# Creates the base of the example. # Creates the base of the example.
# The group should be the example group the example belongs to. # The group should be the example group the example belongs to.
# The `sample_values` are passed to the example code. # The *sample_values* are passed to the example code.
def initialize(@group, sample_values : Internals::SampleValues) def initialize(@group, sample_values : Internals::SampleValues)
end end

View file

@ -10,7 +10,7 @@ module Spectator
# Additionally, the indexer method (`#[]`) will index into sub-groups. # Additionally, the indexer method (`#[]`) will index into sub-groups.
# #
# This class also stores hooks to be associated with all examples in the group. # This class also stores hooks to be associated with all examples in the group.
# The hooks can be invoked by running one of the `#run_x_hooks` methods. # The hooks can be invoked by running the `#run_before_hooks` and `#run_after_hooks` methods.
abstract class ExampleGroup < ExampleComponent abstract class ExampleGroup < ExampleComponent
include Enumerable(ExampleComponent) include Enumerable(ExampleComponent)
include Iterable(ExampleComponent) include Iterable(ExampleComponent)
@ -90,7 +90,7 @@ module Spectator
end end
# Finds the example with the specified index in the children. # Finds the example with the specified index in the children.
# The `index` must be positive and within bounds (use `#check_bounds`). # The *index* must be positive and within bounds (use `#check_bounds`).
private def find_nested(index) private def find_nested(index)
offset = index offset = index
# Loop through each child # Loop through each child
@ -112,7 +112,7 @@ module Spectator
# The remaining offset is passed along to the child. # The remaining offset is passed along to the child.
# If it's an `Example`, it returns itself. # If it's an `Example`, it returns itself.
# Otherwise, the indexer repeats the process for the next child. # Otherwise, the indexer repeats the process for the next child.
# It should be impossible to get `nil` here, # It should be impossible to get nil here,
# provided the bounds check and example counts are correct. # provided the bounds check and example counts are correct.
child.not_nil![offset] child.not_nil![offset]
end end
@ -122,22 +122,14 @@ module Spectator
children.all?(&.finished?) children.all?(&.finished?)
end end
# Runs all of the `before_all` and `before_each` hooks. # Runs all of the "before-each" and "before-all" hooks.
# This should run prior to every example in the group. # This should run prior to every example in the group.
def run_before_hooks def run_before_hooks
run_before_all_hooks run_before_all_hooks
run_before_each_hooks run_before_each_hooks
end end
def run_pre_conditions # Runs all of the "before-all" hooks.
@conditions.run_pre_conditions
end
def run_post_conditions
@conditions.run_post_conditions
end
# Runs all of the `before_all` hooks.
# This should run prior to any examples in the group. # This should run prior to any examples in the group.
# The hooks will be run only once. # The hooks will be run only once.
# Subsequent calls to this method will do nothing. # Subsequent calls to this method will do nothing.
@ -147,20 +139,20 @@ module Spectator
@before_all_hooks_run = true @before_all_hooks_run = true
end end
# Runs all of the `before_each` hooks. # Runs all of the "before-each" hooks.
# This method should run prior to every example in the group. # This method should run prior to every example in the group.
protected def run_before_each_hooks : Nil protected def run_before_each_hooks : Nil
@hooks.run_before_each @hooks.run_before_each
end end
# Runs all of the `after_all` and `after_each` hooks. # Runs all of the "after-all" and "after-each" hooks.
# This should run following every example in the group. # This should run following every example in the group.
def run_after_hooks def run_after_hooks
run_after_each_hooks run_after_each_hooks
run_after_all_hooks run_after_all_hooks
end end
# Runs all of the `after_all` hooks. # Runs all of the "after-all" hooks.
# This should run following all examples in the group. # This should run following all examples in the group.
# The hooks will be run only once, # The hooks will be run only once,
# and only after all examples in the group have finished. # and only after all examples in the group have finished.
@ -172,18 +164,28 @@ module Spectator
@after_all_hooks_run = true @after_all_hooks_run = true
end end
# Runs all of the `after_each` hooks. # Runs all of the "after-each" hooks.
# This method should run following every example in the group. # This method should run following every example in the group.
protected def run_after_each_hooks : Nil protected def run_after_each_hooks : Nil
@hooks.run_after_each @hooks.run_after_each
end end
# Creates a proc that runs the `around_each` hooks # Creates a proc that runs the "around-each" hooks
# in addition to a block passed to this method. # in addition to a block passed to this method.
# To call the block and all `around_each` hooks, # To call the block and all "around-each" hooks,
# just invoke `Proc#call` on the returned proc. # just invoke `Proc#call` on the returned proc.
def wrap_around_each_hooks(&block : ->) : -> def wrap_around_each_hooks(&block : ->) : ->
@hooks.wrap_around_each(&block) @hooks.wrap_around_each(&block)
end end
# Runs all of the pre-conditions for an example.
def run_pre_conditions
@conditions.run_pre_conditions
end
# Runs all of the post-conditions for an example.
def run_post_conditions
@conditions.run_post_conditions
end
end end
end end

View file

@ -24,33 +24,33 @@ module Spectator
) )
end end
# Runs all `before_all` hooks. # Runs all "before-all" hooks.
# These hooks should be run once before all examples in the group start. # These hooks should be run once before all examples in the group start.
def run_before_all def run_before_all
@before_all.each &.call @before_all.each &.call
end end
# Runs all `before_each` hooks. # Runs all "before-each" hooks.
# These hooks should be run every time before each example in a group. # These hooks should be run every time before each example in a group.
def run_before_each def run_before_each
@before_each.each &.call @before_each.each &.call
end end
# Runs all `after_all` hooks. # Runs all "after-all" hooks.
# These hooks should be run once after all examples in group finish. # These hooks should be run once after all examples in group finish.
def run_after_all def run_after_all
@after_all.each &.call @after_all.each &.call
end end
# Runs all `after_each` hooks. # Runs all "after-all" hooks.
# These hooks should be run every time after each example in a group. # These hooks should be run every time after each example in a group.
def run_after_each def run_after_each
@after_each.each &.call @after_each.each &.call
end end
# Creates a proc that runs the `around_each` hooks # Creates a proc that runs the "around-each" hooks
# in addition to a block passed to this method. # in addition to a block passed to this method.
# To call the block and all `around_each` hooks, # To call the block and all "around-each" hooks,
# just invoke `Proc#call` on the returned proc. # just invoke `Proc#call` on the returned proc.
def wrap_around_each(&block : ->) def wrap_around_each(&block : ->)
wrapper = block wrapper = block

View file

@ -8,7 +8,7 @@ module Spectator
@stack : Array(Iterator(ExampleComponent)) @stack : Array(Iterator(ExampleComponent))
# Creates a new iterator. # Creates a new iterator.
# The `group` is the example group to iterate through. # The *group* is the example group to iterate through.
def initialize(@group : Iterable(ExampleComponent)) def initialize(@group : Iterable(ExampleComponent))
iter = @group.each.as(Iterator(ExampleComponent)) iter = @group.each.as(Iterator(ExampleComponent))
@stack = [iter] @stack = [iter]

View file

@ -16,7 +16,7 @@ module Spectator::Expectations
end end
# Creates the expectation partial. # Creates the expectation partial.
# The label is generated by calling `#to_s` on the block. # The label is generated by calling to_s on the block.
# The block is stored for later use. # The block is stored for later use.
protected def initialize(@block : -> ReturnType, source_file, source_line) protected def initialize(@block : -> ReturnType, source_file, source_line)
super(@block.to_s, source_file, source_line) super(@block.to_s, source_file, source_line)

View file

@ -1,11 +1,12 @@
module Spectator::Expectations module Spectator::Expectations
# Ties together a partial, matcher, and their outcome.
class Expectation class Expectation
# Populates the base portiion of the expectation with values. # Populates the base portiion of the expectation with values.
# The `matched` flag should be true if the matcher is satisfied with the partial. # The *matched* flag should be true if the matcher is satisfied with the partial.
# The `negated` flag should be true if the expectation is inverted. # The *negated* flag should be true if the expectation is inverted.
# These options are mutually-exclusive in this context. # These options are mutually-exclusive in this context.
# Don't flip the value of `matched` because `negated` is true. # Don't flip the value of *matched* because *negated* is true.
# The `partial` and the `matcher` arguments should reference # The *partial* and the *matcher* arguments should reference
# the actual and expected result respectively. # the actual and expected result respectively.
def initialize(@matched : Bool, @negated : Bool, def initialize(@matched : Bool, @negated : Bool,
@partial : ExpectationPartial, @matcher : Matchers::Matcher) @partial : ExpectationPartial, @matcher : Matchers::Matcher)

View file

@ -4,8 +4,6 @@ module Spectator::Expectations
# The part of the expectation this class covers is the actual value. # The part of the expectation this class covers is the actual value.
# This can also cover a block's behavior. # This can also cover a block's behavior.
# Sub-types of this class are returned by the `DSL::ExampleDSL.expect` call. # Sub-types of this class are returned by the `DSL::ExampleDSL.expect` call.
# Sub-types are expected to implement `#eval`,
# which returns a corresponding sub-type of `Expectation`.
abstract struct ExpectationPartial abstract struct ExpectationPartial
# User-friendly string displayed for the actual expression being tested. # User-friendly string displayed for the actual expression being tested.
# For instance, in the expectation: # For instance, in the expectation:
@ -27,13 +25,12 @@ module Spectator::Expectations
private def initialize(@label, @source_file, @source_line) private def initialize(@label, @source_file, @source_line)
end end
# Asserts that the `#actual` value matches some criteria. # Asserts that some criteria defined by the matcher is satisfied.
# The criteria is defined by the matcher passed to this method.
def to(matcher) : Nil def to(matcher) : Nil
report(eval(matcher)) report(eval(matcher))
end end
# Asserts that the `#actual` value *does not* match some criteria. # Asserts that some criteria defined by the matcher is not satisfied.
# This is effectively the opposite of `#to`. # This is effectively the opposite of `#to`.
def to_not(matcher) : Nil def to_not(matcher) : Nil
report(eval(matcher, true)) report(eval(matcher, true))

View file

@ -9,7 +9,7 @@ module Spectator::Expectations
@expectations = Array(Expectation).new(1) @expectations = Array(Expectation).new(1)
# Creates the reporter. # Creates the reporter.
# When the `raise_on_failure` flag is set to true, # When the *raise_on_failure* flag is set to true,
# which is the default, an exception will be raised # which is the default, an exception will be raised
# on the first failure that is reported. # on the first failure that is reported.
# To store failures and continue, set the flag to false. # To store failures and continue, set the flag to false.

View file

@ -4,7 +4,7 @@ module Spectator::Expectations
# Expectation partial variation that operates on a value. # Expectation partial variation that operates on a value.
struct ValueExpectationPartial(ActualType) < ExpectationPartial struct ValueExpectationPartial(ActualType) < ExpectationPartial
# Actual value produced by the test. # Actual value produced by the test.
# This is the value passed to the `#expect` call. # This is the value passed to the `Spectator::DSL::ExampleDSL#expect` macro.
getter actual getter actual
# Creates the expectation partial. # Creates the expectation partial.
@ -15,7 +15,7 @@ module Spectator::Expectations
end end
# Creates the expectation partial. # Creates the expectation partial.
# The label is generated by calling `#to_s` on the actual value. # The label is generated by calling `to_s` on the actual value.
# The actual value is stored for later use. # The actual value is stored for later use.
protected def initialize(@actual : ActualType, source_file, source_line) protected def initialize(@actual : ActualType, source_file, source_line)
super(@actual.to_s, source_file, source_line) super(@actual.to_s, source_file, source_line)

View file

@ -10,16 +10,16 @@ module Spectator
getter expectations : Expectations::ExampleExpectations getter expectations : Expectations::ExampleExpectations
# Creates a failed result. # Creates a failed result.
# The `example` should refer to the example that was run # The *example* should refer to the example that was run
# and that this result is for. # and that this result is for.
# The `elapsed` argument is the length of time it took to run the example. # The *elapsed* argument is the length of time it took to run the example.
# The `expectations` references the expectations that were checked in the example. # The *expectations* references the expectations that were checked in the example.
# The `error` is the exception that was raised to cause the failure. # The *error* is the exception that was raised to cause the failure.
def initialize(example, elapsed, @expectations, @error) def initialize(example, elapsed, @expectations, @error)
super(example, elapsed) super(example, elapsed)
end end
# Calls the `failure` method on `interface` and passes `self`. # Calls the `failure` method on *interface* and passes self.
def call(interface) def call(interface)
interface.failure(self) interface.failure(self)
end end

View file

@ -5,9 +5,9 @@ module Spectator
getter elapsed : Time::Span getter elapsed : Time::Span
# Creates a successful result. # Creates a successful result.
# The `example` should refer to the example that was run # The *example* should refer to the example that was run
# and that this result is for. # and that this result is for.
# The `elapsed` argument is the length of time it took to run the example. # The *elapsed* argument is the length of time it took to run the example.
def initialize(example, @elapsed) def initialize(example, @elapsed)
super(example) super(example)
end end

View file

@ -18,7 +18,7 @@ module Spectator::Formatters
} }
# Creates the formatter. # Creates the formatter.
# By default, output is sent to `STDOUT`. # By default, output is sent to STDOUT.
def initialize(@io : IO = STDOUT) def initialize(@io : IO = STDOUT)
end end

View file

@ -14,8 +14,8 @@ module Spectator::Formatters
# ``` # ```
class FailureBlock class FailureBlock
# Creates the failure block. # Creates the failure block.
# The `index` uniquely identifies the failure in the output. # The *index* uniquely identifies the failure in the output.
# The `result` is the outcome of the failed example. # The *result* is the outcome of the failed example.
def initialize(@index : Int32, @result : FailedResult) def initialize(@index : Int32, @result : FailedResult)
end end
@ -28,6 +28,10 @@ module Spectator::Formatters
end end
# Produces the title of the failure block. # Produces the title of the failure block.
# The line takes the form:
# ```text
# 1) Example name
# ```
private def title(io) private def title(io)
io << " " io << " "
io << @index io << @index
@ -37,6 +41,12 @@ module Spectator::Formatters
end end
# Produces the message line of the failure block. # Produces the message line of the failure block.
# The line takes the form:
# ```text
# Failure: Error message
# ```
# The indentation of this line starts directly under
# the example name from the title line.
private def message(io) private def message(io)
io << " Failure: " io << " Failure: "
io << @result.error io << @result.error

View file

@ -1,6 +1,6 @@
module Spectator::Internals module Spectator::Internals
# Helper class that acts as a gateway between example code and the test framework. # Helper class that acts as a gateway between example code and the test framework.
# Every example run must be called with `#run`. # Every example must be invoked by passing it to `#run`.
# This sets up the harness so that the example code can use it. # This sets up the harness so that the example code can use it.
# The test framework does the following: # The test framework does the following:
# ``` # ```
@ -22,7 +22,7 @@ module Spectator::Internals
# Wraps an example with a harness and runs the example. # Wraps an example with a harness and runs the example.
# The `#current` harness will be set # The `#current` harness will be set
# prior to running the example, and reset after. # prior to running the example, and reset after.
# The `example` argument will be the example to run. # The *example* argument will be the example to run.
# The result returned from `Example#run` will be returned. # The result returned from `Example#run` will be returned.
def self.run(example : Example) : Result def self.run(example : Example) : Result
@@current = new(example) @@current = new(example)

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests that multiple attributes match specified conditions. # Matcher that tests that multiple attributes match specified conditions.
# The attributes are tested with the `===` operator. # The attributes are tested with the === operator.
# The `ExpectedType` type param should be a `NamedTuple`. # The `ExpectedType` type param should be a `NamedTuple`.
struct AttributesMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct AttributesMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Common matcher that tests whether two values semantically equal each other. # Common matcher that tests whether two values semantically equal each other.
# The values are compared with the `===` operator. # The values are compared with the === operator.
struct CaseMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct CaseMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a value, such as a `String` or `Array`, contains one or more values. # Matcher that tests whether a value, such as a `String` or `Array`, contains one or more values.
# The values are checked with the `includes?` operator. # The values are checked with the `includes?` method.
struct ContainMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct ContainMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a collection is empty. # Matcher that tests whether a collection is empty.
# The values are checked with the `#empty?` method. # The values are checked with the `empty?` method.
struct EmptyMatcher < Matcher struct EmptyMatcher < Matcher
# Creates the matcher. # Creates the matcher.
def initialize def initialize

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Common matcher that tests whether two values equal each other. # Common matcher that tests whether two values equal each other.
# The values are compared with the `==` operator. # The values are compared with the == operator.
struct EqualityMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct EqualityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether one value is greater than or equal to another. # Matcher that tests whether one value is greater than or equal to another.
# The values are compared with the `>=` operator. # The values are compared with the >= operator.
struct GreaterThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct GreaterThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether one value is greater than another. # Matcher that tests whether one value is greater than another.
# The values are compared with the `>` operator. # The values are compared with the > operator.
struct GreaterThanMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct GreaterThanMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -3,7 +3,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a value, such as a `String` or `Array`, matches one or more values. # Matcher that tests whether a value, such as a `String` or `Array`, matches one or more values.
# For a `String`, the `includes?` method is used. # For a `String`, the `includes?` method is used.
# Otherwise, it expects an `Enumerable` and iterates over each item until `===` is true. # Otherwise, it expects an `Enumerable` and iterates over each item until === is true.
struct HaveMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct HaveMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether two values do not equal each other. # Matcher that tests whether two values do not equal each other.
# The values are compared with the `!=` operator. # The values are compared with the != operator.
struct InequalityMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct InequalityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether one value is less than or equal to another. # Matcher that tests whether one value is less than or equal to another.
# The values are compared with the `<=` operator. # The values are compared with the <= operator.
struct LessThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct LessThanEqualMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether one value is less than another. # Matcher that tests whether one value is less than another.
# The values are compared with the `<` operator. # The values are compared with the < operator.
struct LessThanMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct LessThanMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers module Spectator::Matchers
# Common matcher that tests whether a value is nil. # Common matcher that tests whether a value is nil.
# The values are compared with the `#nil?` method. # The `Object#nil?` method is used for this.
struct NilMatcher < Matcher struct NilMatcher < Matcher
# Creates the matcher. # Creates the matcher.
def initialize def initialize

View file

@ -1,9 +1,9 @@
require "./value_matcher" require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests one or more predicates (methods ending in `?`). # Matcher that tests one or more predicates (methods ending in '?').
# The `ExpectedType` type param should be a `NamedTuple`. # The `ExpectedType` type param should be a `NamedTuple`.
# Each key in the tuple is a predicate (without the `?`) to test. # Each key in the tuple is a predicate (without the '?') to test.
struct PredicateMatcher(ExpectedType) < Matcher struct PredicateMatcher(ExpectedType) < Matcher
# Creates the matcher. # Creates the matcher.
# Constructs the label from the type parameters. # Constructs the label from the type parameters.

View file

@ -2,9 +2,9 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a value is in a given range or set of values. # Matcher that tests whether a value is in a given range or set of values.
# The `#includes?` method is used for this check. # The `includes?` method is used for this check.
# Typically this matcher uses a `Range`, # Typically this matcher uses a `Range`,
# but any type that implements the `#includes?` method is supported. # but any type that implements the `includes?` method is supported.
struct RangeMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct RangeMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.
@ -24,18 +24,17 @@ module Spectator::Matchers
"Expected #{partial.label} to not be in #{label}" "Expected #{partial.label} to not be in #{label}"
end end
# Creates a new range matcher with bounds based off of `center`. # Creates a new range matcher with bounds based off of *center*.
# #
# This method expects that the original matcher was created with a "difference" value. # This method expects that the original matcher was created with a "difference" value.
# That is: # That is:
# ``` # ```
# RangeMatcher.new(diff).of(center) # RangeMatcher.new(diff).of(center)
# ``` # ```
# This implies that `#match?` would not work on the original matcher. # This implies that the `match?` method would not work on the original matcher.
# #
# The new range will be centered at `center` # The new range will be centered at *center*
# and have lower and upper bounds # and have upper and lower bounds equal to *center* plus and minux diff.
# equal to `center - diff` and `center + diff` respectively.
# The range will be inclusive. # The range will be inclusive.
def of(center) def of(center)
diff = @expected diff = @expected

View file

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a value matches a regular expression. # Matcher that tests whether a value matches a regular expression.
# The value is compared with the `=~` operator. # The value is compared with the =~ operator.
struct RegexMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct RegexMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. # True is returned if the match was successful, false otherwise.

View file

@ -3,14 +3,14 @@ require "./value_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests whether a value is truthy or falsey. # Matcher that tests whether a value is truthy or falsey.
# Falsey means a value is considered false by an if-statement, # Falsey means a value is considered false by an if-statement,
# which are `false` and `nil` in Crystal. # which are false and nil in Crystal.
# Truthy is the opposite of falsey. # Truthy is the opposite of falsey.
# #
# Additionally, different matchers can be created # Additionally, different matchers can be created
# by using the `#<`, `#<=`, `#>`, `#>=`, `#==`, and `#!=` operators. # by using the `#<`, `#<=`, `#>`, `#>=`, `#==`, and `#!=` operators.
struct TruthyMatcher < ValueMatcher(Bool) struct TruthyMatcher < ValueMatcher(Bool)
# Creates the truthy matcher. # Creates the truthy matcher.
# The `truthy` argument should be true to match "truthy" values, # The *truthy* argument should be true to match "truthy" values,
# and false to match "falsey" values. # and false to match "falsey" values.
def initialize(truthy : Bool) def initialize(truthy : Bool)
super(truthy ? "truthy" : "falsey", truthy) super(truthy ? "truthy" : "falsey", truthy)

View file

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher that tests a value is of a specified type. # Matcher that tests a value is of a specified type.
# The values are compared with the `#is_a?` method. # The values are compared with the `Object#is_a?` method.
struct TypeMatcher(Expected) < Matcher struct TypeMatcher(Expected) < Matcher
# Creates the type matcher. # Creates the type matcher.
# The `Expected` type param will be used to populate the underlying label. # The `Expected` type param will be used to populate the underlying label.

View file

@ -3,8 +3,7 @@ require "./matcher"
module Spectator::Matchers module Spectator::Matchers
# Category of matcher that uses a value. # Category of matcher that uses a value.
# Matchers of this type expect that a SUT applies to the value in some way. # Matchers of this type expect that a SUT applies to the value in some way.
# Sub-types must implement `#match?`, `#message`, and `#negated_message`. # Sub-types must implement `Matcher#match?`, `Matcher#message`, and `Matcher#negated_message`.
# Those methods accept a `ValueExpectationPartial` to work with.
abstract struct ValueMatcher(ExpectedType) < Matcher abstract struct ValueMatcher(ExpectedType) < Matcher
# Expected value. # Expected value.
# Sub-types may use this value to test the expectation and generate message strings. # Sub-types may use this value to test the expectation and generate message strings.

View file

@ -12,12 +12,12 @@ module Spectator
getter parent : ExampleGroup getter parent : ExampleGroup
# Creates a new example group. # Creates a new example group.
# The `what` argument is a description from the user. # The *what* argument is a description from the user.
# The `parent` should contain this group. # The *parent* should contain this group.
# After creating this group, the parent's children should be updated. # After creating this group, the parent's children should be updated.
# The parent's children must contain this group, # The parent's children must contain this group,
# otherwise there may be unexpected behavior. # otherwise there may be unexpected behavior.
# The `hooks` are stored to be triggered later. # The *hooks* are stored to be triggered later.
def initialize(@what, @parent, hooks : ExampleHooks, conditions : ExampleConditions) def initialize(@what, @parent, hooks : ExampleHooks, conditions : ExampleConditions)
super(hooks, conditions) super(hooks, conditions)
end end
@ -27,43 +27,53 @@ module Spectator
@what.is_a?(Symbol) @what.is_a?(Symbol)
end end
# Runs all of the `before_all` hooks. # Runs all of the "before-all" hooks.
# This should run prior to any examples in the group. # This should run prior to any examples in the group.
# The hooks will be run only once. # The hooks will be run only once.
# Subsequent calls to this method will do nothing. # Subsequent calls to this method will do nothing.
# Parent `before_all` hooks will be run first. # Parent "before-all" hooks will be run first.
protected def run_before_all_hooks : Nil protected def run_before_all_hooks : Nil
parent.run_before_all_hooks parent.run_before_all_hooks
super super
end end
# Runs all of the `before_each` hooks. # Runs all of the "before-each" hooks.
# This method should run prior to every example in the group. # This method should run prior to every example in the group.
# Parent `before_each` hooks will be run first. # Parent "before-each" hooks will be run first.
protected def run_before_each_hooks : Nil protected def run_before_each_hooks : Nil
parent.run_before_each_hooks parent.run_before_each_hooks
super super
end end
# Runs all of the `after_all` hooks. # Runs all of the "after-all" hooks.
# This should run following all examples in the group. # This should run following all examples in the group.
# The hooks will be run only once, # The hooks will be run only once,
# and only after all examples in the group have finished. # and only after all examples in the group have finished.
# Subsequent calls after the hooks have been run will do nothing. # Subsequent calls after the hooks have been run will do nothing.
# Parent `after_all` hooks will be run last. # Parent "after-all" hooks will be run last.
protected def run_after_all_hooks : Nil protected def run_after_all_hooks : Nil
super super
parent.run_after_all_hooks parent.run_after_all_hooks
end end
# Runs all of the `after_each` hooks. # Runs all of the "after-each" hooks.
# This method should run following every example in the group. # This method should run following every example in the group.
# Parent `after_each` hooks will be run last. # Parent "after-each" hooks will be run last.
protected def run_after_each_hooks : Nil protected def run_after_each_hooks : Nil
super super
parent.run_after_each_hooks parent.run_after_each_hooks
end end
# Creates a proc that runs the "around-each" hooks
# in addition to a block passed to this method.
# To call the block and all `around_each` hooks,
# just invoke `Proc#call` on the returned proc.
# Parent "around-each" hooks will be in the outermost wrappings.
def wrap_around_each_hooks(&block : ->) : ->
wrapper = super(&block)
parent.wrap_around_each_hooks(&wrapper)
end
# Runs all of the pre-condition checks. # Runs all of the pre-condition checks.
# This method should run prior to every example in the group. # This method should run prior to every example in the group.
# Parent pre-conditions will be checked first. # Parent pre-conditions will be checked first.
@ -80,20 +90,12 @@ module Spectator
parent.run_post_conditions parent.run_post_conditions
end end
# Creates a proc that runs the `around_each` hooks
# in addition to a block passed to this method.
# To call the block and all `around_each` hooks,
# just invoke `Proc#call` on the returned proc.
# Parent `around_each` hooks will be in the outermost wrappings.
def wrap_around_each_hooks(&block : ->) : ->
wrapper = super(&block)
parent.wrap_around_each_hooks(&wrapper)
end
# Creates a string representation of the group. # Creates a string representation of the group.
# The string consists of `#what` appended to the parent. # The string consists of `#what` appended to the parent.
# This results in a string like: # This results in a string like:
# `Foo #bar does something` # ```text
# Foo#bar does something
# ```
# for the following structure: # for the following structure:
# ``` # ```
# describe Foo do # describe Foo do

View file

@ -5,7 +5,7 @@ module Spectator
# A pending result means the example is not ready to run yet. # A pending result means the example is not ready to run yet.
# This can happen when the functionality to be tested is not implemented yet. # This can happen when the functionality to be tested is not implemented yet.
class PendingResult < Result class PendingResult < Result
# Calls the `pending` method on `interface` and passes `self`. # Calls the `pending` method on *interface* and passes self.
def call(interface) def call(interface)
interface.pending(self) interface.pending(self)
end end

View file

@ -6,8 +6,8 @@ module Spectator
getter runtime : Time::Span getter runtime : Time::Span
# Creates the report. # Creates the report.
# The `results` are from running the examples in the test suite. # The *results* are from running the examples in the test suite.
# The `runtime` is the total time it took to execute the suite. # The *runtime* is the total time it took to execute the suite.
def initialize(@results : Array(Result), @runtime) def initialize(@results : Array(Result), @runtime)
end end

View file

@ -6,14 +6,14 @@ module Spectator
getter example : Example getter example : Example
# Constructs the base of the result. # Constructs the base of the result.
# The `example` should refer to the example that was run # The *example* should refer to the example that was run
# and that this result is for. # and that this result is for.
def initialize(@example) def initialize(@example)
end end
# Calls the corresponding method for the type of result. # Calls the corresponding method for the type of result.
# This is used to avoid placing if or case-statements everywhere based on type. # This is used to avoid placing if or case-statements everywhere based on type.
# Each sub-class implements this method by calling the correct method on `interface`. # Each sub-class implements this method by calling the correct method on *interface*.
abstract def call(interface) abstract def call(interface)
end end
end end

View file

@ -50,7 +50,7 @@ module Spectator
wrapper.call wrapper.call
rescue ex rescue ex
# If an error occurs calling the wrapper, # If an error occurs calling the wrapper,
# it means it came from the `around_each` hooks. # it means it came from the "around-each" hooks.
# This is because the test code is completely wrapped with a begin/rescue block. # This is because the test code is completely wrapped with a begin/rescue block.
raise Exception.new("Error encountered while running around hooks", ex) raise Exception.new("Error encountered while running around hooks", ex)
end end

View file

@ -2,7 +2,7 @@ module Spectator
# Main driver for executing tests and feeding results to formatters. # Main driver for executing tests and feeding results to formatters.
class Runner class Runner
# Creates the test suite runner. # Creates the test suite runner.
# Specify the test `suite` to run and any additonal configuration. # Specify the test *suite* to run and any additonal configuration.
def initialize(@suite : TestSuite, @config : Config) def initialize(@suite : TestSuite, @config : Config)
end end

View file

@ -32,7 +32,10 @@ module Spectator
end end
# String representation of the source. # String representation of the source.
# This is formatted as `FILE:LINE`. # This is formatted as:
# ```text
# FILE:LINE
# ```
def to_s(io) def to_s(io)
io << path io << path
io << ':' io << ':'

View file

@ -7,15 +7,15 @@ module Spectator
getter expectations : Expectations::ExampleExpectations getter expectations : Expectations::ExampleExpectations
# Creates a successful result. # Creates a successful result.
# The `example` should refer to the example that was run # The *example* should refer to the example that was run
# and that this result is for. # and that this result is for.
# The `elapsed` argument is the length of time it took to run the example. # The *elapsed* argument is the length of time it took to run the example.
# The `expectations` references the expectations that were checked in the example. # The *expectations* references the expectations that were checked in the example.
def initialize(example, elapsed, @expectations) def initialize(example, elapsed, @expectations)
super(example, elapsed) super(example, elapsed)
end end
# Calls the `success` method on `interface` and passes `self`. # Calls the `success` method on *interface* and passes self.
def call(interface) def call(interface)
interface.success(self) interface.success(self)
end end

View file

@ -5,7 +5,7 @@ module Spectator
include Enumerable(Example) include Enumerable(Example)
# Creates the test suite. # Creates the test suite.
# The example `group` provided will be run. # The example *group* provided will be run.
def initialize(@group : ExampleGroup) def initialize(@group : ExampleGroup)
end end