หัวข้อ 18 · 12 นาที · เสริม
ทดสอบ API ด้วย Bruno
นึกภาพก่อน
เขียน API เสร็จแล้วจะรู้ได้อย่างไรว่าใช้ได้ พิมพ์ URL ใน browser ทดสอบได้แค่ GET จะลอง POST พร้อม JSON body ต้องเขียน frontend ก่อนหรือ
Bruno คือ API client: โปรแกรมที่ให้เราประกอบ HTTP request เองทุกส่วน (method, URL, header, body) กดส่ง แล้วดู response เหมือนโทรศัพท์ทดสอบที่ช่างใช้เช็กสายก่อนติดตั้งเครื่องจริง
Bruno คืออะไร
- โปรแกรม open source สำหรับทดสอบ API (ทางเลือกของ Postman และ Insomnia)
- ทำงาน offline บนเครื่อง ไม่ต้องสมัครบัญชี
- เก็บ request เป็น ไฟล์ข้อความ (นามสกุล
.bru) ในโฟลเดอร์บนเครื่อง จึง commit เข้า Git ไปกับโค้ดและแชร์กับทีมได้
Collection และ Request
| คำ | ความหมาย |
|---|---|
| Collection | ชุดของ request ของโปรเจกต์หนึ่ง = โฟลเดอร์บนเครื่อง |
| Request | คำขอหนึ่งรายการ = ไฟล์ .bru หนึ่งไฟล์ |
| Folder | จัดกลุ่ม request ภายใน collection |
ส่วนของ request ที่ตั้งได้
ตรงกับโครงสร้าง HTTP request message ในบทที่ 1 ทุกส่วน:
| ส่วน | ตั้งอะไร | ใน Express อ่านด้วย |
|---|---|---|
| Method | GET, POST, PUT, PATCH, DELETE | app.get, app.post, … |
| URL | http://localhost:3000/users/42 | req.params |
| Query / Params | role=admin | req.query |
| Headers | Authorization, Content-Type | req.headers |
| Body | เลือกชนิด JSON แล้วพิมพ์ข้อมูล | req.body |
| Auth | Bearer token, Basic auth | header Authorization |
เมื่อเลือก body แบบ JSON Bruno ใส่ header Content-Type: application/json ให้
อ่าน response
| ส่วน | ดูอะไร |
|---|---|
| Status | status code และ status message เช่น 201 Created — ดูก่อนเสมอ |
| Body | ข้อมูลที่ server ส่งกลับ |
| Headers | เช่น Content-Type |
| Time / Size | เวลาที่ใช้และขนาด |
Environment และตัวแปร
URL ของ server ตอนพัฒนา (http://localhost:3000) ต่างจากตอนใช้งานจริง ถ้าพิมพ์ไว้ในทุก request จะต้องแก้ทุกตัว
environment เก็บ ตัวแปร ที่สลับชุดได้:
| Environment | baseUrl |
|---|---|
| Local | http://localhost:3000 |
| Production | https://api.example.com |
ใช้ตัวแปรด้วยวงเล็บปีกกาสองชั้น:
GET {{baseUrl}}/users/{{userId}}
Authorization: Bearer {{token}}
เปลี่ยน environment ครั้งเดียว ทุก request เปลี่ยนตาม และไม่ต้องเก็บ token ไว้ในตัว request
ไฟล์ .bru
request ถูกเก็บเป็นข้อความที่อ่านได้:
meta {
name: Create user
type: http
seq: 2
}
post {
url: {{baseUrl}}/users
body: json
}
body:json {
{
"name": "Cat"
}
}
เพราะเป็นไฟล์ข้อความ เมื่อมีคนแก้ request จะเห็นความเปลี่ยนแปลงใน Git เหมือนโค้ดทั่วไป
Script และ Test
แต่ละ request มี script (JavaScript) ที่รันก่อนส่งและหลังได้ response ใช้ ตรวจผลอัตโนมัติ หรือ เก็บค่าไว้ใช้กับ request ถัดไป
// Tests
test("should create user", function () {
expect(res.getStatus()).to.equal(201);
expect(res.getBody().name).to.equal("Cat");
});
// Post-response script: เก็บ id ที่ server สร้างไว้ใช้ต่อ
bru.setVar("userId", res.getBody().id);
ขั้นตอนทดสอบ API
- รัน server (
node index.js) ให้ขึ้นข้อความว่ากำลังรอที่ port ใด - สร้าง collection และ environment ที่มี
baseUrl - สร้าง request: เลือก method ใส่ URL (และ body ถ้ามี)
- กด Send
- ดู status code ก่อน แล้วจึงดู body
- ทดสอบกรณีผิดด้วย: ส่งข้อมูลไม่ครบ, id ที่ไม่มี
ตัวอย่างไล่ทีละขั้น
โจทย์: ทดสอบ API ของบท Express ให้ครบวงจร: สร้าง → อ่าน → ลบ → อ่านอีกครั้ง
| # | Request | คาดว่าได้ | ถ้าไม่ได้ ให้สงสัย |
|---|---|---|---|
| 1 | POST {{baseUrl}}/users body JSON {"name":"Cat"} | 201 และ body มี id | ได้ 400 → ไม่ได้เลือก body แบบ JSON หรือลืม express.json() |
| 2 | GET {{baseUrl}}/users/3 | 200 และ {"id":3,"name":"Cat"} | ได้ 404 → id ไม่ตรง |
| 3 | DELETE {{baseUrl}}/users/3 | 204 ไม่มี body | |
| 4 | GET {{baseUrl}}/users/3 | 404 | ได้ 200 → การลบไม่ทำงาน |
ข้อ 4 สำคัญ: การได้ 404 ในที่นี้คือ ผลที่ถูกต้อง การทดสอบไม่ได้แปลว่าต้องได้ 2xx เสมอ แต่ต้องได้ status ที่ควรได้
ถ้ากด Send แล้วขึ้นว่าเชื่อมต่อไม่ได้ (connection refused) และไม่มี status code เลย: server ยังไม่ได้รัน หรือ port ไม่ตรง — เป็นปัญหาก่อนถึงขั้น HTTP
จุดที่มักพลาด
1. ลืมรัน server
ไม่มี response เลย ไม่ใช่ 404
2. ส่ง POST โดยไม่เลือก body แบบ JSON
server ได้ body ว่าง
3. JSON ผิด syntax
key และ string ต้องใช้ double quote และห้ามมี comma ต่อท้าย
4. ดูแต่ body ไม่ดู status
body อาจมีข้อมูลทั้งที่ status เป็น error
5. ใช้ method ผิด
ส่ง GET ไปยัง route ที่ลงทะเบียนเป็น POST ได้ 404
6. พิมพ์ URL ตายตัวทุก request
ใช้ตัวแปร {{baseUrl}} กับ environment
7. คิดว่า Bruno ติด CORS เหมือน browser
ไม่ติด API ที่ทดสอบผ่านใน Bruno อาจยังเรียกจาก frontend ไม่ได้ถ้ายังไม่เปิด CORS
ที่มา: เนื้อหาเสริม ไม่มีเอกสารใน docs/WEB