العرضar

Errors and testing

Error handling#

فابر تفصل ثلاثة أفكار مترابطة تدمجها لغات كثيرة في شكل واحد:

Constructالمعنى
→ Tقناة عودة النجاح المعتادة
T ∪ nihilغياب في نطاق قيمة النجاح
⇥ Eقناة خروج بديلة قابلة للاسترداد للأخطاء

عودة طبيعية#

دالة porta(عدد x)  عدد {
    إذا x ≺ 0 إذن أعد 0
    أعد x * 2
}

دوال قابلة للفشل#

استخدم حين يمكن لدالة أن تخرج عبر قناة خطأ:

دالة divide(عدد a, عدد b)  عددنص {
    إذا b  0 {
        ارم "division by zero"
    }
    أعد a / b
}

رمي — iace#

iace ترسل قيمة على قناة الخطأ:

دالة exigePositivum(عدد value)  فراغنص {
    إذا value ≺ 0 {
        ارم "negative value"
    }
}

استرداد — fac / cape#

يسترد المستدعون محليًا بكتلة افعل ومعالج التقط:

دالة divide(عدد a, عدد b)  عدد {
    إذا b  0 إذن أعد 0
    أعد a / b
}

دالة tutum(عدد a, عدد b)  عدد {
    افعل {
        أعد divide(a, b)
    }
    التقط err {
        نبه err
        أعد 0
    }
}

لا يُعد الاستدعاء المباشر القابل للفشل تعبيرًا عاديًا. ضع استدعاءات الدوال من النمط → T ⇥ E داخل حدود افعل / التقط نشطة.

استرداد تحويل مضمن#

يمكن لـ أيضًا تحديد قيمة استرداد مضمنة على تحويلات :

ثابت نص raw  "42"

ثابت عدد n  raw ↦ عدد0

تأثير قابل للفشل فقط#

للدوال التي تخطئ لكن لا تعيد قيمة نجاح، احذف → T:

دالة exigePositivum(عدد value)  فراغنص {
    إذا value ≺ 0 {
        ارم "negative value"
    }
}

الحالة الراهنة#

و أعد و و iace و افعل / التقط هي أسطح نحوية ومدققة حية. خفض Rust و Go لسلوك / iace / التقط الكامل وقت التشغيل لا يزال فجوة خلفية — فهذه تجتاز فحص النمط لكنها لا تصدر بعد شيفرة وقت تشغيل قابلة للفشل إلى كل الأهداف.

Inline testing#

تمتلك Faber إطار عمل اختبارات من الدرجة الأولى مدمجًا في اللغة بثلاث كلمات مفتاحية: probandum تُعلن عن مجموعة اختبارات، وproba تُعلن عن حالة اختبار مفردة، وadfirma تؤكد صحة شرط. تعيش الاختبارات في نفس الملف مع الشيفرة التي تختبرها، وتُشغَّل عبر faber test، وتدعم نفس خط أنابيب التصريف الخاص بشيفرة الإنتاج — واعية بالإعدادات المحلية، مدققة الأنواع، ومتعددة الأهداف.

الكلمات المفتاحية الثلاث#

الكلمة المفتاحيةالدورالمكافئ التقريبي
probandumتُعلن عن مجموعة اختبارات مسماةdescribe، #[cfg(test)] mod
probaتُعلن عن حالة اختبار مفردةit، #[test]
adfirmaتؤكد صحة شرط أثناء التنفيذassert!، assert_eq!

probandum — مجموعة الاختبارات#

تجمّع كتلة probandum حالات الاختبار المرتبطة ببعضها. يمكن تداخل المجموعات لتنظيم الاختبارات بشكل هرمي:

اختبر "unum plus unum" {
    أكد 1 + 1  2
}

اختبر "multiplicatio" {
    أكد 3 * 4  12
}

اختبر "comparatio" {
    ثابت عدد x  10
    أكد x  10
}

proba — حالة الاختبار#

تحتوي كتلة proba على منطق الاختبار. يمكنها استخدام أي شيفرة Faber — ارتباطات المتغيرات، استدعاءات الدوال، تدفق التحكم — وتنتهي بتأكيد adfirma واحد أو أكثر. يمكن وسم الاختبارات بعلامة tag اختيارية للتنفيذ الانتقائي:

proba "echo formats operands with one space" tag "coreutils" {
    adfirma echo_textus(["hello", "world"]) ≡ "hello world"
}

adfirma — التأكيد#

تقيّم adfirma تعبيرًا منطقيًا وتُبلغ عن الفشل إذا كان خاطئًا. توفر رسالة نصية اختيارية سياقًا عند الفشل:

بداية {
    ثابت عدد x  10

    # Simple assertion
    أكد x ≻ 0

    # With custom message
    أكد x  10 secus "x decem esse debet"

    # Multiple assertions in sequence
    ثابت نص nomen  "Marcus"
    أكد nomen  "Marcus"
    أكد nomen  "" secus "nomen vacuum non sit"
}

سير العمل#

تُشغَّل الاختبارات عبر الأمر faber test:

faber test                        # run all tests in the current package
faber test examples/coreutils/packages/echo  # run tests for a specific package

لأن الاختبارات تعيش جنبًا إلى جنب مع المصدر في نفس ملف .fab، فلا يوجد هيكل مجلدات منفصل للاختبارات، ولا إعلان لوحدة اختبارات، ولا تمييز في سكربت البناء بين بنائي الاختبار والإنتاج. يعرف المصرف أي الكتل هي شيفرة اختبار وأيها شيفرة إنتاج من خلال الكلمات المفتاحية المستخدمة — تُحلَّل probandum وproba لكنها تُستبعد من بنائي الإنتاج.

مثال من العالم الحقيقي#

توضح حزمة echo في coreutils إطار عمل الاختبارات عمليًا. تعيش الاختبارات في نفس ملف التنفيذ، وتغطي تحليل الخيارات، توسيع الرموز الخاصة، والحالات الحدية:

probandum "echo formatting" tag "coreutils" {
    proba "empty operands format as empty text" {
        fixum lista<textus> words ← vacua
        adfirma echo_textus(words) ≡ ""
    }

    proba "single operand is unchanged" {
        adfirma echo_textus(["hello"]) ≡ "hello"
    }

    proba "-E is a leading no-op option" {
        adfirma echo_textus(["-E", "hello", "world"]) ≡ "hello world"
    }

    proba "-n suppresses the trailing newline flag" {
        adfirma echo_novam_lineam(["-n", "hello"]) ≡ falsum
    }

    proba "-e expands the declared escape subset" {
        adfirma echo_textus(["-e", "a\\nb"]) ≡ "a\nb"
        adfirma echo_textus(["-e", "a\\tb"]) ≡ "a\tb"
    }
}

ملاحظات التصميم#

تميز عدة خيارات تصميمية إطار اختبارات Faber عن النهج التقليدية:

  • لا يوجد ثنائي اختبار منفصل. الاختبارات هي تصريحات في نفس ملف المصدر، وليست هدف تصريف منفصل. يصفي المصرف كتل الاختبار من مخرجات الإنتاج.
  • الوسوم، وليس المجلدات. تُنظم الاختبارات بعلامات tag بدلًا من هيكل المجلدات. يمكن للاختبار الانتماء إلى عدة محاور تنظيمية دون نقله.
  • خط أنابيب تصريف كامل. الاختبارات مدققة الأنواع، محللة، وواعية بالإعدادات المحلية — نفس علم --reader-locale ينطبق على مخرجات الاختبار.
  • متعدد الأهداف. تشغّل الاختبارات عبر أي خلفية يستهدفها الرزمة — مُنفّذ MIR لـ faber test --interpret، وRust مصرف لـ faber test.
  • مجموعات متداخلة. يمكن تداخل كتل probandum، معكسةً هيكل الشيفرة التي تختبرها.

المراجع#

  1. examples/corpus/probandum/ — ملفات probandum النموذجية
  2. examples/corpus/proba/ — ملفات proba النموذجية
  3. examples/corpus/adfirma/ — ملفات adfirma النموذجية
  4. examples/coreutils/packages/echo/src/main.fab — استخدام واقعي مع الوسوم