ในบล็อกที่แล้ว เราได้พูดกันถึง module unittest แต่นี่มันก็เป็นแค่ตัวนึงในหลายๆ ตัวที่เราสามารถเลือกมาทำ test ซึ่งถ้าใครอยากกลับไปอ่านก็ลงลิงก์ข้างล่างได้เลยฮะ

Python testing - module unittest
Testing is an essential stage in development lifecycle. Without testing, how do we certain if our program works best and has no critical bugs?

แต่บล็อกนี้ เราจะมาคุยถึงอีกทางเลือกนึง นั่นคือ pytest module ฮะ

pytest ดียังไงอะ

pytest เป็นตัวนึงในบรรดาหลายๆ ตัว ของ python testing module ซึ่งส่วนตัวผมชอบใช้ตัวนี้มากกว่า unittest ด้วยสรรพคุณการใช้งานง่าย เขียนสั้นกว่า แสดงผลได้สีสันแสบตา กว่า (ข้อดีแหละ) รวมถึงออฟชันเพิ่มเติม ให้เราเลือกปรับตามใจ เพื่อความอ่านง่าย และได้ผล test ที่รวบตึงกว่าฮะ

และลิงก์ข้างล่างนี้ เป็น official document ของ pytest เขาล่ะฮะ

pytest: helps you write better programs — pytest documentation

มาเริ่มใช้กันเลย

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 ค่าได้หลักๆ สองแบบตามนี้ฮะ

  1. error type
    ใช้ .type เทียบกับ error type ที่ต้องการเลย หรือ
  2. error message
    ใช้ .value ร่วมกับ module re เพื่อ 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 สามารถจิ้มได้อ่านเพิ่มเติมได้ตรงนี้ฮะ

Unpacking in Python: Beyond Parallel Assignment
Unpacking uses * to assign multiple variables from a single iterable in one assignment statement. This makes your Python code cleaner and quicker to write.

ลอง 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 ไว้ข้างล่างนี้เช่นกันฮะ

GitHub - bluebirz/python-test-module
Contribute to bluebirz/python-test-module development by creating an account on GitHub.