تست یکپارچگی در Rust بدون دردسر
خلاصهٔ کاملتر
نویسندهٔ این مقاله میگه وقتی اولین بار سراغ تست تو Rust رفت، از نبود یه امکان پایه جا خورد: setup و teardown سراسری — چیزی که jest و fixtureهای pytest دارن. تو تستهای یکپارچگی این قضیه مهمتر هم هست، چون کد باید روبهروی زیرساخت واقعی اجرا بشه و دیتابیس و بروکر پیام ماک نمیشن. Rust هم چنین چیزی نداره و هم تستها رو پیشفرض موازی و روی تردهای جدا اجرا میکنه، پس ساختن state سراسری کار راحتی نیست.
به گفتهٔ نویسنده، جواب Rust به این نیاز از خود setup/teardown بهتره: الگوی RAII. کافیه کانتینر داکر رو یه منبع در نظر بگیری و با پیادهسازی تِرِیت Drop پاکسازیش رو خودکار کنی. اونوقت هر تست محیط کاملاً ایزولهٔ خودشو بالا میاره و آخر کار خودش جمعش میکنه، بدون هیچ teardown سراسری:
#[tokio::test]
async fn test_with_rabbitmq() -> anyhow::Result<()> {
let _rabbitmq = RabbitMqContainer::start().await?;
let rabbitmq_channel = get_rabbitmq_channel("amqp://localhost:5672").await?;
// No need to cleanup manually
Ok(())
}دو تا هشدار هم سر راهه. اول اینکه توقف کانتینر یه عملیات async هست، ولی async drop هنوز فقط nightly و در حال توسعهست؛ راهحل عملی همون هکیه که testcontainers-rs به کار میبره — پاکسازی تو یه ترد دیگه اجرا میشه و drop تا تمومشدنش بلاک میمونه. ایدهآل نیست، ولی برای تست کافیه. دوم اینکه drop همیشه صدا زده نمیشه: با SIGINT، SIGTERM، SIGKILL یا OOM کانتینر جا میمونه و Watchdog همون کرِیت بخشی از این مشکل رو پوشش میده.
خود testcontainers-rs همین ایده رو بستهبندی کرده: با تِرِیت Image مشخصات کانتینر مثل نام و تگ رو تعریف میکنی و با متد ready_conditions میگی آمادهبودن سرویس از روی چه نشانهای معلوم میشه — مثلاً ظاهرشدن پیام Server startup complete تو خروجی RabbitMQ. نویسنده میگه جاافتادن همین متد بود که تو مثالش خطای connection reset by peer داد. کرِیت جانبی testcontainers-modules هم ایمیج آمادهٔ RabbitMQ، Postgres و Redis داره، پس معمولاً لازم نیست خودت Image بنویسی.
نکات کلیدی:
- Rust ساز و کار setup/teardown سراسری برای تست نداره و تستها پیشفرض موازی اجرا میشن
- الگوی RAII و تِرِیت Drop جای teardown رو میگیرن و کانتینر داکر رو خودکار پاک میکنن
- کرِیت testcontainers-rs این کارو ساده میکنه و ready_conditions برای صبر تا بالا اومدن سرویس حیاتیه
- drop موقع SIGKILL یا OOM اجرا نمیشه؛ Watchdog تا حدی جبرانش میکنه
- testcontainers-modules ایمیج آمادهٔ Postgres، Redis و RabbitMQ داره




