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

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

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

การทดสอบ JS

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

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

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

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

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

ผู้ช่วยทดสอบ

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

ฟังก์ชันตัวช่วยประกอบด้วย 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 หน่วยจะเป็นไปตามโครงสร้างชุดเดียวกัน ซึ่งสรุปได้เป็นจัดเรียง ดำเนินการ ยืนยัน

  1. จัดเรียง: กำหนดสภาพของโลกและเงื่อนไขใดๆ ที่จำเป็นสำหรับลักษณะการทำงานภายใต้การทดสอบ
  2. ดำเนินการ: เรียกใช้โค้ดที่อยู่ระหว่างการทดสอบเพื่อทริกเกอร์ลักษณะการทำงานที่กำลังทดสอบ
  3. ยืนยัน: ยืนยันค่าที่แสดงผลหรือการโต้ตอบกับออบเจ็กต์ที่จำลองเพื่อยืนยันความถูกต้อง

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