ระหว่างเขียนโค้ดทดสอบด้วย Pytest แล้วใช้ MagicMock หลายคนน่าจะเคยเจอประสบการณ์ที่ IDE ไม่ช่วย autocomplete หรือพิมพ์ชื่อเมธอดผิดแล้วต้องเสียเวลางมหาสาเหตุกันมาบ้าง

mock แบบเดิมนั้นทรงพลังมาก แต่ type hint จะหายไป ทำให้ยากที่จะอาศัยตัวตรวจสอบชนิดข้อมูลอย่าง mypy หรือ pyright มาช่วยได้ เพื่อแก้ปัญหานี้จึงได้สร้าง typed-pytest ที่รองรับ การทำ mock แบบปลอดภัยต่อชนิดข้อมูล (Type-safe mocking) ขึ้นมา

คุณสมบัติหลัก:

  • IDE autocomplete แบบครบถ้วน: รองรับการเติมชื่อเมธอดและพารามิเตอร์ของคลาสจริง รวมถึงเมธอดเฉพาะของ mock อย่าง assert_called_once_with ด้วย
  • ตรวจจับการพิมพ์ผิดตอน lint: หากเรียกเมธอดที่ไม่มีอยู่จริงหรือส่งอาร์กิวเมนต์ผิด ก็จะตรวจพบได้ทันทีตั้งแต่ก่อนรันเทสต์ (mypy/pyright)
  • ตัวสร้างสตับ (Stub) โดยเฉพาะ: วิเคราะห์คลาสในโปรเจกต์แล้วสร้างไฟล์ type hint (.pyi) ให้อัตโนมัติ (รองรับคลาสที่มี dependency ภายนอกอย่าง FastAPI, SQLAlchemy เป็นต้น)
  • แบ็กเอนด์ที่ยืดหยุ่น: ถ้าต้องการความเร็วสามารถใช้ inspect ได้ และถ้าต้องการ type hint ของค่าที่คืนมาอย่างละเอียดกว่าสามารถเลือกแบ็กเอนด์ stubgen ได้ (ปัจจุบัน stubgen ยังอยู่ในขั้นทดลอง)

ตัวอย่างการใช้งาน:

# MagicMock แบบเดิม: แม้พิมพ์ผิดก็ยังไม่รู้ก่อนรัน  
mock = MagicMock(spec=UserService)  
mock.get_usr(1) # พิมพ์ get_user ผิด แต่ linter ตรวจไม่พบ  
  
# typed-pytest: linter แจ้ง error ทันที และรองรับ autocomplete  
from typed_pytest_stubs import typed_mock, UserService  
  
mock = typed_mock(UserService)  
mock.get_usr # ❌ Error: "get_usr" is not a member of UserService  
mock.get_user.assert_called_once_with(user_id=1) # ✅ ผ่านการตรวจสอบชนิดข้อมูลแล้ว  

ไฟล์สตับที่สร้างขึ้นถูกออกแบบมาให้ใช้งานโดยสร้างเฉพาะในสภาพแวดล้อมพัฒนาแบบโลคัลและใน CI โดยไม่จำเป็นต้องอัปขึ้น Git และยังคำนึงถึงความเข้ากันได้กับเครื่องมือสมัยใหม่อย่าง uv ด้วย

GitHub: https://github.com/tmdgusya/typed-pytest

หวังว่าจะเป็นประโยชน์สำหรับคนที่อยากใช้ข้อดีของระบบชนิดข้อมูลได้อย่างเต็มที่แม้ในโค้ดทดสอบ และยินดีรับฟีดแบ็กเพื่อปรับปรุงการใช้งานเสมอ!!

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น