สรุปโดยย่อ
Test case (กรณีทดสอบ) คือสถานการณ์การทดสอบเดียวที่ตรวจสอบพฤติกรรมหรือข้อกำหนดเฉพาะเจาะจงเพียงอย่างเดียว ในขณะที่ Test suite (ชุดทดสอบ) คือชุดของกรณีทดสอบที่เกี่ยวข้องซึ่งจัดกลุ่มเข้าด้วยกันเพื่อการดำเนินการที่เป็นระบบ Test case กำหนดว่าจะทดสอบอะไรและทดสอบอย่างไร Test suite จัดระเบียบกรณีทดสอบหลายกรณีให้เป็นกลุ่มเชิงตรรกะเพื่อเวิร์กโฟลว์การทดสอบที่มีประสิทธิภาพ
บทนำ
คุณกำลังสร้าง API คุณเขียนการทดสอบแรก จากนั้นอีกอัน ในไม่ช้าคุณก็มีการทดสอบ 50 รายการที่กระจัดกระจายอยู่ในไฟล์ต่างๆ อันไหนทดสอบการรับรองความถูกต้อง? อันไหนทำงานก่อนการปรับใช้? คุณจะเรียกใช้การทดสอบที่สำคัญเท่านั้นได้อย่างไร?
ความสับสนนี้เกิดขึ้นเมื่อนักพัฒนาไม่เข้าใจความแตกต่างระหว่าง Test cases และ Test suites การสำรวจนักพัฒนา 1,200 คนในปี 2023 พบว่า 67% ประสบปัญหาในการจัดระเบียบการทดสอบ ซึ่งนำไปสู่ CI/CD pipeline ที่ช้าลงและการแก้ไขข้อบกพร่องที่ยากขึ้น แนวคิดทั้งสองนี้เป็นรากฐานของการทดสอบที่เป็นระบบ แต่บ่อยครั้งที่ใช้สลับกันหรือเข้าใจผิด
การทำความเข้าใจความแตกต่างจะช่วยให้คุณจัดระเบียบการทดสอบได้อย่างมีเหตุผล เรียกใช้งานได้อย่างมีประสิทธิภาพ และบำรุงรักษาได้เมื่อ API ของคุณเติบโตขึ้น ไม่ว่าคุณจะทดสอบด้วย Apidog หรือเครื่องมืออื่น การรู้ว่าเมื่อใดควรสร้าง Test case ใหม่เทียบกับเมื่อใดควรรวม Test cases เข้าด้วยกันเป็น Test suites จะทำให้เวิร์กโฟลว์การทดสอบของคุณเร็วขึ้นและน่าเชื่อถือยิ่งขึ้น
ในคู่มือนี้ คุณจะได้เรียนรู้ความแตกต่างที่ชัดเจนระหว่าง Test cases และ Test suites ดูตัวอย่างการทดสอบ API จริง และค้นพบวิธีการจัดระเบียบทั้งสองอย่างเพื่อประสิทธิภาพสูงสุด ในตอนท้าย คุณจะรู้ได้อย่างถ่องแท้ว่าจะจัดโครงสร้างการทดสอบ API ของคุณสำหรับโครงการทุกขนาดได้อย่างไร
Test Case คืออะไร?
Test case คือสถานการณ์การทดสอบเดียวที่เฉพาะเจาะจงซึ่งยืนยันพฤติกรรมหรือข้อกำหนดเพียงอย่างเดียวของซอฟต์แวร์ของคุณ ลองนึกภาพว่าเป็นคำถามเดียวที่คุณถามโค้ดของคุณ: "สิ่งนี้ทำงานได้อย่างถูกต้องหรือไม่?"

แต่ละ Test case ประกอบด้วย:
- Test ID (รหัสทดสอบ): ตัวระบุเฉพาะ (เช่น TC_001)
- Test description (คำอธิบายการทดสอบ): สิ่งที่คุณกำลังทดสอบ
- Preconditions (เงื่อนไขเบื้องต้น): การตั้งค่าที่จำเป็นก่อนการทดสอบ
- Test steps (ขั้นตอนการทดสอบ): การกระทำที่จะดำเนินการ
- Expected result (ผลลัพธ์ที่คาดหวัง): สิ่งที่ควรจะเกิดขึ้น
- Actual result (ผลลัพธ์จริง): สิ่งที่เกิดขึ้นจริง
- Status (สถานะ): ผ่านหรือไม่ผ่าน
องค์ประกอบของ Test Case
นี่คือ Test case ง่ายๆ สำหรับ API endpoint:
รหัส Test Case: TC_AUTH_001
หัวข้อ: ตรวจสอบการเข้าสู่ระบบของผู้ใช้ด้วยข้อมูลประจำตัวที่ถูกต้อง
เงื่อนไขเบื้องต้น: มีบัญชีผู้ใช้ในฐานข้อมูล
ขั้นตอนการทดสอบ:
1. ส่งคำขอ POST ไปยัง /api/auth/login
2. รวมอีเมลและรหัสผ่านที่ถูกต้องในส่วน Body ของคำขอ
3. ตรวจสอบรหัสสถานะการตอบกลับ
4. ตรวจสอบว่ามี JWT token ถูกส่งกลับมา
ผลลัพธ์ที่คาดหวัง:
- รหัสสถานะ: 200
- การตอบกลับมี JWT token ที่ถูกต้อง
- โทเค็นหมดอายุใน 24 ชั่วโมง
ผลลัพธ์จริง: [จะถูกกรอกระหว่างการดำเนินการ]
สถานะ: [ผ่าน/ไม่ผ่าน]
Test cases เป็นแบบ Atomic ซึ่งหมายถึงจะทดสอบสิ่งหนึ่งสิ่งเดียวเท่านั้น หาก Test case ของคุณตรวจสอบทั้งการเข้าสู่ระบบและการอัปเดตโปรไฟล์ ให้แยกออกเป็นสอง Test case
ตัวอย่าง Test Case ในโค้ด
นี่คือลักษณะของ Test case เดียวกันใน JavaScript โดยใช้ Jest:
describe('Authentication API', () => {
test('TC_AUTH_001: should login user with valid credentials', async () => {
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePass123'
})
});
expect(response.status).toBe(200);
const data = await response.json();
expect(data.token).toBeDefined();
expect(data.expiresIn).toBe(86400); // 24 ชั่วโมงในหน่วยวินาที
});
});
สังเกตว่า Test case นี้มุ่งเน้นไปที่สถานการณ์เดียว: การเข้าสู่ระบบที่สำเร็จ จะไม่ทดสอบการเข้าสู่ระบบที่ล้มเหลว การรีเซ็ตรหัสผ่าน หรือการออกจากระบบ สิ่งเหล่านั้นจะเป็น Test case ที่แยกต่างหาก
เหตุใด Test Case จึงมีความสำคัญ
Test cases ให้ประโยชน์แก่คุณดังนี้:
- Traceability (ความสามารถในการตรวจสอบย้อนกลับ): เชื่อมโยงการทดสอบแต่ละครั้งกับข้อกำหนดเฉพาะ
- Repeatability (ความสามารถในการทำซ้ำ): เรียกใช้การทดสอบเดียวกันได้อย่างสม่ำเสมอ
- Documentation (เอกสารประกอบ): การทดสอบทำหน้าที่เป็นเอกสารประกอบที่มีชีวิต
- Debugging (การแก้ไขข้อบกพร่อง): ระบุได้อย่างแม่นยำว่าอะไรเสียเมื่อการทดสอบล้มเหลว
หากไม่มี Test case ที่ชัดเจน คุณจะลงเอยด้วยการทดสอบที่ไม่ชัดเจนซึ่งตรวจสอบหลายสิ่งพร้อมกัน เมื่อการทดสอบล้มเหลว คุณจะเสียเวลาในการหาสาเหตุว่าส่วนใดเสีย
Test Suite คืออะไร?
Test suite คือชุดของกรณีทดสอบที่จัดกลุ่มเข้าด้วยกันเพื่อการดำเนินการที่เป็นระบบ หาก Test cases คือคำถามแต่ละข้อ Test suite ก็คือข้อสอบที่ประกอบด้วยคำถามที่เกี่ยวข้อง

Test suites จัดระเบียบ Test cases โดย:
- Feature (คุณสมบัติ): การทดสอบทั้งหมดสำหรับการรับรองความถูกต้องของผู้ใช้
- Priority (ลำดับความสำคัญ): การทดสอบที่สำคัญที่ต้องผ่านก่อนการปรับใช้
- Type (ประเภท): Smoke tests, regression tests, integration tests
- Environment (สภาพแวดล้อม): การทดสอบสำหรับ staging เทียบกับ production
- Execution time (เวลาดำเนินการ): การทดสอบที่รวดเร็วเทียบกับการทดสอบที่ช้า
โครงสร้าง Test Suite
นี่คือวิธีการที่ Test suites จัดระเบียบ Test cases:
Test Suite: โมดูลการรับรองความถูกต้อง
├── Test Case 1: เข้าสู่ระบบด้วยข้อมูลประจำตัวที่ถูกต้อง
├── Test Case 2: เข้าสู่ระบบด้วยรหัสผ่านไม่ถูกต้อง
├── Test Case 3: เข้าสู่ระบบด้วยอีเมลที่ไม่มีอยู่จริง
├── Test Case 4: เข้าสู่ระบบด้วยโทเค็นที่หมดอายุ
├── Test Case 5: ออกจากระบบสำเร็จ
└── Test Case 6: รีเฟรช Access token
Test Suite: โมดูลโปรไฟล์ผู้ใช้
├── Test Case 1: ดึงโปรไฟล์ผู้ใช้
├── Test Case 2: อัปเดตข้อมูลโปรไฟล์
├── Test Case 3: อัปโหลดรูปโปรไฟล์
└── Test Case 4: ลบบัญชีผู้ใช้
Test suite แต่ละชุดประกอบด้วย Test cases ที่เกี่ยวข้องหลายกรณี คุณสามารถเรียกใช้ทั้งชุดพร้อมกัน หรือเลือก Test cases แต่ละกรณีเพื่อเรียกใช้
ตัวอย่าง Test Suite ในโค้ด
นี่คือลักษณะของ Test suites ใน JavaScript:
// Test suite สำหรับการรับรองความถูกต้อง
describe('Authentication API Test Suite', () => {
test('TC_AUTH_001: Login with valid credentials', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_002: Login with invalid password', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_003: Login with non-existent email', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_004: Logout successfully', async () => {
// การนำการทดสอบไปใช้
});
});
// Test suite สำหรับโปรไฟล์ผู้ใช้
describe('User Profile API Test Suite', () => {
test('TC_PROFILE_001: Get user profile', async () => {
// การนำการทดสอบไปใช้
});
test('TC_PROFILE_002: Update profile information', async () => {
// การนำการทดสอบไปใช้
});
});
บล็อก describe() สร้าง Test suites แต่ละ test() ที่อยู่ภายในคือ Test case คุณสามารถเรียกใช้การทดสอบการรับรองความถูกต้องทั้งหมดด้วยคำสั่งเดียว หรือเรียกใช้ไฟล์การทดสอบทั้งหมด
Test Suites แบบซ้อนกัน
Test suites สามารถมี Test suites อื่นๆ ได้สำหรับโครงการที่ซับซ้อน:
describe('API Test Suite', () => {
describe('Authentication', () => {
describe('Login', () => {
test('with valid credentials', () => {});
test('with invalid password', () => {});
});
describe('Registration', () => {
test('with valid data', () => {});
test('with duplicate email', () => {});
});
});
describe('User Management', () => {
test('get user list', () => {});
test('update user role', () => {});
});
});
สิ่งนี้สร้างลำดับชั้น: Main Suite (ชุดหลัก) → Sub-suites (ชุดย่อย) → Test Cases (กรณีทดสอบ) โครงสร้างนี้สะท้อนสถาปัตยกรรม API ของคุณ
ความแตกต่างที่สำคัญระหว่าง Test Suites และ Test Cases
นี่คือการเปรียบเทียบที่ชัดเจน:
| ด้าน | Test Case | Test Suite |
|---|---|---|
| คำนิยาม | สถานการณ์การทดสอบเดียว | ชุดของกรณีทดสอบ |
| ขอบเขต | ทดสอบพฤติกรรมเฉพาะเจาะจงหนึ่งอย่าง | ทดสอบหลายพฤติกรรมที่เกี่ยวข้อง |
| ความละเอียด | Atomic (ไม่สามารถแยกย่อยได้) | Composite (ประกอบด้วยหลายรายการ) |
| การดำเนินการ | เรียกใช้การทดสอบหนึ่งครั้ง | เรียกใช้การทดสอบหลายครั้ง |
| วัตถุประสงค์ | ตรวจสอบข้อกำหนดหนึ่งข้อ | จัดระเบียบและจัดกลุ่มการทดสอบ |
| ผลลัพธ์ | ผ่านหรือไม่ผ่าน | สรุปผลการทดสอบทั้งหมด |
| ตัวอย่าง | "เข้าสู่ระบบด้วยข้อมูลประจำตัวที่ถูกต้อง" | "การทดสอบโมดูลการรับรองความถูกต้อง" |
| โค้ด | ฟังก์ชัน test() หรือ it() หนึ่งฟังก์ชัน |
บล็อก describe() หรือ suite() หนึ่งบล็อก |
| การนำกลับมาใช้ใหม่ | สามารถเพิ่มในหลายชุดทดสอบได้ | สามารถมีกรณีทดสอบที่ใช้ร่วมกันได้ |
| การบำรุงรักษา | อัปเดตการทดสอบหนึ่งครั้ง | อัปเดตการทดสอบหลายครั้งพร้อมกัน |
การเปรียบเทียบแบบคอนเทนเนอร์
ลองคิดแบบนี้:
- Test Case = ไฟล์เดียวในคอมพิวเตอร์ของคุณ
- Test Suite = โฟลเดอร์ที่ประกอบด้วยไฟล์ที่เกี่ยวข้อง
คุณสามารถมีไฟล์ที่ไม่มีโฟลเดอร์ได้ (Test cases ที่ไม่มี suites) แต่โฟลเดอร์ช่วยจัดระเบียบไฟล์ (suites ช่วยจัดระเบียบ Test cases) คุณยังสามารถมีโฟลเดอร์ซ้อนอยู่ในโฟลเดอร์ได้ (nested test suites)
ความแตกต่างในการดำเนินการ
เมื่อคุณเรียกใช้ Test case:
# เรียกใช้การทดสอบเฉพาะหนึ่งครั้ง
npm test -- --testNamePattern="Login with valid credentials"
เมื่อคุณเรียกใช้ Test suite:
# เรียกใช้การทดสอบทั้งหมดใน Test suite การรับรองความถูกต้อง
npm test -- --testPathPattern="authentication"
Test suites ช่วยให้คุณเรียกใช้กลุ่มการทดสอบที่เกี่ยวข้องได้โดยไม่ต้องเรียกใช้ชุดการทดสอบทั้งหมดของคุณ
Test Suites และ Test Cases ทำงานร่วมกันอย่างไร
Test cases และ Test suites ไม่ใช่แนวคิดที่แข่งขันกัน แต่ทำงานร่วมกันเพื่อสร้างโค้ดทดสอบที่เป็นระบบและสามารถบำรุงรักษาได้
ความสัมพันธ์
โครงการ
└── Test Suites (โฟลเดอร์)
└── Test Cases (ไฟล์)
└── Test Steps (โค้ด)
Test case ทุกกรณีเป็นส่วนหนึ่งของ Test suite อย่างน้อยหนึ่งชุด Test case สามารถเป็นส่วนหนึ่งของหลายชุดได้:
// smoke-tests.suite.js
describe('Smoke Tests', () => {
test('TC_SMOKE_001: API health check', () => {});
test('TC_SMOKE_002: Database connection', () => {});
test('TC_AUTH_001: Login with valid credentials', () => {}); // ใช้ร่วมกัน
});
// authentication.suite.js
describe('Authentication Tests', () => {
test('TC_AUTH_001: Login with valid credentials', () => {}); // ใช้ร่วมกัน
test('TC_AUTH_002: Login with invalid password', () => {});
test('TC_AUTH_003: Password reset flow', () => {});
});
Test case TC_AUTH_001 ปรากฏอยู่ในทั้ง Smoke test suite และ Authentication test suite การนำกลับมาใช้ใหม่นี้ช่วยให้คุณเรียกใช้การทดสอบเดียวกันในบริบทที่แตกต่างกันได้โดยไม่ต้องทำซ้ำ
การรวมเข้ากับเวิร์กโฟลว์
นี่คือวิธีการทำงานในเวิร์กโฟลว์การพัฒนาทั่วไป:
- เขียน Test cases สำหรับคุณสมบัติใหม่
- จัดกลุ่ม Test cases เป็น Test suites ที่มีเหตุผล
- เรียกใช้ suites เฉพาะระหว่างการพัฒนา (การตอบสนองที่รวดเร็ว)
- เรียกใช้ suites ทั้งหมดก่อนการปรับใช้ (การตรวจสอบที่ครอบคลุม)
- วิเคราะห์ผลลัพธ์ของ suite เพื่อระบุพื้นที่ที่มีปัญหา
กลยุทธ์การดำเนินการ
สถานการณ์ที่แตกต่างกันต้องใช้กลยุทธ์การดำเนินการที่แตกต่างกัน:
# ระหว่างการพัฒนา: เรียกใช้ Test case หนึ่งกรณี
npm test -- --testNamePattern="Login with valid credentials"
# ก่อน Commit: เรียกใช้ Test suite ที่เกี่ยวข้อง
npm test -- authentication.test.js
# ใน CI/CD: เรียกใช้ Test suites ที่สำคัญทั้งหมด
npm test -- --testPathPattern="(smoke|critical)"
# ก่อนปล่อย: เรียกใช้ทั้งหมด
npm test
วิธีการแบบแบ่งชั้นนี้ช่วยประหยัดเวลา เรียกใช้ Smoke test 5 ครั้งใน 10 วินาที แทนที่จะเป็น 200 การทดสอบใน 5 นาทีระหว่างการพัฒนา เก็บ Test suite เต็มสำหรับ CI/CD
Test Suite เทียบกับ Test Case ในการทดสอบ API
การทดสอบ API มีลักษณะเฉพาะที่ส่งผลต่อวิธีที่คุณจัดระเบียบ Test cases และ Test suites
โครงสร้าง Test Case ของ API
Test cases ของ API โดยทั่วไปจะตรวจสอบ:
- Request validation (การตรวจสอบคำขอ): Endpoint, เมธอด, Headers, Body ที่ถูกต้อง
- Response validation (การตรวจสอบการตอบกลับ): รหัสสถานะ, Response body, Headers
- Data validation (การตรวจสอบข้อมูล): รูปแบบข้อมูล, ค่า, ประเภท ที่ถูกต้อง
- Error handling (การจัดการข้อผิดพลาด): ข้อความและรหัสข้อผิดพลาดที่เหมาะสม
- Performance (ประสิทธิภาพ): เวลาตอบสนองภายในขีดจำกัดที่ยอมรับได้
นี่คือ Test case API ที่สมบูรณ์:
test('TC_USER_001: Create new user via POST /api/users', async () => {
// จัดเตรียม
const newUser = {
name: 'John Doe',
email: 'john@example.com',
role: 'user'
};
// กระทำ
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer test-token'
},
body: JSON.stringify(newUser)
});
const data = await response.json();
// ยืนยัน
expect(response.status).toBe(201);
expect(data.id).toBeDefined();
expect(data.name).toBe(newUser.name);
expect(data.email).toBe(newUser.email);
expect(data.createdAt).toBeDefined();
});
Test case นี้ตรวจสอบการดำเนินการ API เพียงอย่างเดียว: การสร้างผู้ใช้ จะไม่ทดสอบการอัปเดต การลบ หรือการแสดงรายการผู้ใช้
การจัดระเบียบ Test Suite ของ API
สำหรับ API ให้จัดระเบียบ Test suites โดย:
1. ตาม Endpoint
Test Suite: /api/users
├── GET /api/users (แสดงรายการผู้ใช้)
├── POST /api/users (สร้างผู้ใช้)
├── GET /api/users/:id (ดึงผู้ใช้)
├── PUT /api/users/:id (อัปเดตผู้ใช้)
└── DELETE /api/users/:id (ลบผู้ใช้)
2. ตามคุณสมบัติ
Test Suite: การจัดการผู้ใช้
├── การลงทะเบียนผู้ใช้
├── การรับรองความถูกต้องของผู้ใช้
├── การจัดการโปรไฟล์
└── การลบบัญชี
3. ตามประเภทการทดสอบ
Test Suite: Smoke Tests
├── ตรวจสอบความสมบูรณ์ของ API
├── การเชื่อมต่อฐานข้อมูล
└── Endpoint ที่สำคัญตอบสนอง
Test Suite: Integration Tests
├── ขั้นตอนการลงทะเบียนผู้ใช้
├── ขั้นตอนการประมวลผลคำสั่งซื้อ
└── ขั้นตอนการประมวลผลการชำระเงิน
การจัดการ Test Suite ของ Apidog
Apidog ทำให้การจัดระเบียบ Test suite API เป็นภาพและใช้งานง่าย แทนที่จะเขียนโค้ด คุณสามารถสร้าง Test cases ใน GUI และจัดกลุ่ม Test cases เหล่านั้นเป็น Test suites ด้วยการลากและวาง วิธีนี้ช่วยลดเวลาในการสร้างการทดสอบได้ 60% เมื่อเทียบกับวิธีการที่ใช้โค้ดเป็นหลัก
นี่คือวิธีการที่ Apidog จัดการการจัดระเบียบการทดสอบ:
Test Cases ใน Apidog:
คุณสามารถสร้าง Test cases ได้หลายวิธี:
ในแท็บ Test Cases ของหน้ารายละเอียด Endpoint ให้คลิก + Add Case เพื่อสร้าง Test case ด้วยตนเอง
เมื่อเพิ่ม Test case คุณสามารถเลือกได้ดังนี้
- Import from Debug Cases เพื่อคัดลอกหรือย้าย Debug cases ที่มีอยู่ให้เป็น Test cases
- Copy: ใช้สิ่งนี้เมื่อคุณยังต้องการ Debug case สำหรับการตรวจสอบอย่างรวดเร็ว แต่ก็ต้องการให้เป็น Test case ด้วย
- Move: ใช้สิ่งนี้เมื่อ Debug case ไม่ได้ถูกใช้งานบ่อยสำหรับการดีบักแล้ว และถูกเขียนขึ้นมาเพื่อทดสอบข้อยกเว้นเป็นหลัก สิ่งนี้จะแปลง Debug case ให้เป็น Test case โดยตรง ทำให้การย้ายข้อมูลรวดเร็วขึ้นหาก Test cases เดิมถูกสร้างขึ้นเป็น Debug cases
Test case ประกอบด้วยข้อมูลดังต่อไปนี้:
- Group (กลุ่ม): จัดระเบียบตามวัตถุประสงค์การทดสอบ (เชิงบวก, เชิงลบ, ขอบเขต, ฯลฯ)
- Case Name (ชื่อกรณี): ชื่อของ Test case
- Request Parameters (พารามิเตอร์คำขอ): พารามิเตอร์ Path, Query, Header และ form-data Body
- Request Body (เนื้อหาคำขอ): รองรับ RAW, JSON, XML, ฯลฯ
- Pre/Post Processors (ตัวประมวลผลก่อน/หลัง)
- Response Validation (การตรวจสอบการตอบกลับ): เปิด/ปิดการตรวจสอบและระบุส่วนประกอบการตอบกลับที่จะตรวจสอบ
Test Suites ใน Apidog:
- เมื่อเปิด Apidog ให้ไปที่โมดูล
Testsจากนั้นค้นหาTest Suite
- คลิกปุ่ม
+ New(หรือคลิกเมนู...ถัดจากโฟลเดอร์แล้วเลือกCreate Test Suite) - กรอกชื่อ Test suite ในหน้าต่างป๊อปอัปและตั้งค่าข้อมูลพื้นฐาน เช่น ลำดับความสำคัญ
- คลิก
Continueเพื่อสร้างสำเร็จและเข้าสู่หน้าออกแบบ Test suite
ประโยชน์:
- ไม่ต้องเขียนโค้ดสำหรับการทดสอบพื้นฐาน
- การจัดระเบียบการทดสอบด้วยภาพ
- การยืนยันและการตรวจสอบในตัว
- การสร้างรายงานการทดสอบอัตโนมัติ
- การรวม CI/CD สำหรับการเรียกใช้อัตโนมัติ
คุณสามารถส่งออก Test suites ของ Apidog เป็นโค้ดได้หากจำเป็น ซึ่งให้ความยืดหยุ่นระหว่างการทดสอบแบบ GUI และแบบใช้โค้ด
เมื่อใดควรใช้ Test Cases เทียบกับ Test Suites
การรู้ว่าเมื่อใดควรสร้าง Test case ใหม่เทียบกับเมื่อใดควรรวม Test cases เข้าด้วยกันเป็น Test suites เป็นสิ่งสำคัญสำหรับการทดสอบที่สามารถบำรุงรักษาได้
สร้าง Test Case ใหม่เมื่อ:
- ทดสอบข้อกำหนดใหม่: แต่ละข้อกำหนดควรมี Test case อย่างน้อยหนึ่งกรณี
- ทดสอบสถานการณ์ที่แตกต่างกัน: การเข้าสู่ระบบที่ถูกต้องเทียบกับการเข้าสู่ระบบที่ไม่ถูกต้อง = สอง Test case
- ทดสอบ Edge cases: อินพุตว่างเปล่า, อินพุตสูงสุด, อักขระพิเศษ
- ทดสอบเงื่อนไขข้อผิดพลาด: ข้อผิดพลาด 400, ข้อผิดพลาด 500, สถานการณ์หมดเวลา
- ทดสอบข้อมูลที่แตกต่างกัน: บทบาทผู้ใช้ที่แตกต่างกัน, สิทธิ์ที่แตกต่างกัน
สร้าง Test Suite ใหม่เมื่อ:
- คุณมี Test cases ที่เกี่ยวข้อง 5+ กรณี: จัดกลุ่มเพื่อจัดระเบียบ
- ทดสอบคุณสมบัติที่สมบูรณ์: การทดสอบการรับรองความถูกต้องทั้งหมดพร้อมกัน
- สร้างหมวดหมู่การทดสอบ: Smoke tests, regression tests, performance tests
- จัดระเบียบตามลำดับความสำคัญ: การทดสอบที่สำคัญ, ลำดับความสำคัญสูง, ลำดับความสำคัญต่ำ
- แยกตามสภาพแวดล้อม: การทดสอบ Staging, การทดสอบ Production
รูปแบบที่ควรหลีกเลี่ยง
อย่าทำสิ่งนี้:
// แย่: Test case ขนาดยักษ์เดียวที่ทดสอบทุกสิ่ง
test('Test entire user flow', () => {
// ทดสอบการลงทะเบียน การเข้าสู่ระบบ การอัปเดตโปรไฟล์ และการลบ
// ถ้าสิ่งนี้ล้มเหลว ส่วนไหนเสียไป?
});
ทำสิ่งนี้แทน:
// ดี: แยก Test cases ใน Test suites ที่เป็นระบบ
describe('User Management Suite', () => {
test('TC_001: Register new user', () => {});
test('TC_002: Login with credentials', () => {});
test('TC_003: Update user profile', () => {});
});
describe('Content Management Suite', () => {
test('TC_004: Create new post', () => {});
test('TC_005: Delete post', () => {});
});
อย่าทำสิ่งนี้:
// แย่: มี suites ซ้อนกันมากเกินไป
describe('API', () => {
describe('V1', () => {
describe('Users', () => {
describe('Authentication', () => {
describe('Login', () => {
describe('Valid Credentials', () => {
test('with email', () => {});
});
});
});
});
});
});
ทำสิ่งนี้แทน:
// ดี: การซ้อนกันที่สมเหตุสมผล (สูงสุด 2-3 ระดับ)
describe('API V1: User Authentication', () => {
describe('Login', () => {
test('with valid email and password', () => {});
test('with invalid password', () => {});
});
describe('Registration', () => {
test('with valid data', () => {});
});
});
แนวปฏิบัติที่ดีที่สุดสำหรับการจัดระเบียบ Test Cases และ Test Suites
ทำตามกลยุทธ์ที่พิสูจน์แล้วเหล่านี้เพื่อรักษาการทดสอบของคุณให้เป็นระบบและสามารถบำรุงรักษาได้
1. ใช้หลักการตั้งชื่อที่ชัดเจน
Test Cases:
// ดี: อธิบายได้และเฉพาะเจาะจง
test('should return 200 when user logs in with valid credentials', () => {});
test('should return 401 when password is incorrect', () => {});
test('should return 404 when user does not exist', () => {});
// แย่: กำกวมและไม่ชัดเจน
test('login test', () => {});
test('test 1', () => {});
test('check user', () => {});
Test Suites:
// ดี: ขอบเขตและวัตถุประสงค์ที่ชัดเจน
describe('Authentication API - Login Endpoint', () => {});
describe('User Profile Management', () => {});
describe('Payment Processing Integration Tests', () => {});
// แย่: ทั่วไปเกินไป
describe('Tests', () => {});
describe('API', () => {});
describe('Stuff', () => {});
2. รักษา Test Cases ให้เป็นอิสระต่อกัน
Test case แต่ละกรณีควรทำงานได้อย่างอิสระโดยไม่ต้องพึ่งพาการทดสอบอื่น:
// แย่: การทดสอบขึ้นอยู่กับกันและกัน
let userId;
test('create user', async () => {
const response = await createUser();
userId = response.id; // การจัดเก็บสถานะ
});
test('update user', async () => {
await updateUser(userId); // ขึ้นอยู่กับการทดสอบก่อนหน้า
});
// ดี: การทดสอบแต่ละครั้งเป็นอิสระ
test('create user', async () => {
const user = await createUser(); // สร้างข้อมูลทดสอบของตัวเอง
const response = await createUser();
expect(response.status).toBe(201);
await cleanup(response.id); // ทำความสะอาดหลังการทดสอบ
});
test('update user', async () => {
const user = await createUser(); // สร้างข้อมูลทดสอบของตัวเอง
const response = await updateUser(user.id);
expect(response.status).toBe(200);
await cleanup(user.id);
});
3. จัดระเบียบ Suites ตามคุณสมบัติหรือโมดูล
สะท้อนโครงสร้าง API ของคุณในการจัดระเบียบการทดสอบของคุณ:
src/
├── auth/
│ ├── login.js
│ └── register.js
├── users/
│ ├── profile.js
│ └── settings.js
└── posts/
├── create.js
└── delete.js
tests/
├── auth/
│ ├── login.test.js (Test Suite)
│ └── register.test.js (Test Suite)
├── users/
│ ├── profile.test.js (Test Suite)
│ └── settings.test.js (Test Suite)
└── posts/
├── create.test.js (Test Suite)
└── delete.test.js (Test Suite)
4. ใช้ Hook สำหรับ Setup และ Teardown
ลดการทำซ้ำด้วย hook 'before/after':
describe('User API Test Suite', () => {
let authToken;
let testUser;
// ทำงานหนึ่งครั้งก่อนการทดสอบทั้งหมดใน Test suite นี้
beforeAll(async () => {
authToken = await getAuthToken();
});
// ทำงานก่อน Test case แต่ละกรณี
beforeEach(async () => {
testUser = await createTestUser();
});
// ทำงานหลัง Test case แต่ละกรณี
afterEach(async () => {
await deleteTestUser(testUser.id);
});
// ทำงานหนึ่งครั้งหลังการทดสอบทั้งหมดใน Test suite นี้
afterAll(async () => {
await revokeAuthToken(authToken);
});
test('TC_001: Get user profile', async () => {
// testUser และ authToken พร้อมใช้งาน
});
test('TC_002: Update user profile', async () => {
// testUser และ authToken พร้อมใช้งาน
});
});
5. ติดแท็กการทดสอบเพื่อการดำเนินการที่ยืดหยุ่น
ใช้แท็กหรือหมวดหมู่เพื่อเรียกใช้กลุ่มการทดสอบเฉพาะ:
describe('Authentication Suite', () => {
test('[smoke] API health check', () => {});
test('[critical] Login with valid credentials', () => {});
test('[regression] Login with expired token', () => {});
test('[edge-case] Login with special characters in password', () => {});
});
// เรียกใช้เฉพาะ Smoke tests
// npm test -- --testNamePattern="smoke"
// เรียกใช้การทดสอบที่สำคัญ
// npm test -- --testNamePattern="critical"
6. รักษาระดับชั้น Test Suite
สร้างระดับชั้นที่ชัดเจนสำหรับโครงการขนาดใหญ่:
ระดับ 1: ประเภทการทดสอบ (Smoke, Integration, E2E)
└── ระดับ 2: โมดูลคุณสมบัติ (Auth, Users, Orders)
└── ระดับ 3: ฟังก์ชันการทำงานเฉพาะ (Login, Register)
└── ระดับ 4: Test Cases (Valid, Invalid, Edge Cases)
ตัวอย่าง:
describe('[Integration] User Management', () => {
describe('Authentication', () => {
describe('Login', () => {
test('with valid credentials', () => {});
test('with invalid password', () => {});
test('with non-existent email', () => {});
});
});
});
ข้อผิดพลาดทั่วไปที่ควรหลีกเลี่ยง
1. สร้าง Test Cases ที่กว้างเกินไป
ปัญหา:
test('test user functionality', () => {
// ทดสอบการลงทะเบียน, การเข้าสู่ระบบ, การอัปเดตโปรไฟล์ และการลบ
// ถ้าสิ่งนี้ล้มเหลว ส่วนไหนเสียไป?
});
วิธีแก้ไข:
test('should register new user', () => {});
test('should login registered user', () => {});
test('should update user profile', () => {});
test('should delete user account', () => {});
2. ไม่จัดกลุ่ม Test Cases ที่เกี่ยวข้อง
ปัญหา:
test('login test 1', () => {});
test('profile test 1', () => {});
test('login test 2', () => {});
test('order test 1', () => {});
test('profile test 2', () => {});
วิธีแก้ไข:
describe('Login Tests', () => {
test('test 1', () => {});
test('test 2', () => {});
});
describe('Profile Tests', () => {
test('test 1', () => {});
test('test 2', () => {});
});
3. สร้าง Suites ที่ซ้อนกันมากเกินไป
ปัญหา:
describe('API', () => {
describe('Version 1', () => {
describe('Users', () => {
describe('Profile', () => {
describe('Update', () => {
test('with valid data', () => {});
});
});
});
});
});
วิธีแก้ไข:
describe('API V1: User Profile', () => {
test('should update profile with valid data', () => {});
});
4. ไม่สนใจลำดับการดำเนินการทดสอบ
ปัญหา:
describe('User Flow', () => {
test('delete user', () => {}); // ทำงานก่อน
test('create user', () => {}); // ทำงานเป็นอันดับสอง
test('update user', () => {}); // ทำงานเป็นอันดับสาม
});
วิธีแก้ไข:
describe('User Flow', () => {
test('1. create user', () => {});
test('2. update user', () => {});
test('3. delete user', () => {});
});
// หรือใช้ beforeEach เพื่อให้แน่ใจว่ามีการตั้งค่าที่เหมาะสม
5. ไม่ใช้ชื่อที่สื่อความหมาย
ปัญหา:
describe('Suite 1', () => {
test('test 1', () => {});
test('test 2', () => {});
});
วิธีแก้ไข:
describe('Authentication API Tests', () => {
test('should return JWT token on successful login', () => {});
test('should return 401 on invalid credentials', () => {});
});
ตัวอย่างในโลกแห่งความเป็นจริง
ตัวอย่าง 1: การจัดระเบียบการทดสอบ API สำหรับอีคอมเมิร์ซ
// Smoke Test Suite - ทำงานทุกครั้งที่ commit
describe('[Smoke] Critical API Endpoints', () => {
test('TC_SMOKE_001: API health check returns 200', async () => {
const response = await fetch('https://api.shop.com/health');
expect(response.status).toBe(200);
});
test('TC_SMOKE_002: Database connection is active', async () => {
const response = await fetch('https://api.shop.com/db-status');
expect(response.json()).toHaveProperty('connected', true);
});
});
// Authentication Test Suite
describe('[Integration] Authentication Module', () => {
describe('User Registration', () => {
test('TC_AUTH_001: Register with valid email and password', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_002: Reject registration with duplicate email', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_003: Reject weak passwords', async () => {
// การนำการทดสอบไปใช้
});
});
describe('User Login', () => {
test('TC_AUTH_004: Login with valid credentials', async () => {
// การนำการทดสอบไปใช้
});
test('TC_AUTH_005: Reject invalid password', async () => {
// การนำการทดสอบไปใช้
});
});
});
// Product Management Test Suite
describe('[Integration] Product Management', () => {
test('TC_PROD_001: Get product list', async () => {
// การนำการทดสอบไปใช้
});
test('TC_PROD_002: Get product by ID', async () => {
// การนำการทดสอบไปใช้
});
test('TC_PROD_003: Search products by name', async () => {
// การนำการทดสอบไปใช้
});
test('TC_PROD_004: Filter products by category', async () => {
// การนำการทดสอบไปใช้
});
});
// Order Processing Test Suite
describe('[Integration] Order Processing', () => {
test('TC_ORDER_001: Create order with valid items', async () => {
// การนำการทดสอบไปใช้
});
test('TC_ORDER_002: Calculate correct order total', async () => {
// การนำการทดสอบไปใช้
});
test('TC_ORDER_003: Apply discount code', async () => {
// การนำการทดสอบไปใช้
});
test('TC_ORDER_004: Process payment', async () => {
// การนำการทดสอบไปใช้
});
});
ตัวอย่าง 2: โครงสร้าง Test Suite ของ Apidog
ใน Apidog คุณจัดระเบียบการทดสอบด้วยภาพ:
📁 การทดสอบ API อีคอมเมิร์ซ
📁 Smoke Tests (ชุด)
✓ ตรวจสอบความสมบูรณ์ของ API (กรณีทดสอบ)
✓ สถานะฐานข้อมูล (กรณีทดสอบ)
📁 การรับรองความถูกต้อง (ชุด)
📁 การลงทะเบียน (ชุดย่อย)
✓ การลงทะเบียนที่ถูกต้อง (กรณีทดสอบ)
✓ อีเมลซ้ำ (กรณีทดสอบ)
✓ รหัสผ่านอ่อนแอ (กรณีทดสอบ)
📁 การเข้าสู่ระบบ (ชุดย่อย)
✓ การเข้าสู่ระบบที่ถูกต้อง (กรณีทดสอบ)
✓ รหัสผ่านไม่ถูกต้อง (กรณีทดสอบ)
📁 สินค้า (ชุด)
✓ แสดงรายการสินค้า (กรณีทดสอบ)
✓ ดึงรายละเอียดสินค้า (กรณีทดสอบ)
✓ ค้นหาสินค้า (กรณีทดสอบ)
📁 คำสั่งซื้อ (ชุด)
✓ สร้างคำสั่งซื้อ (กรณีทดสอบ)
✓ คำนวณยอดรวม (กรณีทดสอบ)
✓ ใช้รหัสส่วนลด (กรณีทดสอบ)
Test case แต่ละกรณีใน Apidog ประกอบด้วย:
- การกำหนดค่าคำขอ (URL, เมธอด, Headers, Body)
- Script ก่อนคำขอ (การตั้งค่า)
- Assertions (การตรวจสอบ)
- Script หลังการตอบกลับ (การล้างข้อมูล)
คุณสามารถเรียกใช้ Test cases แต่ละกรณี, Test suites ทั้งชุด หรือสร้างการเรียกใช้การทดสอบแบบกำหนดเองที่รวม Test cases จากหลาย Test suites ได้
บทสรุป
Test cases และ Test suites มีวัตถุประสงค์ที่แตกต่างกันแต่เสริมซึ่งกันและกันในการทดสอบ API Test cases ตรวจสอบพฤติกรรมแต่ละอย่างด้วยอินพุตเฉพาะและผลลัพธ์ที่คาดหวัง Test suites จัดระเบียบ Test cases ที่เกี่ยวข้องให้เป็นกลุ่มเชิงตรรกะเพื่อการดำเนินการและการบำรุงรักษาที่มีประสิทธิภาพ
ประเด็นสำคัญ:
- Test cases คือการทดสอบแบบ Atomic สำหรับสถานการณ์เดียว
- Test suites คือชุดของกรณีทดสอบที่เกี่ยวข้อง
- ใช้ Test cases เพื่อตรวจสอบข้อกำหนดเฉพาะ
- ใช้ Test suites เพื่อจัดระเบียบและดำเนินการกลุ่มการทดสอบ
- รักษา Test cases ให้เป็นอิสระและมุ่งเน้น
- จัดระเบียบ suites ตามคุณสมบัติ ลำดับความสำคัญ หรือประเภทการทดสอบ
- ตั้งชื่อทั้งสองอย่างให้ชัดเจนและสื่อความหมาย
- ใช้เครื่องมือเช่น Apidog เพื่อจัดการลำดับชั้นการทดสอบที่ซับซ้อนด้วยภาพ
เริ่มต้นด้วยการเขียน Test cases ที่มุ่งเน้นสำหรับแต่ละ API endpoint เมื่อชุดการทดสอบของคุณเติบโตขึ้น ให้จัดกลุ่มกรณีที่เกี่ยวข้องเข้าด้วยกันเป็น suites ใช้แท็กและหลักการตั้งชื่อเพื่อให้การทดสอบค้นหาและเรียกใช้ง่าย ไม่ว่าคุณจะเขียนการทดสอบในโค้ดหรือใช้เครื่องมือเช่น Apidog หลักการยังคงเหมือนเดิม: Test cases แบบ Atomic, Test suites เชิงตรรกะ, การจัดระเบียบที่ชัดเจน
พร้อมที่จะจัดระเบียบการทดสอบ API ของคุณแล้วหรือยัง? ลองใช้การจัดการ Test suite แบบภาพของ Apidog - สร้าง จัดระเบียบ และเรียกใช้ Test cases โดยไม่ต้องเขียนโค้ด ลดเวลาการตั้งค่าการทดสอบของคุณลง 60% และเริ่ม Test suite แรกของคุณได้ภายใน 5 นาที
คำถามที่พบบ่อย
อะไรคือความแตกต่างหลักระหว่าง Test case และ Test suite?
Test case คือการทดสอบเดียวที่ตรวจสอบพฤติกรรมหรือข้อกำหนดเฉพาะเจาะจงเพียงอย่างเดียว Test suite คือชุดของ Test cases ที่เกี่ยวข้องหลายกรณีซึ่งจัดกลุ่มเข้าด้วยกันเพื่อการดำเนินการที่เป็นระบบ ลองนึกภาพ Test cases เป็นคำถามแต่ละข้อ และ Test suites เป็นข้อสอบที่ประกอบด้วยคำถามเหล่านั้น
Test case สามารถเป็นส่วนหนึ่งของ Test suites หลายชุดได้หรือไม่?
ได้ Test case เดียวสามารถรวมอยู่ใน Test suites หลายชุดได้ ตัวอย่างเช่น Test case การเข้าสู่ระบบที่สำคัญอาจปรากฏอยู่ในทั้งชุด "Smoke Tests" และชุด "Authentication Tests" ของคุณ การนำกลับมาใช้ใหม่นี้ช่วยให้คุณเรียกใช้การทดสอบหลายชุดที่แตกต่างกันเพื่อวัตถุประสงค์ที่แตกต่างกัน
ควรมี Test cases กี่กรณีใน Test suite หนึ่งชุด?
ไม่มีกฎเกณฑ์ที่ตายตัว แต่ช่วง 5-15 Test cases ต่อชุดเป็นช่วงที่ดี หากคุณมี Test cases มากกว่า 20 กรณีในชุดเดียว ให้พิจารณาแยกมันออกเป็นชุดย่อยที่เล็กกว่าและมุ่งเน้นมากขึ้น หากคุณมีน้อยกว่า 5 กรณี คุณอาจไม่จำเป็นต้องมีชุดทดสอบเลย
ฉันควรเขียน Test cases หรือ Test suites ก่อน?
เขียน Test cases ก่อน เริ่มต้นด้วยการสร้างการทดสอบแต่ละครั้งสำหรับพฤติกรรมเฉพาะ เมื่อคุณมี Test cases ที่เกี่ยวข้องหลายกรณีแล้ว ให้จัดกลุ่มพวกมันเป็น Test suites แนวทางจากล่างขึ้นบนนี้ช่วยให้แน่ใจว่า Test cases ของคุณมุ่งเน้นและ Test suites ของคุณมีการจัดระเบียบอย่างมีเหตุผล
อะไรคือความแตกต่างระหว่าง Test suite และ Test scenario?
Test scenario คือคำอธิบายระดับสูงของสิ่งที่จะทดสอบ (เช่น "ขั้นตอนการเข้าสู่ระบบของผู้ใช้") Test suite คือชุดจริงของ Test cases ที่สามารถดำเนินการได้ Test scenario อาจกลายเป็น Test suite ที่ประกอบด้วย Test cases หลายกรณีที่ตรวจสอบแง่มุมต่างๆ ของสถานการณ์นั้น
ฉันจะจัดระเบียบ Test suites สำหรับ API ขนาดใหญ่ได้อย่างไร?
ใช้โครงสร้างแบบลำดับชั้น: จัดระเบียบตามคุณสมบัติหรือโมดูลในระดับบนสุด จากนั้นตามฟังก์ชันการทำงาน จากนั้นตามประเภทการทดสอบ ตัวอย่างเช่น: "User Management" (โมดูล) → "Authentication" (ฟังก์ชันการทำงาน) → "Login Tests" (Test suite) → Test cases แต่ละกรณี รักษาระดับการซ้อนกันไม่เกิน 2-3 ระดับ
Test suites สามารถมี Test suites อื่นๆ ได้หรือไม่?
ได้ Test suites สามารถซ้อนกันเพื่อสร้างลำดับชั้นได้ ตัวอย่างเช่น Test suite "API Tests" อาจมีชุดย่อย "Authentication Tests" และ "User Management Tests" อย่างไรก็ตาม ควรหลีกเลี่ยงการซ้อนกันมากเกินไป (มากกว่า 3 ระดับ) เนื่องจากจะทำให้การทดสอบนำทางและบำรุงรักษายากขึ้น
เครื่องมือใดบ้างที่ช่วยจัดการ Test cases และ Test suites?
เครื่องมือยอดนิยม ได้แก่ Jest และ Mocha สำหรับ JavaScript, Pytest สำหรับ Python, JUnit สำหรับ Java และ Postman สำหรับการทดสอบ API Apidog มีการจัดการ Test suite แบบภาพโดยไม่ต้องเขียนโค้ด ทำให้ง่ายต่อการจัดระเบียบและดำเนินการ Test cases ของ API ผ่านอินเทอร์เฟซ GUI
