spectral 0.2.0

Fluent test assertions
Documentation
# spectral
Fluent test assertions for Rust.

Influenced by Google Truth and other fluent assertion frameworks.

## Usage

Add this to your `Cargo.toml`:

```toml
[dependencies]
spectral = "0.1.0"
```

Then add this to your crate:
```rust
extern crate spectral
```

To quickly start using assertions, simply use the `prelude` module in your test module:
```rust
use spectral::prelude::*;
```

## 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:
```rust
assert_that(&1).is_equal_to(&1);
```

Or that a Vec contains a certain number of elements:
```rust
let test_vec = vec![1,2,3];
assert_that(&test_vec).has_length(3);
```

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(...)`:
```rust
asserting(&"test condition").that(&1).is_equal_to(&2);
```

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.
```rust
let test_struct = TestStruct { value: 5 };
assert_that(&test_struct).map(|val| &val.value).is_equal_to(&5);
```

## Macros

If you add `#[macro_use]` to the `extern crate` declaration, you can also use the macro form of `assert_that`.

```rust
assert_that!(test_vec).has_length(5)
```

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.

```rust
assert_that!(&test_vec).has_length(5)
```

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

### Results
#### is_ok
#### is_error

### Strings
#### starts_with
#### ends_with
#### contains

### Vectors
#### has_length
#### mapped_contains

### IntoIterator
#### contains
#### 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:
```rust
pub trait VecSpec {            
    fn has_length(self, expected: usize);
} 
```

Which is then implemented by Spec:
```rust
impl<'s, T> VecSpec for Spec<'s, Vec<T>> {
    fn has_length(self, expected: usize) {
      ...
    }
} 
```

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:
```rust
trait VecAtLeastLength {
    fn has_at_least_length(self, expected: usize);
}

impl<'s, T> VecAtLeastLength for Spec<'s, Vec<T>> {
    fn has_at_least_length(self, expected: usize) {
        let subject = self.subject;
        if expected > subject.len() {
            self.with_expected(format!("vec with length at least <{}>", expected))
                .with_actual(format!("<{}>", subject.len()))
                .fail();
        }
    }
}
```

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