مقدمه
همانطور که در درس قبل اشاره شد، ابزار خط فرمان Cargo، اجرای تستها را بسیار ساده میکند.
با اجرای دستور cargo test در ترمینال، Cargo به صورت خودکار پروژه شما را در حالت تست کامپایل
کرده، تمام توابعی را که با اتریبیوت #[test] مشخص شدهاند، به صورت موازی اجرا میکند و یک خلاصه
از نتایج را نمایش میدهد.
$ cargo test
Compiling adder v0.1.0 (...)
Finished test [unoptimized + debuginfo] target(s) in ...s
Running unittests (target/debug/deps/adder-...)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
خروجی بالا نشان میدهد که یک تست اجرا شده و با موفقیت (ok) به پایان رسیده است. حتی اگر
تستهای ما هیچ ماکروی assert! نداشته باشند، Cargo همچنان بررسی میکند که آیا آنها بدون panic
کردن به پایان میرسند یا خیر.
کنترل نحوه اجرای تستها
تسترانر (test runner) پیشفرض Cargo گزینههای خط فرمان مختلفی را برای سفارشیسازی نحوه اجرای
تستها ارائه میدهد. این گزینهها به ما کمک میکنند تا روی تستهای خاصی تمرکز کرده یا خروجیهای
دقیقتری دریافت کنیم.
اجرای موازی در مقابل اجرای ترتیبی
به صورت پیشفرض، Cargo تستها را با استفاده از چند ریسمان (thread) و به صورت موازی اجرا میکند
تا سرعت فرآیند تست افزایش یابد. این رفتار معمولاً مطلوب است، اما اگر تستهای شما به منابع مشترکی
(مانند یک فایل یا یک پورت شبکه) دسترسی دارند یا به ترتیب خاصی وابسته هستند، اجرای موازی میتواند
باعث تداخل شود.
برای مجبور کردن Cargo به اجرای ترتیبی تستها، میتوانید از فلگ --test-threads استفاده کنید:
$ cargo test -- --test-threads=1
تنظیم تعداد ریسمانها به ۱، تضمین میکند که هیچ دو تستی به صورت همزمان اجرا نخواهند شد.
نمایش خروجی توابع
به صورت پیشفرض، اگر یک تست با موفقیت به پایان برسد، هر خروجیای که توسط println! در آن چاپ
شده باشد، نمایش داده نمیشود. این کار برای تمیز نگه داشتن خروجی تستهای موفق
است. برای اینکه خروجی تمام توابع (حتی توابع موفق) را مشاهده کنید، از فلگ --show-output استفاده
کنید.
$ cargo test -- --show-output
فیلتر کردن تستها
در پروژههای بزرگ با صدها تست، ممکن است بخواهید فقط تستهای مربوط به یک بخش خاص از کد را اجرا
کنید. Cargo به شما اجازه میدهد تا تستها را بر اساس نامشان فیلتر کنید.
اجرای یک تست واحد
برای اجرای یک تابع تست خاص، کافیست نام آن را به عنوان آرگومان به cargo test بدهید.
$ cargo test it_adds_two
این دستور تنها تستی را اجرا میکند که نام آن دقیقاً it_adds_two باشد.
فیلتر کردن بر اساس بخشی از نام
شما همچنین میتوانید یک بخشی از نام را ارائه دهید. در این صورت، Cargo تمام تستهایی را که نامشان
حاوی آن بخش باشد، اجرا خواهد کرد. این روش برای اجرای تمام تستهای مربوط به یک ماژول یا یک قابلیت
خاص، بسیار مفید است.
src/lib.rs
pub fn add_two(a: i32) -> i32 { a + 2 }
pub fn greeting(name: &str) -> String { format!("Hello {}!", name) }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_two_test() {
assert_eq!(4, add_two(2));
}
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
assert!(result.contains("Carol"));
}
}
با اجرای دستور cargo test add، تنها تست add_two_test اجرا خواهد شد زیرا نام آن حاوی کلمه
"add" است.
نادیده گرفتن تستهای خاص
گاهی اوقات تستهایی داریم که اجرای آنها بسیار زمانبر است و نمیخواهیم در هر بار اجرای cargo
test اجرا شوند. برای این موارد، میتوانیم از اتریبیوت #[ignore] استفاده کنیم.
src/lib.rs
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
#[test]
#[ignore]
fn expensive_test() {
}
حالا اگر cargo test را اجرا کنید، تست expensive_test نادیده گرفته شده و در خروجی به صورت
ignored گزارش میشود. برای اجرای تنها تستهای نادیده گرفته شده، میتوانید از فلگ --ignored
استفاده کنید:
$ cargo test -- --ignored
در این درس با ابزار خط فرمان cargo test و گزینههای مختلف آن برای کنترل نحوه اجرای تستها،
فیلتر کردن آنها، و مدیریت خروجی آشنا شدیم. این ابزارها به ما کمک میکنند تا فرآیند تست را متناسب
با نیازهای پروژه خود سفارشی کنیم. اما چگونه باید تستهای خود را در یک پروژه بزرگ سازماندهی کنیم؟
در درس بعدی، به بررسی انواع مختلف تست (unit و integration) و نحوه «سازماندهی تستها» در ساختار
پروژه خواهیم پرداخت.