Python testing - มารู้จัก module unittest
unittest คืออะไร
Testing คือขั้นตอนการทดสอบโปรแกรม เป็นอีกขั้นที่สำคัญใน development lifecycle ซึ่งถ้าเราไม่ทำ เราจะไม่สามารถแน่ใจได้ว่าโปรแกรมที่เราเขียนไปนั้นใช้งานได้จริงหรือไม่ หรือมีบั๊กอะไรใหญ่ๆ หรือเปล่าฮะ
ในภาษา Python เองก็มีตัว packages ที่ช่วยเราทดสอบได้เหมือนกัน ในครั้งนี้ เราจะพูดถึง unittest
กันฮะ
เริ่มจากง่ายๆ กันก่อน
เขียน function หลัก
สมมติว่าเรามี adder function มีความสามารถบวกเลขง่ายๆ ฮะ
ทีนี้ เราจะมาทดสอบว่า function บวกเลขของเราเนี่ย มันทำงานได้ถูกต้องหรือเปล่า เริ่มจากสร้าง unittest
script ให้ชื่อว่า test-one.py
แล้วเราจะใช้มันเนี่ยแหละ มาทดสอบ adder function ข้างบนนั่น
ข้อสำคัญ! ไม่ตั้งชื่อ file ว่า unittest.py
เพราะ Python ใช้คำสั่งชื่อเดียวกัน ไม่อย่างนั้นจะเกิด circular referencing ได้ฮะ
ตั้งชื่อ test function
ปกติเวลาเราเขียน function ใหม่มาใช้งาน เราจะตั้งชื่อให้สื่อว่ามันใช้ทำงานอะไร ในส่วนของ test function เราจะเพิ่มเข้าไปด้วยว่า มันใช้ test case อย่างไรบ้าง ผลลัพท์คือเราจะได้ชื่อ method ยาวยืดกว่าปกติ แต่ไม่ต้องคิดมากฮะ เพราะเราจะไม่ได้เรียกมันตรงๆ อยู่แล้ว เพราะเราจะเรียกผ่านชื่อ file ฮะ
ตัวอย่าง test function เช่น test_get_student_name_boy_only
สื่อว่าเราจะทดสอบ function ดึงชื่อนักเรียน โดยสนใจเฉพาะชื่อนักเรียนชายเท่านั้น หรือแบบข้างบนนั้น test_adder_simple_by_both_positive
ไว้ใช้ทดสอบ adder_simple
โดยป้อนจำนวนเต็มบวกสองค่าเข้าไป
run test
ตอนจะ run ก็แค่เรียก python test file แบบข้างล่างนี้
python3 <unittest.py-filepath>
ผลลัพท์ตามข้างล่างคือ test case ผ่านฮะ เราจะเห็นเป็นจุด (.
)
เพิ่ม test cases
หนึ่ง test case มาจากหนึ่ง test function ดังนั้น ถ้าเราอยากได้กี่ test cases ก็เพิ่มไปเท่านั้น function
ผ่านหลาย test cases ก็จะเห็นหลายจุดหน่อยฮะ
แล้วถ้าไม่ผ่านล่ะ?
เราลองมาสร้าง test case ว่าถ้าไม่ผ่านจะเป็นยังไง
ณ บรรทัดที่ 15 เรารู้ว่า -2 + 2 ≠ 1 แน่ๆ เมื่อเรา run test จะเห็นเป็น F
หมายถึงมี test case ไม่ผ่านตรงนี้ฮะ เมื่อเจอแบบนี้ในงานจริงก็ต้องไปตามเช็คละฮะ ว่าผิดที่ test case ไหม หรือต้องแก้ที่ code ต้นทางเลย
Test กับ error handlings
Python เราสามารถใช้ try-except
structure เพื่อจัดการ error ได้ แล้วอย่างนี้ เราจะสร้าง test case มาเช็คจุดนี้ได้ยังไงบ้างนะ
สร้าง adder function ที่มี error handling
ตัวอย่างสมมติ ให้ raise error ถ้า a
หรือ b
ก็ได้มีค่า 0 หรือน้อยกว่าฮะ
test แบบนี้
unittest
มี method assertRaisesRegex()
ที่ใช้เช็ค error type และ message ตรงตามรูปแบบที่กำหนด โดยเราจะกำหนดเป็น regular expression ฮะ แบบนี้
ถ้าสนใจเรื่อง regular expressions ก็มีเขียนไว้ กดตามลิงก์ข้างล่างนี้เลยฮะ
แล้วถ้าเราต้องการเช็คแค่ error type อย่างเดียว ก็สามารถใช้ assertRaises()
ได้เหมือนกันฮะ
สำหรับ official document ของ package unittest
สามารถไปตามลิงก์นี้ได้เลยนะฮะ
test function ให้แสดงข้อความด้วย
บางครั้ง เราอยากแสดงข้อความไว้ debug อะไรสักอย่าง เราสามารถใช้วิธีการต่อไปนี้ได้ฮะ
print กันโต้ง
ใช่ฮะ print()
กันดื้อๆ เลยเนี่ยแหละ แบบนี้
print(self._testMethodName)
จะแสดงข้อความเป็นชื่อ test method นั้นๆ ถ้ากด run จะได้ผลลัพท์ประมาณนี้ฮะ
ใช้ logging module
มันคือ package logging
ซึ่งเราใช้แสดงข้อความเป็น logs พร้อมระบุ severity levels (ระดับความรุนแรง เช่น DEBUG
, INFO
, ERROR
, เป็นต้น) ซึ่งมีประโยชน์มาก ตอนที่เราจะหา logs เพื่อหาสาเหตุหรือเช็คอะไรบางอย่างฮะ
เริ่มจาก import logging
แล้วสร้าง logger instance หลังจากนั้นก็ใช้ debug()
เพื่อ log ข้อความที่ระดับ DEBUG
ได้เลยฮะ
หน้าตาจะออกมาประมาณนี้ฮะ
วิธีนี้ ผมได้มาจากคอมเมนต์นี้ฮะ ให้เครดิตตรงนี้เลย https://stackoverflow.com/questions/284043/outputting-data-from-unit-test-in-python
นี่ก็เป็นข้อมูลการทำ test ด้วย unittest
ของ Python แบบเบื้องต้นนะฮะ
อย่าลืมทำ test ก่อน deploy บน production นะคร้าบ คนจริงอย่า test on production เน้อ