اختبارات في Rust: الوحدة، التكامل، E2E من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا يُعد الاختبار في Rust أساس الكود الموثوق



لغة Rust هي لغة برمجة أنظمة تُعرف بسلامة الذاكرة والأداء العالي. ومع ذلك، حتى أكثر المترجمات (compilers) صرامة لا تضمن أن برنامجك يفعل بالضبط ما هو مطلوب. هنا يأتي دور الاختبار. في Rust، دعم الاختبار المدمج هو من بين الأفضل في اللغات الحديثة. يمكنك كتابة اختبارات الوحدة (unit tests) واختبارات التكامل (integration tests) واختبارات شاملة (e2e tests) بدون الحاجة إلى مكتبات خارجية.



في هذه المقالة، سنقوم بتفصيل جميع المستويات الثلاثة للاختبار مع أمثلة عملية. ستتعلم كيفية كتابة الاختبارات، وكيفية تشغيلها باستخدام cargo test، وكيفية تنظيم البنية التحتية للاختبار في المشاريع الكبيرة.



1. اختبارات الوحدة (Unit Tests) في Rust: اختبار الدوال والوحدات



تتحقق اختبارات الوحدة من عمل الدوال أو الطرق الفردية بشكل منعزل. في Rust، من الشائع وضع اختبارات الوحدة مباشرة في ملف الكود المصدري، داخل وحدة tests مع الخاصية #[cfg(test)]. هذا يسمح للاختبارات بالوصول إلى الدوال الخاصة (private functions) للوحدة.



1.1. أول اختبار وحدة لك



لنقم بإنشاء مكتبة حسابية بسيطة وكتابة اختبارات لها.



// src/lib.rspub fn add(a: i32, b: i32) -> i32 {    a + b}

pub fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("Division by zero")) } else { Ok(a / b) }}

#[cfg(test)]mod tests { use super::*;

#[test] fn test_add() { assert_eq!(add(2, 3), 5); }

#[test] fn test_divide_success() { let result = divide(10.0, 2.0).unwrap(); assert_eq!(result, 5.0); }

#[test] fn test_divide_by_zero() { let result = divide(10.0, 0.0); assert!(result.is_err()); assert_eq!(result.unwrap_err(), "Division by zero"); }}


قم بتشغيل الاختبارات باستخدام الأمر cargo test. ستظهر علامات اختيار خضراء إذا نجحت جميع الاختبارات.



1.2. خصائص (Attributes) الاختبارات



  • #[test] — تشير إلى أن الدالة هي اختبار.
  • #[should_panic] — يُعتبر الاختبار ناجحًا إذا تسببت الدالة في حالة ذعر (panic).
  • #[ignore] — تعطيل الاختبار مؤقتًا.


#[test]#[should_panic(expected = "panic message")]fn test_panic() {    panic!("panic message");}

#[test]#[ignore = "Test disabled until bug #42 is fixed"]fn test_expensive() { // Long-running test}


2. اختبارات التكامل (Integration Tests): التحقق من تفاعل المكونات



تتحقق اختبارات التكامل من عمل عدة وحدات أو تبعيات خارجية معًا. في Rust، يتم وضعها في مجلد منفصل tests/ على مستوى جذر المشروع. كل ملف في هذا المجلد هو crate اختبار منفصل يرى فقط الواجهة العامة (public API) لمكتبتك.



2.1. هيكل اختبارات التكامل



قم بإنشاء مجلد tests/ وملف tests/integration_test.rs:



// tests/integration_test.rsuse my_crate::add; // Your crate's name

#[test]fn test_add_integration() { // Check that the function works as part of the library let result = add(10, 20); assert_eq!(result, 30);}

#[test]fn test_divide_integration() { // Test with multiple calls let a = 100.0; let b = 4.0; let result = my_crate::divide(a, b).unwrap(); assert!(result > 0.0); assert_eq!(result, 25.0);}


2.2. الوحدات المشتركة لاختبارات التكامل



إذا كنت بحاجة إلى إعادة استخدام الكود بين اختبارات التكامل، قم بإنشاء ملف tests/common/mod.rs. لن يتم التعامل مع هذا الملف كملف اختبار، لكن ستتمكن من استيراده من الاختبارات الأخرى.



// tests/common/mod.rspub fn setu                

المدونات

توصيات الكتب