BDD على Rust: كتابة كود حي مع Cucumber و Specs

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

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

ابدأ الدورة

لماذا BDD على Rust ليس عن اختبارات مملة

\n\n

تخيل: أنت تكتب على Rust خدمة عالية التحميل. الكود آمن، سريع، ولكن عندما يصل المنتج إلى العميل، يقول: "لكنني اعتقدت أن الزر يجب أن يعمل بشكل مختلف". مألوف؟ الفجوة الكلاسيكية بين الكود والتوقعات. هنا يأتي دور BDD (التطوير القائم على السلوك) — منهجية تترجم متطلبات العمل إلى لغة يفهمها المدير ومترجم Rust على حد سواء.

\n\n

في هذه المقالة، سنشرح كيفية تطبيق BDD على Rust عمليًا. ستتعلم كيفية كتابة السيناريوهات بلغة بشرية (Gherkin)، وأتمتتها باستخدام cucumber و specs، ولماذا يجعل هذا كودك ليس فقط موثوقًا، بل شفافًا للفريق بأكمله. لا ماء زائد — فقط كود حي وأمثلة حقيقية.

\n\n

ما هو BDD ولماذا Rust مثالي له

\n\n

التطوير القائم على السلوك هو تطور لـ TDD. إذا كان TDD يركز على "كيف نختبر الكود"، فإن BDD يجيب على السؤال "أي سلوك نريد رؤيته". تكتب سيناريوهات بلغة Gherkin (Given-When-Then)، والتي تكون في نفس الوقت اختبارات ووثائق.

\n\n

Rust — لغة تعشق الصرامة والقابلية للتنبؤ. BDD في Rust يمنح:

\n
    \n
  • كودًا موثقًا ذاتيًا — أي مطور يقرأ السيناريو ويفهم منطق العمل.
  • \n
  • أمانًا على مستوى الأنواع — المترجم يتحقق من أن خطواتك تتوافق مع الهيكل.
  • \n
  • تشغيلًا متوازيًا — اختبارات BDD في Rust تعمل بسرعة بفضل async وتعدد الخيوط.
  • \n
\n\n

متى يكون BDD على Rust مفيدًا بشكل خاص؟

\n
    \n
  • خدمات API بعقود واضحة (REST, GraphQL).
  • \n
  • أنظمة ذات قواعد عمل (المالية، اللوجستيات، الألعاب).
  • \n
  • الخدمات المصغرة حيث التكامل بين المكونات مهم.
  • \n
\n\n

أدوات BDD في Rust: Cucumber و Specs

\n\n

النظام البيئي لـ Rust يقدم نهجين رئيسيين:

\n\n

1. cucumber — إطار BDD الكلاسيكي

\n

يسمح بكتابة السيناريوهات بـ Gherkin (ملفات .feature) وربطها بكود Rust. يدعم async، والماكروات المخصصة، والتقارير.

\n\n

2. specs — بديل خفيف وسريع

\n

لا يتطلب ملفات Gherkin — تُكتب السيناريوهات مباشرة في Rust باستخدام الماكروات. مثالي إذا كنت لا تريد إضافة محلل منفصل.

\n\n

سنركز على cucumber، لأنه يمنح أقصى مرونة ويتوافق مع معيار BDD.

\n\n

كتابة أول سيناريو BDD على Rust

\n\n

لنقم بإنشاء آلة حاسبة خصم بسيطة. قاعدة العمل: إذا كان مبلغ الشراء أكبر من 1000 روبل، الخصم 10%. وإلا — 0%.

\n\n

الخطوة 1. تثبيت التبعيات

\n

أضف إلى Cargo.toml:

\n
[dev-dependencies]\ncucumber = "0.20"\ntokio = { version = "1", features = ["full"] }\nasync-trait = "0.1"\n
\n\n

الخطوة 2. إنشاء ملف feature

\n

ملف tests/features/discount.feature:

\n
Feature: حساب الخصم\n  كمشتري\n  أريد الحصول على خصم على المشتريات الكبيرة\n  لكي أوفر المال\n\n  Scenario: شراء أكبر من 1000 روبل\n    Given مبلغ الشراء يساوي "1500"\n    When أطلب حساب الخصم\n    Then يجب أن يكون حجم الخصم "150"\n\n  Scenario: شراء أقل من 1000 روبل\n    Given مبلغ الشراء يساوي "500"\n    When أطلب حساب الخصم\n    Then يجب أن يكون حجم الخصم "0"\n
\n\n

الخطوة 3. كتابة الخطوات في Rust

\n

أنشئ tests/steps/discount_steps.rs:

\n
use cucumber::{given, then, when, World};\nuse async_trait::async_trait;\n\n#[derive(Debug, Default)]\nstruct DiscountWorld {\n    purchase_amount: f64,\n    discount: f64,\n}\n\n#[async_trait(?Send)]\nimpl World for DiscountWorld {\n    // تنفيذ فارغ للتبسيط\n    async fn new() -> Self {\n        Self::d                

المدونات

توصيات الكتب