Skip to content
Grok

การทดสอบด้วย Snapshot

การทดสอบแบบ Snapshot เป็นเครื่องมือที่มีประโยชน์มากเมื่อคุณต้องการตรวจสอบว่าผลลัพธ์ของฟังก์ชันไม่เปลี่ยนแปลงโดยไม่คาดคิด

เมื่อใช้ Snapshot, Vitest จะบันทึกค่าที่กำหนดไว้ แล้วเปรียบเทียบกับไฟล์ Snapshot อ้างอิงที่เก็บไว้คู่กับการทดสอบ การทดสอบจะล้มเหลวถ้า Snapshot ทั้งสองไม่ตรงกัน: อาจเป็นเพราะการเปลี่ยนแปลงที่ไม่คาดคิด หรือ Snapshot อ้างอิงต้องได้รับการอัปเดตเป็นเวอร์ชันใหม่ของผลลัพธ์

การใช้ Snapshots

เพื่อบันทึก Snapshot ของค่า คุณสามารถใช้ toMatchSnapshot() จาก API expect():

ts
import { expect, it } from "vitest";

it("toUpperCase", () => {
  const result = toUpperCase("foobar");
  expect(result).toMatchSnapshot();
});

เมื่อรันการทดสอบนี้ครั้งแรก Vitest จะสร้างไฟล์ Snapshot ที่มีลักษณะดังนี้:

ts
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports["toUpperCase 1"] = "\"FOOBAR\"";

ไฟล์ Snapshot ควรถูก commit พร้อมกับการเปลี่ยนแปลงโค้ด และตรวจสอบเป็นส่วนหนึ่งของกระบวนการ code review ในการรันทดสอบครั้งต่อๆ ไป Vitest จะเปรียบเทียบผลลัพธ์กับ Snapshot ก่อนหน้า ถ้าตรงกัน การทดสอบจะผ่าน ถ้าไม่ตรงกัน อาจเป็นเพราะ test runner พบข้อผิดพลาดในโค้ดที่ควรแก้ไข หรือการใช้งานได้เปลี่ยนแปลงไปและ Snapshot ต้องได้รับการอัปเดต

WARNING

เมื่อใช้ Snapshots กับการทดสอบแบบ async concurrent ต้องใช้ expect จาก Test Context เฉพาะที่เพื่อให้แน่ใจว่าตรวจพบการทดสอบที่ถูกต้อง

Inline Snapshots

ในทำนองเดียวกัน คุณสามารถใช้ toMatchInlineSnapshot() เพื่อเก็บ Snapshot ไว้ในไฟล์ทดสอบโดยตรง:

ts
import { expect, it } from "vitest";

it("toUpperCase", () => {
  const result = toUpperCase("foobar");
  expect(result).toMatchInlineSnapshot();
});

แทนที่จะสร้างไฟล์ Snapshot, Vitest จะแก้ไขไฟล์ทดสอบโดยตรงเพื่ออัปเดต Snapshot เป็นสตริง:

ts
import { expect, it } from "vitest";

it("toUpperCase", () => {
  const result = toUpperCase("foobar");
  expect(result).toMatchInlineSnapshot("\"FOOBAR\"");
});

วิธีนี้ช่วยให้คุณเห็นผลลัพธ์ที่คาดหวังได้โดยตรงโดยไม่ต้องสลับไปมาระหว่างไฟล์ต่างๆ

WARNING

เมื่อใช้ Snapshots กับการทดสอบแบบ async concurrent ต้องใช้ expect จาก Test Context เฉพาะที่เพื่อให้แน่ใจว่าตรวจพบการทดสอบที่ถูกต้อง

การอัปเดต Snapshots

เมื่อค่าที่ได้รับไม่ตรงกับ Snapshot การทดสอบจะล้มเหลวและแสดงความแตกต่างระหว่างทั้งสอง เมื่อการเปลี่ยนแปลง Snapshot เป็นสิ่งที่คาดหวัง คุณอาจต้องการอัปเดต Snapshot จากสถานะปัจจุบัน

ในโหมด watch คุณสามารถกดปุ่ม u ในเทอร์มินัลเพื่ออัปเดต Snapshot ที่ล้มเหลวได้โดยตรง

หรือคุณสามารถใช้ตัวเลือก --update หรือ -u ใน CLI เพื่อให้ Vitest อัปเดต Snapshots:

ts
vitest - u;

File Snapshots

เมื่อเรียกใช้ toMatchSnapshot() เราจะเก็บ Snapshots ทั้งหมดในไฟล์ snap ที่จัดรูปแบบแล้ว ซึ่งหมายความว่าเราต้อง escape อักขระบางตัว (ได้แก่ double-quote " และ backtick `) ในสตริง Snapshot ในขณะเดียวกัน คุณอาจสูญเสียการเน้นไวยากรณ์สำหรับเนื้อหา Snapshot (ถ้าอยู่ในภาษาใดภาษาหนึ่ง)

ด้วยเหตุนี้ เราจึงได้แนะนำ toMatchFileSnapshot() เพื่อเทียบกับไฟล์โดยเฉพาะ วิธีนี้ช่วยให้คุณกำหนดนามสกุลไฟล์ใดๆ ให้กับไฟล์ Snapshot และทำให้อ่านง่ายขึ้น

ts
import { expect, it } from "vitest";

it("render basic", async () => {
  const result = renderHTML(h("div", { class: "foo" }));
  await expect(result).toMatchFileSnapshot("./test/basic.output.html");
});

มันจะเปรียบเทียบกับเนื้อหาของ ./test/basic.output.html และสามารถเขียนกลับได้ด้วยตัวเลือก --update

Image Snapshots

นอกจากนี้ยังสามารถทำ Snapshot ของรูปภาพโดยใช้ jest-image-snapshot:

ts
test("image snapshot", () => {
  expect(readFileSync("./test/stubs/input-image.png"))
    .toMatchImageSnapshot();
});