Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

क्लाउड फ़ंक्शंस का यूनिट परीक्षण

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

यह पृष्ठ आपके कार्यों के लिए इकाई परीक्षण लिखने के लिए सर्वोत्तम प्रथाओं और उपकरणों का वर्णन करता है, जैसे परीक्षण जो एक सतत एकीकरण (सीआई) प्रणाली का एक हिस्सा होगा। परीक्षण को आसान बनाने के लिए, फायरबेस क्लाउड फ़ंक्शंस के लिए फायरबेस टेस्ट एसडीके प्रदान करता है। इसे npm पर firebase-functions-test रूप में वितरित किया जाता है, और यह firebase-functions के लिए एक सहयोगी परीक्षण SDK है। क्लाउड फ़ंक्शंस के लिए फायरबेस टेस्ट एसडीके:

  • आपके परीक्षणों के लिए उपयुक्त सेटअप और टियरडाउन का ख्याल रखता है, जैसे कि firebase-functions के लिए आवश्यक पर्यावरण चर को सेट करना और अनसेट करना।
  • नमूना डेटा और घटना संदर्भ उत्पन्न करता है, ताकि आपको केवल वही फ़ील्ड निर्दिष्ट करनी पड़े जो आपके परीक्षण के लिए प्रासंगिक हैं।

परीक्षण व्यवस्था

अपने फ़ंक्शन फ़ोल्डर में निम्न कमांड चलाकर, firebase-functions-test और मोचा , एक परीक्षण ढांचा दोनों स्थापित करें:

npm install --save-dev firebase-functions-test
npm install --save-dev mocha

इसके बाद फंक्शन्स फोल्डर के अंदर एक test फोल्डर बनाएं, अपने टेस्ट कोड के लिए इसके अंदर एक नई फाइल बनाएं, और इसे कुछ नाम दें जैसे index.test.js

अंत में, निम्नलिखित जोड़ने के लिए functions/package.json संशोधित करें:

"scripts": {
  "test": "mocha --reporter spec"
}

एक बार जब आप परीक्षण लिख लेते हैं, तो आप उन्हें अपनी फ़ंक्शन निर्देशिका के अंदर npm test चलाकर चला सकते हैं।

क्लाउड फ़ंक्शंस के लिए फायरबेस टेस्ट एसडीके शुरू करना

firebase-functions-test का उपयोग करने के दो तरीके हैं:

  1. ऑनलाइन मोड (अनुशंसित): परीक्षण लिखें जो परीक्षण के लिए समर्पित एक फायरबेस प्रोजेक्ट के साथ इंटरैक्ट करते हैं ताकि डेटाबेस लिखता है, उपयोगकर्ता बनाता है, आदि वास्तव में होता है, और आपका परीक्षण कोड परिणामों का निरीक्षण कर सकता है। इसका मतलब यह भी है कि आपके कार्यों में उपयोग किए जाने वाले अन्य Google एसडीके भी काम करेंगे।
  2. ऑफलाइन मोड: बिना किसी साइड इफेक्ट के साइलेड और ऑफलाइन यूनिट टेस्ट लिखें। इसका मतलब यह है कि कोई भी मेथड कॉल जो फायरबेस उत्पाद के साथ इंटरैक्ट करती है (जैसे डेटाबेस को लिखना या उपयोगकर्ता बनाना) को स्टब करने की आवश्यकता है। यदि आपके पास Cloud Firestore या Realtime Database फ़ंक्शन हैं, तो आमतौर पर ऑफ़लाइन मोड का उपयोग करने की अनुशंसा नहीं की जाती है, क्योंकि यह आपके परीक्षण कोड की जटिलता को बहुत बढ़ा देता है।

SDK को ऑनलाइन मोड में प्रारंभ करें (अनुशंसित)

यदि आप परीक्षण प्रोजेक्ट के साथ इंटरैक्ट करने वाले परीक्षण लिखना चाहते हैं, तो आपको प्रोजेक्ट कॉन्फ़िगरेशन मानों की आपूर्ति करने की आवश्यकता है जो ऐप को firebase-admin माध्यम से शुरू करने के लिए आवश्यक हैं, और एक सेवा खाता कुंजी फ़ाइल का पथ।

अपने फायरबेस प्रोजेक्ट के कॉन्फ़िगरेशन मान प्राप्त करने के लिए:

  1. Firebase कंसोल में अपनी प्रोजेक्ट सेटिंग खोलें।
  2. अपने ऐप्स में, इच्छित ऐप चुनें।
  3. दाएँ फलक में, Apple और Android ऐप्स के लिए कॉन्फ़िगरेशन फ़ाइल डाउनलोड करने के विकल्प का चयन करें।

    वेब ऐप्स के लिए, कॉन्फ़िगरेशन मान प्रदर्शित करने के लिए कॉन्फ़िग का चयन करें।

एक कुंजी फ़ाइल बनाने के लिए:

  1. Google क्लाउड कंसोल का सेवा खाता फलक खोलें।
  2. App Engine डिफ़ॉल्ट सेवा खाता चुनें, और कुंजी बनाएँ चुनने के लिए दाईं ओर विकल्प मेनू का उपयोग करें।
  3. संकेत मिलने पर, कुंजी प्रकार के लिए JSON चुनें, और बनाएँ पर क्लिक करें।

कुंजी फ़ाइल को सहेजने के बाद, SDK प्रारंभ करें:

// At the top of test/index.test.js
const test = require('firebase-functions-test')({
  databaseURL: 'https://my-project.firebaseio.com',
  storageBucket: 'my-project.appspot.com',
  projectId: 'my-project',
}, 'path/to/serviceAccountKey.json');

एसडीके को ऑफलाइन मोड में इनिशियलाइज़ करें

यदि आप पूरी तरह से ऑफ़लाइन परीक्षण लिखना चाहते हैं, तो आप बिना किसी पैरामीटर के SDK को प्रारंभ कर सकते हैं:

// At the top of test/index.test.js
const test = require('firebase-functions-test')();

मॉकिंग कॉन्फ़िगरेशन मान

यदि आप अपने फ़ंक्शन कोड में functions.config() का उपयोग करते हैं, तो आप कॉन्फ़िगरेशन मानों का मजाक उड़ा सकते हैं। उदाहरण के लिए, यदि functions/index.js में निम्न कोड है:

const functions = require('firebase-functions');
const key = functions.config().stripe.key;

फिर आप अपनी टेस्ट फ़ाइल के अंदर मूल्य का नकल कर सकते हैं जैसे:

// Mock functions config values
test.mockConfig({ stripe: { key: '23wr42ewr34' }});

अपने कार्यों को आयात करना

अपने कार्यों को आयात करने के लिए, एक मॉड्यूल के रूप में अपनी मुख्य फ़ंक्शन फ़ाइल को आयात करने के लिए require का उपयोग करें। केवल firebase-functions-test प्रारंभ करने और कॉन्फ़िगरेशन मानों का मज़ाक उड़ाने के बाद ही ऐसा करना सुनिश्चित करें।

// after firebase-functions-test has been initialized
const myFunctions = require('../index.js'); // relative path to functions code

यदि आपने ऑफ़लाइन मोड में firebase-functions-test प्रारंभ किया है, और आपके फ़ंक्शन कोड में admin.initializeApp() है, तो आपको अपने कार्यों को आयात करने से पहले इसे स्टब करना होगा:

// If index.js calls admin.initializeApp at the top of the file,
// we need to stub it out before requiring index.js. This is because the
// functions will be executed as a part of the require process.
// Here we stub admin.initializeApp to be a dummy function that doesn't do anything.
adminInitStub = sinon.stub(admin, 'initializeApp');
// Now we can require index.js and save the exports inside a namespace called myFunctions.
myFunctions = require('../index');

परीक्षण पृष्ठभूमि (गैर-HTTP) कार्य

गैर-HTTP फ़ंक्शन के परीक्षण की प्रक्रिया में निम्नलिखित चरण शामिल हैं:

  1. उस फ़ंक्शन को लपेटें जिसे आप test.wrap विधि से परीक्षण करना चाहते हैं
  2. परीक्षण डेटा का निर्माण करें
  3. आपके द्वारा बनाए गए परीक्षण डेटा और आपके द्वारा निर्दिष्ट किए जाने वाले किसी भी ईवेंट संदर्भ फ़ील्ड के साथ लिपटे हुए फ़ंक्शन को आमंत्रित करें।
  4. व्यवहार के बारे में दावा करें।

पहले उस फ़ंक्शन को लपेटें जिसे आप परीक्षण करना चाहते हैं। मान लें कि आपके पास functions/index.js में एक फ़ंक्शन है जिसे makeUppercase कहा जाता है, जिसे आप परीक्षण करना चाहते हैं। functions/test/index.test.js में निम्नलिखित लिखें:

// "Wrap" the makeUpperCase function from index.js
const myFunctions = require('../index.js');
const wrapped = test.wrap(myFunctions.makeUppercase);

wrapped एक ऐसा फ़ंक्शन है जो इसे कॉल करने पर makeUppercase को आमंत्रित करता है। wrapped 2 पैरामीटर लेता है:

  1. डेटा (आवश्यक): makeUppercase को भेजने के लिए डेटा। यह सीधे आपके द्वारा लिखे गए फ़ंक्शन हैंडलर को भेजे गए पहले पैरामीटर से मेल खाता है। firebase-functions-test कस्टम डेटा या उदाहरण डेटा के निर्माण के लिए तरीके प्रदान करता है।
  2. eventContextOptions (वैकल्पिक): घटना संदर्भ के क्षेत्र जिन्हें आप निर्दिष्ट करना चाहते हैं। ईवेंट संदर्भ आपके द्वारा लिखे गए फ़ंक्शन हैंडलर को भेजा गया दूसरा पैरामीटर है। यदि आप wrapped हुए कॉल करते समय कोई ईवेंट eventContextOptions पैरामीटर शामिल नहीं करते हैं, तो एक ईवेंट संदर्भ अभी भी समझदार फ़ील्ड के साथ उत्पन्न होता है। आप कुछ जेनरेट किए गए फ़ील्ड को यहां निर्दिष्ट करके ओवरराइड कर सकते हैं। ध्यान दें कि आपको केवल उन फ़ील्ड्स को शामिल करना है जिन्हें आप ओवरराइड करना चाहते हैं। कोई भी फ़ील्ड जिसे आपने ओवरराइड नहीं किया है वह जनरेट हो जाती है।
const data = … // See next section for constructing test data

// Invoke the wrapped function without specifying the event context.
wrapped(data);

// Invoke the function, and specify params
wrapped(data, {
  params: {
    pushId: '234234'
  }
});

// Invoke the function, and specify auth and auth Type (for real time database functions only)
wrapped(data, {
  auth: {
    uid: 'jckS2Q0'
  },
  authType: 'USER'
});

// Invoke the function, and specify all the fields that can be specified
wrapped(data, {
  eventId: 'abc',
  timestamp: '2018-03-23T17:27:17.099Z',
  params: {
    pushId: '234234'
  },
  auth: {
    uid: 'jckS2Q0' // only for real time database functions
  },
  authType: 'USER' // only for real time database functions
});

परीक्षण डेटा का निर्माण

एक लिपटे फ़ंक्शन का पहला पैरामीटर अंतर्निहित फ़ंक्शन को लागू करने के लिए परीक्षण डेटा है। परीक्षण डेटा बनाने के कई तरीके हैं।

कस्टम डेटा का उपयोग करना

firebase-functions-test में आपके कार्यों का परीक्षण करने के लिए आवश्यक डेटा बनाने के लिए कई कार्य हैं। उदाहरण के लिए, Firestore DocumentSnapshot बनाने के लिए test.firestore.makeDocumentSnapshot का उपयोग करें। पहला तर्क डेटा है, और दूसरा तर्क पूर्ण संदर्भ पथ है, और स्नैपशॉट के अन्य गुणों के लिए एक वैकल्पिक तीसरा तर्क है जिसे आप निर्दिष्ट कर सकते हैं।

// Make snapshot
const snap = test.firestore.makeDocumentSnapshot({foo: 'bar'}, 'document/path');
// Call wrapped function with the snapshot
const wrapped = test.wrap(myFunctions.myFirestoreDeleteFunction);
wrapped(snap);

यदि आप onUpdate या onWrite फ़ंक्शन का परीक्षण कर रहे हैं, तो आपको दो स्नैपशॉट बनाने होंगे: एक पहले की स्थिति के लिए और दूसरा बाद की स्थिति के लिए। फिर, आप इन स्नैपशॉट के साथ एक Change ऑब्जेक्ट बनाने के लिए makeChange विधि का उपयोग कर सकते हैं।

// Make snapshot for state of database beforehand
const beforeSnap = test.firestore.makeDocumentSnapshot({foo: 'bar'}, 'document/path');
// Make snapshot for state of database after the change
const afterSnap = test.firestore.makeDocumentSnapshot({foo: 'faz'}, 'document/path');
const change = test.makeChange(beforeSnap, afterSnap);
// Call wrapped function with the Change object
const wrapped = test.wrap(myFunctions.myFirestoreUpdateFunction);
wrapped(change);

अन्य सभी डेटा प्रकारों के लिए समान फ़ंक्शन के लिए API संदर्भ देखें।

उदाहरण डेटा का उपयोग करना

यदि आपको अपने परीक्षणों में उपयोग किए गए डेटा को अनुकूलित करने की आवश्यकता नहीं है, तो firebase-functions-test प्रत्येक फ़ंक्शन प्रकार के लिए उदाहरण डेटा उत्पन्न करने के तरीके प्रदान करता है।

// For Firestore onCreate or onDelete functions
const snap = test.firestore.exampleDocumentSnapshot();
// For Firestore onUpdate or onWrite functions
const change = test.firestore.exampleDocumentSnapshotChange();

प्रत्येक फ़ंक्शन प्रकार के लिए उदाहरण डेटा प्राप्त करने के तरीकों के लिए API संदर्भ देखें।

स्टब्ड डेटा का उपयोग करना (ऑफ़लाइन मोड के लिए)

यदि आपने SDK को ऑफ़लाइन मोड में प्रारंभ किया है, और क्लाउड फायरस्टोर या रीयलटाइम डेटाबेस फ़ंक्शन का परीक्षण कर रहे हैं, तो आपको वास्तविक DocumentSnapshot या DataSnapshot बनाने के बजाय स्टब्स के साथ एक सादे ऑब्जेक्ट का उपयोग करना चाहिए।

मान लीजिए कि आप निम्नलिखित फ़ंक्शन के लिए एक यूनिट टेस्ट लिख रहे हैं:

// Listens for new messages added to /messages/:pushId/original and creates an
// uppercase version of the message to /messages/:pushId/uppercase
exports.makeUppercase = functions.database.ref('/messages/{pushId}/original')
    .onCreate((snapshot, context) => {
      // Grab the current value of what was written to the Realtime Database.
      const original = snapshot.val();
      functions.logger.log('Uppercasing', context.params.pushId, original);
      const uppercase = original.toUpperCase();
      // You must return a Promise when performing asynchronous tasks inside a Functions such as
      // writing to the Firebase Realtime Database.
      // Setting an "uppercase" sibling in the Realtime Database returns a Promise.
      return snapshot.ref.parent.child('uppercase').set(uppercase);
    });

फ़ंक्शन के अंदर, snap का दो बार उपयोग किया जाता है:

  • snap.val()
  • snap.ref.parent.child('uppercase').set(uppercase)

परीक्षण कोड में, एक सादा ऑब्जेक्ट बनाएं जहां ये दोनों कोड पथ काम करेंगे, और विधियों को स्टब करने के लिए सिनॉन का उपयोग करें।

// The following lines creates a fake snapshot, 'snap', which returns 'input' when snap.val() is called,
// and returns true when snap.ref.parent.child('uppercase').set('INPUT') is called.
const snap = {
  val: () => 'input',
  ref: {
    parent: {
      child: childStub,
    }
  }
};
childStub.withArgs(childParam).returns({ set: setStub });
setStub.withArgs(setParam).returns(true);

दावे करना

एसडीके को इनिशियलाइज़ करने, फंक्शन्स को रैप करने और डेटा के निर्माण के बाद, आप निर्मित डेटा के साथ रैप्ड फंक्शन्स को इनवाइट कर सकते हैं और व्यवहार के बारे में दावा कर सकते हैं। इन अभिकथनों को करने के लिए आप चाय जैसे पुस्तकालय का उपयोग कर सकते हैं।

ऑनलाइन मोड में दावा करना

यदि आपने ऑनलाइन मोड में क्लाउड फ़ंक्शंस के लिए फायरबेस टेस्ट एसडीके शुरू किया है, तो आप यह दावा कर सकते हैं कि firebase-admin एसडीके का उपयोग करके वांछित क्रियाएं (जैसे डेटाबेस लिखना) हुई हैं।

नीचे दिया गया उदाहरण बताता है कि 'INPUT' को परीक्षण परियोजना के डेटाबेस में लिखा गया है।

// Create a DataSnapshot with the value 'input' and the reference path 'messages/11111/original'.
const snap = test.database.makeDataSnapshot('input', 'messages/11111/original');

// Wrap the makeUppercase function
const wrapped = test.wrap(myFunctions.makeUppercase);
// Call the wrapped function with the snapshot you constructed.
return wrapped(snap).then(() => {
  // Read the value of the data at messages/11111/uppercase. Because `admin.initializeApp()` is
  // called in functions/index.js, there's already a Firebase app initialized. Otherwise, add
  // `admin.initializeApp()` before this line.
  return admin.database().ref('messages/11111/uppercase').once('value').then((createdSnap) => {
    // Assert that the value is the uppercased version of our input.
    assert.equal(createdSnap.val(), 'INPUT');
  });
});

ऑफ़लाइन मोड में अभिकथन करना

आप फ़ंक्शन के अपेक्षित रिटर्न मान के बारे में दावा कर सकते हैं:

const childParam = 'uppercase';
const setParam = 'INPUT';
// Stubs are objects that fake and/or record function calls.
// These are excellent for verifying that functions have been called and to validate the
// parameters passed to those functions.
const childStub = sinon.stub();
const setStub = sinon.stub();
// The following lines creates a fake snapshot, 'snap', which returns 'input' when snap.val() is called,
// and returns true when snap.ref.parent.child('uppercase').set('INPUT') is called.
const snap = {
  val: () => 'input',
  ref: {
    parent: {
      child: childStub,
    }
  }
};
childStub.withArgs(childParam).returns({ set: setStub });
setStub.withArgs(setParam).returns(true);
// Wrap the makeUppercase function.
const wrapped = test.wrap(myFunctions.makeUppercase);
// Since we've stubbed snap.ref.parent.child(childParam).set(setParam) to return true if it was
// called with the parameters we expect, we assert that it indeed returned true.
return assert.equal(wrapped(snap), true);

आप सिनॉन जासूसों का उपयोग यह दावा करने के लिए भी कर सकते हैं कि कुछ विधियों को बुलाया गया है, और आपके द्वारा अपेक्षित पैरामीटर के साथ।

HTTP कार्यों का परीक्षण

HTTP ऑनकॉल फ़ंक्शन का परीक्षण करने के लिए, पृष्ठभूमि फ़ंक्शन के परीक्षण के समान दृष्टिकोण का उपयोग करें।

यदि आप HTTP onRequest फ़ंक्शन का परीक्षण कर रहे हैं, तो आपको firebase-functions-test का उपयोग करना चाहिए यदि:

  • आप functions.config() का उपयोग करते हैं
  • आपका फ़ंक्शन किसी Firebase प्रोजेक्ट या अन्य Google API के साथ इंटरैक्ट करता है, और आप अपने परीक्षणों के लिए एक वास्तविक Firebase प्रोजेक्ट और उसके क्रेडेंशियल्स का उपयोग करना चाहेंगे।

एक HTTP onRequest फ़ंक्शन दो पैरामीटर लेता है: एक अनुरोध वस्तु और एक प्रतिक्रिया वस्तु। यहां बताया गया है कि आप addMessage() उदाहरण फ़ंक्शन का परीक्षण कैसे कर सकते हैं:

  • प्रतिक्रिया ऑब्जेक्ट में रीडायरेक्ट फ़ंक्शन को ओवरराइड करें, क्योंकि sendMessage() इसे कॉल करता है।
  • रीडायरेक्ट फ़ंक्शन के भीतर, उपयोग करें chai.assert इस बारे में दावा करने में सहायता के लिए कि रीडायरेक्ट फ़ंक्शन को किस पैरामीटर के साथ कॉल किया जाना चाहिए:
// A fake request object, with req.query.text set to 'input'
const req = { query: {text: 'input'} };
// A fake response object, with a stubbed redirect function which asserts that it is called
// with parameters 303, 'new_ref'.
const res = {
  redirect: (code, url) => {
    assert.equal(code, 303);
    assert.equal(url, 'new_ref');
    done();
  }
};

// Invoke addMessage with our fake request and response objects. This will cause the
// assertions in the response object to be evaluated.
myFunctions.addMessage(req, res);

परीक्षण सफाई

अपने परीक्षण कोड के अंत में, क्लीनअप फ़ंक्शन को कॉल करें। यह उन पर्यावरण चरों को अनसेट करता है जिन्हें एसडीके ने इनिशियलाइज़ करते समय सेट किया था, और फ़ायरबेस ऐप को हटा देता है जो कि अगर आप एसडीके का उपयोग रीयल टाइम डेटाबेस डेटा DataSnapshot या फायरस्टोर DocumentSnapshot स्नैपशॉट बनाने के लिए करते हैं तो बनाया जा सकता है।

test.cleanup();

संपूर्ण उदाहरणों की समीक्षा करें और अधिक जानें

आप Firebase GitHub रिपॉजिटरी पर संपूर्ण उदाहरणों की समीक्षा कर सकते हैं।

अधिक जानने के लिए, firebase-functions-test लिए एपीआई संदर्भ देखें।