use std::collections::BTreeMap;
pub type TestResult = Result<bool, String>;
pub(crate) struct Test<T> {
name: String,
func: fn(&T) -> TestResult,
config: T,
}
pub struct TestSuite<T> {
tests: Vec<Test<T>>,
}
impl<T> TestSuite<T> {
pub fn new() -> Self {
Self { tests: Vec::new() }
}
pub fn add(&mut self, name: &str, f: fn(&T) -> TestResult, config: T) {
self.tests.push(Test {
name: name.to_string(),
func: f,
config,
});
}
pub fn run(&mut self) -> (bool, BTreeMap<String, TestResult>) {
let total_count = self.tests.len();
let mut passed_count = 0;
let mut test_results = BTreeMap::new();
for test in &self.tests {
println!("\n--- {} ---\n", test.name);
let result = (test.func)(&test.config);
test_results.insert(test.name.clone(), result.clone());
match result {
Ok(_) => {
println!("\nPASSED\n");
passed_count += 1;
}
Err(e) => {
println!("\nFAILED: {e}\n");
}
}
}
println!("-------------------------------------------------------------------------------");
println!("\nPassed {passed_count} from {total_count} tests\n");
let all_passed = passed_count == total_count;
if !all_passed {
println!("Failed tests:");
for (test, result) in test_results.iter() {
if let Err(e) = result {
println!("- {test}: {e}")
}
}
println!();
}
(all_passed, test_results)
}
pub fn run_test(&mut self, name: &str) {
for test in &self.tests {
if test.name == name {
println!("\n--- {} ---\n", test.name);
match (test.func)(&test.config) {
Ok(_) => println!("\nPASSED\n"),
Err(e) => println!("\nFAILED: {e}\n"),
}
}
}
}
}
impl<T> Default for TestSuite<T> {
fn default() -> Self {
TestSuite::new()
}
}