1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! # Fluid
//! 
//! ## Summary
//! 
//! `fluid` is an human readable test library.
//! 
//! The current goals of this crate are:
//! 
//! - Easily readable tests: they should be read like english sentences.
//! - Nice and understandable error messages.
//! - Provide the most possible useful assertions for common cases:
//!   numbers, `Iterator`s, `Option`s, `Result`s, etc.
//! 
//! ## How to use it
//! 
//! Add the crate in your `Cargo.toml`:
//! 
//! ```toml
//! # Do not use in crate build, only in test
//! [dev-dependencies]
//! fluid = "0.2"
//! ```
//! 
//! Reference the crate in your main file:
//! 
//! ```rust
//! #[macro_use] extern crate fluid;
//! ```
//! 
//! Import the crate content in scope of your tests file:
//! 
//! ```rust
//! use fluid::*;
//! ```
//! 
//! ## Examples
//! 
//! ### Simple equality
//! 
//! ```rust
//! # use fluid::*;
//! theory!(1 + 1).should().be_equal_to(2);
//! ```
//! 
//! ### Negation
//! 
//! ```rust
//! # use fluid::*;
//! theory!(1 + 1).should().not().be_equal_to(10);
//! ```
//! 
//! ### Explanation
//! 
//! ```rust
//! # use fluid::*;
//! theory!(1 + 1).should().be_equal_to(2)
//!     .because("this is basic arithmetic");
//! ```
//! 
//! ### Nice error message
//! 
//! ```rust,should_panic
//! # use fluid::*;
//! let the_answer: Result<i32, _> = Err("Oops, error!");
//! 
//! theory!(the_answer).should().not().be_an_error()
//!     .and_should().contain(42)
//!     .because("we need the answer");
//! ```
//! 
//! Displays:
//! 
//! ```none
//! The test failed at src/tests/message.rs:16:
//! 	the_answer is Err("Oops, error!")
//! 	but it should not be an error.
//! 
//! 	the_answer does not contain 42: Err("Oops, error!")
//! 	but it should.
//! This test should pass because we need the answer.
//! ```
//! 
//! ### Floats precision
//! 
//! ```rust
//! # use fluid::*;
//! theory!(1.).should().be_equal_to(1.01).with_precision(0.1);
//! ```
//! 
//! ### `Result::Err`
//! 
//! ```rust
//! # use fluid::*;
//! let parse_error = match "?".parse::<i32>() {
//!     Ok(_) => unreachable!(),
//!     Err(e) => e,
//! };
//! let result = "two".parse::<i32>();
//! theory!(result).should().be_an_error()
//!     .and_should().be_this_error(parse_error);
//! ```
//! 
//! ### `Iterator`s
//! 
//! ```rust
//! # use fluid::*;
//! fn error(e: bool) -> Result<i32, i32> {
//!     match e {
//!         true => Result::Err(0),
//!         false => Result::Ok(0),
//!     }
//! }
//! 
//! theory!(error(false)).should().contain(0);
//! theory!(error(true)).should().not().contain(0);
//! theory!(&[1, 2, 3]).should().not().contain(&0);
//! ```

//TODO: limit the size of displayed data (configurable)

#![deny(missing_docs)]
#![deny(unused)]
#![forbid(unsafe_code)]
#![forbid(missing_debug_implementations)]

extern crate colored;
extern crate num_traits;

#[macro_export]
macro_rules! theory {
    ($e:expr) => {
        LeftElement::new($e, stringify!($e), concat!(file!(), ":", line!()))
    };
}

mod assertions;
mod display;
mod infos;
mod theory;
#[cfg(test)]
mod tests;


mod prelude {
    pub use std::ops::Not;
    pub use theory::{LeftElement, Theory};
}

pub use prelude::*;