หน้านี้ไล่ให้เห็นทั้งระบบ automated test: มีเทสแบบไหนบ้าง ใช้เครื่องมืออะไร รันตอนไหน และ contract กับ characterization test ต่างจากเทสทั่วไปอย่างไร เขียนให้คนที่ยังไม่เคยทำ QA อัตโนมัติอ่านเข้าใจ
ยิ่งเทสอยู่ด้านบนยิ่งเร็วและชี้จุดพังได้ตรง ยิ่งอยู่ด้านล่างยิ่งเหมือนผู้ใช้จริงแต่ช้ากว่า ทั้งหกชั้นนี้เสริมกัน ไม่ได้แทนกัน
เรียกฟังก์ชันหรือเซิร์ฟเวอร์ตรงๆ ไม่เปิดเบราว์เซอร์ จึงจบในเสี้ยววินาที เช่น เช็กว่าเซิร์ฟเวอร์ตอบ 200/301/304/400/404/405/500 ถูกต้อง และสคริปต์แจ้งผลสร้างข้อความ PASS/FAIL ได้ตรง
กำหนด "รูปร่างที่ข้อมูลต้องเป็น" ไว้ที่เดียว (schema) แล้วเช็กทุกจุดที่ข้อมูลข้ามจากส่วนหนึ่งไปอีกส่วน ถ้าฝั่งหนึ่งเปลี่ยนรูปแล้วอีกฝั่งไม่รู้ เทสจะพังทันที ดูรายละเอียดในข้อ 2
ไม่ได้ถามว่า "ควรทำอะไร" แต่บันทึก "ตอนนี้ทำอะไรอยู่จริง" รวมถึงพฤติกรรมแปลกๆ ไว้เป็นหลักฐาน เพื่อให้รู้ทันทีเมื่อมีใครไปเปลี่ยนมันโดยไม่ตั้งใจ ดูรายละเอียดในข้อ 3
เปิดเบราว์เซอร์จริง คลิก กรอก แล้วเช็กผล แบ่งตามส่วนของแอป: สมัคร/login 27, งาน 27, โปรไฟล์ 10 และเส้นทางเต็มหลายหน้า 6 ข้อมูลที่ใช้เป็นผู้ใช้สมมติ (demo, alice)
ให้ axe-core สแกนทุกหน้าและทุกสถานะ (ปกติ, มี error, กำลังแก้, dark mode) ตามมาตรฐาน WCAG 2.1 ระดับ A และ AA และมีเคสพิเศษที่ยัดข้อผิดพลาดเข้าไปเองเพื่อพิสูจน์ว่าตัวสแกนจับได้จริง ไม่ผ่านแบบเงียบๆ
ไม่ใช่เทสชนิดใหม่ แต่เป็นการเลือก 5 เคสจาก E2E ที่เป็นเส้นทางสำคัญที่สุดมารันก่อน (ติด tag @smoke) ใช้กับทุก push และ pull request
| ส่วนของโปรเจกต์ | มีไว้ทำอะไร |
|---|---|
app/index.html, app/server.mjs | แอป Task Board และเซิร์ฟเวอร์ static ที่เป็นเป้าหมายของเทสทั้งหมด |
tests/support/pages.ts | Page Object: รวมวิธี "กดปุ่มนี้ กรอกช่องนั้น" ไว้ที่เดียว เทสจึงอ่านง่ายและแก้ที่เดียวเมื่อหน้าตาเปลี่ยน |
tests/support/storage.ts | ตัวช่วยอ่าน/เขียน localStorage ตรงๆ: seedStorage (ยัดข้อมูลแล้ว reload), readJson, readRaw, dumpStorage |
tests/fixtures/reports/ | รายงานจำลอง 3 แบบ (pass, fail-nested, empty) ให้ unit test ใช้ทดสอบสคริปต์แจ้งผล โดยไม่ต้องรัน Playwright จริง |
contracts/schemas.mjs | ที่เดียวที่นิยามรูปร่างข้อมูลทั้ง 3 ขอบเขต ทั้ง Playwright และ node:test import ไปใช้ร่วมกัน |
เปรียบเหมือนแบบฟอร์มที่สองแผนกตกลงกันว่าต้องกรอกช่องอะไรบ้าง ถ้าแผนกหนึ่งเปลี่ยนแบบฟอร์มโดยไม่บอก อีกแผนกจะอ่านไม่ออก contract test คือคนตรวจแบบฟอร์มทุกครั้งที่ส่งต่อ
| ชื่อ | ข้อตกลงว่าอย่างไร | ตรวจโดย |
|---|---|---|
| C1 localStorage | แอปเขียนได้เฉพาะ key ที่กำหนด และรูปข้อมูลต้องตรง เช่น งานแต่ละชิ้นต้องเป็น { id: จำนวนเต็ม, title: ข้อความ, priority: low|medium|high, done: จริง/เท็จ } id ห้ามซ้ำ session ต้องชี้ไปผู้ใช้ที่มีอยู่จริง และงานต้องเป็นของผู้ใช้ที่มีอยู่ |
tests/contracts/storage.spec.ts ขับ UI จริง (สมัคร เพิ่ม/แก้/ลบงาน เปลี่ยนโปรไฟล์ ลบบัญชี สลับผู้ใช้) แล้วตรวจ storage หลังแต่ละขั้น |
| C2 รายงาน Playwright | ไฟล์ results.json ต้องมี stats (expected, unexpected, flaky, skipped เป็นจำนวนเต็มไม่ติดลบ) และ suites ที่มี title เพราะ notify.mjs พึ่งพาแค่ส่วนนี้ |
unit/contracts.test.mjs ตรวจกับ fixture 3 แบบ และกับรายงานจากการรันจริงครั้งล่าสุด (ถ้ามีไฟล์) พร้อมเคสที่ต้องถูกปฏิเสธ |
| C3 body ที่ส่ง webhook | ต้องมี content (Discord) และ text (Slack) เป็นข้อความไม่ว่างและเหมือนกัน ห้ามมี field เกิน |
unit/contracts.test.mjs ยกเซิร์ฟเวอร์ปลอมขึ้นมารับ แล้วรัน notify.mjs จริง เก็บ body ที่ส่งมาตรวจกับ schema |
จุดเด่นคือ schema อยู่ที่เดียว (contracts/schemas.mjs เขียนด้วย zod) ทั้งเทสในเบราว์เซอร์และเทส node ใช้ไฟล์เดียวกัน จึงไม่มีทางที่สองฝั่งจะเข้าใจ "รูปร่างที่ถูก" ไม่ตรงกัน และ state ที่ตรวจเกิดจากการขับ UI จริง ไม่ได้สร้างขึ้นเองด้วยมือ
เหมือนถ่ายรูปห้องก่อนย้ายของ ไม่ได้บอกว่าห้องควรหน้าตาแบบนี้ แต่ถ้าวันหลังมีอะไรหายไปจะรู้ทันที เหมาะกับโค้ดที่ยังไม่มีสเปกเขียนไว้ชัด หรือก่อนจะแก้ของเก่าที่ไม่แน่ใจว่าอะไรผูกกันอยู่
| ไฟล์ | จดไว้ว่า |
|---|---|
validation.spec.ts | ขอบเขตของทุกฟอร์ม: ความยาว username (3 ถึง 20 ตัว, ใช้ได้เฉพาะตัวอักษร ตัวเลข underscore), รหัสผ่านขั้นต่ำ 8 ตัว, ชื่องานไม่เกิน 80 ตัว, ลำดับการตรวจ (ตรวจ username ก่อนรหัสผ่าน ตรวจรหัสเดิมก่อนความยาวก่อนการยืนยัน), username ไม่สนตัวพิมพ์เล็ก/ใหญ่ แต่รหัสผ่านสนใจ, login ผิดทุกกรณีใช้ข้อความเดียวกัน |
resilience.spec.ts | แอปบูตอย่างไรเมื่อ storage ผิดปกติ (JSON พัง, ข้อมูลผิดชนิด, งานผิดรูปปนกับงานดี, theme แปลก) และกฎการ redirect ของแต่ละ route รวมถึง title ของแต่ละหน้า |
unit/contracts.test.mjs | ข้อความที่ notify.mjs สร้างจากรายงานแต่ละแบบ ตรงตามตัวอักษร และรายงานที่ไม่มีเทสเลยถูกนับเป็น PASS |
__proto__ และ constructor สมัครได้tb.users ถูกเก็บเป็น array แอปจะไม่ซ่อมให้และทุกคน login ไม่ได้รายการนี้ดึงจาก package.json, playwright.config.ts และไฟล์ workflow ที่ใช้งานจริง
เปิด Chromium จริง ควบคุมเบราว์เซอร์ให้คลิกและกรอกข้อมูล มีระบบ assert, retry และรันขนานในตัว ตั้งให้เปิดเว็บเทสให้เองก่อนรัน
playwright.config.ts · retry 2 ครั้งและ 2 workers บน CI · เก็บ screenshot/video/trace เฉพาะเคสที่พังtest runner ที่มีในตัว Node ไม่ต้องติดตั้งเพิ่ม ใช้กับเทสที่ไม่ต้องเปิดเบราว์เซอร์ ผลจึงออกเร็ว มีโหมดวัด coverage ในตัว
npm run test:unit · npm run test:unit:coverageไลบรารีเขียน schema ของข้อมูลแล้วตรวจว่าข้อมูลจริงตรงไหม ใช้เป็นภาษากลางของ contract ทั้งสามขอบเขต
contracts/schemas.mjsสแกนหน้าเว็บหา violation ตาม WCAG 2.1 A/AA เช่น ภาพไม่มี alt, สีตัวอักษรตัดกับพื้นไม่พอ, ฟอร์มไม่มี label
tests/a11y.spec.tsเซิร์ฟเวอร์ static ที่เขียนเอง ไม่ต้องติดตั้งอะไรเพิ่ม Playwright เปิดให้อัตโนมัติ (พอร์ต 3000 เปลี่ยนได้ด้วย PORT) หรือชี้ไปเว็บอื่นด้วย BASE_URL
unit/server.test.mjs)list พิมพ์ผลในเทอร์มินัล html สร้างรายงานเปิดดูด้วย npm run report json เขียน test-results/results.json ซึ่งสคริปต์แจ้งผลอ่านต่อ
--reporter เองจะไม่มี results.json และแจ้งผลผิดเป็น FAILเก็บผลดิบเป็น allure-results แล้วสร้างรายงานที่แบ่งตามพฤติกรรมและ suite ดูย้อนหลังได้ ต้องมี Java ในเครื่องตอนสร้างรายงาน
npm run allure:generate · allure:open · allure:serveรันบนเครื่อง ubuntu และ Node 22 มี 2 workflow: Smoke ทุก push ไป main และทุก PR, Weekend E2E ตามเวลาเสาร์-อาทิตย์ แล้วอัปโหลดรายงานเก็บไว้ (14 วัน)
.github/workflows/smoke.yml · weekend-e2e.ymlสคริปต์อ่าน results.json สรุปเป็นข้อความ ✅/❌ แล้ว POST เข้า webhook ที่เก็บเป็นความลับใน GitHub Secrets (WEBHOOK_URL) รันทุกครั้งแม้เทสพัง
scripts/notify.mjsเส้นทางของ workflow เต็มตอนเสาร์-อาทิตย์ ส่วน Smoke ใช้เฉพาะขั้น 1 ถึง 4 กับเทส 5 เคส
npm ci และ npx playwright install --with-deps chromiumplaywright-report และ test-results เป็น artifactnotify.mjs อ่าน results.json ส่งข้อความสรุปเข้า Discord หรือ Slack พร้อมลิงก์ไปดู run| สถานการณ์ | คำสั่ง |
|---|---|
| เพิ่งแก้นิดเดียว อยากเช็กเร็ว | npm run test:smoke |
| แก้สคริปต์แจ้งผลหรือเซิร์ฟเวอร์ | npm run test:unit |
| แก้รูปแบบข้อมูลที่เก็บใน storage | npx playwright test --grep @contract |
| แก้กฎตรวจข้อมูลหรือข้อความ error | npx playwright test --grep @characterization |
| แก้หน้าตา เลย์เอาต์ สี | npx playwright test --grep @a11y |
| ก่อน release | npm run test:unit แล้ว npm test |
| อยากเห็นว่าคำสั่งจะรันอะไรโดยไม่รัน | npx playwright test --list --grep @contract |
Tag ลักษณะเคสที่ใช้อยู่: @smoke @validation @security @persistence @resilience @destructive @a11y @responsive @contract @characterization และ tag ตามพื้นที่ @auth @tasks @profile @journey เคสหนึ่งมีได้หลาย tag
smoke.yml และ weekend-e2e.yml รันเฉพาะ Playwright เท่านั้น เทส 42 เคสใน unit/ (รวม contract C2 และ C3) ต้องสั่ง npm run test:unit เองในเครื่อง ถ้าอยากให้ถูกจับอัตโนมัติ ให้เพิ่ม step นี้ใน workflow