الاختبار الوظيفي لمهارات Yandex Alice على Node.js

أليس ، إطلاق المهارة


لقد مر عام تقريبًا على ظهور الفرصة لإنشاء مهاراتك الخاصة بـ Alice ، ظهر المساعد الصوتي من Yandex. تصل المهارات الجديدة يوميًا في الكتالوج ، ويبلغ إجمالي عددهم عدة مئات. لسوء الحظ ، التواصل مع بعض المهارات بعبارة ملطفة "لا يضيف". المهارة إما حلقات على نفس العبارة أو مكسورة بشكل عام ولا تستجيب.


في هذه المقالة ، سوف أفكر في كتابة الاختبارات الآلية الوظيفية لمهارة على Node.js. يسمح لك وجود مثل هذه الاختبارات بإنشاء مهارات أفضل وإعطاء الثقة في أدائها.


أدوات الاختبار الحالية


Skill for Alice هو خادم ويب يمكنه الاستجابة لطلبات POST بتنسيق معين. في الوقت الحالي ، هناك العديد من الأدوات التي يمكنك من خلالها نقل عنوان URL للمهارة والتحقق من عملها:


  • وحدة تحكم مطور البرامج الرسمية ، حيث يمكنك اختبار المهارات باستخدام طلبات النص / الإجابات ومشاهدتها
  • Aimylogic Station Simulator ، يدعم الصوت
  • dialogs.popstas.ru مشروع مفتوح المصدر للاختبار المحلي للمهارات

خصوصية هذه الأدوات هي أنها توفر بعض واجهة المستخدم لاختبار المهارات اليدوية. أريد في أفضل تقاليد التكامل المستمر
قم بتشغيل الأمر في وحدة التحكم ، والتحقق من جميع النصوص تلقائيًا وفقط تحميل الإصدار الجديد.


في الوقت نفسه ، لا أريد الخوض في اختبار وحدة من وحدات المهارات الفردية. يتم تسجيل بروتوكول الطلب / الاستجابة في الوثائق ، ومن الأفضل في هذا المستوى اختباره. بعد ذلك ، حتى بعد إعادة كتابة البنية الداخلية بالكامل ، لن يتعين عليك تغيير الاختبارات. هذا ، في جوهره ، هذه اختبارات وظيفية .


لم أجد مكتبة منتهية لـ Node.js لمثل هذه المهمة ، لذلك سنكتب :)



خذ مثال المهارة الرسمية من مستودع ياندكس على جيثب. هذه هي مهارة "الببغاء" ، والتي ببساطة تكرر كل ما قاله المستخدم. مبني على أساس الإطار الصغير ويحتوي فقط على بضعة أسطر من التعليمات البرمجية:


// server.js const micro = require('micro'); const {json} = micro; module.exports = micro(async req => { const {request, session, version} = await json(req); return { version, session, response: { text: request.original_utterance || 'Hello!', end_session: false, }, }; }); 

في المكالمة الأولى ، ستتلقى المهارة رسالة فارغة من المستخدم (النص الأصلي) والإجابة "Hello!" . في حالات أخرى ، يقوم ببساطة بنسخ رسالة المستخدم في حقل response.text .


لقد قمت بلف كود مثال GitHub الأصلي في وظيفة micro() بحيث يقوم التصدير بإرجاع خادم http ، والذي سنستخدمه في الاختبارات.


خطة الاختبار


لذلك ، لتغطية مثل هذه المهارة مع الاختبارات ، فأنت بحاجة إلى ما يلي:


  1. رفع خادم بمهارة على المنفذ المحلي
  2. تحقق حالتين:
    • يدخل المستخدم المهارة ، يجب أن تجيب المهارة "مرحبًا!"
    • يرسل المستخدم رسالة إلى المهارة ، يجب أن تستجيب المهارة بنفس الرسالة
  3. وقف الخادم مع المهارة وعرض التقرير

من خلال أتمتة هذه الفحوصات ، يمكنك تشغيلها قبل كل التزام وتأكد من عدم كسر أي شيء.


سنكتب رمز الاختبار وفقًا للخطة ، وذلك باستخدام بناء جملة mocha . افترض أن لدينا بالفعل بعض فئات User التي يمكنها القيام بكل ما نحتاج إليه:


 // test.js const assert = require('assert'); before(done => { //    server.listen(PORT, done); }); it('should get hello on enter', async () => { //     const user = new User(`http://localhost:${PORT}`); //       const response = await user.enter(); //    assert.equal(response.text, 'Hello!'); }); after(done => { //   server.close(done); }); 

يبقى لكتابة فئة User وسيكون من الممكن تشغيل الاختبار.


المستخدم الظاهري


الشيء الرئيسي الذي يجب على مستخدم الاختبار أن يكون قادرًا عليه هو إرسال طلبات POST إلى عنوان url للمهارة مع البيانات بالتنسيق المطلوب. يتم وصف تنسيق الطلب في الوثائق . الآن نحن لسنا بحاجة إلى جميع الحقول ، لذلك تركت فقط اللازمة حتى لا تضخيم رمز المثال. فئة User مع التعليقات:


 // user.js const fetch = require('node-fetch'); module.exports = class User { /** *  * @param {String} webhookUrl */ constructor(webhookUrl) { this._webhookUrl = webhookUrl; } /** *     */ async enter() { const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' }; //    ,  -   const body = this._buildRequest(''); const response = await fetch(this._webhookUrl, { method: 'post', headers, body: JSON.stringify(body), }); const json = await response.json(); return json.response; } /** *        * @param {String} message */ _buildRequest(message) { return { request: { command: message, original_utterance: message, type: 'SimpleUtterance', }, session: { new: true, user_id: 'user-1', session_id: 'session-1' }, version: '1.0' } } }; 

إطلاق


للبدء ، يبقى استيراد فئات المستخدم والخادم في ملف الاختبار ، وكذلك تعيين قيمة المنفذ الذي سيرتفع عليه الخادم:


 // test.js ... const server = require('./server'); const User = require('./user'); const PORT = 3456; ... 

تثبيت جميع التبعيات اللازمة:


 npm install micro node-fetch mocha 

وإجراء الاختبار:


 $ mocha test.js ✓ should get hello on enter 1 passing (34ms) 

كل شيء على ما يرام ، لقد مر الاختبار!


ولكن قبل المضي قدماً ، يجب عليك التأكد من نجاح الاختبار حقًا. للقيام بذلك ، استبدل مهارة الاستجابة "Hello!" إلى "مرحبا!" وتشغيله مرة أخرى:


 $ mocha test.js 0 passing (487ms) 1 failing 1) should get hello on enter: AssertionError [ERR_ASSERTION]: '!' == 'Hello!' + expected - actual -! +Hello! 

أظهر الاختبار خطأ - كما يجب أن يكون.
الآن ، بالتأكيد ، نحن نعتبر أن أول حالة يتم تغطيتها.


نحن نعلم المستخدم التواصل


تبقى الحالة الثانية عندما يرسل المستخدم رسالة إلى المهارة ويجب أن يتلقى نفس الرسالة مرة أخرى. حتى يتمكن المستخدم من "التواصل" ، أضفت طريقة say(message) إلى فئة User . لقد قمت أيضًا بإعادة هيكلة بعض الشيء: لقد قمت بإرسال طلبات http إلى طريقة منفصلة واستخدمتها داخل enter() say(message) :


 // user.js const fetch = require('node-fetch'); module.exports = class User { /** *  * @param {String} webhookUrl */ constructor(webhookUrl) { this._webhookUrl = webhookUrl; } /** *     */ async enter() { //    ,  -   const body = this._buildRequest(''); return this._sendRequest(body); } /** *     * @param {String} message */ async say(message) { const body = this._buildRequest(message); return this._sendRequest(body); } /** *  http- * @param {Object} body   */ async _sendRequest(body) { const headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' }; const response = await fetch(this._webhookUrl, { method: 'post', headers, body: JSON.stringify(body), }); const json = await response.json(); return json.response; } // ... }; 

يبدو رمز الاختبار للحالة الثانية كما يلي:


 it('should reply the same message', async () => { //   const user = new User(`http://localhost:${PORT}`); //    await user.enter(); //   const response = await user.say('  ?'); //    assert.equal(response.text, '  ?'); }); 

نبدأ من جديد ، ونرى أن كلا الاختبارين قد نجحا:


 $ mocha test.js ✓ should get hello on enter ✓ should reply the same message 2 passing (37ms) 

خطوات إضافية


بنفس الطريقة ، يمكنك إضافة نصوص أكثر تعقيدًا إلى المهارة ، وتغطيتها بالاختبارات. هذا سيضمن أن التغييرات الجديدة لا تضيع.


يمكن أيضًا تحسين البنية الأساسية للاختبار التي تم إنشاؤها:


  • تعديل فئة User بحيث يمكن تغيير الحقول المتبقية في الطلب (على سبيل المثال ، حدد المربع الذي لا يمتلك المستخدم شاشة)
  • توصيل تغطية الشفرة (مثل مدينة نيويورك )
  • تعليق جميع عمليات الفحص على خطافات ما قبل الالتزام / الدفع المسبق (مثل استخدام أجش )

لدي العديد من المهارات ، لذلك وضعت فئة المستخدم للاختبار في حزمة اختبار أليس منفصلة ، ربما شخص ما سيكون في متناول اليدين.


نشرت أيضًا رمز العمل الكامل للمثال من المقالة على جيثب . يمكنك استنساخ مستودع والتجربة.


شكرا لاهتمامكم!

Source: https://habr.com/ru/post/ar441978/


All Articles