WEB · เสริม: Backend Backend

หัวข้อ 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 อ่านด้วย
MethodGET, POST, PUT, PATCH, DELETEapp.get, app.post, …
URLhttp://localhost:3000/users/42req.params
Query / Paramsrole=adminreq.query
HeadersAuthorization, Content-Typereq.headers
Bodyเลือกชนิด JSON แล้วพิมพ์ข้อมูลreq.body
AuthBearer token, Basic authheader Authorization

เมื่อเลือก body แบบ JSON Bruno ใส่ header Content-Type: application/json ให้

อ่าน response

ส่วนดูอะไร
Statusstatus code และ status message เช่น 201 Created — ดูก่อนเสมอ
Bodyข้อมูลที่ server ส่งกลับ
Headersเช่น Content-Type
Time / Sizeเวลาที่ใช้และขนาด

Environment และตัวแปร

URL ของ server ตอนพัฒนา (http://localhost:3000) ต่างจากตอนใช้งานจริง ถ้าพิมพ์ไว้ในทุก request จะต้องแก้ทุกตัว environment เก็บ ตัวแปร ที่สลับชุดได้:

EnvironmentbaseUrl
Localhttp://localhost:3000
Productionhttps://api.example.com

ใช้ตัวแปรด้วยวงเล็บปีกกาสองชั้น:

text
GET {{baseUrl}}/users/{{userId}}
Authorization: Bearer {{token}}

เปลี่ยน environment ครั้งเดียว ทุก request เปลี่ยนตาม และไม่ต้องเก็บ token ไว้ในตัว request

ไฟล์ .bru

request ถูกเก็บเป็นข้อความที่อ่านได้:

text
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 ถัดไป

js
// 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

  1. รัน server (node index.js) ให้ขึ้นข้อความว่ากำลังรอที่ port ใด
  2. สร้าง collection และ environment ที่มี baseUrl
  3. สร้าง request: เลือก method ใส่ URL (และ body ถ้ามี)
  4. กด Send
  5. ดู status code ก่อน แล้วจึงดู body
  6. ทดสอบกรณีผิดด้วย: ส่งข้อมูลไม่ครบ, id ที่ไม่มี

ตัวอย่างไล่ทีละขั้น

โจทย์: ทดสอบ API ของบท Express ให้ครบวงจร: สร้าง → อ่าน → ลบ → อ่านอีกครั้ง

#Requestคาดว่าได้ถ้าไม่ได้ ให้สงสัย
1POST {{baseUrl}}/users body JSON {"name":"Cat"}201 และ body มี idได้ 400 → ไม่ได้เลือก body แบบ JSON หรือลืม express.json()
2GET {{baseUrl}}/users/3200 และ {"id":3,"name":"Cat"}ได้ 404 → id ไม่ตรง
3DELETE {{baseUrl}}/users/3204 ไม่มี body
4GET {{baseUrl}}/users/3404ได้ 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