การทดสอบ 1 หน่วย

หลังจากเปลี่ยนแปลงหรือเพิ่มโค้ด คุณควรเรียกใช้การทดสอบหน่วยที่มีอยู่และลองเขียนเพิ่ม การทดสอบทั้งหมดจะดำเนินการกับโค้ดเวอร์ชันที่ไม่มีการบีบอัด

การทดสอบหน่วยมี 2 ชุด ได้แก่ การทดสอบ JS และการทดสอบเครื่องมือสร้างบล็อก

การทดสอบ JS

การทดสอบ JS จะยืนยันการทำงานของฟังก์ชัน JavaScript ภายในในบริการหลักของ Blockly เราใช้ Mocha เพื่อเรียกใช้การทดสอบหน่วย, Sinon เพื่อจำลองการพึ่งพา และ Chai เพื่อยืนยันเกี่ยวกับโค้ด

การทดสอบที่ทำงานอยู่

ทั้ง blockly และ blockly-samples npm run test จะเรียกใช้การทดสอบหน่วย ในบล็อกลี่ การดำเนินการนี้จะทำการทดสอบอื่นๆ ด้วย เช่น การตรวจหาข้อบกพร่องและการคอมไพล์ นอกจากนี้ คุณยังเปิด tests/mocha/index.html ในเบราว์เซอร์เพื่อเรียกใช้การทดสอบ mocha ทั้งหมดแบบอินเทอร์แอกทีฟได้ด้วย

การทดสอบการเขียน

เราใช้อินเทอร์เฟซ Mocha TDD เพื่อทำการทดสอบ การทดสอบจะแบ่งออกเป็นชุดต่างๆ ซึ่งสามารถมีได้ทั้งชุดย่อยและ/หรือการทดสอบเพิ่มเติม โดยทั่วไปแล้ว คอมโพเนนต์แต่ละรายการของ Blockly (เช่น toolbox หรือ workspace) จะมีไฟล์ทดสอบของตัวเองซึ่งมีชุดทดสอบอย่างน้อย 1 ชุด ชุดผลิตภัณฑ์แต่ละรายการจะมีเมธอด setup และ teardown ซึ่งจะเรียกใช้ก่อนและหลังการทดสอบแต่ละรายการในชุดนั้นตามลำดับ

ตัวช่วยทดสอบ

เรามีฟังก์ชันตัวช่วยมากมายเฉพาะสำหรับ Blockly ซึ่งอาจเป็นประโยชน์ในการทำข้อสอบ ซึ่งจะอยู่ในไฟล์ core และ blockly-samples

ฟังก์ชันตัวช่วย ได้แก่ sharedTestSetup และ sharedTestTeardown ซึ่งต้องเรียกใช้ก่อนและหลังการทดสอบ (ดูส่วนข้อกำหนด)

sharedTestSetup:
  • ตั้งค่าตัวจับเวลาปลอมแบบ Sinon (ในการทดสอบบางอย่าง คุณจะต้องใช้ this.clock.runAll)
  • Stubs Blockly.Events.fire ให้เริ่มทำงานทันที (กำหนดค่าได้)
  • ตั้งค่าการล้างข้อมูล blockTypes ที่กําหนดผ่าน defineBlocksWithJsonArray โดยอัตโนมัติ
  • ประกาศพร็อพเพอร์ตี้ 2-3 รายการในบริบท this ที่มีไว้เพื่อให้เข้าถึงได้ ดังนี้
    • this.clock (แต่ไม่ควรกู้คืน มิเช่นนั้นจะเกิดปัญหาใน sharedTestTeardown)
    • this.eventsFireStub
    • this.sharedCleanup (ใช้กับ addMessageToCleanup และ addBlockTypeToCleanup) (หมายเหตุ: คุณไม่จำเป็นต้องใช้ addBlockTypeToCleanup หากกำหนดบล็อกโดยใช้ defineBlocksWithJsonArray)

ฟังก์ชันมีพารามิเตอร์ options ที่ไม่บังคับ 1 รายการเพื่อกําหนดค่าการตั้งค่า ปัจจุบันมีไว้เพื่อพิจารณาว่าจะจำลอง 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. Assert: ยืนยันเกี่ยวกับผลลัพธ์ที่แสดงหรือการทำงานกับออบเจ็กต์จำลองเพื่อตรวจสอบความถูกต้อง

ในการทดสอบง่ายๆ อาจไม่มีลักษณะการทำงานใดๆ ให้จัดเรียง และสามารถรวมขั้นตอนการดำเนินการและการยืนยันไว้โดยใส่การเรียกโค้ดภายใต้การทดสอบในการยืนยัน ในกรณีที่ซับซ้อนมากขึ้น การทดสอบจะอ่านได้ง่ายขึ้นหากคุณทำตาม 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 ข้อความแสดงข้อผิดพลาดจะดูไม่สมเหตุสมผล
  • 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 หน่วยของตัวเอง การทดสอบเหล่านี้จะยืนยันว่าบล็อกสร้างโค้ดมากกว่าฟังก์ชันตามที่ตั้งใจไว้

  1. โหลด tests/generators/index.html ใน Firefox หรือ Safari โปรดทราบว่า Chrome และ Opera มีข้อจำกัดด้านความปลอดภัยที่ป้องกันไม่ให้โหลดการทดสอบจากระบบ "file://" ในเครื่อง (ปัญหา 41024 และ 47416)
  2. เลือกส่วนที่เกี่ยวข้องของระบบที่จะทดสอบจากเมนูแบบเลื่อนลง และคลิก "โหลด" การบล็อกควรปรากฏในพื้นที่ทำงาน
  3. คลิกที่ "JavaScript"
    คัดลอกและเรียกใช้โค้ดที่สร้างขึ้นในคอนโซล JavaScript หากเอาต์พุตลงท้ายด้วย "OK" แสดงว่าการทดสอบผ่านไปแล้ว
  4. คลิก "Python"
    คัดลอกและเรียกใช้โค้ดที่สร้างขึ้นในโปรแกรมแปลภาษา Python หากผลลัพธ์ลงท้ายด้วย "OK" แสดงว่าการทดสอบผ่านแล้ว
  5. คลิก "PHP"
    คัดลอกและเรียกใช้โค้ดที่สร้างขึ้นในอินเตอร์พรีเตอร์ PHP หากเอาต์พุตลงท้ายด้วย "OK" แสดงว่าการทดสอบผ่าน
  6. คลิก "Lua"
    คัดลอกและเรียกใช้โค้ดที่สร้างขึ้นในโปรแกรมแปลภาษา Lua หากเอาต์พุตลงท้ายด้วย "OK" แสดงว่าการทดสอบผ่าน
  7. คลิก "Dart"
    คัดลอกและเรียกใช้โค้ดที่สร้างขึ้นในโปรแกรมแปลภาษา Dart หากเอาต์พุตลงท้ายด้วย "OK" แสดงว่าการทดสอบผ่าน

การแก้ไขการทดสอบเครื่องมือสร้างบล็อก

  1. โหลด tests/generators/index.html ในเบราว์เซอร์
  2. เลือกส่วนที่เกี่ยวข้องของระบบจากเมนูแบบเลื่อนลง แล้วคลิก "โหลด" บล็อกจะปรากฏในพื้นที่ทํางาน
  3. ทำการเปลี่ยนแปลงหรือเพิ่มเติมบล็อก
  4. คลิก "XML"
  5. คัดลอก XML ที่สร้างขึ้นลงในไฟล์ที่เหมาะสมใน tests/generators/