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
# 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
# when the group being started is finished.
# See `SampleExampleGroupBuilder#initialize` for the arguments
@ -91,10 +91,12 @@ module Spectator::DSL
current_group.add_around_each_hook(block)
end
# Adds a pre-condition to run at the start of every example in the current group.
def add_pre_condition(&block : ->) : Nil
current_group.add_pre_condition(block)
end
# Adds a post-condition to run at the end of every example in the current group.
def add_post_condition(&block : ->) : Nil
current_group.add_post_condition(block)
end

View File

@ -1,12 +1,14 @@
require "./matcher_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
include MatcherDSL
# 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
# to see if it satisfies the conditions specified.
#
@ -21,7 +23,8 @@ module Spectator::DSL
end
# 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
# to see if it satisfies the conditions specified.
#
@ -40,7 +43,7 @@ module Spectator::DSL
# ```
# 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)
{% if block.is_a?(Nop) %}
{% 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.
# 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.
{% 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.
# The raw block can't be used because it's not clear to the user.
{% 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}})
{% else %}
# In this case, it looks like the short-hand method syntax wasn't used.
@ -64,7 +74,8 @@ module Spectator::DSL
end
# 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
# to see if it satisfies the conditions specified.
#
@ -81,7 +92,8 @@ module Spectator::DSL
end
# 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
# to see if it satisfies the conditions specified.
#
@ -102,7 +114,7 @@ module Spectator::DSL
# ```
# 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)
expect {{block}}
end

View File

@ -7,7 +7,7 @@ module Spectator::DSL
end
# 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
@example_type.new(group, sample_values)
end

View File

@ -53,16 +53,18 @@ module Spectator::DSL
@around_each_hooks << block
end
# Adds a pre-condition to run at the start of every example in this group.
def add_pre_condition(block : ->) : Nil
@pre_conditions << block
end
# Adds a post-condition to run at the end of every example in this group.
def add_post_condition(block : ->) : Nil
@post_conditions << block
end
# 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.
private def hooks
ExampleHooks.new(
@ -74,6 +76,10 @@ module Spectator::DSL
)
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
ExampleConditions.new(@pre_conditions, @post_conditions)
end

View File

@ -4,7 +4,7 @@ module Spectator::DSL
# Methods for defining matchers for expectations.
module MatcherDSL
# 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.
#
# Example:
@ -16,7 +16,7 @@ module Spectator::DSL
end
# 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.
#
# Example:
@ -28,7 +28,8 @@ module Spectator::DSL
end
# 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:
# ```
@ -47,8 +48,8 @@ module Spectator::DSL
end
# Indicates that some value should semantically equal another.
# The `===` operator is used for this check.
# This has identical behavior as a `when` condition in a `case` block.
# The === operator is used for this check.
# This has identical behavior as a "when" condition in a case block.
#
# Examples:
# ```
@ -61,8 +62,8 @@ module Spectator::DSL
end
# Indicates that some value should be of a specified type.
# The `#is_a?` method is used for this check.
# A type name or type union should be used for `expected`.
# The `Object#is_a?` method is used for this check.
# A type name or type union should be used for *expected*.
#
# Examples:
# ```
@ -76,8 +77,8 @@ module Spectator::DSL
end
# Indicates that some value should be of a specified type.
# The `#is_a?` method is used for this check.
# A type name or type union should be used for `expected`.
# The `Object#is_a?` method is used for this check.
# A type name or type union should be used for *expected*.
# This method is identical to `#be_a`,
# and exists just to improve grammar.
#
@ -90,7 +91,7 @@ module Spectator::DSL
end
# 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.
#
# Example:
@ -102,7 +103,7 @@ module Spectator::DSL
end
# 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.
#
# Example:
@ -114,7 +115,7 @@ module Spectator::DSL
end
# 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.
#
# Example:
@ -126,7 +127,7 @@ module Spectator::DSL
end
# 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.
#
# Example:
@ -138,9 +139,9 @@ module Spectator::DSL
end
# 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,
# but any type that has the `=~` operator will work.
# but any type that has the =~ operator will work.
#
# Examples:
# ```
@ -174,7 +175,7 @@ module Spectator::DSL
end
# 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:
# ```
@ -186,7 +187,7 @@ module Spectator::DSL
end
# 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:
# ```
@ -200,7 +201,8 @@ module Spectator::DSL
# Indicates that some value should be contained within another.
# 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`.
#
# Examples:
@ -209,9 +211,9 @@ module Spectator::DSL
# 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
# 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.
#
# Examples:
@ -220,13 +222,13 @@ module Spectator::DSL
# expect(speed).to be_within(5).of(speed_limit)
# ```
#
# NOTE: The `of` suffix must be used
# if the `expected` argument does not implement `#includes?`
# NOTE: The of suffix must be used
# if the *expected* argument does not implement an includes? method.
#
# 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.
# By default, the range is *inclusive*.
# By default, the range is inclusive.
#
# Examples:
# ```
@ -247,9 +249,9 @@ module Spectator::DSL
# 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.
# By default, the range is *inclusive*.
# By default, the range is inclusive.
#
# Examples:
# ```
@ -301,10 +303,10 @@ module Spectator::DSL
# Indicates that some value or set should start with another value.
# 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`.
# 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.
#
# Examples:
@ -323,10 +325,10 @@ module Spectator::DSL
# Indicates that some value or set should end with another value.
# 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`.
# 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.
#
# Examples:
@ -345,7 +347,7 @@ module Spectator::DSL
# Indicates that some value or set should contain another value.
# 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`.
# For `Enumerable` types, items are compared using the underying implementation.
# 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.
# This is similar to `#contain`, but uses a different method for matching.
# 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`.
# The `includes?` method is used for this case.
# 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:
# ```
@ -432,7 +434,7 @@ module Spectator::DSL
# Indicates that some value should have a set of attributes matching some conditions.
# A list of named arguments are expected.
# 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:
# ```
@ -444,10 +446,10 @@ module Spectator::DSL
end
# 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.
#
# 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:
# ```
# expect("foobar").to be_ascii_only
@ -456,7 +458,7 @@ module Spectator::DSL
# ```
macro method_missing(call)
{% 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
{% else %}
{% raise "Undefined local variable or method '#{call}'" %}

View File

@ -3,7 +3,7 @@ module Spectator::DSL
# Creates groups of examples and nested groups.
class NestedExampleGroupBuilder < ExampleGroupBuilder
# 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:
# ```
@ -23,8 +23,8 @@ module Spectator::DSL
# Builds the example group.
# A new `NestedExampleGroup` will be returned
# which can have instances of `Example` and `ExampleGroup` nested in it.
# 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 *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.
def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
NestedExampleGroup.new(@what, parent, hooks, conditions).tap do |group|
# 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".
class RootExampleGroupBuilder < ExampleGroupBuilder
# 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
RootExampleGroup.new(hooks, conditions).tap do |group|
# 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.
class SampleExampleGroupBuilder(T) < NestedExampleGroupBuilder
# Creates a new group builder.
# 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 `name` is the variable name that the user accesses the current collection item with.
# 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 *name* is the variable name that the user accesses the current collection item with.
#
# In this code:
# ```
@ -18,11 +18,11 @@ module Spectator::DSL
# # ...
# end
# ```
# The `what` value would be "random_integers"
# and the collection would contain the items returned by calling `random_integers`.
# The `name` would be "integer".
# The *what* would be "random_integers"
# and the collection would contain the items returned by calling *random_integers*.
# 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.
# The symbol should be unique.
def initialize(what : String, @collection : Array(T), @name : String, @symbol : Symbol)
@ -32,8 +32,8 @@ module Spectator::DSL
# Builds the example group.
# A new `NestedExampleGroup` will be returned
# which can have instances of `Example` and `ExampleGroup` nested in it.
# 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 *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.
def build(parent : ExampleGroup, sample_values : Internals::SampleValues) : NestedExampleGroup
# This creates the container for the sub-groups.
# The hooks are defined here, instead of repeating for each sub-group.
@ -47,9 +47,9 @@ module Spectator::DSL
end
# 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 `sample_values` should be the same as what was passed to the `#build` call.
# The `value` is the current item in the collection.
# 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 *value* is the current item in the collection.
# The value will be added to the sample values for the sub-group,
# 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

View File

@ -20,9 +20,11 @@ module Spectator::DSL
# it "does something" do
# # Test code goes here...
# end
# ```
#
# # becomes...
# becomes...
#
# ```
# # Class describing the example
# # and provides a means of running the test.
# # Typically every class, module, and method
@ -85,9 +87,11 @@ module Spectator::DSL
# end
# end
# end
# ```
#
# # becomes...
# becomes...
#
# ```
# # describe "#foo"
# module Context123
# # Start a new group.
@ -148,13 +152,13 @@ module Spectator::DSL
# For more information, see `Internals::SampleValues`.
module StructureDSL
# 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.
def initialize(sample_values : Internals::SampleValues)
end
# 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.
#
# Typically when testing a method,
@ -168,7 +172,7 @@ module Spectator::DSL
# ```
#
# 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
# it "does something" do
@ -196,7 +200,7 @@ module Spectator::DSL
end
# 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.
#
# The `#describe` and `#context` are identical in terms of functionality.
@ -352,12 +356,12 @@ module Spectator::DSL
#
# given value = 5 do
# expect(&.odd?).to be_true
# expect(&.event?).to be_false
# expect(&.even?).to be_false
# end
#
# given value = 42 do
# expect(&.odd?).to be_false
# expect(&.event?).to be_true
# expect(&.even?).to be_true
# end
# end
# ```
@ -438,18 +442,18 @@ module Spectator::DSL
# Creates a new example group to test multiple values with.
# This method takes a collection of values
# 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.
# Additionally, a count may be specified to limit the number of values tested.
#
# NOTE: If an infinite enumerable is provided for the collection,
# 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.
# If it does, then the argument's name is used to reference
# 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:
# ```
@ -472,8 +476,8 @@ module Spectator::DSL
# ```
#
# In the examples above, the test case (`#it` block)
# is repeated for each element in `some_integers`.
# `some_integers` is a ficticous collection.
# is repeated for each element in *some_integers*.
# *some_integers* is a ficticous collection.
# The collection will be iterated once.
# `#sample` and `#random_sample` blocks can be nested,
# and work similarly to loops.
@ -521,7 +525,7 @@ module Spectator::DSL
# Iterating multiple times would generate inconsistent values at runtime.
def %to_a
# 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.
{% if count %}
%sample.first({{count}})
@ -535,7 +539,7 @@ module Spectator::DSL
# The module uses a generated unique name.
module Context%sample
# Include the parent module.
# Since `@type` resolves immediately,
# Since @type resolves immediately,
# this will reference the parent type.
include {{@type.id}}
@ -545,7 +549,7 @@ module Spectator::DSL
# Retrieves the current element from the collection.
def {{name}}
# 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.
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value
end
@ -576,8 +580,8 @@ module Spectator::DSL
# Creates a new example group to test multiple random values with.
# This method takes a collection of values and count
# and repeats the contents of the block with each value.
# This method randomly selects `count` items from the collection.
# The `collection` argument should be a literal collection,
# This method randomly selects *count* items from the collection.
# The *collection* argument should be a literal collection,
# such as an array, or a function that returns an enumerable.
#
# NOTE: If an enumerable is used, it must be finite.
@ -585,7 +589,7 @@ module Spectator::DSL
# The block can accept an argument.
# If it does, then the argument's name is used to reference
# 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:
# ```
@ -608,8 +612,8 @@ module Spectator::DSL
# ```
#
# In the examples above, the test case (`#it` block)
# is repeated for 5 random elements in `some_integers`.
# `some_integers` is a ficticous collection.
# is repeated for 5 random elements in *some_integers*.
# *some_integers* is a ficticous collection.
# The collection will be iterated once.
# `#sample` and `#random_sample` blocks can be nested,
# and work similarly to loops.
@ -655,7 +659,7 @@ module Spectator::DSL
# The module uses a generated unique name.
module Context%sample
# Include the parent module.
# Since `@type` resolves immediately,
# Since @type resolves immediately,
# this will reference the parent type.
include {{@type.id}}
@ -665,7 +669,7 @@ module Spectator::DSL
# Retrieves the current element from the collection.
def {{name}}
# 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.
@%wrapper.as(::Spectator::Internals::TypedValueWrapper(typeof(%sample.first))).value
end
@ -714,13 +718,13 @@ module Spectator::DSL
# ```
#
# By using a subject, some of the DSL becomes simpler.
# For example, `ExampleDSL#is_expected` can be used
# as short-hand for `expect(subject)`.
# For example, `ExampleDSL#is_expected` can be used.
# ```
# subject { "foobar" }
#
# 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
# ```
#
@ -807,18 +811,18 @@ module Spectator::DSL
let!(%value) {{block}}
# 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.
@%wrapper : ::Spectator::Internals::ValueWrapper?
# Method for returning the value.
def {{name.id}}
# 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)
# It is cached, return that value.
# 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.
wrapper.unsafe_as(::Spectator::Internals::TypedValueWrapper(typeof(%value))).value
else
@ -1326,7 +1330,7 @@ module Spectator::DSL
end
# 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.
# 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.
# 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.
# One or more expectations should be in the block.
#
@ -1422,7 +1426,7 @@ module Spectator::DSL
end
# Same as `#pending`.
# Include for compatibility with RSpec.
# Included for compatibility with RSpec.
macro xit(what, &block)
pending({{what}}) {{block}}
end
@ -1435,8 +1439,8 @@ module Spectator::DSL
#
# Since the names are generated, and macros can't return values,
# the names for everything must be passed in as arguments.
# 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 *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
# that will actually run the test code.
# The block passed to this macro is the actual test code.
private macro _spectator_test(class_name, run_method_name, &block)
@ -1465,12 +1469,12 @@ module Spectator::DSL
# Creates an example class.
# Since the names are generated, and macros can't return values,
# the names for everything must be passed in as arguments.
# 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 *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.
# 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`.
# 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.
# 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
# in that the error was not from a failed expectation.
class ErroredResult < FailedResult
# Calls the `error` method on `interface` and passes `self`.
# Calls the `error` method on *interface* and passes self.
def call(interface)
interface.error(self)
end

View File

@ -2,7 +2,7 @@ require "./example_component"
module Spectator
# 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
# Indicates whether the example has already been run.
getter? finished = false
@ -31,7 +31,7 @@ module Spectator
# Creates the base of the example.
# 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)
end

View File

@ -10,7 +10,7 @@ module Spectator
# Additionally, the indexer method (`#[]`) will index into sub-groups.
#
# 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
include Enumerable(ExampleComponent)
include Iterable(ExampleComponent)
@ -90,7 +90,7 @@ module Spectator
end
# 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)
offset = index
# Loop through each child
@ -112,7 +112,7 @@ module Spectator
# The remaining offset is passed along to the child.
# If it's an `Example`, it returns itself.
# 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.
child.not_nil![offset]
end
@ -122,22 +122,14 @@ module Spectator
children.all?(&.finished?)
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.
def run_before_hooks
run_before_all_hooks
run_before_each_hooks
end
def run_pre_conditions
@conditions.run_pre_conditions
end
def run_post_conditions
@conditions.run_post_conditions
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.
# The hooks will be run only once.
# Subsequent calls to this method will do nothing.
@ -147,20 +139,20 @@ module Spectator
@before_all_hooks_run = true
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.
protected def run_before_each_hooks : Nil
@hooks.run_before_each
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.
def run_after_hooks
run_after_each_hooks
run_after_all_hooks
end
# Runs all of the `after_all` hooks.
# Runs all of the "after-all" hooks.
# This should run following all examples in the group.
# The hooks will be run only once,
# and only after all examples in the group have finished.
@ -172,18 +164,28 @@ module Spectator
@after_all_hooks_run = true
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.
protected def run_after_each_hooks : Nil
@hooks.run_after_each
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.
# 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.
def wrap_around_each_hooks(&block : ->) : ->
@hooks.wrap_around_each(&block)
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

View File

@ -24,33 +24,33 @@ module Spectator
)
end
# Runs all `before_all` hooks.
# Runs all "before-all" hooks.
# These hooks should be run once before all examples in the group start.
def run_before_all
@before_all.each &.call
end
# Runs all `before_each` hooks.
# Runs all "before-each" hooks.
# These hooks should be run every time before each example in a group.
def run_before_each
@before_each.each &.call
end
# Runs all `after_all` hooks.
# Runs all "after-all" hooks.
# These hooks should be run once after all examples in group finish.
def run_after_all
@after_all.each &.call
end
# Runs all `after_each` hooks.
# Runs all "after-all" hooks.
# These hooks should be run every time after each example in a group.
def run_after_each
@after_each.each &.call
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.
# 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.
def wrap_around_each(&block : ->)
wrapper = block

View File

@ -8,7 +8,7 @@ module Spectator
@stack : Array(Iterator(ExampleComponent))
# 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))
iter = @group.each.as(Iterator(ExampleComponent))
@stack = [iter]

View File

@ -16,7 +16,7 @@ module Spectator::Expectations
end
# 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.
protected def initialize(@block : -> ReturnType, source_file, source_line)
super(@block.to_s, source_file, source_line)

View File

@ -1,11 +1,12 @@
module Spectator::Expectations
# Ties together a partial, matcher, and their outcome.
class Expectation
# Populates the base portiion of the expectation with values.
# 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 *matched* flag should be true if the matcher is satisfied with the partial.
# The *negated* flag should be true if the expectation is inverted.
# These options are mutually-exclusive in this context.
# Don't flip the value of `matched` because `negated` is true.
# The `partial` and the `matcher` arguments should reference
# Don't flip the value of *matched* because *negated* is true.
# The *partial* and the *matcher* arguments should reference
# the actual and expected result respectively.
def initialize(@matched : Bool, @negated : Bool,
@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.
# This can also cover a block's behavior.
# 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
# User-friendly string displayed for the actual expression being tested.
# For instance, in the expectation:
@ -27,13 +25,12 @@ module Spectator::Expectations
private def initialize(@label, @source_file, @source_line)
end
# Asserts that the `#actual` value matches some criteria.
# The criteria is defined by the matcher passed to this method.
# Asserts that some criteria defined by the matcher is satisfied.
def to(matcher) : Nil
report(eval(matcher))
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`.
def to_not(matcher) : Nil
report(eval(matcher, true))

View File

@ -9,7 +9,7 @@ module Spectator::Expectations
@expectations = Array(Expectation).new(1)
# 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
# on the first failure that is reported.
# 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.
struct ValueExpectationPartial(ActualType) < ExpectationPartial
# 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
# Creates the expectation partial.
@ -15,7 +15,7 @@ module Spectator::Expectations
end
# 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.
protected def initialize(@actual : ActualType, source_file, source_line)
super(@actual.to_s, source_file, source_line)

View File

@ -10,16 +10,16 @@ module Spectator
getter expectations : Expectations::ExampleExpectations
# 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.
# 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 `error` is the exception that was raised to cause the failure.
# 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 *error* is the exception that was raised to cause the failure.
def initialize(example, elapsed, @expectations, @error)
super(example, elapsed)
end
# Calls the `failure` method on `interface` and passes `self`.
# Calls the `failure` method on *interface* and passes self.
def call(interface)
interface.failure(self)
end

View File

@ -5,9 +5,9 @@ module Spectator
getter elapsed : Time::Span
# 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.
# 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)
super(example)
end

View File

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

View File

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

View File

@ -1,6 +1,6 @@
module Spectator::Internals
# 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.
# The test framework does the following:
# ```
@ -22,7 +22,7 @@ module Spectator::Internals
# Wraps an example with a harness and runs the example.
# The `#current` harness will be set
# 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.
def self.run(example : Example) : Result
@@current = new(example)

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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`.
struct AttributesMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers
# 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
# Creates the matcher.
def initialize

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -3,7 +3,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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.
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers
# 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
# Creates the matcher.
def initialize

View File

@ -1,9 +1,9 @@
require "./value_matcher"
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`.
# 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
# Creates the matcher.
# Constructs the label from the type parameters.

View File

@ -2,9 +2,9 @@ require "./value_matcher"
module Spectator::Matchers
# 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`,
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# 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}"
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.
# That is:
# ```
# 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`
# and have lower and upper bounds
# equal to `center - diff` and `center + diff` respectively.
# The new range will be centered at *center*
# and have upper and lower bounds equal to *center* plus and minux diff.
# The range will be inclusive.
def of(center)
diff = @expected

View File

@ -2,7 +2,7 @@ require "./value_matcher"
module Spectator::Matchers
# 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)
# Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise.

View File

@ -3,14 +3,14 @@ require "./value_matcher"
module Spectator::Matchers
# Matcher that tests whether a value is truthy or falsey.
# 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.
#
# Additionally, different matchers can be created
# by using the `#<`, `#<=`, `#>`, `#>=`, `#==`, and `#!=` operators.
struct TruthyMatcher < ValueMatcher(Bool)
# 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.
def initialize(truthy : Bool)
super(truthy ? "truthy" : "falsey", truthy)

View File

@ -2,7 +2,7 @@ require "./matcher"
module Spectator::Matchers
# 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
# Creates the type matcher.
# The `Expected` type param will be used to populate the underlying label.

View File

@ -3,8 +3,7 @@ require "./matcher"
module Spectator::Matchers
# Category of matcher that uses a value.
# Matchers of this type expect that a SUT applies to the value in some way.
# Sub-types must implement `#match?`, `#message`, and `#negated_message`.
# Those methods accept a `ValueExpectationPartial` to work with.
# Sub-types must implement `Matcher#match?`, `Matcher#message`, and `Matcher#negated_message`.
abstract struct ValueMatcher(ExpectedType) < Matcher
# Expected value.
# 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
# Creates a new example group.
# The `what` argument is a description from the user.
# The `parent` should contain this group.
# The *what* argument is a description from the user.
# The *parent* should contain this group.
# After creating this group, the parent's children should be updated.
# The parent's children must contain this group,
# 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)
super(hooks, conditions)
end
@ -27,43 +27,53 @@ module Spectator
@what.is_a?(Symbol)
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.
# The hooks will be run only once.
# 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
parent.run_before_all_hooks
super
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.
# Parent `before_each` hooks will be run first.
# Parent "before-each" hooks will be run first.
protected def run_before_each_hooks : Nil
parent.run_before_each_hooks
super
end
# Runs all of the `after_all` hooks.
# Runs all of the "after-all" hooks.
# This should run following all examples in the group.
# The hooks will be run only once,
# and only after all examples in the group have finished.
# 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
super
parent.run_after_all_hooks
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.
# Parent `after_each` hooks will be run last.
# Parent "after-each" hooks will be run last.
protected def run_after_each_hooks : Nil
super
parent.run_after_each_hooks
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.
# This method should run prior to every example in the group.
# Parent pre-conditions will be checked first.
@ -80,20 +90,12 @@ module Spectator
parent.run_post_conditions
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.
# The string consists of `#what` appended to the parent.
# This results in a string like:
# `Foo #bar does something`
# ```text
# Foo#bar does something
# ```
# for the following structure:
# ```
# describe Foo do

View File

@ -5,7 +5,7 @@ module Spectator
# 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.
class PendingResult < Result
# Calls the `pending` method on `interface` and passes `self`.
# Calls the `pending` method on *interface* and passes self.
def call(interface)
interface.pending(self)
end

View File

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

View File

@ -6,14 +6,14 @@ module Spectator
getter example : Example
# 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.
def initialize(@example)
end
# Calls the corresponding method for the type of result.
# 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)
end
end

View File

@ -50,7 +50,7 @@ module Spectator
wrapper.call
rescue ex
# 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.
raise Exception.new("Error encountered while running around hooks", ex)
end

View File

@ -2,7 +2,7 @@ module Spectator
# Main driver for executing tests and feeding results to formatters.
class 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)
end

View File

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

View File

@ -7,15 +7,15 @@ module Spectator
getter expectations : Expectations::ExampleExpectations
# 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.
# 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 *elapsed* argument is the length of time it took to run the example.
# The *expectations* references the expectations that were checked in the example.
def initialize(example, elapsed, @expectations)
super(example, elapsed)
end
# Calls the `success` method on `interface` and passes `self`.
# Calls the `success` method on *interface* and passes self.
def call(interface)
interface.success(self)
end

View File

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