اختبار الوحدات في AngularJS باستخدام Karma و Jasmine
⚡ ملخص ذكي
تتيح اختبارات الوحدات في AngularJS باستخدام Karma و Jasmine التحقق من صحة المتحكمات والتوجيهات والخدمات بشكل منفصل. يقوم Karma بتشغيل المواصفات داخل متصفحات حقيقية، ويوفر Jasmine صيغة التأكيد، ويقوم angular-mocks بحقن التبعيات دون الحاجة إلى خادم مباشر.

من أبرز ميزات AngularJS هي الاختبار جانب. عندما يكون المطورون في Google قاموا بتطوير AngularJS، مع مراعاة الاختبار والتأكد من أن إطار عمل AngularJS بأكمله قابل للاختبار.
في AngularJS، يتم إجراء الاختبارات عادةً باستخدام Karma (إطار عمل). يمكن إجراء اختبارات AngularJS بدون Karma، ولكن إطار عمل Karma يتمتع بوظائف ممتازة لاختبار كود AngularJS، مما يجعل استخدامه خيارًا منطقيًا.
- في AngularJS، يمكننا الأداء وحدة التجارب بشكل منفصل لوحدات التحكم والتوجيهات.
- يمكننا أيضا أن نؤدي الاختبار الشامل من AngularJS، والتي تختبر من منظور المستخدم.
⚠️ ملاحظة حول الإصدار: وصل دعم AngularJS (الإصدار 1.x) إلى نهايته الرسمية في 31 ديسمبر 2021، و Protracتم إيقاف برنامج تور في أغسطس 2023. لا تزال آلية العمل الموضحة في هذه الصفحة صالحة لصيانة تطبيقات AngularJS 1.x الحالية. يجب على المشاريع الجديدة استخدام Angular حديث مع مُشغّل مدعوم حاليًا.
مقدمة وتركيب إطار الكرمة
الكرمة هي أ أداة أتمتة الاختبار تم إنشاؤه بواسطة فريق AngularJS في Googleالخطوة الأولى لاستخدام Karma هي تثبيت Karma. يتم تثبيت Karma عبر npm (وهو مدير حزم يُستخدم لتسهيل تثبيت الوحدات على الجهاز المحلي).
تركيب الكرمة
يتم تثبيت Karma عبر npm في عملية مكونة من خطوتين.
الخطوة 1) قم بتنفيذ السطر أدناه من داخل سطر الأوامر
npm install karma karma-chrome-launcher karma-jasmine --save-dev
حيث،
- npm هي أداة سطر الأوامر لمدير حزم Node.js، وتُستخدم لتثبيت وحدات نمطية مخصصة على أي جهاز. وهي تأتي مع Node.js .
- تقوم معلمة التثبيت بإرشاد الأداة المساعدة لسطر الأوامر npm بأن التثبيت مطلوب.
- هناك 3 مكتبات محددة في سطر الأوامر مطلوبة للعمل مع الكارما.
- الكرمة هي المكتبة الأساسية التي سيتم استخدامها لأغراض الاختبار.
- karma-chrome-launcher هي مكتبة منفصلة تتيح لمتصفح Chrome التعرف على أوامر karma.
- كارما-ياسمين - يؤدي هذا إلى تثبيت الياسمين الذي يعد إطارًا تابعًا للكارما.
الخطوة 2) الخطوة التالية هي تثبيت الأداة المساعدة لسطر أوامر Karma. هذا مطلوب لتنفيذ أوامر خط الكارما. سيتم استخدام الأداة المساعدة لخط karma لتهيئة بيئة karma للاختبار.
لتثبيت الأداة المساعدة لسطر الأوامر، قم بتنفيذ السطر أدناه من داخل سطر الأوامر
npm install -g karma-cli
- تُستخدم أداة karma-cli لتثبيت واجهة سطر الأوامر الخاصة بـ Karma، والتي تُستخدم لكتابة أوامر Karma من خلالها. يُثبّت الخيار -g الأداة على مستوى النظام بحيث يكون أمر Karma متاحًا من أي مجلد.
تكوين إطار الكرمة
الخطوة التالية هي تكوين الكارما والتي يمكن إجراؤها عبر الأمر
karma init
بعد تنفيذ الخطوة أعلاه، سيقوم karma بإنشاء ملف karma.conf.js. من المحتمل أن يبدو الملف مثل المقتطف الموضح أدناه
files: [ 'node_modules/angular/angular.js', 'node_modules/angular-mocks/angular-mocks.js', 'lib/app.js', 'tests/*.js' ]
تخبر ملفات التكوين أعلاه محرك تشغيل الكارما بالأشياء التالية
- angular.js – هذا يخبر كارما أن تطبيقك يعتمد على الوحدات الأساسية في AngularJS.
- angular-mocks.js – هذا يخبر كارما باستخدام وظيفة اختبار الوحدة لـ AngularJS من ملف angular-mocks.js.
- جميع ملفات التطبيق أو منطق الأعمال الرئيسية موجودة في مجلد lib الخاص بالتطبيق الخاص بك.
- سيحتوي مجلد الاختبارات على جميع اختبارات الوحدة.
💡 نصيحة: ترتيب الملفات داخل مصفوفة الملفات مهم. يجب تحميل ملف angular.js قبل ملف angular-mocks.js، ويجب تحميل كليهما قبل كود التطبيق الخاص بك، وإلا فلن يكون المُحقِّن متاحًا عند تشغيل المواصفات.
للتحقق مما إذا كانت الكارما تعمل، قم بإنشاء ملف يسمى Sample.js، وأدخل الكود أدناه وضعه في دليل الاختبار.
describe('Sample test', function() { it('Condition is true', function() { expect('AngularJS').toBe('AngularJS'); }); });
يحتوي الكود أعلاه على الجوانب التالية
- يتم استخدام وظيفة الوصف لإعطاء وصف للاختبار. في حالتنا، نحن نعطي الوصف "اختبار العينة" للاختبار الخاص بنا.
- يتم استخدام الدالة "it" لإعطاء اسم للاختبار. في حالتنا، نعطي اسم الاختبار الخاص بنا على أنه "الحالة صحيحة". يجب أن يكون اسم الاختبار ذا معنى.
- يشير الجمع بين الكلمة الأساسية "expect" و"toBe" إلى القيمة المتوقعة والفعلية لنتيجة الاختبار. إذا كانت القيمة الفعلية والمتوقعة هي نفسها، فإن الاختبار سينجح وإلا فإنه سيفشل.
عند تنفيذ السطر التالي في موجه الأوامر، سيتم تنفيذ ملف الاختبار أعلاه
karma start
الإخراج أدناه مأخوذ من IDE Webstorm حيث تم تنفيذ الخطوات المذكورة أعلاه.
- يأتي الإخراج في مستكشف Karma بالداخل Webstorm. تعرض هذه النافذة تنفيذ جميع الاختبارات المحددة في إطار عمل الكارما.
- هنا يمكنك أن ترى أن وصف الاختبار الذي تم تنفيذه يظهر وهو "اختبار العينة".
- بعد ذلك، يمكنك أن ترى أن الاختبار نفسه الذي يحمل اسم "الشرط صحيح" قد تم تنفيذه.
- لاحظ أنه نظرًا لأن جميع الاختبارات تحتوي على أيقونة "موافق" الخضراء بجوارها والتي ترمز إلى اجتياز جميع الاختبارات.
ما هي جاسمين في اختبارات الوحدة في AngularJS؟
يُحدد Karma مكان تشغيل الاختبارات، بينما يُحدد Jasmine كيفية كتابتها. Jasmine هو إطار عمل لتحديد المواصفات يعتمد على السلوك، ويُوفر المصطلحات المستخدمة في كل مثال على هذه الصفحة، ولهذا السبب يتم تثبيت مُهايئ karma-jasmine بجانب المُشغّل.
تساهم ياسمين بأربعة عناصر أساسية:
- يصف(): يقوم بتجميع المواصفات ذات الصلة في مجموعة واحدة ويقبل وصفًا واضحًا للوحدة قيد الاختبار.
- هو - هي(): يُعلن عن مواصفة واحدة. يجب أن يُشير الاسم إلى السلوك الذي يتم التحقق منه بدلاً من الطريقة التي يتم استدعاؤها.
- توقع باستخدام المطابقات: يقارن القيمة الفعلية بالقيمة المتوقعة. تشمل دوال المطابقة الشائعة toBe و toEqual و toContain و toBeDefined.
- قبل كل عملية (beforeEach()) وبعد كل عملية (afterEach()): قم بتشغيل الإعداد والتنظيف قبل وبعد كل مواصفة، مما يحافظ على استقلالية كل اختبار.
توفر Jasmine أيضًا أدوات تجسس. تستبدل هذه الأدوات وظيفة حقيقية بوظيفة مسجلة بديلة، مما يسمح باختبار وحدة التحكم دون الحاجة إلى استدعاء نقطة نهاية HTTP مباشرة. ولأن Jasmine لا تحتاج إلى DOM أو مكتبة تأكيد خاصة بها، فإن الجمع بين Karma وJasmine يظل أخف طريقة لتشغيل AngularJS. Javaاختبارات الوحدة البرمجية.
اختبار وحدات تحكم AngularJS
يتمتع إطار اختبار الكارما أيضًا بوظيفة اختبار وحدات التحكم من البداية إلى النهاية. يتضمن ذلك اختبار كائن النطاق $ الذي يتم استخدامه داخل وحدات التحكم.
دعونا نلقي نظرة على مثال لكيفية تحقيق ذلك.
في مثالنا ،
سنحتاج أولاً إلى تحديد وحدة التحكم. ستقوم وحدة التحكم هذه بتنفيذ الخطوات المذكورة أدناه
- قم بإنشاء متغير معرف وقم بتعيين القيمة 5 له.
- قم بتعيين متغير المعرف إلى كائن النطاق $.
سيختبر اختبارنا وجود وحدة التحكم هذه وسيختبر أيضًا معرفة ما إذا كان متغير ID الخاص بكائن $scope مضبوطًا على 5.
أولاً، نحتاج إلى التأكد من توافر الشرط المسبق التالي
قم بتثبيت مكتبة angular-mocks عبر npm. يمكنك القيام بذلك عن طريق تنفيذ السطر التالي في موجه الأوامر.
npm install angular-mocks --save-dev
الخطوة التالية هي تعديل ملف karma.conf.js لضمان تضمين الملفات الصحيحة للاختبار. يعرض المقطع أدناه فقط جزء الملفات من karma.conf.js الذي يحتاج إلى تعديل
files: ['lib/angular.js', 'lib/angular-mocks.js', 'lib/index.js', 'test/*.js']
- تخبر المعلمة "الملفات" Karma بشكل أساسي بجميع الملفات المطلوبة أثناء تشغيل الاختبارات.
- يلزم وجود ملفي angular.js و angular-mocks.js لتشغيل اختبارات وحدة AngularJS
- سيحتوي ملف Index.js على الكود الخاص بوحدة التحكم
- سيحتوي مجلد الاختبار على جميع اختبارات AngularJS
فيما يلي كود AngularJS الخاص بنا والذي سيتم تخزينه كملف Index.js في مجلد الاختبار الخاص بتطبيقنا.
الكود أدناه يقوم بالأشياء التالية فقط
- خلق وحدة AngularJS يسمى SampleApp
- قم بإنشاء وحدة تحكم تسمى AngularJSController
- قم بإنشاء متغير يسمى ID، وأعطه القيمة 5 وقم بتعيينه للكائن $scope
var sampleApp = angular.module('sampleApp', []); sampleApp.controller('AngularJSController', function($scope) { $scope.ID = 5; });
بمجرد تنفيذ التعليمات البرمجية أعلاه بنجاح، ستكون الخطوة التالية هي إنشاء ملف حالة الاختبار للتأكد من كتابة التعليمات البرمجية وتنفيذها بشكل صحيح.
سيكون رمز اختبارنا كما هو موضح أدناه.
سيكون الكود في ملف منفصل يسمى ControllerTest.js، والذي سيتم وضعه في مجلد الاختبار. الكود أدناه يقوم فقط بالأشياء الرئيسية التالية
- دالة beforeEach – تُستخدم هذه الدالة لتحميل وحدة AngularJS المسماة 'sampleApp' قبل تشغيل الاختبار. لاحظ أن هذا هو اسم الوحدة في ملف index.js.
- يُنشأ الكائن $controller ككائن وهمي لوحدة التحكم "AngularJSController" المُعرّفة في ملف index.js. في أي نوع من اختبارات الوحدة، يُمثّل الكائن الوهمي كائنًا افتراضيًا يُستخدم فعليًا للاختبار، حيث يُحاكي سلوك وحدة التحكم.
- beforeEach(inject(function(_$controller_) - يُستخدم هذا لإدخال كائن وهمي في اختبارنا بحيث يتصرف مثل وحدة التحكم الفعلية.
- فار $النطاق = {}; هذا كائن وهمي يتم إنشاؤه لكائن $scope.
- var controller = $controller('AngularJSController', { $scope: $scope }); – هنا نتحقق من وجود وحدة تحكم باسم 'AngularJSController'. كما نقوم هنا بتعيين جميع المتغيرات من كائن $scope الموجود في وحدة التحكم في ملف Index.js إلى كائن $scope الموجود في ملف الاختبار.
- وأخيرًا، نقوم بمقارنة $scope.ID بـ 5
describe('AngularJSController', function() { beforeEach(module('sampleApp')); var $controller; beforeEach(inject(function(_$controller_){ $controller = _$controller_; })); describe('$scope.ID', function() { it('Check the scope object', function() { var $scope = {}; var controller = $controller('AngularJSController', { $scope: $scope }); expect($scope.ID).toEqual(5); }); }); });
سيتم تشغيل الاختبار أعلاه في متصفح Karma وسيعطي نفس نتيجة النجاح كما هو موضح في الموضوع السابق.
اختبار توجيهات AngularJS
يحتوي إطار اختبار Karma أيضًا على وظيفة لاختبار التوجيهات المخصصة. وهذا يشمل القالبURLوالتي تُستخدم ضمن التوجيهات المخصصة.
دعونا نلقي نظرة على مثال لكيفية تحقيق ذلك.
في مثالنا، سنقوم أولاً بتعريف توجيه مخصص يقوم بالأشياء التالية
- قم بإنشاء وحدة AngularJS تسمى SampleApp
- أنشئ توجيهًا مخصصًا باسم – guru99
- قم بإنشاء دالة تقوم بإرجاع قالب بعلامة رأس تعرض النص "هذا هو اختبار AngularJS".
var sampleApp = angular.module('sampleApp', []); sampleApp.directive('guru99', function () { return { restrict: 'E', replace: true, template: '<h1>This is AngularJS Testing</h1>' }; });
بمجرد تنفيذ الكود أعلاه بنجاح، ستكون الخطوة التالية هي إنشاء حالة اختبار للتأكد من كتابة الكود وتنفيذه بشكل صحيح. سيكون رمز اختبارنا كما هو موضح أدناه
سيكون الكود في ملف منفصل يسمى DirectiveTest.js، والذي سيتم وضعه في مجلد الاختبار. الكود أدناه يقوم فقط بالأشياء الرئيسية التالية
- دالة beforeEach - تُستخدم هذه الدالة لتحميل وحدة AngularJS الخاصة بنا والتي تسمى 'sampleApp' قبل تشغيل الاختبار.
- تُستخدم خدمة $compile لتجميع التوجيه. هذه الخدمة إلزامية ويجب تعريفها حتى يتمكن AngularJS من استخدامها لتجميع التوجيه المخصص.
- يُعدّ $rootScope النطاق الأساسي لأي تطبيق AngularJS. وقد رأينا كائن $scope الخاص بالمتحكم في فصول سابقة. في الواقع، كائن $scope هو كائن فرعي لكائن $rootScope. سبب تعريفه هنا هو أننا نجري تغييرًا على عنصر HTML فعلي في DOM عبر توجيه مخصص. لذا، نحتاج إلى استخدام خدمة $rootScope التي تستمع إلى أي تغيير يحدث داخل مستند HTML.
- var element = $compile(“ يُستخدم ()($rootScope) للتحقق مما إذا كان التوجيه قد تم حقنه بشكل صحيح. تم تسجيل التوجيه باسم guru99 (باستخدام نمط Camel Case)، لذا فإن AngularJS يطابق العنصر ذي الأحرف الصغيرة. في لغة الترميز. لذا تُستخدم هذه العبارة لإجراء هذا الفحص.
- expect(element.html()).toContain(“This is AngularJS Testing”) – يتم استخدام هذا لإرشاد دالة expect بأنها يجب أن تجد العنصر (في حالتنا علامة h1) ليحتوي على نص innerHTML "This is AngularJS Testing".
describe('Unit testing directives', function() { var $compile, $rootScope; beforeEach(module('sampleApp')); beforeEach(inject(function(_$compile_, _$rootScope_){ $compile = _$compile_; $rootScope = _$rootScope_; })); it('Check the directive', function() { // Compile a piece of HTML containing the directive var element = $compile("<guru99></guru99>")($rootScope); $rootScope.$digest(); expect(element.html()).toContain("This is AngularJS Testing"); }); });
سيتم تشغيل الاختبار أعلاه في متصفح Karma وسيعطي نفس نتيجة النجاح كما هو موضح في الموضوع السابق.
اختبار تطبيقات AngularJS من البداية إلى النهاية
إطار اختبار الكارما بالإضافة إلى إطار عمل يسمى Protracيتمتع برنامج Tor بوظيفة اختبار تطبيق الويب من البداية إلى النهاية.
لذا، لا يقتصر الأمر على اختبار التوجيهات ووحدات التحكم فحسب، بل أيضًا اختبار أي شيء آخر قد يظهر على صفحة HTML.
دعونا نلقي نظرة على مثال لكيفية تحقيق ذلك.
في المثال أدناه، سيكون لدينا تطبيق AngularJS الذي يقوم بإنشاء جدول بيانات باستخدام التوجيه ng-repeat.
- نقوم أولاً بإنشاء متغير يسمى "البرنامج التعليمي" ونخصص له بعض أزواج القيمة الرئيسية في خطوة واحدة. سيتم استخدام كل زوج من القيمة الرئيسية كبيانات عند عرض الجدول. يتم بعد ذلك تعيين المتغير التعليمي لكائن النطاق بحيث يمكن الوصول إليه من وجهة نظرنا.
- لكل صف من البيانات في الجدول، نستخدم التوجيه ng-repeat. يمر هذا التوجيه عبر كل زوج من قيمة المفتاح في كائن نطاق البرنامج التعليمي باستخدام المتغير ptutor.
- وأخيرا، نحن نستخدم ضع علامة مع أزواج القيمة الرئيسية (ptutor.Name وptutor.Description) لعرض بيانات الجدول.
<table> <tr ng-repeat="ptutor in tutorial"> <td>{{ ptutor.Name }}</td> <td>{{ ptutor.Description }}</td> </tr> </table> </div> <script type="text/javascript"> var app = angular.module('DemoApp', []); app.controller('DemoController', function($scope) { $scope.tutorial = [ {Name: "Controllers", Description: "Controllers in action"}, {Name: "Models", Description: "Models and binding data"}, {Name: "Directives", Description: "Flexibility of Directives"} ]; });
بمجرد تنفيذ الكود أعلاه بنجاح، ستكون الخطوة التالية هي إنشاء حالة اختبار للتأكد من كتابة الكود وتنفيذه بشكل صحيح. سيكون رمز اختبارنا كما هو موضح أدناه
سيقوم اختبارنا في الواقع باختبار التوجيه ng-repeat والتأكد من احتوائه على 3 صفوف من البيانات كما ينبغي من المثال أعلاه.
أولاً، نحتاج إلى التأكد من توافر الشرط المسبق التالي
قم بتثبيت النسخة الاحترافيةtracتثبيت مكتبة Tor عبر npm. يمكن القيام بذلك عن طريق تنفيذ السطر التالي في موجه الأوامر.
npm install -g protractor
سيكون رمز اختبارنا كما هو موضح أدناه.
سيكون الكود في ملف منفصل يسمى CompleteTest.js، والذي سيتم وضعه في مجلد الاختبار. الكود أدناه يقوم فقط بالأشياء الرئيسية التالية
- يتم توفير وظيفة المتصفح بواسطة المحترفtracمكتبة تور وتفترض أن تطبيق AngularJS الخاص بنا (بالكود الموضح أعلاه) يعمل على موقعنا URL – http://localhost:8080/Guru99 /
- var list = element.all(by.repeater('ptutor in tutorial')); - يقوم هذا السطر البرمجي بجلب توجيه ng-repeat الذي يتم ملؤه بواسطة الكود 'ptutor in tutorial'. العنصر و by.repeater كلمتان مفتاحيتان خاصتان يوفرهما البرنامج الاحترافيtracمكتبة tor التي تسمح لنا بالحصول على تفاصيل توجيه ng-repeat.
- توقع(list.count()).toEqual(3); - أخيرًا، نحن نستخدم الدالة المتوقعة لنرى أننا حصلنا بالفعل على 3 عناصر يتم ملؤها في جدولنا نتيجة لتوجيه ng-repeat.
describe('Unit testing end to end', function() { beforeEach(function() { browser.get('http://localhost:8080/Guru99/'); }); it('Check the ng directive', function() { var list = element.all(by.repeater('ptutor in tutorial')); expect(list.count()).toEqual(3); }); });
سيتم تشغيل الاختبار أعلاه في متصفح Karma وسيعطي نفس نتيجة النجاح كما هو موضح في الموضوع السابق.
كارما ضد ياسمين ضد بروtracتور: الاختلافات الرئيسية
غالباً ما يتم الخلط بين الأدوات الثلاث المستخدمة في هذه الصفحة لأنها تظهر في سطر الأوامر نفسه. كل أداة منها تشغل طبقة مختلفة من بنية الاختبار، كما يوضح الجدول أدناه.
| معامل | الكارما | الياسمين | بروtracتور |
| الفئة | عداء الاختبار | إطار المواصفات | إطار عمل أتمتة شامل |
| الوظيفة الرئيسية | يقوم بتشغيل المتصفحات وعرض النتائج | يُقدّم وصفًا، ويتوقع ذلك | يقوم بتشغيل تطبيق مباشر في متصفح حقيقي |
| مستوى الاختبار | وحدة و التكامل | الوحدة والتكامل | من البداية إلى النهاية |
| يحتاج إلى خادم قيد التشغيل | لا | لا | نعم |
| ملف الضبط | karma.conf.js | لا شيء، إنه يعمل داخل عداء | إلىtractor.conf.js |
| الحالة الحالية | مُهمل، للصيانة فقط | صيانة نشطة | تقاعد في أغسطس 2023 |
باختصار، تقوم ياسمين بكتابة الاختبار، وتقوم كارما بتنفيذه، وبروtracيقوم برنامج tor بتوسيع نفس صيغة Jasmine لتشمل صفحة يتم عرضها بالكامل.
أفضل الممارسات لاختبار وحدة AngularJS
مجموعة صغيرة من العادات تحافظ على سرعة وموثوقية مجموعة AngularJS مع نمو التطبيق.
- اختبر وحدة واحدة في كل مرة. قم بتحميل الوحدة قيد الاختبار فقط داخل beforeEach، وقم بمحاكاة كل متعاون بحيث يشير الفشل إلى ملف واحد.
- لا تتصل أبدًا بخادم خلفي حقيقي. استخدم خدمة $httpBackend من angular-mocks لإرجاع استجابات جاهزة. ثم تُجرى الاختبارات دون اتصال بالإنترنت وتُنتج نتائج متطابقة على كل جهاز.
- اجعل أسماء المواصفات سلوكية. اسم مثل "يعيد 5 عند تهيئة وحدة التحكم" يبدو أفضل في التقرير من "test1".
- احرص دائمًا على تنظيف دورة الهضم. قم باستدعاء $rootScope.$digest() بعد تغيير بيانات النطاق، وإلا فلن يتم تحديث الروابط والمراقبين وستفشل التأكيدات لسبب خاطئ.
- قم بقياس التغطية، ولكن احكم عليها بعناية. أضف karma-coverage لعرض الفروع غير المختبرة. التغطية العالية مع التأكيدات الضعيفة لا تزال تخفي العيوب.
- قم بتشغيل مجموعة البرامج في وضع التكامل المستمر. استخدم مشغل Chrome بدون واجهة رسومية حتى يتم تنفيذ نفس المواصفات في كل عملية إيداع بدلاً من تنفيذها فقط على جهاز المطور.
يؤدي تطبيق هذه القواعد إلى تحويل الأمثلة المذكورة أعلاه من عروض توضيحية معزولة إلى شبكة أمان ضد التراجع لقاعدة بيانات AngularJS القديمة. للاطلاع على الصورة الأوسع، انظر برنامج تعليمي لـ AngularJS سلسلة.

