Expand description
Kernal allows you to use fluent assertions in Rust tests. That is, instead of writing
assert_eq!(my_vec.len(), 10)
, you can write assert_that!(my_vec).has_length(10)
, making your
tests more readable and enabling the framework to provide more expressive error messages. Kernal
aims to provide specialized assertions for as many commonly tested properties as possible.
§Writing an assertion
When you write an assertion over a value, you always start withassert_that!(<your value>)
. The
assert_that macro gives you an instance on which you can call associated functions to make
your assertions. To be able to use these assertions, the specialized extension traits must be
imported, such as StringAssertions when using special assertions for
Strings. You can glob-import the prelude module to get all imports you need to write every
assertion supported by Kernal.
use kernal::prelude::*;
assert_that!("hello world").contains("world");
§Chaining
Every assertion returns the same asserter instance to continue writing assertions on the same value. In addition, some extension traits define mapping methods that manipulate the data in some way and return asserter instances on the new data.
use kernal::prelude::*;
assert_that!("almost")
.has_char_length(6)
.ends_with("most")
.to_chars()
.is_sorted_in_strictly_ascending_order();
§Creating custom assertions
kernal
allows the creation of custom assertions to test instances of your types in a more
natural way. To do this, create a new trait which has a method for your assertion. This will be
called on the output of the assert_that macro. In order to enable its usage, you need to
implement your trait on the AssertThat with the type you want to test as a type parameter.
Import the AssertThatData trait to get access to the tested data. It is not provided in the
prelude module in order to avoid presenting these methods every time the user looks for an
assertion. You can use the Failure struct to compose an error message consistent with the
kernal
crate. The example below demonstrates this process.
use kernal::{AssertThat, AssertThatData, Failure};
use kernal::prelude::*;
// Our type for which we want to write assertions.
struct Vector2f32 { x: f32, y: f32 }
// The custom assertion trait we will later implement on `AssertThat`.
trait Vector2f32Assertions {
// The custom assertion we want to supply. It is recommended to take an owned `self` and
// return the same instance to support chaining.
fn has_euclidean_norm(self, expected_norm: f32, epsilon: f32) -> AssertThat<Vector2f32>;
}
impl Vector2f32Assertions for AssertThat<Vector2f32> {
fn has_euclidean_norm(self, expected_norm: f32, epsilon: f32) -> AssertThat<Vector2f32> {
// We get our data with `self.data()`, supplied by `AssertThatData`
let vector = self.data();
let actual_norm = (vector.x * vector.x + vector.y * vector.y).sqrt();
if (actual_norm - expected_norm).abs() > epsilon {
// Here we must fail - using the `Failure` struct
Failure::new(&self)
.expected_it(format!("to have a euclidean norm within <{}> of <{}>",
epsilon, expected_norm))
.but_it(format!("was <({}, {})>, with a euclidean norm of <{}>",
vector.x, vector.y, actual_norm))
.fail()
}
// Here the test passes, so we return `self` for chaining
self
}
}
assert_that!(Vector2f32 { x: 3.0, y: 4.0 }).has_euclidean_norm(5.0, 0.01);
assert_that!(|| assert_that!(Vector2f32 { x: 3.0, y: 3.0 }).has_euclidean_norm(5.0, 0.01))
.panics();
§Notes on performance
Should you write assertions on large amounts of data, the standard assertions may become a bottleneck. For some use cases, there are specialized assertions that use additional trait bounds to improve performance. These are available under the fast_prelude module. See below for an example on how to use it.
use kernal::prelude::*;
use kernal::fast_prelude::*;
assert_that!([1, 2, 3, 4, 5])
.contains_all_of_using_hash([2, 3, 4])
.contains_none_of_using_ord([6, 7, 8]);
If no sufficiently performant assertion is available, you should consider falling back to standard assertions.
Modules§
- abs_
diff - Contains assertions for values whose distance to each other can be measured, to check whether values are close. Such types are grouped by the AbsDiff trait. See AbsDiffPartialOrdAssertions for more details.
- boolean
- Contains assertions for bool values. See the BooleanAssertions trait for more details.
- character
- Contains assertions for char values. See the CharacterAssertions trait for more details.
- collections
- Defines the basic Collection trait to generalize collections such as sets and lists. Additional assertions for collections are provided by CollectionAssertions. Sub-modules provide further specialization.
- error
- Contains assertions for types which implement Error. See the ErrorAssertions trait for more details.
- fast_
prelude - This module re-exports all assertion traits which have specialized implementations of other assertions with additional trait bounds, but better performance. This means that by glob-importing this and prelude, all assertion methods become available.
- lock
- Contains assertions for standard library lock types. These are additionally grouped by the Lock trait used to check whether locks are poisoned in LockAssertions. Furthermore, specialized assertions are provided by the MutexAssertions and RwLockAssertions traits.
- maps
- Defines the basic Map to generalize all types of maps (such as hash maps) and defines wrapper structs to create Collection views of a map. In addition, general map-based assertions are provided by MapAssertions. Sub-modules of this module provide more specialized assertions.
- num
- Defines basic numeric traits implemented on appropriate primitive types. Sub-modules contain assertions for numeric types implementing these traits.
- option
- Contains assertions for Option values. The OptionAssertions works for all Options which implement Debug. OptionPartialEqAssertions provides additional assertions if the value type implements PartialEq.
- panic
- Contains assertions to test potentially panicking functions. See PanicAssertions for more details.
- partial_
eq - Contains assertions for values which implement PartialEq. See PartialEqAssertions for more details.
- partial_
ord - Contains assertions for values which implement PartialOrd. See PartialOrdAssertions for more details.
- path
- Contains assertions for Paths. See PathAssertions for more details.
- pointer
- Contains assertions for pointers, which are grouped by the Pointer trait. See PointerAssertions for more details.
- prelude
- This module re-exports the assert_that macro as well as all assertion traits implemented by some results of that macro, except performance-optimized ones (see fast_prelude). This means that by glob-importing this module all functionally distinguishable assertion methods become available.
- result
- Contains assertions for Result values. The ResultAssertions works for all Results which implement Debug. ResultValuePartialEqAssertions provides additional assertions if the value type implements PartialEq and ResultErrorPartialEqAssertions if the error type implements PartialEq.
- string
- Contains assertions for string values, including among others String and references to str. See StringAssertions for more details.
Macros§
- assert_
that - This macro starts every assertion. It takes an expression and returns an AssertThat instance which allows to perform various assertions on the value generated by the expression. Remember to import prelude in order to get access to all assertions. That import also provides this macro.
- dyn_
assertions - A utility macro for constructing slices of assertion trait objects, that is, boxed functions which take some input and have no output. These are used as input to assertions which distribute items over assertions, such as OrderedCollectionAssertions::satisfies_exactly_in_given_order. It accepts patterns in the form of a list of lambda expressions, ignores the output of each one and wraps it in a box.
Structs§
- Assert
That - This struct holds the evaluated result of an expression for further assertions. It also contains metadata used for generating helpful error messages should an assertion fail.
- Failure
- This type is used to generate error messages of a specific format. It is mostly used internally, but exported to enable users to extend the assertions provided by this crate for custom types.
Traits§
- Assert
That Data - This trait provides access to the tested data of an AssertThat to write custom assertions.