Node.js पर यैंडेक्स एलिस कौशल का कार्यात्मक परीक्षण

ऐलिस, कौशल का शुभारंभ


यैंडेक्स के वॉयस असिस्टेंट एलिस के लिए अपना कौशल बनाने के अवसर को लगभग एक साल बीत चुका है। कैटलॉग में नए कौशल रोज़ आते हैं, और उनकी कुल संख्या कई सौ है। दुर्भाग्य से, इसे हल्के ढंग से डालने के लिए कुछ कौशल के साथ संचार "जोड़ नहीं करता है।" कौशल या तो एक ही वाक्यांश पर लूप करता है या आमतौर पर टूट जाता है और प्रतिक्रिया नहीं करता है।


इस लेख में, मैं Node.js. पर कौशल के लिए कार्यात्मक स्वचालित परीक्षण लिखने पर विचार करूंगा। ऐसे परीक्षणों की उपस्थिति आपको बेहतर कौशल बनाने की अनुमति देती है और उनके प्रदर्शन में आत्मविश्वास देती है।


मौजूदा परीक्षण उपकरण


ऐलिस के लिए कौशल एक वेब सर्वर है जो एक विशिष्ट प्रारूप में POST अनुरोधों का जवाब दे सकता है। फिलहाल, कई उपकरण हैं जहाँ आप कौशल URL को स्थानांतरित कर सकते हैं और इसके संचालन की जाँच कर सकते हैं:


  • आधिकारिक डेवलपर कंसोल , जहां आप पाठ के साथ कौशल का परीक्षण कर सकते हैं और अनुरोध / उत्तर देख सकते हैं
  • Aimylogic स्टेशन सिम्युलेटर, आवाज का समर्थन करता है
  • कौशल के स्थानीय परीक्षण के लिए ओपन-सोर्स प्रोजेक्ट डायलॉग .popstas.ru

इन उपकरणों की ख़ासियत यह है कि वे मैनुअल कौशल परीक्षण के लिए कुछ यूआई प्रदान करते हैं। मैं निरंतर एकीकरण की सर्वश्रेष्ठ परंपराओं में चाहता हूं
कंसोल में कमांड चलाएँ, स्वचालित रूप से सभी लिपियों की जांच करें और उसके बाद ही नया संस्करण अपलोड करें।


उसी समय, मैं व्यक्तिगत कौशल मॉड्यूल की इकाई परीक्षण में तल्लीन नहीं करना चाहता। अनुरोध / प्रतिक्रिया प्रोटोकॉल प्रलेखन में दर्ज किया गया है , और यह इस स्तर पर है कि परीक्षण करना बेहतर है। फिर, आंतरिक वास्तुकला को पूरी तरह से फिर से लिखने के बाद भी, आपको परीक्षणों को बदलना नहीं होगा। यही है, संक्षेप में, ये कार्यात्मक परीक्षण हैं।


मुझे इस तरह के कार्य के लिए Node.js के लिए एक तैयार पुस्तकालय नहीं मिला, इसलिए हम अपना खुद का लिखेंगे :)



GitHub पर Yandex रिपॉजिटरी से आधिकारिक कौशल उदाहरण लें। यह कौशल "तोता" है, जो उपयोगकर्ता द्वारा कही गई हर बात को दोहराता है। माइक्रो फ्रेमवर्क के आधार पर निर्मित और इसमें कोड की केवल कुछ पंक्तियाँ होती हैं:


// 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 फ़ील्ड में कॉपी करता है।


मैंने micro() फ़ंक्शन में मूल GitHub उदाहरण कोड को लपेटा ताकि निर्यात एक http सर्वर लौटाए, जिसे हम परीक्षणों में उपयोग करेंगे।


टेस्ट प्लान


तो, इस तरह के कौशल को परीक्षणों के साथ कवर करने के लिए, आपको निम्नलिखित की आवश्यकता है:


  1. स्थानीय पोर्ट पर कौशल के साथ एक सर्वर उठाएँ
  2. दो मामलों की जाँच करें:
    • उपयोगकर्ता कौशल में प्रवेश करता है, कौशल को "हैलो!"
    • उपयोगकर्ता कौशल के लिए एक संदेश भेजता है, कौशल को उसी संदेश के साथ जवाब देना चाहिए
  3. कौशल और शो रिपोर्ट के साथ सर्वर बंद करो

इन जांचों को स्वचालित करके, आप उन्हें प्रत्येक कमिट से पहले चला सकते हैं और सुनिश्चित करें कि कुछ भी टूटा हुआ नहीं है।


हम योजना के अनुसार परीक्षण कोड लिखेंगे, मोचा के लिए वाक्यविन्यास का उपयोग करते हुए। मान लें कि हमारे पास पहले से ही कुछ 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 वर्ग लिखने के लिए रहता है और परीक्षण चलाना संभव होगा।


आभासी उपयोगकर्ता


मुख्य बात जो एक परीक्षण उपयोगकर्ता को करने में सक्षम होना चाहिए, वांछित प्रारूप में डेटा के साथ कौशल url के लिए POST अनुरोध भेजना है। अनुरोध प्रारूप प्रलेखन में वर्णित है । अब हमें सभी क्षेत्रों की आवश्यकता नहीं है, इसलिए मैंने केवल आवश्यक छोड़ दिया ताकि उदाहरण कोड को न बढ़ाया जाए। टिप्पणियों के साथ 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) 

सब ठीक है, परीक्षा पास हो गई!


लेकिन आगे बढ़ने से पहले, आपको यह सुनिश्चित करने की ज़रूरत है कि परीक्षण वास्तव में काम करता है। ऐसा करने के लिए, प्रतिक्रिया कौशल को "हैलो!" "नमस्ते!" और इसे फिर से चलाएं:


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

परीक्षण में एक त्रुटि दिखाई दी - जैसा कि यह होना चाहिए।
अब हमें लगता है कि पहला मामला कवर किया गया है।


हम उपयोगकर्ता को संवाद करना सिखाते हैं


दूसरा मामला तब रहता है जब उपयोगकर्ता कौशल के लिए एक संदेश भेजता है और उसी संदेश को वापस प्राप्त करना चाहिए। ताकि उपयोगकर्ता "संवाद" कर सके, मैंने User वर्ग में say(message) विधि जोड़ दी। मैंने थोड़ा रिफैक्टिंग भी किया: मैंने http- रिक्वेस्ट को एक अलग तरीके से भेजा और इसे enter() अंदर इस्तेमाल किया 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 वर्ग को संशोधित करें ताकि अनुरोध में शेष फ़ील्ड को बदला जा सके (उदाहरण के लिए, उस बॉक्स को चेक करें जिसे उपयोगकर्ता के पास स्क्रीन नहीं है)
  • कनेक्ट कोड-कवरेज (उदा। nyc )
  • प्री-कमिट / प्री-पुश हुक (जैसे हस्की का उपयोग करके) पर सभी चेक लटकाएं

मेरे पास कई कौशल हैं, इसलिए मैंने परीक्षण उपयोगकर्ता वर्ग को एक अलग एलिस-टेस्टर पैकेज में रखा, शायद कोई काम आएगा।


मैंने GitHub पर लेख से उदाहरण का पूर्ण कार्य कोड भी पोस्ट किया । आप रिपॉजिटरी और प्रयोग को क्लोन कर सकते हैं।


आपका ध्यान के लिए धन्यवाद!

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


All Articles