spectral
Fluent test assertions for Rust.
Influenced by Google Truth and other fluent assertion frameworks.
Usage
Add this to your Cargo.toml
:
[]
= "0.3.0"
Then add this to your crate:
extern crate spectral
To quickly start using assertions, simply use the prelude
module in your test module:
use *;
Overview
Spectral allows you to write your assertions in a fluent manner by seperating out what you are testing with, what you are testing against and how you are asserting.
Simple asserts
For example, to test that a produced value is equal to an expected value, you would write:
assert_that.is_equal_to;
Or that a Vec contains a certain number of elements:
let test_vec = vec!;
assert_that.has_length;
The methods avaliable for asserting depend upon the type under test and what traits are implemented.
Failure messages
For failing assertions, the usual panic message follows the following format:
expected <something> but was <something else>
To add additional clarification to the panic message, you can also deliberately state what you are asserting by calling the asserting(...)
function rather than assert_that(...)
:
asserting.that.is_equal_to;
Which will produce:
test condition: expected <2> but was <1>
Mapping values
If you want to assert against a value contained within a struct, you can call map(...)
with a closure, which will create a new Spec
based upon the return value of the closure. You can then call any applicable assertions against the mapped value.
let test_struct = TestStruct ;
assert_that.map.is_equal_to;
Macros
If you add #[macro_use]
to the extern crate
declaration, you can also use the macro form of assert_that
.
assert_that!.has_length
This allows you to pass through a subject to test without needing to deliberately turn it into a reference. However, for consistency, you can also use a deliberate reference in the macro as well.
assert_that!.has_length
Assertions
As a general note, any type under test will usually need to implement at least Debug
. Other assertions will have varying bounds attached to them.
General
is_equal_to
matches
Numbers
is_less_than
is_less_than_or_equal_to
is_greater_than
is_greater_than_or_equal_to
Options
is_some
is_none
contains_value
Paths
exists
is_file
is_directory
has_file_name
Results
is_ok
is_error
is_ok_containing
is_err_containing
Strings
starts_with
ends_with
contains
Vectors
has_length
IntoIterator/Iterator
contains
mapped_contains
equals_iterator
IntoIterator
matching_contains
How it works
The Spec
struct implements a number of different bounded traits which provide assertions based upon the bound type.
As a single example, length assertions are provided by the VecSpec
trait:
Which is then implemented by Spec:
Naturally traits need to be included with a use
before they apply, but to avoid an excessive number of use
statements there is a prelude
module which re-exports commonly used assertion traits.
Creating your own
To create your own assertions, simply create a new trait containing your assertion methods and implement Spec against it.
The Spec
struct always implements with_expected(...)
, with_actual(...)
and fail(...)
, which provides the necessary functionality to fail the test with the usual message format. If you need greater control of the failure message, you can call fail_with_message(...)
which will directly print the provided message.
In either case, any description provided using asserting(...)
will always be prepended to the panic message.
For example, to create an assertion that the length of a Vec
is at least a certain value:
Notes
This is still very much a work in progress. There are still many assertions missing on basic types, and the ones that are there may still change or be updated as required.