module Spectator::DSL

Overview

Namespace containing methods representing the spec domain specific language.

Direct including types

Defined in:

spectator/dsl.cr
spectator/dsl/assertions.cr
spectator/dsl/examples.cr
spectator/dsl/groups.cr
spectator/dsl/hooks.cr
spectator/dsl/matchers.cr
spectator/dsl/mocks.cr
spectator/dsl/values.cr

Instance Method Summary

Macro Summary

Instance Method Detail

def allow(thing) #

[View source]
def allow_any_instance_of(type : T.class) forall T #

[View source]
def anonymous_double(name = "Anonymous", **stubs) #

[View source]
def anonymous_null_double(name = "Anonymous", **stubs) #

[View source]
def fail(reason : String) #

Immediately fail the current test. A reason can be passed, which is reported in the output.


[View source]
def fail #

Immediately fail the current test. A reason can be passed, which is reported in the output.


[View source]

Macro Detail

macro after_all(&block) #

[View source]
macro after_each(&block) #

[View source]
macro all(matcher) #

Verifies that all elements of a collection satisfy some matcher. The collection should implement Enumerable.

Examples:

array = [1, 2, 3, 4]
expect(array).to all(be_even)  # Fails.
expect(array).to all(be_lt(5)) # Passes.

[View source]
macro around_each(&block) #

[View source]
macro be #

Indicates that some value when compared to another satisfies an operator. An operator can follow, such as: <, <=, >, or >=. See Spectator::Matchers::TruthyMatcher for a full list of operators.

Examples:

expect(1 + 1).to be > 1
expect(5).to be >= 3

Additionally, a value can just "be" truthy by omitting an operator.

expect("foo").to be
# is the same as:
expect("foo").to be_truthy

[View source]
macro be(expected) #

Indicates that some object should be the same as another. This checks if two references are the same. The Reference#same? method is used for this check.

Examples:

obj = "foobar"
expect(obj).to be(obj)
expect(obj.dup).to_not be(obj)

[View source]
macro be_a(expected) #

Indicates that some value should be of a specified type. The Object#is_a? method is used for this check. A type name or type union should be used for expected.

Examples:

expect("foo").to be_a(String)

x = Random.rand(2) == 0 ? "foobar" : 5
expect(x).to be_a(Int32 | String)

[View source]
macro be_a_kind_of(expected) #

Indicates that some value should be of a specified type. 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.

Examples:

expect(123).to be_a_kind_of(Int)

[View source]
macro be_an(expected) #

Indicates that some value should be of a specified type. 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.

Examples:

expect(123).to be_an(Int32)

[View source]
macro be_an_instance_of(expected) #

Indicates that some value should be of a specified type. The value's runtime class is checked. A type name or type union should be used for expected. This method is identical to #be_an_instance_of, and exists just to improve grammar.

Examples:

expect(123).to be_an_instance_of(Int32)

[View source]
macro be_between(min, max) #

Indicates that some value should be between a lower and upper-bound.

Example:

expect(7).to be_between(1, 10)

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.

Examples:

expect(days).to be_between(28, 31).inclusive # 28, 29, 30, or 31
expect(100).to be_between(97, 101).exclusive # 97, 98, 99, or 100 (not 101)

[View source]
macro be_close(expected, delta) #

Indicates that some value should be within a delta of an expected value.

Example:

expect(pi).to be_close(3.14159265359, 0.0000001)

This is functionly equivalent to:

be_within(expected).of(delta)

[View source]
macro be_empty #

Indicates that some collection should be empty.

Example:

expect([]).to be_empty

[View source]
macro be_false #

Indicates that some value should be false.

Examples:

expect("foo".nil?).to be_false
expect(%i[a b c].empty?).to be_false

[View source]
macro be_falsey #

Indicates that some value should be falsey. This means that the value is either false or nil.

Examples:

expect(false).to be_falsey
expect(nil).to be_falsey

[View source]
macro be_ge(expected) #

Indicates that some value should be greater than or equal to another. The >= operator is used for this check. The value passed to this method is the value expected to be smaller or equal.

Example:

expect(3 + 1).to be_ge(3)

[View source]
macro be_gt(expected) #

Indicates that some value should be greater than another. The > operator is used for this check. The value passed to this method is the value expected to be smaller.

Example:

expect(3 + 1).to be_gt(3)

[View source]
macro be_instance_of(expected) #

Indicates that some value should be of a specified type. The value's runtime class is checked. A type name or type union should be used for expected.

Examples:

expect(123).to be_instance_of(Int32)

[View source]
macro be_kind_of(expected) #

Indicates that some value should be of a specified type. 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.

Examples:

expect(123).to be_kind_of(Int)

[View source]
macro be_le(expected) #

Indicates that some value should be less than or equal to another. The <= operator is used for this check. The value passed to this method is the value expected to be larger or equal.

Example:

expect(3 - 1).to be_le(3)

[View source]
macro be_lt(expected) #

Indicates that some value should be less than another. The < operator is used for this check. The value passed to this method is the value expected to be larger.

Example:

expect(3 - 1).to be_lt(3)

[View source]
macro be_nil #

Indicates that some value should or should not be nil.

Examples:

expect(error).to be_nil
expect(input).to_not be_nil

[View source]
macro be_true #

Indicates that some value should be true.

Examples:

expect(nil.nil?).to be_true
expect(%i[a b c].any?).to be_true

[View source]
macro be_truthy #

Indicates that some value should be truthy. This means that the value is not false and not nil.

Examples:

expect(123).to be_truthy
expect(true).to be_truthy

[View source]
macro be_within(expected) #

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 the includes? method. This is typically a Range, but can also be Enumerable.

Examples:

expect(:foo).to be_within(%i[foo bar baz])
expect(7).to be_within(1..10)

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. This usage is helpful for comparisons on floating-point numbers.

Examples:

expect(50.0).to be_within(0.01).of(50.0)
expect(speed).to be_within(5).of(speed_limit)

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. These modify the upper-bound on the range being checked against. By default, the range is inclusive.

Examples:

expect(days).to be_within(1).of(30).inclusive # 29, 30, or 31
expect(100).to be_within(2).of(99).exclusive  # 97, 98, 99, or 100 (not 101)

NOTE Do not attempt to mix the two use cases. It likely won't work and will result in a compilation error.


[View source]
macro before_all(&block) #

[View source]
macro before_each(&block) #

[View source]
macro change(&expression) #

Indicates that some expression's value should change after taking an action.

Examples:

i = 0
expect { i += 1 }.to change { i }
expect { i += 0 }.to_not change { i }
i = 0
expect { i += 5 }.to change { i }.from(0).to(5)
i = 0
expect { i += 5 }.to change { i }.to(5)
i = 0
expect { i += 5 }.to change { i }.from(0)
i = 0
expect { i += 42 }.to change { i }.by(42)

The block short-hand syntax can be used here. It will reference the current subject.

expect { subject << :foo }.to change(&.size).by(1)

[View source]
macro contain(*expected) #

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 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.

Examples:

expect("foobar").to contain("foo")
expect("foobar").to contain('o')
expect(%i[a b c]).to contain(:b)

Additionally, multiple arguments can be specified.

expect("foobarbaz").to contain("foo", "bar")
expect(%i[a b c]).to contain(:a, :b)

[View source]
macro contain_elements(expected) #

Indicates that some value or set should contain specific items. This is typically used on a String or Array (any Enumerable works). 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.

This is identical to #contain, but accepts an array (or enumerable type) instead of multiple arguments.

Examples:

expect("foobar").to contain_elements(["foo", "bar"])
expect("foobar").to contain_elements(['a', 'b'])
expect(%i[a b c]).to contain_elements(%i[a b])

[View source]
macro contain_exactly(*expected) #

Indicates that some set should contain some values in any order.

Example:

expect([1, 2, 3]).to contain_exactly(3, 2, 1)

[View source]
macro context(what, &block) #

[View source]
macro cover(*expected) #

Indicates that some range (or collection) should contain another value. This is typically used on a Range (although any Enumerable works). The includes? method is used.

Examples:

expect(1..10).to contain(5)
expect((1..)).to contain(100)
expect(..100).to contain(50)

Additionally, multiple arguments can be specified.

expect(1..10).to contain(2, 3)
expect(..100).to contain(0, 50)

[View source]
macro create_double(type_name, name, **stubs) #

[View source]
macro create_null_double(type_name, name, **stubs) #

[View source]
macro define_double(type_name, name, **stubs, &block) #

[View source]
macro define_null_double(type_name, name, **stubs, &block) #

[View source]
macro describe(what, &block) #

[View source]
macro double(name = "Anonymous", **stubs, &block) #

[View source]
macro end_with(expected) #

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 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, so that values, types, regular expressions, and others can be tested.

Examples:

expect("foobar").to end_with("bar")
expect("foobar").to end_with('r')
expect("FOOBAR").to end_with(/bar/i)

expect(%i[a b c]).to end_with(:c)
expect(%i[a b c]).to end_with(Symbol)
expect(%w[foo bar]).to end_with(/bar/)

[View source]
macro eq(expected) #

Indicates that some value should equal another. The == operator is used for this check. The value passed to this method is the expected value.

Example:

expect(1 + 2).to eq(3)

[View source]
macro expect(actual, _source_file = __FILE__, _source_line = __LINE__) #

Starts an expectation. 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.

This method should be used like so:

expect(actual).to eq(expected)

Where the actual value is returned by the system-under-test, and the expected value is what the actual value should be to satisfy the condition.


[View source]
macro expect(&block) #

Starts an expectation on a block of code. 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.

This method should be used like so:

expect { raise "foo" }.to raise_error

The block of code is passed along for validation to the matchers.

The short, one argument syntax used for passing methods to blocks can be used. So instead of doing this:

expect(subject.size).to eq(5)

The following syntax can be used instead:

expect(&.size).to eq(5)

The method passed will always be evaluated on the subject.


[View source]
macro expect_any_instance_of(type, _source_file = __FILE__, _source_line = __LINE__) #

[View source]
macro expect_raises #

Indicates that some block should raise an error.

Examples:

expect_raises { raise "foobar" }

[View source]
macro expect_raises(type, &block) #

Indicates that some block should raise an error with a given type. The type parameter should be an exception type.

Examples:

hash = {"foo" => "bar"}
expect_raises(KeyError) { hash["baz"] }.to raise_error(KeyError)

[View source]
macro expect_raises(type, message, &block) #

Indicates that some block should raise an error with a given message and type. The type is the exception type expected to be raised. The message is a string or regex to match to exception message against. This method is included for compatibility with Crystal's default spec.

Examples:

hash = {"foo" => "bar"}
expect_raises(KeyError, /baz/) { hash["baz"] }
expect_raises(ArgumentError, "foobar") { raise ArgumentError.new("foobar") }

[View source]
macro expects(actual) #

Starts an expectation. 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.

This method is identical to #expect, but is grammatically correct for the one-liner syntax. It can be used like so:

it expects(actual).to eq(expected)

Where the actual value is returned by the system-under-test, and the expected value is what the actual value should be to satisfy the condition.


[View source]
macro expects(&block) #

Starts an expectation on a block of code. 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.

This method is identical to #expect, but is grammatically correct for the one-liner syntax. It can be used like so:

it expects { 5 / 0 }.to raise_error

The block of code is passed along for validation to the matchers.

The short, one argument syntax used for passing methods to blocks can be used. So instead of doing this:

it expects(subject.size).to eq(5)

The following syntax can be used instead:

it expects(&.size).to eq(5)

The method passed will always be evaluated on the subject.


[View source]
macro given(*assignments, &block) #

[View source]
macro has_key(expected) #

Indicates that some set, such as a Hash, has a given key. The has_key? method is used for this check.

Examples:

expect({foo: "bar"}).to have_key(:foo)
expect({"lucky" => 7}).to have_key("lucky")

[View source]
macro has_value(expected) #

Indicates that some set, such as a Hash, has a given value. The has_value? method is used for this check.

Examples:

expect({foo: "bar"}).to have_value("bar")
expect({"lucky" => 7}).to have_value(7)

[View source]
macro have(*expected) #

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 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.

Examples:

expect("foobar").to have("foo")
expect("foobar").to have('o')

expect(%i[a b c]).to have(:b)
expect(%w[FOO BAR BAZ]).to have(/bar/i)
expect([1, 2, 3, :a, :b, :c]).to have(Int32)

Additionally, multiple arguments can be specified.

expect("foobarbaz").to have("foo", "bar")
expect(%i[a b c]).to have(:a, :b)
expect(%w[FOO BAR BAZ]).to have(/foo/i, String)

[View source]
macro have_attributes(**expected) #

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.

Examples:

expect("foobar").to have_attributes(size: 6, upcase: "FOOBAR")
expect(%i[a b c]).to have_attributes(size: 1..5, first: Symbol)

[View source]
macro have_elements(expected) #

Indicates that some value or set should contain specific items. This is similar to #contain_elements, 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 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.

Examples:

expect("foobar").to have_elements(["foo", "bar"])
expect("foobar").to have_elements(['a', 'b'])

expect(%i[a b c]).to have_elements(%i[b c])
expect(%w[FOO BAR BAZ]).to have_elements([/FOO/, /bar/i])
expect([1, 2, 3, :a, :b, :c]).to have_elements([Int32, Symbol])

[View source]
macro have_key(expected) #

Indicates that some set, such as a Hash, has a given key. The has_key? method is used for this check.

Examples:

expect({foo: "bar"}).to have_key(:foo)
expect({"lucky" => 7}).to have_key("lucky")

[View source]
macro have_received(method) #

[View source]
macro have_size(expected) #

Indicates that some set should have a specified size.

Example:

expect([1, 2, 3]).to have_size(3)

[View source]
macro have_size_of(expected) #

Indicates that some set should have the same size (number of elements) as another set.

Example:

expect([1, 2, 3]).to have_size_of(%i[x y z])

[View source]
macro have_value(expected) #

Indicates that some set, such as a Hash, has a given value. The has_value? method is used for this check.

Examples:

expect({foo: "bar"}).to have_value("bar")
expect({"lucky" => 7}).to have_value(7)

[View source]
macro is(expected) #

Short-hand form of #is_expected that can be used for one-liner syntax. For instance:

it "is 42" do
  expect(subject).to eq(42)
end

Can be shortened to:

it is(42)

These three are functionally equivalent:

expect(subject).to eq("foo")
is_expected.to eq("foo")
is("foo")

See also: #is_not


[View source]
macro is_expected #

Short-hand for expecting something of the subject. These two are functionally equivalent:

expect(subject).to eq("foo")
is_expected.to eq("foo")

[View source]
macro is_not(expected) #

Short-hand, negated form of #is_expected that can be used for one-liner syntax. For instance:

it "is not 42" do
  expect(subject).to_not eq(42)
end

Can be shortened to:

it is_not(42)

These three are functionally equivalent:

expect(subject).to_not eq("foo")
is_expected.to_not eq("foo")
is_not("foo")

See also: #is


[View source]
macro it(description = nil, &block) #

[View source]
macro let(name, &block) #

[View source]
macro let!(name, &block) #

[View source]
macro match(expected) #

Indicates that some value should match another. The === (case equality) operator is used for this check. Typically a regular expression is used. This has identical behavior as a "when" condition in a case block.

Examples:

expect("foo").to match(/foo|bar/)
expect("BAR").to match(/foo|bar/i)
expect(1 + 2).to match(3)
expect(5).to match(Int32) # Using `#be_a` instead is recommened here.
expect({:foo, 5}).to match({Symbol, Int32})

[View source]
macro match_array(expected) #

Indicates that some set should contain the same values in any order as another set. This is the same as #contain_exactly, but takes an array as an argument.

Example:

expect([1, 2, 3]).to match_array([3, 2, 1])

[View source]
macro method_missing(call) #

Used to create predicate matchers. Any missing method that starts with 'be_' or 'have_' 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 '?'. For instance:

expect("foobar").to be_ascii_only
# Is equivalent to:
expect("foobar".ascii_only?).to be_true

expect("foobar").to_not have_back_references
# Is equivalent to:
expect("foobar".has_back_references?).to_not be_true

[View source]
macro mock(name, &block) #

[View source]
macro ne(expected) #

Indicates that some value should not equal another. The != operator is used for this check. The value passed to this method is the unexpected value.

Example:

expect(1 + 2).to ne(5)

[View source]
macro null_double(name, **stubs, &block) #

[View source]
macro pending(description = nil, &block) #

[View source]
macro post_condition(&block) #

[View source]
macro pre_condition(&block) #

[View source]
macro raise_error #

Indicates that some block should raise an error.

Examples:

expect { raise "foobar" }.to raise_error

[View source]
macro raise_error(type_or_message) #

Indicates that some block should raise an error with a given message or type. The type_or_message parameter should be an exception type or a string or regex to match the exception's message against.

Examples:

hash = {"foo" => "bar"}
expect { hash["baz"] }.to raise_error(KeyError)
expect { hash["baz"] }.to raise_error(/baz/)
expect { raise "foobar" }.to raise_error("foobar")

[View source]
macro raise_error(type, message) #

Indicates that some block should raise an error with a given message and type. The type is the exception type expected to be raised. The message is a string or regex to match to exception message against.

Examples:

hash = {"foo" => "bar"}
expect { hash["baz"] }.to raise_error(KeyError, /baz/)
expect { raise ArgumentError.new("foobar") }.to raise_error(ArgumentError, "foobar")

[View source]
macro random_sample(collection, count = nil, &block) #

[View source]
macro receive(method_name, _source_file = __FILE__, _source_line = __LINE__, &block) #

[View source]
macro receive_messages(_source_file = __FILE__, _source_line = __LINE__, **stubs) #

[View source]
macro respond_to(*expected) #

Indicates that some value should respond to a method call. One or more method names can be provided.

Examples:

expect("foobar").to respond_to(:downcase)
expect(%i[a b c]).to respond_to(:size, :first)

[View source]
macro sample(collection, count = nil, &block) #

[View source]
macro should(matcher) #

[View source]
macro should_eventually(matcher) #

[View source]
macro should_never(matcher) #

[View source]
macro should_not(matcher) #

[View source]
macro skip(description = nil, &block) #

[View source]
macro specify(description = nil, &block) #

[View source]
macro start_with(expected) #

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 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, so that values, types, regular expressions, and others can be tested.

Examples:

expect("foobar").to start_with("foo")
expect("foobar").to start_with('f')
expect("FOOBAR").to start_with(/foo/i)

expect(%i[a b c]).to start_with(:a)
expect(%i[a b c]).to start_with(Symbol)
expect(%w[foo bar]).to start_with(/foo/)

[View source]
macro subject(&block) #

[View source]
macro subject(name, &block) #

[View source]
macro subject!(&block) #

[View source]
macro subject!(name, &block) #

[View source]
macro verify_double(name, &block) #

[View source]
macro xit(description = nil, &block) #

[View source]