- การทดสอบ API ด้วย Playwright
- 1. สร้างโครงการ Playwright
- 2. โครงสร้างโครงการ
- 3. ตั้งค่า Base URL
- 4. ทดสอบ GET Request
- 5. ตรวจสอบ Response ด้วย toBeOK()
- 6. ตรวจสอบ JSON Response
- 7. ทดสอบ API ที่คืน Array
- 8. ส่ง Query Parameters
- 9. ทดสอบ POST Request
- 10. ทดสอบ PUT Request
- 11. ทดสอบ PATCH Request
- 12. ทดสอบ DELETE Request
- 13. ตรวจสอบ Response Headers
- 14. HTTP Status Code ที่ควรรู้
- 15. Negative Testing
- 16. Authentication ด้วย Bearer Token
- 17. กำหนด Header ส่วนกลาง
- 18. ใช้ไฟล์ .env
- 19. แยก Environment
- 20. สร้าง APIRequestContext เอง
- 21. API Context และ Cookie
- 22. ใช้ API เตรียมข้อมูลก่อน UI Test
- 23. ใช้ API ตรวจสอบผลหลัง UI Test
- 24. สร้าง Reusable API Client
- 25. เขียน Test แบบ Arrange–Act–Assert
- 26. ตรวจสอบหลายเงื่อนไขใน Response
- 27. ตรวจสอบ Response Time เบื้องต้น
- 28. Polling สำหรับ Asynchronous API
- 29. ใช้ Test Hooks
- 30. Group Test ด้วย test.describe()
- 31. Tag API Tests
- 32. รัน Test และดู Report
- 33. ตัวอย่าง CRUD Test Suite
- 34. รัน API Test บน GitHub Actions
- 35. Test Cases ที่ควรมี
- 36. แนวทางจัด API Test Suite
- 37. Best Practices
- 38. Playwright API Testing Workflow
- 39. Playwright หรือ Postman/Newman
- 40. Playwright หรือ k6/JMeter
- สรุป
#การทดสอบ API ด้วย Playwright
เมื่อพูดถึง Playwright หลายคนมักนึกถึงการทดสอบเว็บแบบ End-to-End หรือการควบคุม Browser อัตโนมัติ แต่ Playwright สามารถใช้สำหรับ API Testing ได้โดยตรงเช่นกัน
Playwright Test มี request fixture ซึ่งเป็น APIRequestContext สำหรับส่ง HTTP Request ไปยัง REST API โดยไม่ต้องเปิด Browser ทำให้เราสามารถเขียน Automated API Test ด้วย TypeScript/JavaScript และใช้ Test Runner, Assertions, Fixtures, Reporting และ CI/CD ชุดเดียวกับ UI Test ได้
Playwright เหมาะอย่างยิ่งกับโครงการที่ต้องการรวม
API Testing
+
UI / E2E Testing
+
CI/CD
=
Automated Quality Pipeline
#API Testing คืออะไร
API Testing คือการตรวจสอบการทำงานของ API โดยส่ง HTTP Request ไปยัง Endpoint และตรวจสอบ HTTP Response ที่ได้รับกลับมา
ตัวอย่างเช่น
Test
|
| GET /api/users/1
v
REST API
|
| 200 OK
| application/json
v
Assertions
สิ่งที่ควรตรวจสอบในการทดสอบ API ได้แก่
- HTTP Status Code
- Response Body
- Response Headers
- Data Type
- Business Rules
- Authentication
- Authorization
- Error Handling
- API Contract
- Response Time
#ทำไมจึงใช้ Playwright สำหรับ API Testing
Playwright มี APIRequestContext ซึ่งสามารถส่ง HTTP(S) Request ได้โดยตรง
Playwright Test ยังมี request fixture ที่สร้าง API Request Context แบบแยกสำหรับแต่ละ Test และสามารถใช้ค่าจาก playwright.config.ts เช่น baseURL และ extraHTTPHeaders ได้ทันที
จุดเด่นของการใช้ Playwright คือ
- ทดสอบ API และ UI ด้วย Framework เดียวกัน
- ใช้ TypeScript/JavaScript ได้โดยตรง
- มี Test Runner และ Assertions ในตัว
- รองรับ Fixtures และ Hooks
- รองรับ Parallel Testing
- มี HTML Report
- เชื่อมต่อ CI/CD ได้ง่าย
- ใช้ API เตรียมข้อมูลก่อน UI Test ได้
- ใช้ API ตรวจสอบ Backend State หลังทำงานผ่าน UI ได้
#1. สร้างโครงการ Playwright
ต้องติดตั้ง Node.js ก่อน
สร้างโครงการใหม่ด้วยคำสั่ง
mkdir playwright-api-testing
cd playwright-api-testing
npm init playwright@latest
หรือถ้ามีโครงการ Node.js อยู่แล้ว สามารถติดตั้ง Playwright Test ได้ด้วย
npm install -D @playwright/test@latest
ตรวจสอบเวอร์ชัน
npx playwright --version
จากนั้นรัน Test ด้วย
npx playwright test
#2. โครงสร้างโครงการ
ตัวอย่างโครงสร้างสำหรับแยก API Test ออกจาก UI Test
playwright-api-testing/
├── tests/
│ ├── api/
│ │ ├── users.spec.ts
│ │ └── posts.spec.ts
│ └── e2e/
├── utils/
│ └── api-client.ts
├── playwright.config.ts
├── package.json
└── .env
แนวทางนี้ช่วยให้สามารถรันเฉพาะ API Test ได้ง่าย เช่น
npx playwright test tests/api
#3. ตั้งค่า Base URL
กำหนด baseURL ใน playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
use: {
baseURL: 'https://jsonplaceholder.typicode.com',
},
reporter: 'html',
});
เมื่อกำหนด Base URL แล้ว จากเดิมที่ต้องเขียน
await request.get(
'https://jsonplaceholder.typicode.com/users/1'
);
สามารถเขียนเพียง
await request.get('/users/1');
ทำให้ Test อ่านง่ายและเปลี่ยน Environment ได้สะดวกขึ้น
#4. ทดสอบ GET Request
สร้างไฟล์
tests/api/users.spec.ts
ตัวอย่าง
import { test, expect } from '@playwright/test';
test('GET /users/1 should return user', async ({ request }) => {
const response = await request.get('/users/1');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.id).toBe(1);
expect(body.name).toBeTruthy();
expect(body.email).toContain('@');
});
ตัวอย่างนี้ประกอบด้วย 3 ขั้นตอนหลัก
Arrange
|
Act
|
Assert
ในกรณีนี้เราไม่มีข้อมูลที่ต้องเตรียมมาก จึงเริ่มจากส่ง GET Request แล้วตรวจสอบ Response ได้ทันที
#5. ตรวจสอบ Response ด้วย toBeOK()
Playwright มี API Response Assertion สำหรับตรวจสอบว่า Status Code อยู่ในช่วง 200-299
await expect(response).toBeOK();
ตัวอย่าง
test('API should return success', async ({ request }) => {
const response = await request.get('/users/1');
await expect(response).toBeOK();
});
หาก Test ต้องการ Status Code ที่เจาะจง เช่น 201 Created ควรตรวจสอบโดยตรง
expect(response.status()).toBe(201);
#6. ตรวจสอบ JSON Response
สมมติ API คืนข้อมูล
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz"
}
สามารถตรวจสอบบาง Field ด้วย toMatchObject()
const body = await response.json();
expect(body).toMatchObject({
id: 1,
username: 'Bret',
});
ตรวจสอบชนิดข้อมูลได้ด้วย
expect(body.id).toEqual(expect.any(Number));
expect(body.name).toEqual(expect.any(String));
expect(body.email).toEqual(expect.any(String));
#7. ทดสอบ API ที่คืน Array
ตัวอย่าง
test('GET /users should return array', async ({ request }) => {
const response = await request.get('/users');
expect(response.status()).toBe(200);
const users = await response.json();
expect(Array.isArray(users)).toBe(true);
expect(users.length).toBeGreaterThan(0);
expect(users[0]).toEqual(
expect.objectContaining({
id: expect.any(Number),
name: expect.any(String),
email: expect.any(String),
})
);
});
การตรวจสอบลักษณะนี้มีประโยชน์มากกว่าเช็กเพียง Status Code เพราะช่วยยืนยันว่าโครงสร้างข้อมูลยังตรงกับสิ่งที่ Application คาดหวัง
#8. ส่ง Query Parameters
สามารถใช้ params เพื่อสร้าง Query String ได้
const response = await request.get('/posts', {
params: {
userId: 1,
},
});
ตัวอย่าง Test
test('GET posts by userId', async ({ request }) => {
const response = await request.get('/posts', {
params: {
userId: 1,
},
});
expect(response.status()).toBe(200);
const posts = await response.json();
expect(posts.length).toBeGreaterThan(0);
for (const post of posts) {
expect(post.userId).toBe(1);
}
});
#9. ทดสอบ POST Request
POST มักใช้สำหรับสร้าง Resource ใหม่
test('POST /posts should create post', async ({ request }) => {
const payload = {
title: 'Playwright API Testing',
body: 'Learning API testing with Playwright',
userId: 1,
};
const response = await request.post('/posts', {
data: payload,
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body).toMatchObject(payload);
expect(body.id).toBeDefined();
});
เมื่อส่ง Object ผ่าน data Playwright สามารถ serialize เป็น JSON Request Body ให้ได้
#10. ทดสอบ PUT Request
PUT มักใช้สำหรับ Update Resource ทั้งชุด
test('PUT /posts/1 should update post', async ({ request }) => {
const payload = {
id: 1,
title: 'Updated title',
body: 'Updated body',
userId: 1,
};
const response = await request.put('/posts/1', {
data: payload,
});
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.title).toBe('Updated title');
expect(body.body).toBe('Updated body');
});
#11. ทดสอบ PATCH Request
PATCH เหมาะสำหรับแก้ไขข้อมูลเพียงบางส่วน
test('PATCH /posts/1 should update title', async ({ request }) => {
const response = await request.patch('/posts/1', {
data: {
title: 'New title',
},
});
expect(response.status()).toBe(200);
const body = await response.json();
expect(body.title).toBe('New title');
});
#12. ทดสอบ DELETE Request
test('DELETE /posts/1', async ({ request }) => {
const response = await request.delete('/posts/1');
expect(response.status()).toBe(200);
});
ในระบบจริง ไม่ควรตรวจเพียงว่า DELETE สำเร็จ แต่ควรตรวจ Post-condition ต่อด้วย เช่น
DELETE /api/users/10
|
v
GET /api/users/10
|
v
404 Not Found
#13. ตรวจสอบ Response Headers
สามารถอ่าน Header จาก Response ได้
test('response should be JSON', async ({ request }) => {
const response = await request.get('/users/1');
const headers = response.headers();
expect(headers['content-type']).toContain('application/json');
});
Header ที่มักใช้ตรวจสอบ เช่น
Content-Type
Cache-Control
Authorization
Location
ETag
Retry-After
#14. HTTP Status Code ที่ควรรู้
| Status Code | ความหมาย |
|---|---|
200 |
OK |
201 |
Created |
204 |
No Content |
400 |
Bad Request |
401 |
Unauthorized |
403 |
Forbidden |
404 |
Not Found |
409 |
Conflict |
422 |
Unprocessable Content |
500 |
Internal Server Error |
ตัวอย่าง
expect(response.status()).toBe(201);
ควรตรวจ Status Code ให้ตรงกับ API Contract ของระบบ ไม่ควรสมมติว่า Request ที่สำเร็จต้องเป็น 200 เสมอ
#15. Negative Testing
API Test ที่ดีไม่ควรมีเฉพาะ Happy Path
ควรทดสอบกรณีผิดพลาด เช่น
Invalid ID
Missing Required Field
Invalid Data Type
Invalid Format
Invalid Token
Expired Token
Unauthorized User
Forbidden Resource
Duplicate Data
Resource Not Found
ตัวอย่าง
test('should reject invalid payload', async ({ request }) => {
const response = await request.post('/api/users', {
data: {
email: 'invalid-email',
},
});
expect([400, 422]).toContain(response.status());
});
ในระบบจริงควรระบุ Status Code ตาม Contract ที่ชัดเจน เช่น
expect(response.status()).toBe(422);
แทนการยอมรับหลายค่าโดยไม่จำเป็น
#16. Authentication ด้วย Bearer Token
API จำนวนมากใช้ JWT หรือ Bearer Token
test('authenticated API', async ({ request }) => {
const response = await request.get('/api/profile', {
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
});
expect(response.status()).toBe(200);
});
ไม่ควร Hard-code Token ใน Source Code
หลีกเลี่ยง
Authorization: 'Bearer eyJhbGciOi...'
ควรเก็บ Secret ไว้ใน Environment Variable หรือ Secret Manager ของ CI/CD
#17. กำหนด Header ส่วนกลาง
ถ้าทุก Request ใช้ Header เดียวกัน สามารถกำหนด extraHTTPHeaders ใน Config
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
baseURL: process.env.API_URL,
extraHTTPHeaders: {
Accept: 'application/json',
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
},
});
จากนั้น Test จะสั้นลง
test('get profile', async ({ request }) => {
const response = await request.get('/api/profile');
expect(response.status()).toBe(200);
});
#18. ใช้ไฟล์ .env
ติดตั้ง dotenv
npm install dotenv
สร้างไฟล์ .env
API_URL=https://api.example.com
API_TOKEN=your-token
เพิ่ม .env ลงใน .gitignore
.env
แก้ playwright.config.ts
import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';
dotenv.config();
export default defineConfig({
use: {
baseURL: process.env.API_URL,
extraHTTPHeaders: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
},
});
#19. แยก Environment
โครงการจริงมักมีหลาย Environment เช่น
Development
Testing
Staging
Production
สามารถส่ง Base URL จาก Environment Variable
Linux/macOS:
API_URL=https://staging-api.example.com npx playwright test
Windows PowerShell:
$env:API_URL="https://staging-api.example.com"
npx playwright test
แนวทางนี้ดีกว่าการแก้ URL ใน Source Code ทุกครั้ง
#20. สร้าง APIRequestContext เอง
นอกจาก request fixture แล้ว ยังสามารถสร้าง Context เองเพื่อควบคุม Configuration ได้ละเอียดขึ้น
import {
test,
expect,
APIRequestContext,
} from '@playwright/test';
let apiContext: APIRequestContext;
test.beforeAll(async ({ playwright }) => {
apiContext = await playwright.request.newContext({
baseURL: 'https://jsonplaceholder.typicode.com',
extraHTTPHeaders: {
Accept: 'application/json',
},
});
});
test.afterAll(async () => {
await apiContext.dispose();
});
test('GET user', async () => {
const response = await apiContext.get('/users/1');
expect(response.status()).toBe(200);
});
เหมาะกับกรณี
- ต้องเรียก API หลาย Service
- ต้องใช้ Authentication ต่างกัน
- ต้องแยก Cookie Storage
- ต้องสร้าง API Client สำหรับแต่ละ Role
- ต้องใช้ Configuration เฉพาะชุด Test
#21. API Context และ Cookie
Playwright มี API Request Context สองลักษณะสำคัญ
BrowserContext
|
+-- context.request
|
+-- page.request
context.request และ page.request ใช้ Cookie Storage ร่วมกับ Browser Context
จึงเหมาะกับ Flow เช่น
Login ผ่าน UI
|
v
Browser Session
|
v
page.request
|
v
Authenticated API
หากต้องการ Context ที่ไม่แชร์ Cookie กับ Browser ให้สร้างด้วย
playwright.request.newContext()
#22. ใช้ API เตรียมข้อมูลก่อน UI Test
หนึ่งในแนวทางที่มีประสิทธิภาพมากคือใช้ API สำหรับ Setup Test Data
แทนที่จะเปิด Browser แล้วกรอก Form หลายขั้นตอน สามารถสร้างข้อมูลผ่าน API ก่อน
test('user can view created post', async ({ request, page }) => {
const response = await request.post('/posts', {
data: {
title: 'Playwright',
body: 'API + UI',
userId: 1,
},
});
expect(response.status()).toBe(201);
const post = await response.json();
await page.goto(`/posts/${post.id}`);
});
Workflow
API
|
| Create Test Data
v
Backend
|
v
UI Test
ข้อดีคือ Setup Test ได้เร็วกว่าใช้ UI ทุกขั้นตอน
#23. ใช้ API ตรวจสอบผลหลัง UI Test
อีก Pattern คือให้ User ทำงานผ่าน UI แล้วตรวจสอบข้อมูล Backend ผ่าน API
Browser
|
| Create Order
v
Web Application
|
v
Backend
|
| GET /api/orders/{id}
v
API Assertion
ตัวอย่าง
test('created order should exist in backend', async ({
page,
request,
}) => {
await page.goto('/orders/new');
// ทำรายการผ่าน UI
// ...
const response = await request.get('/api/orders/1001');
expect(response.status()).toBe(200);
const order = await response.json();
expect(order.status).toBe('pending');
});
รูปแบบนี้ทำให้ Test ครอบคลุมทั้ง UI และ Backend State
#24. สร้าง Reusable API Client
เมื่อ Test Suite มีขนาดใหญ่ ไม่ควรเขียน Endpoint เดิมซ้ำในทุกไฟล์
สร้าง
utils/users-api.ts
import { APIRequestContext } from '@playwright/test';
export class UsersApi {
constructor(
private request: APIRequestContext
) {}
async getUser(id: number) {
return this.request.get(`/users/${id}`);
}
async getUsers() {
return this.request.get('/users');
}
async createUser(data: object) {
return this.request.post('/users', {
data,
});
}
}
ใช้งาน
import { test, expect } from '@playwright/test';
import { UsersApi } from '../../utils/users-api';
test('get user', async ({ request }) => {
const usersApi = new UsersApi(request);
const response = await usersApi.getUser(1);
expect(response.status()).toBe(200);
});
ข้อดีคือหาก Endpoint เปลี่ยน สามารถแก้ไขได้จาก API Client จุดเดียว
#25. เขียน Test แบบ Arrange–Act–Assert
รูปแบบ AAA ช่วยให้ Test อ่านง่าย
test('create post', async ({ request }) => {
// Arrange
const payload = {
title: 'Playwright',
body: 'API Testing',
userId: 1,
};
// Act
const response = await request.post('/posts', {
data: payload,
});
// Assert
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.title).toBe(payload.title);
});
โครงสร้างคือ
Arrange
|
v
Act
|
v
Assert
#26. ตรวจสอบหลายเงื่อนไขใน Response
test('validate user response', async ({ request }) => {
const response = await request.get('/users/1');
expect(response.status()).toBe(200);
const body = await response.json();
expect(body).toMatchObject({
id: expect.any(Number),
name: expect.any(String),
username: expect.any(String),
email: expect.any(String),
});
expect(body.address).toBeDefined();
expect(body.company).toBeDefined();
});
ควรเลือก Assert เฉพาะข้อมูลที่เป็น Requirement สำคัญ ไม่ควร Assert ทุก Field โดยไม่มีเหตุผล เพราะอาจทำให้ Test เปราะเกินไป
#27. ตรวจสอบ Response Time เบื้องต้น
สามารถวัดเวลาของ Request ได้
test('response time should be acceptable', async ({ request }) => {
const start = Date.now();
const response = await request.get('/users');
const duration = Date.now() - start;
expect(response.status()).toBe(200);
expect(duration).toBeLessThan(1000);
});
อย่างไรก็ตาม วิธีนี้เหมาะกับ Threshold เบื้องต้นเท่านั้น
หากต้องการทำ
Load Testing
Stress Testing
Spike Testing
Soak Testing
ควรใช้เครื่องมือเฉพาะทาง เช่น
- k6
- JMeter
- Gatling
#28. Polling สำหรับ Asynchronous API
บางระบบไม่ได้ประมวลผลเสร็จทันที เช่น
Create Job
|
v
queued
|
v
processing
|
v
completed
สามารถใช้ expect.poll() เพื่อรอผล
await expect.poll(async () => {
const response = await request.get('/api/jobs/100');
const body = await response.json();
return body.status;
}, {
timeout: 30_000,
}).toBe('completed');
เหมาะกับระบบประเภท
- Background Job
- Queue
- Report Generation
- File Processing
- AI Job
- Payment Processing
#29. ใช้ Test Hooks
Playwright รองรับ Hooks เช่น
test.beforeAll()
test.beforeEach()
test.afterEach()
test.afterAll()
ตัวอย่าง
test.beforeEach(async ({ request }) => {
await request.post('/api/test/reset');
});
เหมาะกับงาน เช่น
Reset Database
Seed Test Data
Login
Create Resource
Cleanup Resource
#30. Group Test ด้วย test.describe()
test.describe('Users API', () => {
test('GET user', async ({ request }) => {
// ...
});
test('CREATE user', async ({ request }) => {
// ...
});
test('UPDATE user', async ({ request }) => {
// ...
});
test('DELETE user', async ({ request }) => {
// ...
});
});
ช่วยจัด Test Suite ให้อ่านง่ายและแบ่งตาม Resource หรือ Feature
#31. Tag API Tests
สามารถใส่ Tag ให้ Test
test(
'GET users',
{
tag: '@api',
},
async ({ request }) => {
const response = await request.get('/users');
expect(response.status()).toBe(200);
}
);
รันเฉพาะ Test ที่มี Tag
npx playwright test --grep @api
ตัวอย่าง Tag ที่เหมาะกับโครงการจริง
@api
@smoke
@regression
@critical
@auth
@negative
#32. รัน Test และดู Report
รัน Test ทั้งหมด
npx playwright test
รันเฉพาะ API Test
npx playwright test tests/api
รันไฟล์เดียว
npx playwright test tests/api/users.spec.ts
ดู HTML Report
npx playwright show-report
#33. ตัวอย่าง CRUD Test Suite
import { test, expect } from '@playwright/test';
test.describe('Posts API', () => {
test('GET posts', async ({ request }) => {
const response = await request.get('/posts');
expect(response.status()).toBe(200);
const posts = await response.json();
expect(Array.isArray(posts)).toBe(true);
});
test('CREATE post', async ({ request }) => {
const response = await request.post('/posts', {
data: {
title: 'Playwright',
body: 'API Testing',
userId: 1,
},
});
expect(response.status()).toBe(201);
const body = await response.json();
expect(body.title).toBe('Playwright');
});
test('UPDATE post', async ({ request }) => {
const response = await request.put('/posts/1', {
data: {
id: 1,
title: 'Updated',
body: 'Updated body',
userId: 1,
},
});
expect(response.status()).toBe(200);
});
test('DELETE post', async ({ request }) => {
const response = await request.delete('/posts/1');
expect(response.status()).toBe(200);
});
});
#34. รัน API Test บน GitHub Actions
สร้างไฟล์
.github/workflows/playwright-api.yml
ตัวอย่าง
name: Playwright API Tests
on:
push:
pull_request:
jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install dependencies
run: npm ci
- name: Run API tests
run: npx playwright test tests/api
env:
API_URL: ${{ secrets.API_URL }}
API_TOKEN: ${{ secrets.API_TOKEN }}
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
สำหรับ Test Suite ที่ทดสอบ API อย่างเดียว ไม่จำเป็นต้องเปิด Browser ใน Test
ถ้า Repository เดียวกันมี UI Test ด้วย ควรติดตั้ง Browser Dependencies ตาม Workflow ของ Playwright เช่น
npx playwright install --with-deps
#35. Test Cases ที่ควรมี
| กลุ่ม | ตัวอย่าง Test |
|---|---|
| Happy Path | Request ถูกต้องและสำเร็จ |
| Validation | Required Field |
| Validation | Invalid Type |
| Validation | Invalid Format |
| Authentication | ไม่มี Token |
| Authentication | Token ผิด |
| Authentication | Token หมดอายุ |
| Authorization | Role ไม่มี Permission |
| Resource | Resource ไม่มีอยู่ |
| Duplicate | ข้อมูลซ้ำ |
| Business Rule | ผิดเงื่อนไขธุรกิจ |
| Header | Content-Type |
| Contract | Field และ Data Type |
| Performance | Response Time |
| Security | Sensitive Data ไม่ถูกส่งกลับ |
#36. แนวทางจัด API Test Suite
tests/api/
│
├── smoke/
│ └── critical-api.spec.ts
│
├── users/
│ ├── get-users.spec.ts
│ ├── create-user.spec.ts
│ ├── update-user.spec.ts
│ └── delete-user.spec.ts
│
├── auth/
│ ├── login.spec.ts
│ └── authorization.spec.ts
│
├── validation/
│ └── user-validation.spec.ts
│
└── regression/
└── business-rules.spec.ts
การจัด Folder ควรเลือกตามขนาดของโครงการ ไม่จำเป็นต้องแบ่งละเอียดเกินไปในโครงการเล็ก
#37. Best Practices
#ใช้ baseURL
ช่วยลด URL ซ้ำและเปลี่ยน Environment ได้ง่าย
#อย่า Hard-code Secret
ใช้
Environment Variables
GitHub Secrets
CI/CD Secret Store
Vault
#ตรวจสอบทั้ง Status และ Body
ไม่ควรตรวจเพียง
expect(response.status()).toBe(200);
ควรตรวจข้อมูลหรือ Business Rule ที่สำคัญด้วย
#มีทั้ง Positive และ Negative Test
Happy Path อย่างเดียวไม่เพียงพอสำหรับ Regression Test
#แยก Test Data จาก Production
ไม่ควรใช้ Production Data เป็นข้อมูลหลักของ Automated Test
#Cleanup Test Data
โดยเฉพาะ Test ที่สร้าง แก้ไข หรือลบข้อมูล
#ทำ Test ให้ Independent
หลีกเลี่ยง Test ที่ต้องพึ่งผลจาก Test ก่อนหน้า
#ใช้ API สำหรับ Setup UI Test
ลดเวลาในการเตรียมข้อมูลผ่านหน้าเว็บ
#ใช้ API ตรวจสอบ Backend State
ช่วยเพิ่มความมั่นใจว่า Operation ที่ทำผ่าน UI ส่งผลถึง Backend จริง
#รันบน CI/CD
อย่างน้อยควรรัน Smoke Test หรือ Critical API Tests ทุก Pull Request
#38. Playwright API Testing Workflow
Developer
|
v
Write API Test
|
v
Playwright Test
|
+-------------------------+
| |
v v
HTTP Request Assertions
| |
v |
REST API |
| |
v |
HTTP Response ---------------+
|
v
Pass / Fail
|
v
HTML Report
|
v
CI/CD
#39. Playwright หรือ Postman/Newman
Playwright และ Postman/Newman ไม่จำเป็นต้องแทนกันทั้งหมด
| ประเด็น | Playwright | Postman / Newman |
|---|---|---|
| REST API Testing | ดีมาก | ดีมาก |
| UI Testing | ดีมาก | ไม่ใช่งานหลัก |
| API Exploration | พอใช้ | เด่น |
| Automated Regression | เด่น | เด่น |
| UI + API ใน Test เดียว | เด่นมาก | จำกัด |
| TypeScript Project | เหมาะมาก | ใช้งานได้ |
| CI/CD | ดีมาก | ดีมาก |
| Shared Test Fixtures | เด่น | Workflow ต่างกัน |
ถ้าโครงการใช้ Playwright ทำ E2E Test อยู่แล้ว การเพิ่ม API Test เข้าใน Repository เดียวกันช่วยลดจำนวนเครื่องมือและทำให้ Test Infrastructure เป็นชุดเดียวกัน
#40. Playwright หรือ k6/JMeter
ควรแยกวัตถุประสงค์ให้ชัดเจน
Playwright
|
+-- Functional API Testing
+-- Integration Testing
+-- E2E Testing
+-- UI + API Testing
k6 / JMeter
|
+-- Load Testing
+-- Stress Testing
+-- Spike Testing
+-- Soak Testing
Playwright สามารถวัด Response Time เบื้องต้นได้ แต่ไม่ได้ถูกออกแบบเป็น Load Testing Tool สำหรับสร้าง Concurrent Users จำนวนมาก
#สรุป
Playwright เป็น Framework ที่สามารถใช้ทดสอบได้มากกว่า UI Automation เพราะ APIRequestContext และ request fixture ช่วยให้สามารถส่ง HTTP Request และตรวจสอบ API Response ได้โดยตรง
ความสามารถที่สำคัญประกอบด้วย
GET
POST
PUT
PATCH
DELETE
Query Parameters
Headers
Authentication
Assertions
Fixtures
Hooks
Polling
API + UI Testing
HTML Report
CI/CD
ถ้าทีมใช้ Playwright สำหรับ End-to-End Testing อยู่แล้ว การเพิ่ม API Testing เข้าไปใน Playwright Test ช่วยให้ใช้ Configuration, Assertions, Test Runner, Fixtures, Reporting และ CI Pipeline ร่วมกันได้
แนวทางที่เหมาะกับโครงการจริงคือ
API Smoke Test
+
API Regression Test
+
UI / E2E Test
+
CI/CD
=
Continuous Quality
#เอกสารอ้างอิง
-
Playwright — API testing
https://playwright.dev/docs/api-testing -
Playwright — APIRequestContext
https://playwright.dev/docs/api/class-apirequestcontext -
Playwright — APIResponseAssertions
https://playwright.dev/docs/api/class-apiresponseassertions -
Playwright — Fixtures
https://playwright.dev/docs/api/class-fixtures -
Playwright — Test Assertions
https://playwright.dev/docs/test-assertions -
Playwright — Configuration
https://playwright.dev/docs/test-use-options
หมายเหตุ: ตัวอย่างบางส่วนในบทความใช้ JSONPlaceholder เพื่ออธิบายแนวคิด สำหรับระบบจริงควรปรับ Endpoint, Authentication, Status Code, Validation และ Business Rules ให้ตรงกับ API Contract ของระบบ