Crate smoothy

Crate smoothy 

Source
Expand description

Write smooth assertions in a fluent and human-readable way.

§Quick Start

Start asserting by calling assert_that on a value. Then chain assertions based on the type you are asserting.

assert_that("Hello World")
    .contains("Hello")
    .and() // the "and" is purly cosmetic and can be omitted
    .contains("World");

Smoothy prevents you from writing assertions that make no sense at compile time.

This also means that the autocompletion will only show meaningful assertions when writing tests.

assert_that("Hello World").is_true();

§Available Assertions

  1. Basic value assertions
  2. String-likes
  3. Result
  4. Option
  5. Iterables
  6. Filesystem / Path Assertions
  7. File Handle Assertions
  8. Json
  9. Accessors

§Basic value assertions

There are several assertions available for all types:

§Equality

There are two ways to assert equality:

  • is compares the value with something of the same type.
  • equals compares the value with something that can be converted into the same type. This is done by using the Into trait.

All equality assertions

assert_that(1).equals(1);
assert_that(String::from("Hello")).equals("Hello");
assert_that(1).not_equals(2);
assert_that(String::from("Hello")).not_equals("Hello There");

Same for try_into_equals and try_into_not_equals but here the trait TryInto is used.

assert_that(1u8).try_into_equals(1i8);
assert_that(1u8).try_into_not_equals(2i8);

When one wants to assert a value while assuring the same type without any conversions is used is can be used.

assert_that(1).is(1);
assert_that(1).is_not(2);

§Booleans

There are convenience methods for asserting booleans:

assert_that(true).is_true();
assert_that(false).is_false();

Or one can assert with equality:

assert_that(true).is(true);

§String-likes

String-likes can be asserted by calling contains, starts_with or by calling matches.

All string assertions

assert_that("Hello World")
    .contains("Hello")
    .and()
    .contains("World");
assert_that("Hello World").starts_with("Hello");
assert_that("Hello World").matches(&Regex::new(r"\bHello\b").unwrap());

§Result

Results can be asserted by calling is_err or is_ok. Furthermore, their actual content can be asserted as well.

All result assertions

§Ok

Asserts that the result is Ok:

let result: Result<u8, ()> = Ok(1);
assert_that(result).is_ok();

Asserting the Ok-value:

let result: Result<u8, ()> = Ok(1);
assert_that(result).is_ok().and_value().equals(1);

§Err

Asserts that the result is Err:

let result: Result<(), String> = Err(String::from("Oh no!"));
assert_that(result).is_err();

Asserting the Err-value:

#[derive(Debug, PartialEq)]
struct CustomError(String);

let result: Result<(), CustomError> = Err(CustomError(String::from("Oh no!")));
assert_that(result)
    .is_err()
    .and_error()
    .equals(CustomError(String::from("Oh no!")));

Alternatively one can assert the error message (given the error implements Display):

#[derive(Debug)]
struct CustomError(String);

let result: Result<(), CustomError> = Err(CustomError(String::from("Oh no!")));
assert_that(result)
    .is_err()
    .and_error()
    .to_string()
    .equals("Oh no!");

§Option

Options can be asserted by calling is_none or is_some. Instances of Some can be further asserted with and_value.

All option assertions

§None

let option: Option<()> = None;

assert_that(option).is_none();

§Some

let option: Option<u8> = Some(1);
let asserter: Asserter<u8> = assert_that(option).is_some().and_value();
// further assertions
asserter.equals(1);

§Iterables

Anything that implements IntoIterator can be asserted in content and size.

All iterable assertions

let vec: Vec<u8> = vec![];
assert_that(vec).is_empty();
let vec: Vec<u8> = vec![1, 2, 3];
assert_that(vec).is_not_empty();
let vec: Vec<u8> = vec![1, 2, 3];
assert_that(vec).size().is(3);
assert_that([1, 2, 3]).first().is(1);
assert_that([1, 2, 3]).second().is(2);
assert_that([1, 2, 3]).third().is(3);
assert_that([1, 2, 3]).nth(0).is(1);

§Content assertions

The content of iterables can be asserted in different ways depending on the invariants one wants to assert

  • Ordered The order of expected items must match the order of the actual items.
  • In Sequence The expected items must be in the same order as the actual items without any items in between.
  • Exclusive Only the expected items should exist in the iterable and all the expected items should be present in the iterable.
AssertionOrderedIn SequenceExclusiveNote
contains / contains_allfalsefalsefalse
contains_onlyfalsefalsetrue
-falsetruefalseDoes not make sense
-falsetruetrueDoes not make sense
contains_in_order (WIP)truefalsefalse
-truefalsetrueCould be useful, but is it needed?
contains_in_sequence (WIP)truetruefalse
is / equalstruetruetrue
assert_that([1, 2, 3]).is([1, 2, 3]);
assert_that([1, 2, 3]).contains(1);
assert_that([1, 2, 3]).contains_all([2, 1]);
assert_that([1, 2, 3, 2]).contains_only([3, 1, 2, 2]);

§Predicate-based assertions

Predicate-based assertions can be used to validate the contents of an iterable.

// Assert that all elements match a condition
let numbers = vec![2, 4, 6, 8];
assert_that(numbers).all_match(|x| x % 2 == 0);
let numbers = vec![1, 2, 3];
assert_that(numbers).any_match(|x| x % 2 == 0);
let numbers = vec![1, 3, 5];
assert_that(numbers).none_match(|x| x % 2 == 0);

§Filesystem / Path Assertions

Path assertions work with any type implementing AsRef<Path> such as str, String, &Path, and PathBuf.

All path assertions

§Existence checks

let temp_file = NamedTempFile::new().unwrap();

assert_that(temp_file.path()).exists();
assert_that("/path/that/does/not/exist").not_exists();

§Type checks

Check if a path points to a regular file:

let temp_file = NamedTempFile::new().unwrap();

assert_that(temp_file.path()).is_file();

Check if a path points to a directory:

let temp_dir = TempDir::new().unwrap();

assert_that(temp_dir.path()).is_directory();

Check if a path is a symlink (without following it):

let temp_dir = TempDir::new().unwrap();
let target = temp_dir.path().join("target");
let link = temp_dir.path().join("link");
std::fs::write(&target, "content").unwrap();
symlink(&target, &link).unwrap();

assert_that(&link).is_symlink();

§File Handle Assertions

File handle assertions work with File handles and types that implement Borrow<File>. These assertions check the metadata of the file handle itself.

All file assertions

Check if a file handle points to a regular file:

let file = tempfile().unwrap();

assert_that(file).is_file();

Check if a file handle points to a directory:

let temp_dir = TempDir::new().unwrap();
let dir = File::open(temp_dir.path()).unwrap();

assert_that(dir).is_directory();

§JSON

JSON values as used by serde_json can be asserted about JSON types and values.

use serde_json::json;
let json = json!({"test": 42});

assert_that(json)
    .is_object()
    .and()
    .get("test")
    .is_number()
    .and()
    .equals(42);
use serde_json::json;
let json = json!("test");

assert_that(json).is_string().and().equals("test");

§Accessors

Sometimes one wants to assert only one specific value of a struct. To do so one can use the extract method.

struct Struct(pub String);

assert_that(Struct("hello".to_string()))
    .extract(|s| s.0.clone())
    .equals("hello");

Modules§

prelude
The prelude for smoothy. Contains the most important structs, traits and functions but not all

Structs§

Asserter
Main struct with various assertions on AssertedType
ErrAsserter
Enables various assertions on Err-values
OkAsserter
Enables various assertions on Ok-values
SomeAsserter
Enables various assertions on Some-values

Traits§

BooleanAssertion
Specifies various assertions on values that can be converted to a boolean. Implemented on Asserter
EqualityAssertion
Specifies various equality assertions. Implemented on Asserter
FileAssertion
Specifies various assertions on file handles. Implemented on Asserter
IteratorAssertion
Specifies various assertions on IntoIterator. Implemented on Asserter
JsonObjectAssertionjson
Specifies various assertions on Map<String, Value>. Implemented on Asserter
JsonValueAssertionjson
Specifies various assertions on Value. Implemented on Asserter
OptionAssertion
Specifies various assertions on Option. Implemented on Asserter
PathAssertion
Specifies various assertions on file system paths. Implemented on Asserter
ResultAssertion
Specifies various assertions on Result. Implemented on Asserter
StringAssertion
Specifies various assertions on String. Implemented on Asserter

Functions§

assert_that
Entrypoint for all assertions