Notes & software courses · Free to learn
Aph's Blog
On this page

TDD & Coverage

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

เขียนเทสต์ก่อนโค้ด (Red → Green → Refactor) และวัดว่าเทสต์ครอบคลุมโค้ดแค่ไหน

Test-Driven Development (TDD) คือแนวทางเขียน "เทสต์ก่อน" แล้วค่อยเขียนโค้ดให้ผ่าน ฟังดูกลับด้านแต่ช่วยให้คิดชัดว่าโค้ดควรทำอะไร และได้เทสต์ครบเป็นของแถม

วงจร TDD: Red → Green → Refactor

  1. 🔴 Red — เขียนเทสต์สำหรับสิ่งที่ยังไม่มี รันแล้วต้องแดง (พัง) เพราะยังไม่มีโค้ด
  2. 🟢 Green — เขียนโค้ดน้อยที่สุดที่ทำให้เทสต์ผ่าน (เขียว)
  3. 🔵 Refactor — ปรับโค้ดให้สะอาดขึ้น โดยเทสต์ยังเขียวอยู่
python
# 1. 🔴 เขียนเทสต์ก่อน (ยังไม่มีฟังก์ชัน is_palindrome)
def test_is_palindrome():
    assert is_palindrome("racecar") is True
    assert is_palindrome("hello") is False
    assert is_palindrome("") is True

# 2. 🟢 เขียนโค้ดให้ผ่าน
def is_palindrome(s):
    return s == s[::-1]

# 3. 🔵 refactor ถ้าจำเป็น (เทสต์ยังเขียว = ปลอดภัย)
ทำไม TDD ช่วย

การเขียนเทสต์ก่อนบังคับให้คุณคิดว่า "ฟังก์ชันนี้ควรรับอะไร คืนอะไร" ก่อนลงมือ ทำให้ออกแบบ interface ชัดขึ้น และได้เทสต์ครบโดยไม่ต้องมาตามเขียนทีหลัง (ซึ่งมักถูกข้าม)

Coverage — วัดความครอบคลุม

coverage บอกว่าเทสต์ของเรา "แตะ" โค้ดไปกี่เปอร์เซ็นต์ ช่วยหาส่วนที่ยังไม่มีเทสต์

bash
pip install pytest-cov
pytest --cov=myapp           # แสดง % coverage
pytest --cov=myapp --cov-report=html   # รายงาน HTML ดูบรรทัดที่ยังไม่ถูกเทสต์
100% coverage ≠ ไม่มี bug

coverage สูงดี แต่ "แตะโค้ด" ไม่เท่ากับ "ทดสอบถูกต้อง" — อาจรันทุกบรรทัดแต่ไม่ได้ตรวจผลที่สำคัญ เน้นเขียนเทสต์ที่มีความหมาย (เคสปกติ/ขอบ/ผิด) มากกว่าไล่ตัวเลข coverage ให้ครบ 100%

สรุปหัวข้อนี้

  • TDD: 🔴 เขียนเทสต์ให้พังก่อน → 🟢 เขียนโค้ดให้ผ่าน → 🔵 refactor
  • เขียนเทสต์ก่อนช่วยออกแบบ interface ชัดและได้เทสต์ครบ
  • pytest-cov วัด coverage หาส่วนที่ยังไม่มีเทสต์
  • coverage สูง ≠ ไม่มี bug — เน้นเทสต์ที่มีความหมาย
แบบฝึกหัด

1) ใช้ TDD สร้างฟังก์ชัน count_vowels(s): เขียนเทสต์ให้พังก่อน แล้วค่อยเขียนโค้ด 2) เพิ่มเคสขอบ (string ว่าง, ตัวพิมพ์ใหญ่) แล้วทำให้ผ่าน 3) รัน pytest --cov ดู % 4) อธิบายว่าทำไม 100% coverage ไม่การันตีว่าไม่มี bug