
ที่มาภาพ: Unknown Source
วิธีทำ Unit Testing แบบ Property‑Based Testing ด้วย Hypothesis ใน Python อย่างปลอดภัย
⚡ สรุป 30 วิ
การทดสอบหน่วย (Unit Testing) แบบ Property‑Based Testing ช่วยให้เราตรวจจับบั๊กที่ไม่คาดคิดจากข้อมูลหลายชุดโดยอัตโนมัติ Hypothesis คือไลบรารียอดนิยมในภาษา Python ที่ทำหน้าที่นี้ได้อย่างเต็มประสิทธิภาพ บ…
ภาพรวม — Overview
การทดสอบหน่วย (Unit Testing) แบบ Property‑Based Testing ช่วยให้เราตรวจจับบั๊กที่ไม่คาดคิดจากข้อมูลหลายชุดโดยอัตโนมัติ Hypothesis คือไลบรารียอดนิยมในภาษา Python ที่ทำหน้าที่นี้ได้อย่างเต็มประสิทธิภาพ บทความนี้จะสอนวิธีใช้ Hypothesis อย่างปลอดภัยเพื่อให้โค้ดของคุณมีคุณภาพสูงขึ้น
- Property‑Based Testing มุ่งเน้นการตรวจสอบกฎ (property) แทนค่าตัวอย่างเฉพาะ
- Hypothesis สร้างข้อมูลแบบสุ่มตามกลยุทธ์ที่กำหนดและทำให้เทสต์ทำซ้ำอัตโนมัติเมื่อพบข้อผิดพลาด
- การตั้งค่าอย่างเหมาะสมช่วยหลีกเลี่ยงการทดสอบที่ช้าเกินไปหรือผลลัพธ์ไม่สอดคล้อง
Property‑Based Testing คืออะไร — What Is Property‑Based Testing
Property‑Based Testing ตรวจสอบว่าโค้ดของเรายังคงเป็นจริงต่อกฎทั่วไป (property) สำหรับทุกอินพุตที่อาจเกิดขึ้น ไม่ใช่แค่กรณีตัวอย่างเดียว
- กำหนด property เช่น “ผลลัพธ์บวกสองจำนวนต้องเท่ากับผลบวกของแต่ละส่วน”
- Hypothesis สร้างชุดข้อมูลหลายพันค่าเพื่อทดสอบ property นี้โดยอัตโนมัติ
- ถ้าพบกรณีที่ทำให้ property ผิดพลาด ระบบจะ shrink ข้อมูลลงเป็นตัวอย่างที่ง่ายที่สุดเพื่อช่วยวิเคราะห์
**Tip: เริ่มจากกำหนด property ที่ชัดเจนและง่ายต่อการอธิบาย ก่อนเขียนโค้ดทดสอบจริง
การติดตั้งและเตรียมสภาพแวดล้อม — Installation & Setup
การเริ่มต้นใช้ Hypothesis เพียงไม่กี่ขั้นตอนเท่านั้น
- ใช้ pip ติดตั้งไลบรารีหลักและ plugin ของ unittest หรือ pytest
```bash pip install hypothesis pip install pytest-hypothesis ```
- ตรวจสอบเวอร์ชันที่รองรับ Python 3.7 ขึ้นไป
- แนะนำให้เปิด coverage เพื่อติดตามส่วนของโค้ดที่ถูกทดสอบ
| ตัวเลือก | คำสั่งติดตั้ง | เหมาะกับ |
|---|---|---|
| unittest + hypothesis | `pip install hypothesis` | โปรเจกต์เดิมใช้ unittest อยู่แล้ว |
| pytest + hypothesis | `pip install pytest-hypothesis` | ต้องการฟีเจอร์ fixtures และ parametrize |
ตัวอย่างพื้นฐาน — Basic Example
สมมติเรามีฟังก์ชันคูณสองตัวเลขที่ต้องทำงานกับจำนวนเต็มบวกเท่านั้น
```python def multiply(a: int, b: int) -> int: return a * b ```
เขียนเทสต์ด้วย Hypothesis — Writing the Test
- ใช้ `@given` เพื่อกำหนดกลยุทธ์ของข้อมูล
- ระบุ `assume` เพื่อตัดกรณีที่ไม่ตรงตามเงื่อนไข
```python from hypothesis import given, assume import hypothesis.strategies as st
@given(st.integers(min_value=0), st.integers(min_value=0)) def test_multiply_non_negative(a, b): assume(a >= 0 and b >= 0) result = multiply(a, b) assert result >= 0 # property: ผลลัพธ์ต้องไม่ติดลบ assert result == a * b # ตรวจสอบผลคูณที่คาดไว้ ```
- รันเทสต์ด้วย `python -m unittest` หรือ `pytest` แล้ว Hypothesis จะทำการสร้างข้อมูลหลายพันชุดโดยอัตโนมัติ
ขั้นตอนเพิ่มความปลอดภัย — Safety Enhancements
เพื่อให้การทดสอบไม่ก่อให้เกิดปัญหาใน CI/CD หรือเครื่องผู้พัฒนา ควรตั้งค่าขอบเขตและจำกัดทรัพยากร
- จำกัดจำนวนตัวอย่าง (`max_examples`) เพื่อควบคุมเวลาการทดสอบ
```python @given(st.lists(st.integers())) @settings(max_examples=200) def test_sort_is_idempotent(lst): assert sorted(sorted(lst)) == sorted(lst) ```
- ใช้ `deadline=None` หากฟังก์ชันต้องทำงานนาน (เช่น การคำนวณทางคณิตศาสตร์)
```python @settings(deadline=None) @given(st.floats(allow_nan=False, allow_infinity=False)) def test_sqrt_positive(x): assert math.sqrt(abs(x)) >= 0 ```
- เปิด profiling เพื่อตรวจจับเทสต์ที่ทำให้ใช้หน่วยความจำหรือ CPU มากเกินไป
```python @settings(profile=True) @given(st.text()) def test_reverse_twice(s): assert s == s[::-1][::-1] ```
**Tip: ใน CI ควรตั้งค่า `max_examples` ให้ต่ำกว่า 500 เพื่อลดเวลาโดยรวมของการทดสอบ
เคล็ดลับขั้นสูง — Advanced Tips
เมื่อเข้าใจพื้นฐานแล้ว สามารถใช้ฟีเจอร์เพิ่มเติมเพื่อเพิ่มประสิทธิภาพและความชัดเจน
- Composite strategies สร้างข้อมูลซับซ้อนจากหลายกลยุทธ์
```python @st.composite def user_dict(draw): name = draw(st.text(min_size=1)) age = draw(st.integers(min_value=0, max_value=120)) return {"name": name, "age": age} ```
- Stateful testing ใช้ `RuleBasedStateMachine` เพื่อตรวจสอบพฤติกรรมของอ็อบเจ็กต์ที่มีหลายขั้นตอน
```python from hypothesis.stateful import RuleBasedStateMachine, rule
class StackMachine(RuleBasedStateMachine): def __init__(self): super().__init__() self.stack = []
@rule(value=st.integers()) def push(self, value): self.stack.append(value)
@rule() def pop(self): assume(self.stack) # ต้องมีอย่างน้อยหนึ่งค่า assert self.stack.pop() is not None
TestStack = StackMachine.TestCase ```
- ใช้ `@example` เพื่อเพิ่มกรณีที่ต้องการตรวจสอบเป็นพิเศษ
```python @given(st.lists(st.integers())) @example([0, 0, 0]) def test_sum_non_negative(lst): assert sum(lst) >= min(lst) ```
ข้อควรระวังทั่วไป — Common Pitfalls
แม้ Hypothesis จะเป็นเครื่องมือที่ทรงพลัง แต่การใช้งานไม่ถูกต้องอาจทำให้เกิดปัญหา
- อย่าใช้ `assume` มากเกินไป จะทำให้ส่วนใหญ่ของข้อมูลถูกตัดออกและลดประสิทธิภาพของการค้นหาบั๊ก
- ตรวจสอบว่ากลยุทธ์ที่เลือกครอบคลุมกรณีขอบ (edge cases) เช่น ค่าศูนย์, ค่าแม็กซิมัม, ค่าว่าง
| ปัญหา | ผลกระทบ | วิธีแก้ |
|---|---|---|
| `assume` มากเกินไป | ลดจำนวนตัวอย่างที่ใช้จริง | ใช้เงื่อนไขใน property แทนการตัดข้อมูล |
| ไม่ตั้งค่า `max_examples` | เวลา CI เพิ่มขึ้นหลายเท่า | กำหนดค่าให้เหมาะกับความซับซ้อนของฟังก์ชัน |
| ลืมตรวจสอบ `NaN`/`Infinity` | เทสต์อาจผ่านโดยไม่ได้ทดสอบกรณีจริง | ระบุ `allow_nan=False`, `allow_infinity=False` ใน strategies |
**Tip: เริ่มจากใช้ `st.integers()` หรือ `st.text()` ที่ไม่มีข้อจำกัด แล้วค่อยเพิ่มเงื่อนไขเฉพาะเมื่อจำเป็น
สรุป — Summary
การทำ Unit Testing แบบ Property‑Based ด้วย Hypothesis ทำให้คุณสามารถค้นพบบั๊กที่ซ่อนอยู่ได้เร็วและครอบคลุมมากขึ้น หากตั้งค่าขอบเขตอย่างเหมาะสมและกำหนด property อย่างชัดเจน โค้ดของคุณจะปลอดภัยต่อการเปลี่ยนแปลงในระยะยาว
- กำหนด property ให้ตรงกับความต้องการธุรกิจหรือกฎเกณฑ์ทางคณิตศาสตร์
- **ตั้งค่า `max_examples` และ `deadline` เพื่อลดภาระเวลาและทรัพยากรในการทดสอบ
- ใช้ strategies ที่เหมาะสม รวมถึง composite และ stateful เพื่อครอบคลุมกรณีซับซ้อน
- ระวังการใช้ `assume` มากเกินไปและตรวจสอบ edge cases อย่างเต็มที่
ด้วยขั้นตอนเหล่านี้ คุณจะสามารถนำ Hypothesis ไปประยุกต์ใช้ในโปรเจกต์ Python ของคุณได้อย่างมั่นใจและปลอดภัย.
แชร์บทความนี้:
ชอบบทความแบบนี้?
สมัคร AI Automate Weekly Newsletter — รับเคล็ดลับ AI + how-to ใหม่
ทุกสัปดาห์ตรงถึง inbox ฟรี ไม่มีสแปม
แหล่งข่าวต้นฉบับ
- ชื่อต้นฉบับ
- วิธีทำ Unit Testing แบบ Property‑Based Testing ด้วย Hypothesis ใน Python อย่างปลอดภัย
- ผู้เขียน
- กองบรรณาธิการ Thai Tech News
- แหล่ง
- บทความต้นฉบับ Thai Tech News · ช่วยร่างด้วย AI, เรียบเรียง/ตรวจสอบโดยกองบรรณาธิการ
- วันที่เผยแพร่
- 23 สิงหาคม 2569 เวลา 17:51



