bouzuya/rust-examples 。 test で beforeEach / afterEach が欲しいと言われたので catch_unwind を調べた。
std::panic::catch_unwind
で一部の panic は catch できる。
fn test3_setup() { println!("test3 setup") } fn test3_teardown() { println!("test3 teardown"); } fn run_test3<F, R>(f: F) where F: FnOnce() -> R + std::panic::UnwindSafe, { test3_setup(); let result = std::panic::catch_unwind(f); test3_teardown(); assert!(result.is_ok()); } #[test] #[should_panic] fn test3() { run_test3(|| { assert_eq!(2 + 2, 5); }); }
あとは crates:futures の futures:FutureExt::catch_unwind
で async のときも。
async fn test6_setup() { println!("test6 setup") } async fn test6_teardown() { println!("test6 teardown"); } async fn run_test6<R>( f: impl std::future::Future<Output = R> + Sized + std::panic::UnwindSafe, ) { test6_setup().await; let result = futures::FutureExt::catch_unwind(f).await; test6_teardown().await; assert!(result.is_ok()); } #[tokio::test] #[should_panic] async fn test6() { run_test6(async { assert_eq!(2 + 2, 5); }) .await }
普段使っている crates:anyhow と組み合わせて……。
async fn test8_setup() -> anyhow::Result<()> { println!("test8 setup"); Ok(()) } async fn test8_teardown() -> anyhow::Result<()> { println!("test8 teardown"); Ok(()) } async fn run_test8<F, FutS, FutT, S, T>(f: F, setup: S, teardown: T) -> anyhow::Result<()> where F: std::future::Future<Output = anyhow::Result<()>> + Sized + std::panic::UnwindSafe, FutS: std::future::Future<Output = anyhow::Result<()>>, FutT: std::future::Future<Output = anyhow::Result<()>>, S: Fn() -> FutS, T: Fn() -> FutT, { setup().await?; let result = futures::FutureExt::catch_unwind(f).await; teardown().await?; result.unwrap() } #[tokio::test] async fn test8() -> anyhow::Result<()> { run_test8( async { assert_eq!(2 + 2, 4); Ok(()) }, test8_setup, test8_teardown, ) .await }
今日のコミット。
- rust-atcoder 1 commit
- rust-examples 1 commit