لماذا اختبار E2E في Rust ليس ترفًا بل ضرورة
\n\nهل سبق لك أن شغّلت تطبيق Rust في الإنتاج وبعد ساعة تلقيت شكاوى من المستخدمين؟ "كل شيء يعمل بشكل مثالي على جهازي!" - عبارة مألوفة؟ المشكلة أن اختبارات الوحدة تختبر فقط أجزاء معزولة من الكود، واختبارات التكامل تختبر تفاعل المكونات. لكن الجحيم الحقيقي يبدأ عندما يفشل خط الأنابيب بأكمله، من طلب HTTP إلى قاعدة البيانات، بسبب ترابط غير واضح.
\n\nاختبار E2E لتطبيقات Rust (من البداية إلى النهاية) هو الطريقة الوحيدة لضمان أن API الخاص بك، أو أداة CLI، أو خدمة الويب تعمل كوحدة واحدة متكاملة. في هذه المقالة، لن نتحدث فقط عن النظرية، بل سنكتب اختبارات حقيقية يمكن دمجها فورًا في CI/CD. لا ماء - فقط Rust ومنهجية جاهزة للإنتاج.
\n\nما هو اختبار E2E في سياق Rust؟
\n\nعلى عكس اختبارات الوحدة (التي تختبر الدوال) واختبارات التكامل (التي تختبر الوحدات)، فإن اختبارات end-to-end في Rust تتحقق من دورة العمل الكاملة للتطبيق: من المدخل إلى المخرج. بالنسبة لخدمة الويب، يبدو الأمر كالتالي:
\n\n- \n
- تشغيل خادم حقيقي (أو صورته في Docker). \n
- إرسال طلب HTTP عبر عميل (مثل
reqwest). \n - التحقق من الاستجابة: الحالة، النص، الرؤوس. \n
- التحقق من حالة قاعدة البيانات (إن وجدت). \n
بالنسبة لتطبيقات CLI - هو تشغيل الملف الثنائي مع الوسائط والتحقق من stdout/stderr. بالنسبة لتطبيقات سطح المكتب - محاكاة إجراءات المستخدم عبر WebDriver (Selenium).
\n\nمتى تكون اختبارات E2E إلزامية؟
\n- \n
- عند تطوير API عام. \n
- عند وجود بنية خدمات مصغرة. \n
- عند عمل التطبيق مع خدمات خارجية (قواعد بيانات، قوائم انتظار، S3). \n
- عند الرغبة في تجنب الانحدارات مع كل commit. \n
الأدوات اللازمة لاختبار E2E في Rust
\n\nالنظام البيئي لـ Rust غني، لكن لاختبار E2E نحتاج فقط إلى عدد قليل من المكتبات الرئيسية:
\n\n| المكتبة | الغرض |
|---|---|
reqwest | عميل HTTP لإرسال الطلبات إلى الخادم قيد الاختبار. |
tokio | بيئة تشغيل غير متزامنة - أساس تشغيل الاختبارات والخادم. |
wiremock | خادم mock لمحاكاة واجهات API الخارجية. |
assert_cmd + predicates | لاختبار تطبيقات CLI. |
fantoccini | عميل WebDriver (إذا كنت بحاجة لاختبار المتصفح). |
سنستخدم إطار اختبار Rust المدمج (وحدة test)، لكننا سنضيف عدم التزامن عبر tokio::test.
تطبيق عملي: كتابة اختبارات E2E لخدمة ويب على Actix-Web
\n\nلنفترض أن لدينا تطبيق ويب بسيط بلغة Rust على Actix-Web مع نقطة نهاية /api/users، والتي تعيد قائمة المستخدمين من PostgreSQL. نريد التأكد من أن كل شيء يعمل عند التشغيل الفعلي.
الخطوة 1: إعداد بيئة الاختبار
\n\nلننشئ ملفًا منفصلاً tests/e2e.rs (يتعامل Rust تلقائيًا مع الملفات في مجلد tests/ كاختبارات تكامل).
// tests/e2e.rs\nuse std::process::{Command, Stdio};\nuse std::time::Duration;\nuse tokio::time::sleep;\n\n// دالة مساعدة: تشغيل الخادم في الخلفية\nasync fn start_server() -> std::process::Child {\n let child = Command::new("cargo")\n .args(&["run", "--bin", "my_app"])\n .stdout(Stdio::null())\n .stderr(Stdio::null())\n .spawn()\n .expect("فشل في بدء تشغيل الخادم");\n\n // إعطاء الخادم وقتًا للتشغيل\n sleep(Duration::from_secs(5)).await;\n child\n}\n\nهام: في المشروع الحقيقي، استخدم Docker أو تكوين قاعدة بيانات منفصل للاختبارات، لتجنب تلويث بيئة الإنتاج.
\n\n