Created
May 3, 2013 02:42
-
-
Save wilkie/5506860 to your computer and use it in GitHub Desktop.
WIP Rust testing framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Compile: rustc my_spec.rs | |
Run: ./my_spec | |
Output: | |
math | |
addition | |
should add numbers together - Pass | |
should add with a negative number - Pass | |
should add two negative numbers - Pass | |
multiplication | |
should multiply numbers together - Pass | |
should multiply with a negative number - Pass | |
should multiply two negative numbers - Pass | |
floating point division | |
should divide roughly well - Pass | |
7 tests 8 assertions 0 failures | |
*/ | |
use tester::*; | |
mod tester; | |
describe!("math", { | |
test!("addition", { | |
should!("add numbers together", { | |
must!(2 + 2 eq 4) | |
}) | |
should!("add with a negative number", { | |
must!(2 + -4 eq -2) | |
}) | |
should!("add two negative numbers", { | |
must!(-2 + -4 eq -6) | |
}) | |
}) | |
test!("multiplication", { | |
should!("multiply numbers together", { | |
must!(2 * 2 eq 4) | |
}) | |
should!("multiply with a negative number", { | |
must!(2 * -4 eq -8) | |
}) | |
should!("multiply two negative numbers", { | |
must!(-2 * -4 eq 8) | |
}) | |
}) | |
test!("floating point division", { | |
should!("divide roughly well", { | |
let x = 2.3; | |
let y = 5.6; | |
must!(y / x near 2.43478) | |
must!(y / x near 2.43478) | |
}) | |
}) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_escape]; | |
pub fn report_failure(expected: ~str, actual: ~str) { | |
io::print(fmt!("\n\x1b[31;1mFail\x1b[39;0m - %s vs %s", actual, expected)); | |
} | |
trait TestInput { | |
fn compare(&self, b: &Self) -> bool; | |
fn compare_near(&self, b: &Self) -> bool; | |
fn fail(&self, b: Self); | |
} | |
macro_rules! impl_test_input( | |
($t:ty) => { | |
impl TestInput for $t { | |
pub fn compare(&self, b: &$t) -> bool { | |
*self == *b | |
} | |
pub fn compare_near(&self, b: &$t) -> bool { | |
*self == *b | |
} | |
pub fn fail(&self, b: $t) { | |
report_failure(self.to_str(), b.to_str()); | |
} | |
} | |
} | |
) | |
macro_rules! impl_test_float( | |
($t:ty) => { | |
impl TestInput for $t { | |
pub fn compare(&self, b: &$t) -> bool { | |
*self == *b | |
} | |
pub fn compare_near(&self, b: &$t) -> bool { | |
(*self > b - 0.00001) && (*self < b + 0.00001) | |
} | |
pub fn fail(&self, b: $t) { | |
report_failure(self.to_str(), b.to_str()); | |
} | |
} | |
} | |
) | |
macro_rules! impl_test_char( | |
($t:ty) => { | |
impl TestInput for $t { | |
pub fn compare(&self, b: &$t) -> bool { | |
*self == *b | |
} | |
pub fn compare_near(&self, b: &$t) -> bool { | |
*self == *b | |
} | |
pub fn fail(&self, b: $t) { | |
report_failure(fmt!("%c", *self), fmt!("%c", b)) | |
} | |
} | |
} | |
) | |
impl_test_input!(~str) | |
impl_test_input!(u8) | |
impl_test_input!(u16) | |
impl_test_input!(u32) | |
impl_test_input!(u64) | |
impl_test_input!(uint) | |
impl_test_input!(i8) | |
impl_test_input!(i16) | |
impl_test_input!(i32) | |
impl_test_input!(i64) | |
impl_test_input!(int) | |
impl_test_input!(bool) | |
impl_test_char!(char) | |
impl_test_float!(float) | |
impl_test_float!(f32) | |
impl_test_float!(f64) | |
pub fn perform_test<T:TestInput>(a:T, b:T, negate: bool) -> bool { | |
if (a.compare(&b) ^ negate) { | |
true | |
} | |
else { | |
a.fail(b); | |
false | |
} | |
} | |
pub fn perform_near<T:TestInput>(a:T, b:T, negate: bool) -> bool { | |
if (a.compare_near(&b) ^ negate) { | |
true | |
} | |
else { | |
a.fail(b); | |
false | |
} | |
} | |
pub fn describe(prompt: &str, function: &fn()) { | |
io::println(prompt); | |
function(); | |
} | |
pub fn test(prompt: &str, function: &fn()) { | |
io::print(" "); | |
io::println(prompt); | |
function(); | |
} | |
pub fn should(prompt: &str, function: &fn()) { | |
io::print(" should "); | |
io::print(prompt); | |
io::print(" - "); | |
function(); | |
} | |
macro_rules! describe( | |
($prompt:expr, $func:expr) => ( | |
fn main() { | |
let module_name = $prompt; | |
let mut _current_test = "<invalid>"; | |
let mut _indent = 0; | |
let mut _tests:uint = 0; | |
let mut _fails:uint = 0; | |
let mut _successes:uint = 0; | |
io::println(module_name); | |
$func; | |
let assertions = _successes + _fails; | |
io::println(fmt!("%u tests %u assertions %u failures", _tests, assertions, _fails)); | |
} | |
) | |
) | |
macro_rules! test( | |
($prompt:expr, $func:expr) => ({ | |
_current_test = $prompt; | |
_indent += 1; | |
for uint::range(0, _indent) |_| { | |
io::print(" "); | |
} | |
io::println(_current_test); | |
$func; | |
_indent -= 1; | |
}) | |
) | |
macro_rules! must( | |
($a:expr eq $b:expr) => ( | |
if (perform_test($a, $b, false)) { _successes += 1; } else { _failure = true; _fails += 1; } | |
); | |
($a:expr near $b:expr) => ( | |
if (perform_near($a, $b, false)) { _successes += 1; } else { _failure = true; _fails += 1; } | |
); | |
) | |
macro_rules! wont( | |
($a:expr eq $b:expr) => ( | |
if (perform_test($a, $b, true)) { _successes += 1; } else { _failure = true; _fails += 1; } | |
); | |
($a:expr near $b:expr) => ( | |
if (perform_near($a, $b, true)) { _successes += 1; } else { _failure = true; _fails += 1; } | |
); | |
) | |
macro_rules! should( | |
($prompt:expr, $func:expr) => ({ | |
let mut _failure = false; | |
_tests += 1; | |
_indent += 1; | |
for uint::range(0, _indent) |_| { | |
io::print(" "); | |
} | |
io::print("should "); | |
io::print($prompt); | |
$func; | |
if (!_failure) { | |
io::print(" - "); | |
io::println("\x1b[32;1mPass\x1b[39;0m"); | |
} | |
else { | |
io::println(""); | |
} | |
_indent -= 1; | |
}) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment