BDD في Kotlin: كتابة اختبارات يقرأها المدراء والمطورون
\n\nهل سبق لك أن أريت اختبار وحدة لمدير منتجك؟ على الأرجح لا. لأن ذلك يشبه إظهار مخططات محرك نفاث لطيار - مفيد لكنه غير مفهوم. التطوير القائم على السلوك (BDD) في Kotlin يحل هذه المشكلة تحديدًا: فهو يحول التأكيدات الجافة إلى سيناريوهات حية تصف سلوك النظام بلغة بشرية.
\n\nفي هذه المقالة، سنشرح كيفية تطبيق BDD في Kotlin باستخدام أطر العمل الحديثة - Kotest و Spek. سترى كيفية كتابة اختبارات بأسلوب Given-When-Then والتي تكون في نفس الوقت توثيقًا وتحققًا آليًا. ونعم، سيتمكن حتى قائد فريقك من قراءتها دون تحضير مسبق.
\n\nما هو BDD وكيف يختلف عن TDD؟
\n\nكثيرون يخلطون بين TDD (التطوير القائم على الاختبار) و BDD (التطوير القائم على السلوك). الفرق بسيط:
\n\n- \n
- TDD يدور حول "كيف سأختبر هذه الدالة؟" \n
- BDD يدور حول "كيف سيحصل المستخدم على قيمة من هذه الميزة؟" \n
التطوير القائم على السلوك يركز على سلوك النظام، وليس على تفاصيل التنفيذ. تصف سيناريو: في ظل شروط معينة (Given)، عند حدوث إجراء (When)، يُنتج النظام النتيجة المتوقعة (Then).
\n\nعلى سبيل المثال، بدلاً من كتابة: assertEquals(42, calculator.add(20, 22))،
ستكتب:
Given("لدي آلة حاسبة") {\n val calc = Calculator()\n When("أجمع 20 و 22") {\n val result = calc.add(20, 22)\n Then("يجب أن تكون النتيجة 42") {\n result shouldBe 42\n }\n }\n}\n\n\nتوافق معي، الخيار الثاني يُقرأ كقصة، وليس كتعليمات تقنية.
\n\nلماذا Kotlin مثالي لـ BDD
\n\nKotlin هي لغة تشجع بطبيعتها على كتابة كود قابل للقراءة. دوال التوسيع، الترميز الوسيطي، لامبدا مع المستقبل - كل هذا يجعل اختبارات BDD في Kotlin طبيعية للغاية. يمكنك كتابة shouldBe، shouldThrow ومطابقات أخرى تبدو كاللغة الإنجليزية.
علاوة على ذلك، تدعم Kotlin عدة نماذج برمجية، مما يسمح باستخدام أطر عمل مختلفة لـ BDD. دعنا نستعرض الأكثر شيوعًا.
\n\nإطار Kotest: BDD جاهز للاستخدام
\n\nKotest (المعروف سابقًا بـ KotlinTest) هو إطار اختبار متعدد المنصات وقوي. يدعم عدة أنماط، بما في ذلك BehaviorSpec، وهو مثالي لـ BDD.
\n\nإليك كيف يبدو سيناريو BDD كامل في Kotlin باستخدام Kotest:
\n\nimport io.kotest.core.spec.style.BehaviorSpec\nimport io.kotest.matchers.shouldBe\n\nclass CartSpec : BehaviorSpec({\n given("سلة تسوق فارغة") {\n val cart = ShoppingCart()\n `when`("نضيف منتجًا بسعر 100") {\n cart.addItem(Item("كتاب", 100.0))\n then("يجب أن يكون في السلة منتج واحد") {\n cart.itemCount shouldBe 1\n }\n then("يجب أن يكون المجموع 100") {\n cart.total shouldBe 100.0\n }\n }\n `when`("نضيف منتجًا ونطبق خصم 10%") {\n cart.addItem(Item("كتاب", 100.0))\n cart.applyDiscount(10.0)\n then("يجب أن يكون المجموع النهائي 90") {\n cart.total shouldBe 90.0\n }\n }\n }\n})\n\n\nلاحظ علامات الاقتباس العكسية حول when. هذه ميزة في Kotlin: when كلمة محجوزة، لكنها تعمل كمعرف داخل الاقتباسات. بعض المطورين يفضلون استخدام When بحرف كبير.
Spek: BDD منظم لـ Kotlin
\n\nSpek