بعد تغيير التعليمات البرمجية أو إضافتها، يجب عليك إجراء اختبارات الوحدات الحالية والنظر في كتابة المزيد. يتم تنفيذ جميع الاختبارات على النُسخ غير المضغوطة من الرمز.
هناك مجموعتان من اختبارات الوحدات: اختبارات JavaScript واختبارات منشئ الكتل.
اختبارات JavaScript
تؤكد اختبارات JavaScript تشغيل دوال JavaScript الداخلية في نواة حظر. نستخدم Mocha لإجراء اختبارات الوحدات، وSinon لتقليل التبعيات، وChai للتأكد من صحة الرمز.
إجراء الاختبارات
في كلٍّ من العينات المجمّعة والكتلة، سيجري npm run test
اختبارات الوحدات. في الغالب، سيؤدي ذلك أيضًا إلى إجراء اختبارات أخرى مثل تحويل المحتوى إلى كلام وتجميعه. يمكنك أيضًا فتح tests/mocha/index.html
في متصفّح لإجراء جميع اختبارات Mocha بشكل تفاعلي.
اختبارات كتابة
نستخدم واجهة Mocha TDD لإجراء الاختبارات. يتم تنظيم الاختبارات في مجموعات، والتي يمكن أن تحتوي
على أجنحة فرعية و/أو اختبارات إضافية. وبشكل عام، لكل مكوِّن من عناصر Blockly (مثل toolbox
أو workspace
) ملف اختبار خاص به يحتوي على مجموعة واحدة أو أكثر. يمكن أن تحتوي كل مجموعة على طريقة setup
وteardown
التي سيتم استدعاؤها قبل وبعد كل اختبار على التوالي في تلك المجموعة.
أدوات مساعدة الاختبار
لدينا عدد من الوظائف المساعدة الخاصة بتطبيق Blockly والتي قد تكون مفيدة عند كتابة الاختبارات. ويمكن العثور عليها في العيّنات الأساسية وفي النماذج المتوفرة فقط.
تشمل الوظائف المساعدة sharedTestSetup
وsharedTestTeardown
، وهما مطلوب من أجل طلب إجراء الاختبار قبل إجراء الاختبارات وبعدها (راجِع قسم "المتطلبات").
sharedTestSetup
:
- إعداد موقّتات sinon المزيفة (ستحتاج في بعض الاختبارات إلى استخدام
this.clock.runAll
). - StubsBlockly.Events.fire للتنشيط على الفور (قابل للتهيئة).
- إعداد التنظيف التلقائي لأنواع الكتل المحدّدة على الرغم من
defineBlocksWithJsonArray
. - يوضح بعض السمات في سياق
this
التي من المفترض أن تكون متاحة للوصول إليها:this.clock
(ولكن يجب عدم استعادته، فسينتج عن ذلك مشاكل فيsharedTestTeardown
)this.eventsFireStub
this.sharedCleanup
(يُستخدم معaddMessageToCleanup
وaddBlockTypeToCleanup
) (ملاحظة: لن تحتاج إلى استخدامaddBlockTypeToCleanup
إذا تم تحديد الحظر باستخدامdefineBlocksWithJsonArray
)
تتضمن الدالة مَعلمة options
اختيارية واحدة لضبط الإعدادات. وتُستخدَم في الوقت الحالي
فقط لتحديد ما إذا كان يجب دفع Blockly.Events.fire
لكي يتم تنشيطها فورًا (سيتم التخفّي تلقائيًا).
sharedTestTeardown
:
- يتم التخلص من مساحة العمل
this.workspace
(حسب المكان الذي تم تحديده فيها، راجع قسم "متطلبات الاختبار" لمزيد من المعلومات). - استعادة جميع التنويهات الموجزة.
- تتيح لك هذه الميزة إزالة جميع أنواع المكعبات التي تمت إضافتها من خلال
defineBlocksWithJsonArray
وaddBlockTypeToCleanup
. - يؤدي هذا الإجراء إلى إزالة جميع الرسائل التي تمت إضافتها حتى
addMessageToCleanup
.
متطلبات الاختبار
- يجب أن يستدعي كل اختبار
sharedTestSetup.call(this);
باعتباره السطر الأول في إعداد المجموعة الخارجية وsharedTestTeardown.call(this);
كسطر أخير في عملية تقسيم المجموعة الخارجية للملف. - إذا كنت بحاجة إلى مساحة عمل مع مجموعة أدوات عامة، يمكنك استخدام إحدى
صناديق الأدوات المعدّة مسبقًا
في الاختبار
index.html
. انظر أدناه للاطّلاع على مثال. - يجب التخلص من "
this.workspace
" بشكل صحيح. في معظم الاختبارات، عليك تحديدthis.workspace
في المجموعة الخارجية واستخدامه في جميع الاختبارات اللاحقة، ولكن في بعض الحالات قد تحدّده أو تعيد تعريفه في مجموعة داخلية (على سبيل المثال، يتطلّب أحد اختباراتك مساحة عمل بخيارات مختلفة عن الطريقة التي أعددتها في الأصل). يجب التخلص منها في نهاية الاختبار.- إذا حدّدت
this.workspace
في المجموعة الخارجية ولم تتم إعادة تعريفه مطلقًا، لن تحتاج إلى اتّخاذ أي إجراء آخر. وسيتم التخلص منها تلقائيًا بحلول "sharedTestTeardown
". - إذا حدّدت
this.workspace
للمرة الأولى في مجموعة داخلية (على سبيل المثال، لم تحدِّده في المجموعة الخارجية)، عليك التخلص منه يدويًا من خلال طلب الرمزworkspaceTeardown.call(this, this.workspace)
عند إيقاف ذلك الجناح. - إذا عرّفت
this.workpace
في المجموعة الخارجية، ثم أعدت تعريفها في مجموعة اختبار داخلية، عليك أولاً طلبworkspaceTeardown.call(this, this.workspace)
قبل إعادة تعريفها لهدم مساحة العمل الأصلية المحددة في مجموعة المستوى الأعلى. عليك أيضًا التخلص من القيمة الجديدة يدويًا من خلال استدعاءworkspaceTeardown.call(this, this.workspace)
مرة أخرى ضمن عملية تقسيم هذه المجموعة الداخلية.
- إذا حدّدت
بنية الاختبار
تتبع اختبارات الوحدات بشكل عام بنية محددة، والتي يمكن تلخيصها بالترتيب والتنفيذ والتأكيد.
- الترتيب: عليك إعداد حالة العالم وأي شروط ضرورية للسلوك الذي يخضع للاختبار.
- التنفيذ: يمكنك استدعاء الرمز الذي يخضع للاختبار لتشغيل السلوك الذي يتم اختباره.
- تأكيد: عليك تقديم تأكيدات بشأن القيمة المعروضة أو التفاعلات مع العناصر الوهمية للتحقّق من الصحّة.
في اختبار بسيط، قد لا يكون هناك أي سلوك يجب ترتيبه، ويمكن دمج مرحلتي الفعل والتأكيد من خلال تضمين الاستدعاء في التعليمة البرمجية تحت الاختبار في التأكيد. بالنسبة إلى الحالات الأكثر تعقيدًا، ستكون اختباراتك أكثر سهولة في القراءة إذا التزمت بهذه المراحل الثلاث.
إليك مثال على ملف اختبار (تم تبسيطه من الشيء الحقيقي).
suite('Flyout', function() {
setup(function() {
sharedTestSetup.call(this);
this.toolboxXml = document.getElementById('toolbox-simple');
this.workspace = Blockly.inject('blocklyDiv',
{
toolbox: this.toolboxXml
});
});
teardown(function() {
sharedTestTeardown.call(this);
});
suite('simple flyout', function() {
setup(function() {
this.flyout = this.workspace.getFlyout();
});
test('y is always 0', function() {
// Act and assert stages combined for simple test case
chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout is 0');
});
test('x is right of workspace if flyout at right', function() {
// Arrange
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
viewWidth: 100,
});
this.flyout.targetWorkspace.toolboxPosition = Blockly.TOOLBOX_AT_RIGHT;
this.flyout.toolboxPosition_ = Blockly.TOOLBOX_AT_RIGHT;
// Act
var x = this.flyout.getX();
// Assert
chai.assert.equal(x, 100, 'x is right of workspace');
});
});
});
أشياء يجب ملاحظتها من هذا المثال:
- ويمكن أن يحتوي الجناح على مجموعات أخرى تتضمّن طرق
setup
وteardown
إضافية. - لكل جناح واختبار اسم وصفي.
- تُستخدم تأكيدات شاي لتقديم تأكيدات حول التعليمة البرمجية.
- يمكنك توفير وسيطة سلسلة اختيارية سيتم عرضها إذا فشل الاختبار. ويُسهِّل ذلك تصحيح أخطاء الاختبارات المعطّلة.
- ترتيب المعلَمات هو
chai.assert.equal(actualValue, expectedValue, optionalMessage)
. إذا بدّلتactual
وexpected
، لن تكون رسائل الخطأ منطقية.
- يُستخدم Sinon لكبر الأساليب عندما لا تريد استدعاء الرمز الحقيقي. في هذا المثال، لا نريد استدعاء دالة المقاييس الحقيقية لأنها
ليست ذات صلة بهذا الاختبار. نحن نهتم فقط بكيفية استخدام النتائج
من خلال الطريقة قيد الاختبار. يستخدم Sinon الدالة
getMetrics
لعرض استجابة جاهزة يمكننا التحقق منها بسهولة في تأكيدات الاختبار. - يجب أن تحتوي طرق
setup
لكل مجموعة على إعداد عام فقط ينطبق على جميع الاختبارات. إذا كان اختبار سلوك معين يعتمد على حالة معينة، فيجب تحديد هذا الشرط بوضوح في الاختبار ذي الصلة.
اختبارات تصحيح الأخطاء
- يمكنك فتح الاختبارات في متصفح واستخدام أدوات المطوّرين لتحديد نقاط التوقف والتحقّق ممّا إذا كانت اختباراتك تفشل بشكل غير متوقّع (أو تجتازها بشكلٍ غير متوقّع).
يجب ضبط
.only()
أو.skip()
على اختبار أو مجموعة لتشغيل هذه المجموعة فقط من الاختبارات، أو يمكنك تخطّي الاختبار. مثال:suite.only('Workspace', function () { suite('updateToolbox', function () { test('test name', function () { // ... }); test.skip('test I don’t care about', function () { // ... }); }); });
تذكر إزالة هذه الأدوات قبل تنفيذ الكود الخاص بك.
حظر اختبارات المنشئ
لكل كتلة اختبارات وحدة خاصة بها. تتحقّق هذه الاختبارات من أنّ عمليات الحظر تنشئ رمزًا بدلاً من الوظائف على النحو المنشود.
- حمِّل
tests/generators/index.html
في Firefox أو Safari. تجدُر الإشارة إلى أنّ متصفّح Chrome وOpera لديهم قيود أمان تمنع تحميل الاختبارات من نظام "file://" المحلي (المشكلتان 41024 و47416). - اختر الجزء المناسب من النظام لاختباره من القائمة المنسدلة، ثم انقر على "تحميل". من المفترض أن تظهر القوالب في مساحة العمل.
- انقر على "JavaScript".
انسخ الرمز الذي تم إنشاؤه وشغِّله في وحدة تحكّم JavaScript. إذا انتهى الإخراج بـ "OK"، فهذا يعني أن الاختبار قد تم بنجاح. - انقر فوق "Python".
انسخ الرمز الذي تم إنشاؤه وشغِّله في مترجم Python. إذا انتهت النتيجة بـ "حسنًا"، يعني ذلك أنّ الاختبار قد اكتمل. - انقر فوق "PHP".
انسخ الرمز الذي تم إنشاؤه وشغِّله في مترجم لغة PHP. إذا انتهت النتيجة بـ "حسنًا"، يعني ذلك أنّ الاختبار قد اكتمل. - انقر فوق "Lua".
انسخ الرمز الذي تم إنشاؤه وشغِّله في مترجم Lua. إذا انتهت النتيجة بـ "حسنًا"، يعني ذلك أنّ الاختبار قد اكتمل. - انقر فوق "Dart".
انسخ الرمز الذي تم إنشاؤه وشغِّله في مترجم Dart. إذا انتهت النتيجة بـ "حسنًا"، يعني ذلك أنّ الاختبار قد اكتمل.
تعديل اختبارات منشئ الكتل
- يجب تحميل "
tests/generators/index.html
" في متصفّح. - اختر الجزء المناسب من النظام من القائمة المنسدلة، وانقر فوق "تحميل". من المفترض أن تظهر القوالب في مساحة العمل.
- أجرِ أي تغييرات أو إضافات على الوحدات.
- انقر فوق "XML".
- انسخ ملف XML الذي تم إنشاؤه في الملف المناسب في
tests/generators/
.