यूनिट की जांच

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

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

JS टेस्ट

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

चल रहे परीक्षण

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

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

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

टेस्ट हेल्पर

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

हेल्पर फ़ंक्शन में sharedTestSetup और sharedTestTeardown शामिल हैं. इन्हें जांच से पहले और बाद में कॉल करना ज़रूरी है. ज़्यादा जानकारी वाला सेक्शन देखें.

sharedTestSetup:
  • sinon के नकली टाइमर सेट अप करता है (कुछ टेस्ट में आपको this.clock.runAll का इस्तेमाल करना होगा).
  • Stubs Blockly.Events.fire तुरंत फ़ायर करने के लिए फ़ायर हो (कॉन्फ़िगर किया जा सकता है).
  • defineBlocksWithJsonArray के हिसाब से, ब्लॉक किए गए ब्लॉक टाइप का अपने-आप क्लीनअप सेट अप किया जाता है.
  • this कॉन्टेक्स्ट पर, कुछ ऐसी प्रॉपर्टी के बारे में बताता है जिन्हें ऐक्सेस किया जा सकता है:
    • this.clock (हालांकि, इसे पहले जैसा नहीं किया जाना चाहिए, क्योंकि इससे sharedTestTeardown में समस्याएं आ सकती हैं)
    • this.eventsFireStub
    • this.sharedCleanup (addMessageToCleanup और addBlockTypeToCleanup के साथ इस्तेमाल किया जाना चाहिए) (ध्यान दें: अगर आपने defineBlocksWithJsonArray का इस्तेमाल करके ब्लॉक को तय किया है, तो आपको addBlockTypeToCleanup का इस्तेमाल करने की ज़रूरत नहीं है)

सेटअप कॉन्फ़िगर करने के लिए, फ़ंक्शन में एक वैकल्पिक 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.assert.equal(actualValue, expectedValue, optionalMessage) है. actual और expected को बदलने पर गड़बड़ी के मैसेज का कोई मतलब नहीं होगा.
  • जब आप असली कोड को कॉल नहीं करना चाहते, तो Sinon का इस्तेमाल तरीकों को स्टब करने के लिए किया जाता है. इस उदाहरण में, हम रीयल मेट्रिक फ़ंक्शन को कॉल नहीं करना चाहते, क्योंकि यह इस टेस्ट के लिए काम का नहीं है. हम सिर्फ़ इस बात की परवाह करते हैं कि जांच में बताए गए तरीके के नतीजों का इस्तेमाल कैसे किया जाता है. Sinon, पहले से तैयार जवाब देने के लिए 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. tests/generators/index.html को Firefox या Safari में लोड करें. ध्यान दें कि Chrome और Opera में सुरक्षा से जुड़ी पाबंदियां हैं, जो लोकल "file://" सिस्टम से टेस्ट को लोड होने से रोकती हैं. (समस्याएं 41024 और 47416).
  2. ड्रॉप-डाउन मेन्यू से जांच करने के लिए, सिस्टम का सही हिस्सा चुनें और "लोड करें" पर क्लिक करें. ब्लॉक, फ़ाइल फ़ोल्डर में दिखने चाहिए.
  3. "JavaScript" पर क्लिक करें.
    जनरेट किए गए कोड को कॉपी करके, JavaScript कंसोल में चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि टेस्ट पास हो गया है.
  4. "Python" पर क्लिक करें.
    जनरेट किए गए कोड को Python इंटरप्रेटर में कॉपी करें और चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि जांच पास हो गई है.
  5. "PHP" पर क्लिक करें.
    जनरेट किए गए कोड को PHP अनुवादक में कॉपी करें और चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि जांच पास हो गई है.
  6. "लुआ" पर क्लिक करें.
    जनरेट किए गए कोड को Lua अनुवादक में कॉपी करें और चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि जांच पास हो गई है.
  7. "डार्ट" पर क्लिक करें.
    जनरेट किए गए कोड को Dart के लिए इंटरप्रेटर में कॉपी करें और चलाएं. अगर आउटपुट "ठीक है" पर खत्म होता है, तो इसका मतलब है कि जांच पास हो गई है.

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

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