เครื่องมือประกอบธุรกิจ

โดยพื้นฐานแล้ว การทดสอบอัตโนมัติเป็นเพียงโค้ดที่จะทำให้เกิดข้อผิดพลาดหรือ มีบางอย่างไม่ถูกต้อง ไลบรารีหรือกรอบการทดสอบส่วนใหญ่มี พื้นฐานที่ทำให้เขียนการทดสอบได้ง่ายขึ้น

ดังที่กล่าวไว้ในส่วนก่อนหน้านี้ ตัวแปรพื้นฐานเหล่านี้มักจะรวม วิธีกําหนดการทดสอบอิสระ (เรียกว่ากรอบการทดสอบ) และระบุ การยืนยันของคุณ การยืนยันเป็นวิธีหนึ่งที่จะผสมผสานการตรวจสอบผลลัพธ์กับการโยน หากมีข้อผิดพลาดเกิดขึ้น และถือได้ว่าเป็นข้อมูลพื้นฐาน กับการทดสอบพื้นฐาน

หน้านี้จะกล่าวถึงวิธีการทั่วไปเกี่ยวกับคำพื้นฐานเหล่านี้ เฟรมเวิร์กที่คุณเลือก อาจมีข้อความแบบนี้ แต่นี่ไม่ใช่การอ้างอิงที่ถูกต้อง

เช่น

import { fibonacci, catalan } from '../src/math.js';
import { assert, test, suite } from 'a-made-up-testing-library';

suite('math tests', () => {
  test('fibonacci function', () => {
    // check expected fibonacci numbers against our known actual values
    // with an explanation if the values don't match
    assert.equal(fibonacci(0), 0, 'Invalid 0th fibonacci result');
    assert.equal(fibonacci(13), 233, 'Invalid 13th fibonacci result');
  });
  test('relationship between sequences', () => {
    // catalan numbers are greater than fibonacci numbers (but not equal)
    assert.isAbove(catalan(4), fibonacci(4));
  });
  test('bugfix: check bug #4141', () => {
    assert.isFinite(fibonacci(0)); // fibonacci(0) was returning NaN
  })
});

ตัวอย่างนี้สร้างกลุ่มการทดสอบ (บางครั้งเรียกว่าชุด) ที่เรียกว่า "คณิตศาสตร์" ทดสอบ" และระบุกรอบการทดสอบอิสระ 3 กรณีซึ่งแต่ละกรณีมีการยืนยันบางอย่าง โดยปกติแล้ว กรอบการทดสอบเหล่านี้จะสามารถจัดการหรือเรียกใช้ได้ทีละกรณี ตัวอย่างเช่น Flag ตัวกรองในตัวดำเนินการทดสอบ

ตัวช่วยการยืนยันในฐานะพื้นฐาน

เฟรมเวิร์กการทดสอบส่วนใหญ่ รวมถึง Vitest มีคอลเล็กชันการยืนยัน ในออบเจ็กต์ assert ซึ่งช่วยให้คุณตรวจสอบค่าที่แสดงผลหรือ รัฐอื่นๆ เมื่อเทียบกับความคาดหวังบางอย่าง ความคาดหวังนั้นมักจะ "เป็นที่รู้จักดี" ในตัวอย่างก่อนหน้านี้ เราทราบว่าหมายเลข Fibonacci หมายเลข 13 ควรเป็น 233 เพื่อให้เราสามารถยืนยันได้โดยใช้ assert.equal โดยตรง

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

  • 'truthy' ตรวจสอบ โดยทั่วไปเรียกว่า "ตกลง" ตรวจสอบ ตรวจสอบว่าเงื่อนไขเป็นจริง ตรงกับวิธีที่คุณเขียน if ที่ตรวจสอบว่าบางสิ่งประสบความสำเร็จ หรือ ถูกต้อง ซึ่งมักจะระบุเป็น assert(...) หรือ assert.ok(...) และ ต้องใช้ค่าเดียวบวกกับความคิดเห็นเสริม

  • การตรวจสอบความเท่ากันดังเช่นในตัวอย่าง คณิตศาสตร์ซึ่งคุณคาดหวังว่า แสดงผลค่าหรือสถานะของออบเจ็กต์ให้เท่ากับค่าที่ดีที่ทราบ ตัวเลือกเหล่านี้มีไว้เพื่อ ความเท่าเทียมกันพื้นฐาน (เช่น สำหรับตัวเลขและสตริง) หรือความเท่าเทียมกันของการอ้างอิง (เป็นวัตถุเดียวกัน) เบื้องหลังเหล่านี้เป็นเพียง 'ตัวจริง' ทำเครื่องหมาย ด้วยการเปรียบเทียบ == หรือ ===

    • JavaScript จะแยกความแตกต่างระหว่างความเท่าเทียมแบบหลวม (==) และเข้มงวด (===) ไลบรารีการทดสอบส่วนใหญ่มีเมธอด assert.equal และ assert.strictEqual ตามลำดับ
  • การตรวจสอบความเท่าเทียมกันอย่างละเอียด ซึ่งขยายการตรวจสอบความเท่าเทียมกัน ซึ่งรวมถึงการตรวจสอบ เนื้อหาของออบเจ็กต์ อาร์เรย์ และข้อมูลประเภทอื่นๆ ที่ซับซ้อนมากขึ้น รวมถึง ตรรกะภายในข้ามผ่านวัตถุเพื่อเปรียบเทียบ สิ่งเหล่านี้มีความสำคัญ เนื่องจาก JavaScript ไม่มีวิธีในตัวสำหรับเปรียบเทียบเนื้อหาของ 2 ออบเจ็กต์หรืออาร์เรย์ เช่น [1,2,3] == [1,2,3] จะเป็นเท็จเสมอ ทดสอบ เฟรมเวิร์กมักมีผู้ช่วย deepEqual หรือ deepStrictEqual

โปรแกรมช่วยยืนยันที่จะเปรียบเทียบค่า 2 ค่า (ไม่ใช่การตรวจสอบ 'ตัวจริง' เพียงอย่างเดียว) โดยทั่วไปแล้วจะใช้อาร์กิวเมนต์ 2 หรือ 3 รายการดังนี้

  • ค่าจริงตามที่สร้างขึ้นจากโค้ดภายใต้การทดสอบหรืออธิบายพารามิเตอร์ สถานะที่ต้องตรวจสอบ
  • ค่าที่คาดไว้ ซึ่งโดยทั่วไปจะฮาร์ดโค้ด (เช่น ตัวเลขลิเทอรัล หรือ สตริง)
  • ความคิดเห็นที่ไม่บังคับเพื่ออธิบายสิ่งที่คาดว่าจะเกิดหรือสิ่งที่อาจล้มเหลว ซึ่งจะรวมอยู่ด้วยหากบรรทัดนี้ล้มเหลว

และยังเป็นแนวทางปฏิบัติที่ใช้กันโดยทั่วไปในการรวมการยืนยันเข้าด้วยกันเพื่อสร้าง เนื่องจากมีโอกาสน้อยที่เราจะสามารถยืนยันสถานะ ด้วยตัวเอง เช่น

  test('JWT parse', () => {
    const json = decodeJwt('eyJieSI6InNhbXRob3Ii');

    assert.ok(json.payload.admin, 'user should be admin');
    assert.deepEqual(json.payload.groups, ['role:Admin', 'role:Submitter']);
    assert.equal(json.header.alg, 'RS265')
    assert.isAbove(json.payload.exp, +new Date(), 'expiry must be in future')
  });

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

การรับรองด้านความคล่องแคล่วและ BDD

นักพัฒนาแอปบางรายชอบรูปแบบการยืนยันที่เรียกได้ว่าเป็นการขับเคลื่อนด้วยพฤติกรรม (BDD) หรือ สไตล์คล่องแคล่ว การยืนยันของคุณ หรือที่เรียกว่า "ความคาดหวัง" เพราะเป็นจุดแรกเข้าที่ การตรวจสอบความคาดหวังคือเมธอดชื่อ expect()

คาดหวังว่าผู้ช่วยเหลือจะมีพฤติกรรมเหมือนกับการยืนยันที่เขียนในวิธีง่ายๆ อย่าง assert.ok หรือ assert.strictDeepEquals แต่นักพัฒนาซอฟต์แวร์บางรายกลับอ่านง่ายกว่า การยืนยัน BDD อาจมีรูปแบบดังนี้

// A failure here would generate "Expect result to be an array that does include 42"
const result = await possibleMeaningsOfLife();
expect(result).to.be.an('array').that.does.include(42);

// or a simpler form
expect(result).toBe('array').toContainEqual(42);

// the same in assert might be
assert.typeOf(result, 'array', 'Expected the result to be an array');
assert.include(result, 42, 'Expected the result to include 42');

การยืนยันรูปแบบนี้ได้ผลเพราะเทคนิคที่เรียกว่าการทำห่วงโซ่เมธอด โดยที่ออบเจ็กต์ที่ expect แสดงผลมาสามารถเชื่อมโยงเข้าด้วยกันอย่างต่อเนื่องกับ ในการเรียกเมธอดเพิ่มเติม บางส่วนของการโทร รวมถึง to.be และ that.does ในตัวอย่างก่อนหน้านี้ ไม่มีฟังก์ชัน และรวมอยู่เพื่อทำการเรียก อ่านง่ายขึ้น และมีแนวโน้มที่จะสร้างความคิดเห็นอัตโนมัติขึ้นหากการทดสอบ ล้มเหลว (โปรดทราบว่าโดยปกติแล้ว expect จะไม่รองรับความคิดเห็นที่ไม่บังคับเนื่องจาก โซ่ควรอธิบายถึงความล้มเหลวอย่างชัดเจน)

เฟรมเวิร์กการทดสอบจำนวนมากรองรับทั้ง Fluent/BDD และการยืนยันตามปกติ ล่าสุด ตัวอย่างเช่น ส่งออกทั้ง แนวทางของชามีแนวทางที่ชัดเจนมากขึ้นอีกเล็กน้อยสำหรับ BDD เจสต์ ในทางกลับกัน จะมีเพียงความคาดหวัง โดยค่าเริ่มต้น

จัดกลุ่มการทดสอบในไฟล์ต่างๆ

เวลาเขียนข้อสอบ เรามักจะใช้การจัดกลุ่มแบบโดยนัยอยู่แล้ว การทดสอบทั้งหมดที่อยู่ในไฟล์เดียว จึงเป็นเรื่องปกติที่จะเขียนการทดสอบในหลายๆ อันที่จริง ผู้ดำเนินการทดสอบมักจะทราบเพียงว่าไฟล์มีไว้สำหรับการทดสอบเนื่องจาก ของตัวกรองหรือนิพจน์ทั่วไปที่กำหนดไว้ล่วงหน้า เช่น Vitest ประกอบด้วย ไฟล์ในโปรเจ็กต์ที่ลงท้ายด้วยส่วนขยาย เช่น ".test.jsx" หรือ ".spec.ts" (".test" และ ".spec" รวมถึงส่วนขยายที่ถูกต้องอีกจำนวนหนึ่ง)

การทดสอบคอมโพเนนต์มักจะอยู่ในไฟล์เพียร์กับคอมโพเนนต์ที่อยู่ระหว่างการทดสอบ เช่นในโครงสร้างไดเรกทอรีต่อไปนี้

วันที่ รายการไฟล์ใน
  ซึ่งรวมถึง UserList.tsx และ UserList.test.tsx
ไฟล์คอมโพเนนต์และไฟล์ทดสอบที่เกี่ยวข้อง

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

จัดกลุ่มการทดสอบภายในไฟล์

ตามที่ใช้ในตัวอย่างก่อนหน้านี้ ถือเป็นแนวทางปฏิบัติทั่วไปที่จะทำการทดสอบภายในการประชุมเพื่อ suite() ที่จัดกลุ่มการทดสอบที่คุณตั้งค่าไว้ด้วย test() ปกติแล้วห้องสวีทจะไม่ให้บริการ ด้วยตนเอง แต่ช่วยกำหนดโครงสร้างโดยการจัดกลุ่มการทดสอบที่เกี่ยวข้องกัน หรือเป้าหมายโดยเรียกใช้เมธอดที่ผ่าน สำหรับ test() เมธอดที่ส่งผ่านจะอธิบาย การทำงานของการทดสอบเอง

เช่นเดียวกับการยืนยัน ความเทียบเท่ากันก็อยู่ในระดับที่ค่อนข้างเป็นมาตรฐานใน Fluent/BDD การจัดกลุ่มการทดสอบ ตัวอย่างทั่วไปบางส่วนจะมีการเปรียบเทียบในโค้ดต่อไปนี้

// traditional/TDD
suite('math tests', () => {
  test('handle zero values', () => {
    assert.equal(fibonacci(0), 0);
  });
});

// Fluent/BDD
describe('math tests', () => {
  it('should handle zero values', () => {
    expect(fibonacci(0)).toBe(0);
  });
})

ในเฟรมเวิร์กส่วนใหญ่ suite และ describe มีลักษณะการทํางานคล้ายคลึงกัน เช่นเดียวกับ test และ it ซึ่งตรงข้ามกับความแตกต่างที่มากกว่าระหว่างการใช้ expect และ assert เพื่อเขียนการยืนยัน

เครื่องมืออื่นๆ มีแนวทางในการจัดเรียงชุดโปรแกรมและการทดสอบที่ค่อนข้างแตกต่างกัน สำหรับ ตัวอย่างเช่น ตัวดำเนินการทดสอบในตัวของ Node.js รองรับการเรียกซ้อนไปยัง test() เพื่อ สร้างลำดับชั้นการทดสอบโดยปริยาย อย่างไรก็ตาม Vitest จะอนุญาตเฉพาะ การซ้อนโดยใช้ suite() และจะไม่เรียกใช้ test() ที่กำหนดไว้ภายใน test() อื่น

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

วิธีการใช้วงจร

เหตุผลหนึ่งที่ต้องจัดกลุ่มการทดสอบของคุณ แม้ว่าจะไม่ได้เจาะจงที่ระดับบนสุดภายใน คือการระบุวิธีการตั้งค่าและแยกส่วนที่ใช้สำหรับการทดสอบแต่ละครั้ง สำหรับกลุ่มการทดสอบ เฟรมเวิร์กส่วนใหญ่จะมี 4 วิธี ดังนี้

สำหรับทุก "test()" หรือ "it()" ครั้งสำหรับห้องสวีท
ก่อนทำการทดสอบ `beforeแต่ละแคมเปญ()` `beforeAll()`
หลังทำการทดสอบ "หลังจากแต่ละรายการ()" "afterAll()"

เช่น คุณอาจต้องการสร้างฐานข้อมูลผู้ใช้เสมือนไว้ล่วงหน้าก่อนแต่ละรายการ แล้วล้างออกหลังจากนั้น

suite('user test', () => {
  beforeEach(() => {
    insertFakeUser('bob@example.com', 'hunter2');
  });
  afterEach(() => {
    clearAllUsers();
  });

  test('bob can login', async () => {  });
  test('alice can message bob', async () => {  });
});

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

คำแนะนำทั่วไป

ต่อไปนี้คือเคล็ดลับที่ควรคำนึงถึงเมื่อคิดถึงปัจจัยพื้นฐานเหล่านี้

แบบพื้นฐานคือแนวทาง

อย่าลืมว่าเครื่องมือและคำพื้นฐานที่นี่ และในอีก 2-3 หน้าถัดไปจะไม่ ตรงกับ Vitest, Jest, Mocha หรือ Web Test Runner ทุกประการ เฟรมเวิร์กที่เฉพาะเจาะจง แม้ว่าเราจะใช้ Vitest เป็นคำแนะนำทั่วไป แต่คุณก็ควรแมป ตามกรอบโครงสร้างที่คุณเลือก

ผสมผสานการยืนยันตามความจำเป็น

โดยพื้นฐานแล้ว การทดสอบอาจเป็นโค้ดที่ทำให้เกิดข้อผิดพลาดได้ นักวิ่งทุกคนจะจัดให้มี พื้นฐาน น่าจะเป็น test() เพื่ออธิบายกรอบการทดสอบที่แตกต่างกัน

แต่หากตัวดำเนินการดังกล่าวมี assert(), expect() และผู้ช่วยเหลือด้านการยืนยันด้วย อย่าลืมว่าส่วนนี้เป็นเรื่องของความสะดวกสบายมากกว่า และคุณสามารถข้ามส่วนนี้ไปได้ จำเป็น คุณสามารถเรียกใช้โค้ดใดๆ ที่อาจทำให้เกิดข้อผิดพลาด รวมถึงโค้ดอื่นๆ ไลบรารีการยืนยัน หรือคำสั่ง if ที่ล้าสมัยแล้ว

การตั้งค่า IDE อาจช่วยชีวิตคนได้

ตรวจสอบว่า IDE เช่น VSCode มีสิทธิ์เข้าถึงการเติมข้อความอัตโนมัติและ เกี่ยวกับเครื่องมือทดสอบที่เลือก จะช่วยให้คุณมีประสิทธิภาพมากขึ้น สำหรับ ตัวอย่างเช่น มีเมธอดกว่า 100 รายการใน assert ในการยืนยัน Chai และมีเอกสารประกอบสำหรับ การปรากฏแบบอินไลน์ก็สะดวก

ซึ่งเป็นสิ่งสำคัญอย่างยิ่งสำหรับกรอบการทดสอบบางกรอบที่สร้าง ของ Namespace ทั่วโลก พร้อมกับวิธีการทดสอบ นี่คือความแตกต่างเพียงเล็กน้อย แต่ คุณใช้ไลบรารีการทดสอบโดยไม่ต้องนำเข้าได้ หาก เพิ่มลงในเนมสเปซส่วนกลางโดยอัตโนมัติ:

// some.test.js
test('using test as a global', () => {  });

เราขอแนะนำให้นำเข้าตัวช่วยแม้ว่าจะมีการรองรับโดยอัตโนมัติ เพราะจะช่วยให้ IDE ของคุณมีวิธีการค้นหาวิธีการเหล่านี้ที่ชัดเจน (คุณอาจ พบปัญหานี้เมื่อสร้าง React เนื่องจากโค้ดเบสบางตัวมีความพิเศษ React ทั่วโลก แต่บางรายการไม่มี และกำหนดให้นำเข้าในไฟล์ทั้งหมดโดยใช้ React.)

// some.test.js
import { test } from 'vitest';
test('using test as an import', () => {  });