use async_std::task;
use std::error::Error;
use test_casing::{cases, test_casing, Product, TestCases};
const CASES: TestCases<i32> = cases!([2, 3, 5, 8]);
#[test_casing(4, CASES)]
#[test]
fn numbers_are_small(number: i32) {
assert!((0..10).contains(&number));
}
#[test]
fn another_number_is_small() {
numbers_are_small(1);
}
#[allow(unused_variables)] #[test_casing(4, CASES)]
#[ignore = "testing that `#[ignore]` attr works"]
fn numbers_are_large(number: i32) {
unimplemented!("implement later");
}
#[test_casing(4, CASES)]
fn numbers_are_small_with_errors(number: i32) -> Result<(), Box<dyn Error>> {
if number < 10 {
Ok(())
} else {
Err("number is too large".into())
}
}
const MULTI_ARG_CASES: TestCases<(i32, &str)> = cases!([(2, "2"), (3, "3"), (5, "5")]);
#[test_casing(3, MULTI_ARG_CASES)]
#[test]
fn number_can_be_converted_to_string(number: i32, expected: &str) {
assert_eq!(number.to_string(), expected);
}
#[test_casing(3, MULTI_ARG_CASES)]
fn number_can_be_converted_to_string_with_tuple_input((number, expected): (i32, &str)) {
assert_eq!(number.to_string(), expected);
}
#[test_casing(12, Product((CASES, ["first", "second", "third"])))]
fn cartesian_product(number: i32, s: &str) {
assert_ne!(number.to_string(), s);
}
#[test_casing(5, cases!{(0..5).map(|i| (i.to_string(), i))})]
fn string_conversion(#[map(ref = String::as_str)] s: &str, expected: i32) {
let actual: i32 = s.parse().unwrap();
assert_eq!(actual, expected);
}
#[test_casing(3, ["not a number", "-", ""])]
#[should_panic(expected = "ParseIntError")]
fn string_conversion_fail(bogus_str: &str) {
string_conversion(bogus_str, 42);
}
const STRING_CASES: TestCases<(String, i32)> = cases!((0..5).map(|i| (i.to_string(), i)));
#[test_casing(5, STRING_CASES)]
#[async_std::test]
async fn async_string_conversion_without_output(#[map(ref)] s: &str, expected: i32) {
let actual: i32 = s.parse().unwrap();
assert_eq!(actual, expected);
let expected_string = task::spawn_blocking(move || expected.to_string()).await;
assert_eq!(expected_string, s);
}
#[test_casing(5, STRING_CASES)]
#[async_std::test]
async fn async_string_conversion(#[map(ref)] s: &str, expected: i32) -> Result<(), Box<dyn Error>> {
let actual: i32 = s.parse()?;
assert_eq!(actual, expected);
let expected_string = task::spawn_blocking(move || expected.to_string()).await;
assert_eq!(expected_string, s);
Ok(())
}
#[test]
fn unit_test_detection_works() {
assert!(option_env!("CARGO_TARGET_TMPDIR").is_some());
}
mod random {
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::iter;
use test_casing::{cases, test_casing, TestCases};
const RANDOM_NUMBERS: TestCases<u32> = cases!({
let mut rng = StdRng::seed_from_u64(123_456);
iter::repeat_with(move || rng.gen())
});
#[test_casing(10, RANDOM_NUMBERS)]
fn randomized_tests(value: u32) {
assert!(value.to_string().len() <= 10);
}
}