الاختبار في مسار Arturo

تعرّف على كيفية اختبار تمارين Arturo على Exercism


يستخدم مسار Arturo حزمة Unitt 3.0.0 لاختبار الوحدات في اختبارات جميع التمارين. توفّر هذه الحزمة إطار اختبار يدعم كلاً من الصياغة الحديثة المستوحاة من RSpec والصياغة القديمة المستوحاة من XUnit. عند تشغيل arturo tester.art أو exercism test من داخل مجلد التمرين المحلي لديك، ستُثبَّت الحزمة من الإنترنت عند أول تشغيل. بدلًا من ذلك، يمكنك تثبيت Unitt بتشغيل arturo --package install unitt 3.0.0. سيُشغَّل الاختبار الأول فقط وتُعرض نتيجته لك. بمجرد نجاح ذلك الاختبار، ألغِ تخطي الاختبار التالي وأعد تشغيل الاختبارات حتى ينجح كل اختبار. وبالنسبة لكل من إعدادي RSpec وXUnit، فالأمر بهذه البساطة: احذف .skip من it.skip أو test.skip على الترتيب. بمجرد نجاح جميع الاختبارات، أرسل حلك، لكن انتبه إلى أن مشغّل الاختبارات يشغّل جميع الاختبارات، حتى المتخطّاة منها.

البداية

سيحتوي مجلد التمرين الذي نزّلته على بعض الملفات، لكن هذه هي الملفات الثلاثة الأساسية.

leap/
├── src/leap.art         # Your solution file
├── tests/test-leap.art  # Test cases for the exercise
└── tester.art           # Test runner entry point

تشغيل arturo tester.art سيهيّئ Unitt ثم يشغّل الاختبارات داخل tests/test-leap.art. ستستورد الاختبارات src/leap.art الذي يحتوي على حلك، ثم تقوم بسلسلة من التأكيدات حول ما ينبغي أن يُرجعه حلك لمدخلات محددة.

ملف الحل

isLeap?: function [year][
    panic "please implement the isLeap? function"
]

عند بدء تمرين، يأتي ملف حلك بقالب يحتوي على البنية الأساسية لما هو متوقع. في هذا المثال من Leap، يحتوي الملف على تعريف مبدئي للدالة المتوقعة isLeap?، ولا سيما panic التي توقف تنفيذ الاختبارات. احذف سطر panic ثم ابدأ بكتابة تنفيذك لـ isLeap?.

بنية اختبارات RSpec

import.version:3.0.0 {unitt}!
import {src/leap}!

describe "Leap" [
    it "a year not divisible by 4 is a common year" [
        expects.be:'false? @[isLeap? 2015]
    ]

    it.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
        expects.be:'true? @[isLeap? 1996]
    ]
]
  • يحدّد describe كتلة من حالات الاختبار التي تتحقق من أمر مشترك. ويمكن تداخل هذه الكتل.
  • يعرّف كل من it وit.skip حالة اختبار واحدة، يجري تشغيلها أو تخطيها على الترتيب.
  • يقدّم expects التأكيد الذي يشكّل جوهر حالة الاختبار. ويأخذ expects.be دالة تُرجع قيمة منطقية تُستخدم لإجراء التأكيد.

في expects.be:'false? @[isLeap? 2015]، تؤكد مجموعة الاختبارات أنه ينبغي أن تُرجع الدالة isLeap? القيمة false للسنة 2015. وثمة طريقة أخرى لكتابة ذلك، وهي expects.be:'equal? @[false isLeapYear? 2015]، حيث نؤكد أن القيمة المُرجعة من isLeapYear? 2015 تساوي false. هذه الصيغة الأطول التي تقارن قيمتين هي أكثر أنواع التأكيدات شيوعًا في مسار Arturo. تأتي القيمة المتوقعة دائمًا أولًا في الكتلة، قبل قيمة النتيجة.

بنية اختبارات XUnit

suite "Leap" [
    test "a year not divisible by 4 is a common year" [
        result: isLeap? 2015
        assert -> false = result
    ]

    test.skip "a year divisible by 4 and not divisible by 100 is a leap year" [
        result: isLeap? 1996
        assert -> true = result
    ]
]

واجهة برمجة التطبيقات على غرار XUnit، التي قُدّمت في الإصدار الأول من Unitt، مدعومة للتوافق مع الإصدارات السابقة، وهي مكافئة إلى حد كبير لواجهة RSpec الحديثة، باستثناء تأكيداتها الأقل مرونة.

  • يحدّد suite كتلة من حالات الاختبار التي تتحقق من أمر مشترك. ويمكن تداخل هذه الكتل.
  • يعرّف كل من test وtest.skip حالة اختبار واحدة، يجري تشغيلها أو تخطيها على الترتيب.
  • يقدّم assert التأكيد الذي يشكّل جوهر حالة الاختبار. ويجب أن يكون التعبير الواقع على الجانب الأيمن من -> التالي صحيحًا.

مع اختبارات XUnit، تُنشأ عادةً متغيرات تمثّل النتيجة، واختياريًا القيمة المتوقعة، قبل سطر assert.

مخرجات الاختبار

سواء كنت تستخدم واجهة RSpec أو واجهة XUnit، ستكون مخرجات الاختبار متشابهة إلى حد كبير. سيكون الفرق الوحيد في ما يُطبع تحت كل اسم اختبار. تُبلّغ XUnit عن التأكيد باستخدام القيم المُقيَّمة، لذا سترى false = false. أما RSpec فتبلّغ عنه بصيغة false? false لأننا استخدمنا الدالة false? مع expects.

في البداية، سيبلّغ Arturo عن خطأ إذا لم يُحذف panic من ملف البداية، ولن يُقيّم أي اختبارات.

Uncaught error in tests/test-leap.art:
#[
        output: {
                
                ══╡ Program Error ╞═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════ <script> ══
                
                  Please implement the isLeap? function
                
                
        }
        code: 1
]

بمجرد استبدال panic، سيبلّغ Arturo عن حالة كل تأكيد يُجرى داخل اختبار. الآن ينجح الاختبار الأول، لكن الاختبار الثاني متخطّى.

======== .unitt/tests/test-leap.art ========

Describe: Leap

    ✅ - assert that a year not divisible by 4 is a common year
         ✅: false? false

    ⏩ - assert that a year divisible by 4 and not divisible by 100 is a leap year
         skipped!


========== Summary ==========

⏏️   TOTAL: 2 assertions
✅  PASSED: 1 assertion
⏩ SKIPPED: 1 assertion
❌  FAILED: 0 assertion

========== ======= ==========

بعد إلغاء تخطي الاختبار الثاني يدويًا، سيُشغَّل كلا الاختبارين. لكن تنفيذ الكود الحالي لـ isLeap? يُرجع false فقط، لذا يفشل الاختبار الثاني في تأكيده.

======== .unitt/tests/test-leap.art ========

Describe: Leap

    ✅ - assert that a year not divisible by 4 is a common year
         ✅: false? false

    ❌ - assert that a year divisible by 4 and not divisible by 100 is a leap year
         ❌: true? false


========== Summary ==========

⏏️   TOTAL: 2 assertions
✅  PASSED: 1 assertion
⏩ SKIPPED: 0 assertion
❌  FAILED: 1 assertion

========== ======= ==========

ستستمر هذه العملية مع إلغائك تخطي مزيد من الاختبارات. بمجرد نجاح جميع الاختبارات، تكون قد أنهيت التمرين ويمكنك إرسال الحل. يرجى ملاحظة أن مشغّل الاختبارات سيشغّل جميع الاختبارات، سواء كانت متخطّاة أم لا محليًا.