यूनिट टेस्ट

कोड में बदलाव करने या उसे जोड़ने के बाद, आपको मौजूदा यूनिट टेस्ट चलाने चाहिए और ज़्यादा लिखने के बारे में सोचना चाहिए. सभी टेस्ट, कोड के अनकंप्रेस किए गए वर्शन पर चलाए जाते हैं.

यूनिट टेस्ट के दो सेट होते हैं: JS टेस्ट और ब्लॉक जनरेटर टेस्ट.

JS टेस्ट

JS टेस्ट, Blockly's में इंटरनल JavaScript फ़ंक्शन के काम करने की पुष्टि करता है कोर. हम यूनिट टेस्ट चलाने के लिए Mocha, डिपेंडेंसी को स्टब करने के लिए Sinon, और कोड के बारे में दावे करने के लिए Chai का इस्तेमाल करते हैं.

टेस्ट चलाना

blockly और blockly-samples, दोनों में npm run test यूनिट टेस्ट चलाएगा. Blockly में, यह लिंटिंग और कंपाइलेशन जैसे अन्य टेस्ट भी चलाएगा. आप सभी मोका को इंटरैक्टिव तरीके से चलाने के लिए tests/mocha/index.html को ब्राउज़र में भी खोलें टेस्ट.

राइटिंग टेस्ट

हम जांच करने के लिए, Mocha TDD इंटरफ़ेस का इस्तेमाल करते हैं. टेस्ट को सुइट में व्यवस्थित किया जाता है. इनमें अतिरिक्त सब-सुइट और/या टेस्ट, दोनों शामिल हो सकते हैं. आम तौर पर, Blockly के हर कॉम्पोनेंट (जैसे, toolbox या workspace) की अपनी टेस्ट फ़ाइल होती है. इसमें एक या उससे ज़्यादा सुइट होते हैं. हर सुइट में setup और teardown तरीका हो सकता है. इसे उस सुइट के हर टेस्ट से पहले और बाद में, क्रमशः कॉल किया जाएगा.

टेस्ट हेल्पर

ब्लॉकली के लिए, हमारे पास ऐसे कई हेल्पर फ़ंक्शन हैं जो इन मामलों में काम आ सकते हैं कॉन्टेंट लिखने में मदद करता है. ये core और blockly-samples में मिल सकते हैं.

हेल्पर फ़ंक्शन में sharedTestSetup और sharedTestTeardown शामिल हैं, जो को टेस्ट से पहले और बाद में कॉल करना ज़रूरी है (ज़रूरी शर्तें देखें सेक्शन में बताया गया है).

sharedTestSetup:
  • साइनन नकली टाइमर सेट अप करता है (कुछ टेस्ट में आपको इनका इस्तेमाल करना होगा this.clock.runAll).
  • Stubs Blockly.Events.fire तुरंत फ़ायर करने के लिए कॉन्फ़िगर करता है.
  • हालांकि, तय किए गए blockTypes का अपने-आप क्लीनअप सेट अप करता है 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) को फिर से कॉल करके, नई वैल्यू को मैन्युअल तरीके से भी हटाना होगा.

टेस्ट का स्ट्रक्चर

यूनिट टेस्ट आम तौर पर एक तय स्ट्रक्चर का पालन करते हैं. इसे व्यवस्थित करें, कार्रवाई करें, पुष्टि करें के तौर पर बताया जा सकता है.

  1. व्यवस्थित करें: टेस्ट किए जा रहे व्यवहार के लिए, दुनिया की स्थिति और ज़रूरी शर्तें सेट अप करें.
  2. कार्रवाई: जिस व्यवहार की जांच की जा रही है उसे ट्रिगर करने के लिए, जांच में कोड को कॉल करें.
  3. दावा करें: रिटर्न वैल्यू या इनसे होने वाले इंटरैक्शन के बारे में दावे करें बनावटी ऑब्जेक्ट दिखाएं, ताकि उनके सही होने की पुष्टि की जा सके.

एक सामान्य टेस्ट में, हो सकता है कि व्यवस्थित करने का कोई तरीका न हो और काम और इन स्टेज को जोड़ने के लिए, टेस्ट में मौजूद कोड को इनलाइन करें दावा. ज़्यादा मुश्किल मामलों के लिए, इन तीन चरणों का पालन करने पर, आपके टेस्ट ज़्यादा आसानी से पढ़े जा सकेंगे.

यहां टेस्ट फ़ाइल का एक उदाहरण दिया गया है. इसे असल फ़ाइल से आसान बनाया गया है.

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 के दावों का इस्तेमाल, कोड के बारे में दावे करने के लिए किया जाता है.
    • आप एक वैकल्पिक स्ट्रिंग तर्क दे सकते हैं, जो तब दिखाया जाएगा, जब जांच नहीं की जा सकी. इससे, गड़बड़ी वाली जांचों को डीबग करना आसान हो जाता है.
    • पैरामीटर का क्रम chai.assert.equal(actualValue, expectedValue, optionalMessage) है. अगर आपने actual और expected को स्वैप किया है, तो गड़बड़ी के मैसेज का कोई मतलब नहीं निकलेगा.
  • जब आप असली कोड को कॉल न करना चाहें, तब सिनोन का इस्तेमाल मेथड को स्टब करने के लिए किया जाता है. इस उदाहरण में, हमें रीयल मेट्रिक फ़ंक्शन को कॉल नहीं करना है, क्योंकि यह इस टेस्ट के लिए काम का नहीं है. हम केवल इस बात पर ध्यान देते हैं कि परिणामों का उपयोग कैसे किया जाता है जांच की जा रही है. सिनोन, getMetrics फ़ंक्शन को एक-एक करके दिखाता है पहले से तैयार जवाब मिलता है जिसकी जांच हम अपने टेस्ट दावों में आसानी से कर सकते हैं.
  • हर सुइट के लिए, setup तरीकों में सिर्फ़ सामान्य सेटअप होना चाहिए सभी टेस्ट पर लागू होता है. अगर किसी खास व्यवहार की जांच तो उस शर्त का परीक्षण.

डीबगिंग टेस्ट

  • ब्राउज़र में टेस्ट खोले जा सकते हैं. साथ ही, डेवलपर टूल का इस्तेमाल करके ब्रेकपॉइंट सेट किए जा सकते हैं. इससे यह पता लगाया जा सकता है कि आपके टेस्ट अचानक से फ़ेल हो रहे हैं या अचानक से पास हो रहे हैं!
  • किसी टेस्ट या सुइट पर .only() या .skip() सेट करें, ताकि सिर्फ़ उस टेस्ट का सेट चलाया जा सके या किसी टेस्ट को स्किप किया जा सके. उदाहरण के लिए:

    suite.only('Workspace', function () {
      suite('updateToolbox', function () {
        test('test name', function () {
          // ...
        });
        test.skip('test I don’t care about', function () {
          // ...
        });
      });
    });
    

    कोड को कमिट करने से पहले, इन टिप्पणियों को हटाना न भूलें.

जनरेटर जांच ब्लॉक करें

हर ब्लॉक का अपना यूनिट टेस्ट होता है. इन टेस्ट से यह पुष्टि होती है कि ब्लॉक से फ़ंक्शन के बजाय कोड का इस्तेमाल करें.

  1. Firefox या Safari में tests/generators/index.html लोड करें. ध्यान दें कि Chrome और Opera ऐसी सुरक्षा पाबंदियां लागू होती हैं जो लोकल "file://" से टेस्ट लोड करने से रोकती हैं सिस्टम (समस्याएं 41024 और 47416).
  2. ड्रॉप-डाउन मेन्यू से सिस्टम का वह हिस्सा चुनें जिसकी जांच करनी है. इसके बाद, "लोड करें" पर क्लिक करें. ब्लॉक, फ़ाइल फ़ोल्डर में दिखने चाहिए.
  3. "JavaScript" पर क्लिक करें.
    अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है जनरेट किए गए कोड को कॉपी करके, JavaScript कंसोल में चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि जांच पूरी हो गई है.
  4. "Python" पर क्लिक करें.
    जनरेट किए गए कोड को कॉपी करके, Python इंटरप्रेटर में चलाएं. अगर आउटपुट "OK" पर खत्म होता है, तो इसका मतलब है कि जांच पूरी हो गई है.
  5. "PHP" पर क्लिक करें.
    जनरेट किए गए कोड को कॉपी करके, PHP इंटरप्रेटर में चलाएं. अगर आउटपुट "OK" पर खत्म होता है, तो इसका मतलब है कि जांच पूरी हो गई है.
  6. "Lua" पर क्लिक करें.
    अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है जनरेट किया गया कोड, Lua अनुवादक की मदद से कॉपी करें और चलाएं. अगर आउटपुट "OK" पर खत्म होता है, तो इसका मतलब है कि टेस्ट पास हो गया है.
  7. "Dart" पर क्लिक करें.
    अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है जनरेट किया गया कोड, Dart अनुवादक की मदद से कॉपी करें और चलाएं. अगर आउटपुट "OK" पर खत्म होता है, तो इसका मतलब है कि टेस्ट पास हो गया है.

ब्लॉक जनरेटर टेस्ट में बदलाव करना

  1. tests/generators/index.html को ब्राउज़र में लोड करें.
  2. ड्रॉप-डाउन मेन्यू में जाकर, सिस्टम का वह हिस्सा चुनें जो सही हो. इसके बाद, "लोड करें". ब्लॉक, फ़ाइल फ़ोल्डर में दिखने चाहिए.
  3. ब्लॉक में कोई बदलाव करें या कोई जानकारी जोड़ें.
  4. "एक्सएमएल" पर क्लिक करें.
  5. जनरेट किए गए एक्सएमएल को tests/generators/ में मौजूद सही फ़ाइल में कॉपी करें.