Python testing - มารู้จัก module pytest
ในบล็อกที่แล้ว เราได้พูดกันถึง module unittest
แต่นี่มันก็เป็นแค่ตัวนึงในหลายๆ ตัวที่เราสามารถเลือกมาทำ test ซึ่งถ้าใครอยากกลับไปอ่านก็ลงลิงก์ข้างล่างได้เลยฮะ
แต่บล็อกนี้ เราจะมาคุยถึงอีกทางเลือกนึง นั่นคือ pytest
module ฮะ
pytest
ดียังไงอะ
pytest
เป็นตัวนึงในบรรดาหลายๆ ตัว ของ python testing module ซึ่งส่วนตัวผมชอบใช้ตัวนี้มากกว่า unittest
ด้วยสรรพคุณการใช้งานง่าย เขียนสั้นกว่า แสดงผลได้สีสันแสบตา กว่า (ข้อดีแหละ) รวมถึงออฟชันเพิ่มเติม ให้เราเลือกปรับตามใจ เพื่อความอ่านง่าย และได้ผล test ที่รวบตึงกว่าฮะ
และลิงก์ข้างล่างนี้ เป็น official document ของ pytest
เขาล่ะฮะ
มาเริ่มใช้กันเลย
install module
รอบนี้ เราจำเป็นต้องติดตั้ง module ของมันก่อนนะฮะ รายละเอียดอยู่ในลิงก์นี้ module document on PyPI.
pip install pytest
function ง่ายๆ ก่อน
ขอรีไซเคิลจากบล็อก unittest
นะฮะ function บวกเลขโง่ๆ มาเลย
สร้าง pytest
script
ทีนี้ก็ถึงตา pytest
script หน้าตาประมาณนี้ ธรรมดาๆ ไปก่อน
เช่นเคยฮะ เราจะไม่ตั้งชื่อ file ว่า pytest.py
เพราะเหตุผลเหมือนกับ unittest
เลย นั่นคือ pytest
มันเป็นชื่อ command ไปแล้ว ไม่งั้นเราจะเจอ import error แทนได้ฮะ
เสร็จแล้ว run คำสั่งนี้ เพื่อ run test กันเลย
pytest <pytest-script>
หน้าตาของ test ที่ผ่านฉลุย จะเป็นสีเขียวนีออนแบบนี้แหละ อ่านง่าย สบายตาใช่มั้ยล่ะ
เติม test cases ไปอีก
แบบนี้
สามผ่านไปเลยฮะ ได้มาสามจุด คล้ายๆ กับ unittest
แต่มีรายละเอียดอะไรใส่เข้ามาให้ดูดีขึ้นเนอะ
แล้วถ้าไม่ผ่านขึ้นมา?
อันนี้ จะเป็นเคสที่เรา run ไม่ผ่านนะฮะ
เห็นสีแดงมั้ย แดงฉาน สะท้อนความผิดที่ได้ทำเอาไว้
จะเห็นว่า มันแสดง error ได้เยอะกว่า ละเอียดกว่า แล้วอ่านง่ายกว่าด้วยเนอะ เห็นด้วยมั้ยฮะ แล้วก็จะมีตรงด้านล่าง ที่เขียนว่า "summary info" ที่สรุปให้เราอ่านว่า failed กี่ case แล้ว passed กี่ case
อยากเห็นละเอียดกว่านี้อะ
ถ้าอยากเห็นรายละเอียดของทั้ง pass และ fail ลองใช้คำสั่งนี้ฮะ
pytest -rA <pytest-script>
-rA
flag หมายถึง แสดงผลทุก case ออกมาเลย มันจะแจงยิบว่า case ไหน มาจาก function ชื่ออะไร ผ่านรึเปล่า ไม่ผ่านเพราะอะไร ไว้ที่ "summary info" ฮะ ชัดเจนกันไปเลย จะแก้ก็รู้ว่าแก้ตรงไหน เพราะอะไร
มี flag อื่นอีกมั้ยล่ะ
pytest
มีให้เราเลือกหลาย flag เลยฮะ เช่น ตัวอย่างข้างบนที่เราใช้ -rA
กันไปแล้ว เราสามารถพิมพ์คำสั่งนี้
pytest -h
มันคือ help ที่จะร่ายทุก flag ให้เราเลือกใช้ตามสะดวกเลยแหละ ปรับได้ตามใจเราเลยฮะ
Error handling
เอาล่ะ ถ้าเราอยากจะ capture error handling กันล่ะ ยกตัวอย่างของเก่าเลยนะฮะ อันนี้
เรามีแนวทาง compare ค่าได้หลักๆ สองแบบตามนี้ฮะ
- error type
ใช้.type
เทียบกับ error type ที่ต้องการเลย หรือ - error message
ใช้.value
ร่วมกับ modulere
เพื่อ compare มันฮะ
เนี่ย มันก็จะสามารถ run test ได้ประมาณนี้แหละฮะ
Parametrize
หนึ่ง feature เด่นของ pytest
คือ อันนี้ฮะ parametrize
ที่จะช่วยให้เราเขียนแค่ test function เดียวแล้วป้อน test case เป็น list ไปได้เลย ช่วยประหยัดเวลาได้มากเลยฮะ
วิธีการคือ ให้เราเติม pytest
decorator หน้าตาราวนี้ ไปบนหัว function
@pytest.mark.parametrize("arguments, expect", test_cases)
def test_functions(arguments, expect):
# code stubs
ตัวอย่างเช่น
ตัวอย่างนี้ ผมเขียนไว้ 2 test function นะฮะ อันนึงจะ unpack dict
โดยการกำหนดค่าตัวแปร อีกอันนึงจะใช้เครื่องหมาย *
แทน
เรื่อง unpacking สามารถจิ้มได้อ่านเพิ่มเติมได้ตรงนี้ฮะ
ลอง run test ดูก็เขียวตามคาดแหละ
แสดง output จาก program
สมมตว่า program ของเรามีแสดงข้อความอะไรบางอย่างแบบนี้
run pytest
ตรงๆ จะไม่แสดงข้อความพวกนั้นออกมานะฮะ
ให้เราใช้ flag -rA
หรือ -ra
เพื่อแสดง extra summary เหมือนที่เล่าไว้ข้างบน โดย -rA
จะแสดงหมดเลย ไม่ว่า case ที่ผ่านหรือไม่ผ่าน ส่วน -ra
แสดงอันที่ไม่ผ่านเท่านั้นฮะ
เนี่ย มันแสดงเป็นทีละ function มาแยกๆ แบบนี้แหละ
หรืออีกแบบนึง ใช้ flag -s
ความหมายคือ "no capture" นั่นคือ มันจะไม่จับแยกมาให้ละ มันจะกองมาที่เดียวเลยแบบรูปข้างล่างนี้ ซึ่งส่วนตัวผมชอบ -rA
อ่ะ ด้วยความที่อ่านง่ายกว่า แสดงผลได้งามตากว่า
นี่เป็นแค่การใช้งานเบื้องต้นของ pytest
module แต่ก็คิดว่าเพียงพอกับการใช้งานทั่วไปล่ะนะ แล้วก็มี repo ของเรื่อง python testing ทั้ง unittest
และ pytest
ไว้ข้างล่างนี้เช่นกันฮะ