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 ก็มีเขียนไว้ กดตามลิงก์ข้างล่างนี้เลยฮะ

REGEX ไม่เล็กนะครับ
Regular Expression ถูกใช้เป็นเครื่องมือตรวจสอบและแก้ไขข้อความที่ใช้เป็นพื้นฐานสำหรับทุกภาษาโปรแกรมมิ่งเลยล่ะฮะ

แล้วถ้าเราต้องการเช็คแค่ error type อย่างเดียว ก็สามารถใช้ assertRaises() ได้เหมือนกันฮะ

สำหรับ official document ของ package unittest สามารถไปตามลิงก์นี้ได้เลยนะฮะ

unittest — Unit testing framework
Source code: Lib/unittest/__init__.py(If you are already familiar with the basic concepts of testing, you might want to skip to the list of assert methods.) The unittest unit testing framework was ...

test function ให้แสดงข้อความด้วย

บางครั้ง เราอยากแสดงข้อความไว้ debug อะไรสักอย่าง เราสามารถใช้วิธีการต่อไปนี้ได้ฮะ

ใช่ฮะ 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 เน้อ