module Spectator::DSL
Overview
Namespace containing methods representing the spec domain specific language.
Direct including types
Defined in:
spectator/dsl.crspectator/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
- #allow(thing)
- #allow_any_instance_of(type : T.class) forall T
- #anonymous_double(name = "Anonymous", **stubs)
- #anonymous_null_double(name = "Anonymous", **stubs)
-
#fail(reason : String)
Immediately fail the current test.
-
#fail
Immediately fail the current test.
Macro Summary
- after_all(&block)
- after_each(&block)
-
all(matcher)
Verifies that all elements of a collection satisfy some matcher.
- around_each(&block)
-
be
Indicates that some value when compared to another satisfies an operator.
-
be(expected)
Indicates that some object should be the same as another.
-
be_a(expected)
Indicates that some value should be of a specified type.
-
be_a_kind_of(expected)
Indicates that some value should be of a specified type.
-
be_an(expected)
Indicates that some value should be of a specified type.
-
be_an_instance_of(expected)
Indicates that some value should be of a specified type.
-
be_between(min, max)
Indicates that some value should be between a lower and upper-bound.
-
be_close(expected, delta)
Indicates that some value should be within a delta of an expected value.
-
be_empty
Indicates that some collection should be empty.
-
be_false
Indicates that some value should be false.
-
be_falsey
Indicates that some value should be falsey.
-
be_ge(expected)
Indicates that some value should be greater than or equal to another.
-
be_gt(expected)
Indicates that some value should be greater than another.
-
be_instance_of(expected)
Indicates that some value should be of a specified type.
-
be_kind_of(expected)
Indicates that some value should be of a specified type.
-
be_le(expected)
Indicates that some value should be less than or equal to another.
-
be_lt(expected)
Indicates that some value should be less than another.
-
be_nil
Indicates that some value should or should not be nil.
-
be_true
Indicates that some value should be true.
-
be_truthy
Indicates that some value should be truthy.
-
be_within(expected)
Indicates that some value should be contained within another.
- before_all(&block)
- before_each(&block)
-
change(&expression)
Indicates that some expression's value should change after taking an action.
-
contain(*expected)
Indicates that some value or set should contain another value.
-
contain_elements(expected)
Indicates that some value or set should contain specific items.
-
contain_exactly(*expected)
Indicates that some set should contain some values in any order.
- context(what, &block)
-
cover(*expected)
Indicates that some range (or collection) should contain another value.
- create_double(type_name, name, **stubs)
- create_null_double(type_name, name, **stubs)
- define_double(type_name, name, **stubs, &block)
- define_null_double(type_name, name, **stubs, &block)
- describe(what, &block)
- double(name = "Anonymous", **stubs, &block)
-
end_with(expected)
Indicates that some value or set should end with another value.
-
eq(expected)
Indicates that some value should equal another.
-
expect(actual, _source_file = __FILE__, _source_line = __LINE__)
Starts an expectation.
-
expect(&block)
Starts an expectation on a block of code.
- expect_any_instance_of(type, _source_file = __FILE__, _source_line = __LINE__)
-
expect_raises
Indicates that some block should raise an error.
-
expect_raises(type, &block)
Indicates that some block should raise an error with a given type.
-
expect_raises(type, message, &block)
Indicates that some block should raise an error with a given message and type.
-
expects(actual)
Starts an expectation.
-
expects(&block)
Starts an expectation on a block of code.
- given(*assignments, &block)
-
has_key(expected)
Indicates that some set, such as a
Hash
, has a given key. -
has_value(expected)
Indicates that some set, such as a
Hash
, has a given value. -
have(*expected)
Indicates that some value or set should contain another value.
-
have_attributes(**expected)
Indicates that some value should have a set of attributes matching some conditions.
-
have_elements(expected)
Indicates that some value or set should contain specific items.
-
have_key(expected)
Indicates that some set, such as a
Hash
, has a given key. - have_received(method)
-
have_size(expected)
Indicates that some set should have a specified size.
-
have_size_of(expected)
Indicates that some set should have the same size (number of elements) as another set.
-
have_value(expected)
Indicates that some set, such as a
Hash
, has a given value. -
is(expected)
Short-hand form of
#is_expected
that can be used for one-liner syntax. -
is_expected
Short-hand for expecting something of the subject.
-
is_not(expected)
Short-hand, negated form of
#is_expected
that can be used for one-liner syntax. - it(description = nil, &block)
- let(name, &block)
- let!(name, &block)
-
match(expected)
Indicates that some value should match another.
-
match_array(expected)
Indicates that some set should contain the same values in any order as another set.
-
method_missing(call)
Used to create predicate matchers.
- mock(name, &block)
-
ne(expected)
Indicates that some value should not equal another.
- null_double(name, **stubs, &block)
- pending(description = nil, &block)
- post_condition(&block)
- pre_condition(&block)
-
raise_error
Indicates that some block should raise an error.
-
raise_error(type_or_message)
Indicates that some block should raise an error with a given message or type.
-
raise_error(type, message)
Indicates that some block should raise an error with a given message and type.
- random_sample(collection, count = nil, &block)
- receive(method_name, _source_file = __FILE__, _source_line = __LINE__, &block)
- receive_messages(_source_file = __FILE__, _source_line = __LINE__, **stubs)
-
respond_to(*expected)
Indicates that some value should respond to a method call.
- sample(collection, count = nil, &block)
- should(matcher)
- should_eventually(matcher)
- should_never(matcher)
- should_not(matcher)
- skip(description = nil, &block)
- specify(description = nil, &block)
-
start_with(expected)
Indicates that some value or set should start with another value.
- subject(&block)
- subject(name, &block)
- subject!(&block)
- subject!(name, &block)
- verify_double(name, &block)
- xit(description = nil, &block)
Instance Method Detail
Immediately fail the current test. A reason can be passed, which is reported in the output.
Immediately fail the current test. A reason can be passed, which is reported in the output.
Macro Detail
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.
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
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)
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)
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)
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)
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)
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)
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)
Indicates that some value should be false.
Examples:
expect("foo".nil?).to be_false
expect(%i[a b c].empty?).to be_false
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
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)
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)
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)
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)
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)
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)
Indicates that some value should or should not be nil.
Examples:
expect(error).to be_nil
expect(input).to_not be_nil
Indicates that some value should be true.
Examples:
expect(nil.nil?).to be_true
expect(%i[a b c].any?).to be_true
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
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.
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)
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)
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])
Indicates that some set should contain some values in any order.
Example:
expect([1, 2, 3]).to contain_exactly(3, 2, 1)
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)
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/)
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)
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.
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.
Indicates that some block should raise an error.
Examples:
expect_raises { raise "foobar" }
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)
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") }
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.
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.
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")
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)
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)
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)
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])
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")
Indicates that some set should have a specified size.
Example:
expect([1, 2, 3]).to have_size(3)
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])
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)
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
Short-hand for expecting something of the subject. These two are functionally equivalent:
expect(subject).to eq("foo")
is_expected.to eq("foo")
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
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})
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])
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
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)
Indicates that some block should raise an error.
Examples:
expect { raise "foobar" }.to raise_error
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")
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")
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)
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/)