บทแนะนำการใช้งาน PyTest: PyTest คืออะไร? (พร้อมตัวอย่าง)
⚡ สรุปอย่างชาญฉลาด
Pytest คือ Python เฟรมเวิร์กสำหรับการทดสอบที่ช่วยให้คุณเขียนการทดสอบที่เรียบง่ายและปรับขนาดได้สำหรับฐานข้อมูล API และส่วนติดต่อผู้ใช้ รองรับฟิกซ์เจอร์ การกำหนดพารามิเตอร์ มาร์กเกอร์ การทำงานแบบขนาน และการรายงานการยืนยันโดยละเอียด ตั้งแต่การทดสอบหน่วยพื้นฐานไปจนถึงการทดสอบฟังก์ชันที่ซับซ้อน

ไพเทส เป็นหนึ่งในเฟรมเวิร์กการทดสอบที่ใช้กันอย่างแพร่หลายที่สุด Python ระบบนิเวศนี้ช่วยให้โค้ดทดสอบสั้นและอ่านง่าย ค้นหาการทดสอบโดยอัตโนมัติ และเติบโตจากการตรวจสอบเบื้องต้นไปสู่ชุดทดสอบที่สมบูรณ์สำหรับฐานข้อมูล API และส่วนติดต่อผู้ใช้ ส่วนด้านล่างจะอธิบายเกี่ยวกับการติดตั้ง การตรวจสอบ ฟิกซ์เจอร์ มาร์กเกอร์ การกำหนดพารามิเตอร์ และการรันแบบขนาน พร้อมตัวอย่างเชิงปฏิบัติ
Pytest คืออะไร?
ไพเทส เป็นเฟรมเวิร์กสำหรับการทดสอบที่ช่วยให้คุณเขียนโค้ดทดสอบโดยใช้ Python ภาษาโปรแกรมมิ่ง ช่วยให้คุณเขียนกรณีทดสอบที่ง่ายและปรับขนาดได้สำหรับฐานข้อมูล API และแม้แต่ส่วนติดต่อผู้ใช้ Pytest ใช้เป็นหลักในการเขียนการทดสอบสำหรับ API และสามารถรองรับได้ตั้งแต่การทดสอบหน่วยแบบง่ายไปจนถึงการทดสอบฟังก์ชันที่ซับซ้อน
เหตุใดจึงต้องใช้ Pytest?
ข้อดีบางประการของ pytest ได้แก่:
- เริ่มต้นใช้งานได้ง่ายมาก เนื่องจากไวยากรณ์ที่เรียบง่ายและชัดเจน
- สามารถรันการทดสอบแบบขนานได้
- สามารถเรียกใช้การทดสอบเฉพาะรายการหรือชุดย่อยของการทดสอบได้
- ตรวจจับการทดสอบโดยอัตโนมัติ
- สามารถข้ามการทดสอบได้
- โอเพ่นซอร์ส.
วิธีการติดตั้ง Pytest
ขั้นตอนการติดตั้ง pytest มีดังนี้:
ขั้นตอน 1) คุณสามารถติดตั้ง pytest ได้โดยใช้คำสั่งด้านล่างนี้
pip install pytest==2.9.1
เมื่อการติดตั้งเสร็จสมบูรณ์ คุณสามารถตรวจสอบได้ด้วยคำสั่งต่อไปนี้
py.test -h
นี่จะแสดงส่วนช่วยเหลือ
ตัวอย่าง Pytest พื้นฐานตัวแรก
ต่อไปนี้ คุณจะได้เรียนรู้วิธีการใช้งาน pytest โดยใช้ตัวอย่างพื้นฐานของ pytest
สร้างโฟลเดอร์ชื่อ study_pytest คุณจะสร้างไฟล์ทดสอบไว้ภายในโฟลเดอร์นี้ โปรดไปยังโฟลเดอร์นั้นในบรรทัดคำสั่งของคุณ จากนั้นสร้างไฟล์ชื่อ test_sample1.py ภายในโฟลเดอร์นั้น
เพิ่มโค้ดด้านล่างลงไปแล้วบันทึก
import pytest def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed" def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
เรียกใช้การทดสอบโดยใช้คำสั่งด้านล่าง
py.test
คุณจะได้รับผลลัพธ์ดังต่อไปนี้
test_sample1.py F.
============================================== FAILURES ========================================
____________________________________________ test_sample1 ______________________________________
def test_file1_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed"
E AssertionError: test failed
E assert 5 == 6
test_sample1.py:6: AssertionError
ในไฟล์ test_sample1.py F. นี้ ตัวอักษร F หมายถึงความล้มเหลว และจุด (.) หมายถึงความสำเร็จ ในส่วนของความล้มเหลว คุณจะเห็นเมธอดที่ล้มเหลวและบรรทัดที่เกิดความล้มเหลว ในที่นี้ x==y หมายถึง 5==6 ซึ่งเป็นเท็จ
ต่อไป คุณจะได้เรียนรู้เกี่ยวกับ assertions ใน pytest
การตรวจสอบใน Pytest
คำสั่ง assertion ใน Pytest จะส่งคืนค่า True หรือ False หากคำสั่ง assertion ล้มเหลวในเมธอดทดสอบ การทำงานของเมธอดนั้นจะหยุดลง โค้ดส่วนที่เหลือในเมธอดทดสอบนั้นจะไม่ถูกเรียกใช้งาน และ pytest จะดำเนินการต่อในเมธอดทดสอบถัดไป
ตัวอย่างการใช้คำสั่ง assert ใน Pytest:
assert "hello" == "Hai" is an assertion failure. assert 4==4 is a successful assertion assert True is a successful assertion assert False is an assertion failure.
ลองพิจารณาสิ่งต่อไปนี้
assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
วางโค้ดนี้ไว้ใน test_file1_method1() แทนคำสั่ง assertion ด้านล่าง
assert x == y,"test failed"
การรันการทดสอบจะทำให้เกิดความล้มเหลวดังเช่น AssertionError: การทดสอบล้มเหลว x=5 y=6.
วิธีที่ Pytest ระบุไฟล์ทดสอบและเมธอดทดสอบ
โดยค่าเริ่มต้น pytest จะระบุเฉพาะชื่อไฟล์ที่ขึ้นต้นด้วย .py เท่านั้น ทดสอบ_ หรือลงท้ายด้วย _ทดสอบ เช่นเดียวกับไฟล์ทดสอบ เราสามารถระบุชื่อไฟล์อื่นๆ ได้อย่างชัดเจน (จะอธิบายในภายหลัง) Pytest กำหนดให้ชื่อเมธอดทดสอบต้องขึ้นต้นด้วย ทดสอบชื่อเมธอดอื่นๆ ทั้งหมดจะถูกละเลย แม้ว่าเราจะระบุให้เรียกใช้เมธอดเหล่านั้นอย่างชัดเจนก็ตาม
ดูตัวอย่างชื่อไฟล์ pytest ที่ถูกต้องและไม่ถูกต้องได้ที่นี่
test_login.py - valid login_test.py - valid testlogin.py -invalid logintest.py -invalid
หมายเหตุ: ใช่ เราสามารถระบุอย่างชัดเจนให้ pytest เลือก testlogin.py และ logintest.py ได้
ดูตัวอย่างวิธีการทดสอบ pytest ที่ถูกต้องและไม่ถูกต้องได้ที่นี่
def test_file1_method1(): - valid def testfile1_method1(): - valid def file1_method1(): - invalid
หมายเหตุ: แม้ว่าเราจะระบุ file1_method1() อย่างชัดเจนแล้วก็ตาม pytest ก็จะไม่รันเมธอดนี้
เรียกใช้การทดสอบหลายรายการจากไฟล์เฉพาะและหลายไฟล์
ปัจจุบัน ภายในโฟลเดอร์ study_pytest เรามีไฟล์ test_sample1.py อยู่ สมมติว่าเรามีไฟล์หลายไฟล์ เช่น test_sample2.py และ test_sample3.py หากต้องการรันการทดสอบทั้งหมดจากทุกไฟล์ในโฟลเดอร์และโฟลเดอร์ย่อย เราเพียงแค่ต้องรันคำสั่ง pytest เท่านั้น
py.test
คำสั่งนี้จะรันไฟล์ทั้งหมดที่มีชื่อขึ้นต้นด้วย test_ และลงท้ายด้วย _test ในโฟลเดอร์นั้น รวมถึงโฟลเดอร์ย่อยที่อยู่ภายใต้โฟลเดอร์นั้นด้วย
หากต้องการเรียกใช้การทดสอบเฉพาะจากไฟล์ที่ระบุ เราสามารถใช้ py.test ได้ .
py.test test_sample1.py
เรียกใช้ชุดย่อยของการทดสอบทั้งหมดด้วย Pytest
บางครั้งเราไม่ต้องการรันชุดทดสอบทั้งหมด Pytest อนุญาตให้เรารันเฉพาะการทดสอบที่ต้องการได้ โดยสามารถทำได้สองวิธี:
- กลุ่มping ของชื่อทดสอบโดยการจับคู่สตริงย่อย
- กลุ่มping จากการทดสอบโดยผู้ประเมิน
เรามีไฟล์ test_sample1.py อยู่แล้ว สร้างไฟล์ test_sample2.py และเพิ่มโค้ดด้านล่างลงไป
def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
ดังนั้นขณะนี้เรามีข้อมูลดังต่อไปนี้
• test_sample1.py • test_file1_method1() • test_file1_method2() • test_sample2.py • test_file2_method1() • test_file2_method2()
ตัวเลือกที่ 1) เรียกใช้การทดสอบโดยการจับคู่สตริงย่อย
ในที่นี้ หากต้องการเรียกใช้การทดสอบทั้งหมดที่มี method1 อยู่ในชื่อ เราต้องเรียกใช้คำสั่งด้านล่างนี้
py.test -k method1 -v
-k <expression> is used to represent the substring to match
-v increases the verbosity
ดังนั้น การรันคำสั่ง py.test -k method1 -v จะให้ผลลัพธ์ดังต่อไปนี้
test_sample2.py::test_file2_method1 FAILED
test_sample1.py::test_file1_method1 FAILED
============================================== FAILURES ==============================================
_________________________________________ test_file2_method1 _________________________________________
def test_file2_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E AssertionError: test failed because x=5 y=6
E assert 5 == 6
test_sample2.py:5: AssertionError
_________________________________________ test_file1_method1 _________________________________________
@pytest.mark.only
def test_file1_method1():
x=5
y=6
assert x+1 == y,"test failed"
> assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E AssertionError: test failed because x=5 y=6
E assert 5 == 6
test_sample1.py:8: AssertionError
================================= 2 tests deselected by '-kmethod1' ==================================
=============================== 2 failed, 2 deselected in 0.02 seconds ===============================
ตรงนี้คุณจะเห็นได้ว่า ในช่วงท้ายๆ นั้น... ยกเลิกการเลือกการทดสอบ 2 รายการโดย '-kmethod1'ซึ่งก็คือ test_file1_method2 และ test_file2_method2
ลองใช้การผสมผสานต่างๆ ดังต่อไปนี้ดู
py.test -k method -v - will run all the four methods py.test -k methods -v – will not run any test as there is no test name matches the substring 'methods'
ตัวเลือกที่ 2) ทำการทดสอบโดยใช้เครื่องหมาย
Pytest อนุญาตให้เรากำหนดคุณลักษณะต่างๆ สำหรับเมธอดทดสอบโดยใช้เครื่องหมาย pytest (@pytest.mark) ในการใช้เครื่องหมายในไฟล์ทดสอบ เราต้องนำเข้า pytest เข้าไปในไฟล์ทดสอบก่อน ในที่นี้เราจะกำหนดชื่อเครื่องหมายที่แตกต่างกันให้กับเมธอดทดสอบและเรียกใช้การทดสอบเฉพาะตามชื่อเครื่องหมายเหล่านั้น เราสามารถกำหนดเครื่องหมายให้กับชื่อการทดสอบแต่ละชื่อได้โดยใช้ดังต่อไปนี้
@pytest.mark.<name>.
เรากำลังกำหนดตัวบ่งชี้ set1 และ set2 ในเมธอดทดสอบ และเราจะทำการทดสอบโดยใช้ชื่อตัวบ่งชี้เหล่านั้น อัปเดตไฟล์ทดสอบด้วยโค้ดต่อไปนี้
test_sample1.py
import pytest @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set2 def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
test_sample2.py
import pytest @pytest.mark.set1 def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set1 def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
เราสามารถเรียกใช้การทดสอบที่ทำเครื่องหมายไว้โดยใช้คำสั่งด้านล่าง
py.test -m <name> -m <name> mentions the marker name
เรียกใช้คำสั่ง `py.test -m set1` เพื่อรันเมธอด `test_file1_method1`, `test_file2_method1` และ `test_file2_method2` ส่วนการเรียกใช้คำสั่ง `py.test -m set2` จะรันเมธอด `test_file1_method2`
เรียกใช้การทดสอบแบบขนานด้วย Pytest
โดยปกติแล้ว ชุดทดสอบจะมีไฟล์ทดสอบหลายไฟล์และเมธอดทดสอบหลายร้อยรายการ ซึ่งจะใช้เวลาในการประมวลผลค่อนข้างนาน Pytest ช่วยให้เราสามารถรันการทดสอบแบบขนานได้ สำหรับการนั้น เราจำเป็นต้องติดตั้ง pytest-xdist ก่อนโดยการรันคำสั่งด้านล่าง
pip install pytest-xdist
คุณสามารถเริ่มการทดสอบได้โดยใช้คำสั่งต่อไปนี้
py.test -n 4
ที่นี่ -n เรียกใช้การทดสอบโดยใช้เวิร์กเกอร์หลายตัว ในคำสั่งข้างต้น จะมีเวิร์กเกอร์สี่ตัวเพื่อเรียกใช้การทดสอบ
โปรแกรมการแข่งขัน ไพเทสต์
Fixtures คือไฟล์ที่ใช้เมื่อเราต้องการรันโค้ดบางส่วนก่อนทำการทดสอบแต่ละครั้ง ดังนั้น แทนที่จะเขียนโค้ดเดิมซ้ำในทุกการทดสอบ เราจึงกำหนด fixtures ขึ้นมา โดยปกติแล้ว fixtures จะใช้ในการเริ่มต้นการเชื่อมต่อฐานข้อมูล และส่งค่าพื้นฐานไปยังฐานข้อมูล URLและอื่นๆ เมธอดจะถูกทำเครื่องหมายว่าเป็น pytest fixture โดยการทำเครื่องหมายด้วยข้อความต่อไปนี้
@pytest.fixture
วิธีการทดสอบสามารถใช้ฟิกซ์เจอร์ของ pytest ได้โดยการระบุฟิกซ์เจอร์เป็นพารามิเตอร์อินพุต สร้างไฟล์ใหม่ชื่อ test_basic_fixture.py โดยใส่โค้ดต่อไปนี้
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc] def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
ที่นี่:
- เรามีฟิกซ์เจอร์ชื่อ supply_AA_BB_CC เมธอดนี้จะส่งคืนลิสต์ของค่าสามค่า
- เรามีวิธีการทดสอบสามวิธีที่ใช้เปรียบเทียบกับค่าแต่ละค่า
ฟังก์ชันทดสอบแต่ละฟังก์ชันมีอาร์กิวเมนต์อินพุตที่มีชื่อตรงกับฟิกซ์เจอร์ที่มีอยู่ จากนั้น Pytest จะเรียกใช้เมธอดฟิกซ์เจอร์ที่เกี่ยวข้อง และค่าที่ส่งคืนจะถูกเก็บไว้ในอาร์กิวเมนต์อินพุต ในที่นี้คือลิสต์ [25,35,45] จากนั้นรายการในลิสต์จะถูกนำไปใช้ในเมธอดทดสอบเพื่อเปรียบเทียบ ตอนนี้ลองรันการทดสอบและดูผลลัพธ์
py.test test_basic_fixture
test_basic_fixture.py::test_comparewithAA FAILED
test_basic_fixture.py::test_comparewithBB PASSED
test_basic_fixture.py::test_comparewithCC FAILED
============================================== FAILURES ==============================================
_________________________________________ test_comparewithAA _________________________________________
supply_AA_BB_CC = [25, 35, 45]
def test_comparewithAA(supply_AA_BB_CC):
zz=35
> assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"
E AssertionError: aa and zz comparison failed
E assert 25 == 35
test_basic_fixture.py:10: AssertionError
_________________________________________ test_comparewithCC _________________________________________
supply_AA_BB_CC = [25, 35, 45]
def test_comparewithCC(supply_AA_BB_CC):
zz=35
> assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
E AssertionError: cc and zz comparison failed
E assert 45 == 35
test_basic_fixture.py:16: AssertionError
================================= 2 failed, 1 passed in 0.05 seconds =================================
การทดสอบ test_comparewithBB ผ่าน เนื่องจาก zz=BB=35 ส่วนการทดสอบอีกสองรายการที่เหลือล้มเหลว
เมธอด fixture มีขอบเขตการใช้งานเฉพาะภายในไฟล์ทดสอบที่กำหนดไว้เท่านั้น หากเราพยายามเข้าถึง fixture ในไฟล์ทดสอบอื่น เราจะได้รับข้อผิดพลาดเกี่ยวกับ fixture ไม่พบ 'supply_AA_BB_CC' สำหรับวิธีการทดสอบในไฟล์อื่นๆ
เพื่อใช้ fixture เดียวกันกับไฟล์ทดสอบหลายไฟล์ เราจึงสร้างเมธอด fixture ในไฟล์ชื่อ conftest.py มาดูตัวอย่าง pytest ด้านล่างกัน สร้างไฟล์สามไฟล์ ได้แก่ conftest.py, test_basic_fixture.py และ test_basic_fixture2.py โดยใช้โค้ดต่อไปนี้
conftest.py
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc]
test_basic_fixture.py
import pytest def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
test_basic_fixture2.py
import pytest def test_comparewithAA_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
Pytest จะค้นหา fixture ในไฟล์ทดสอบก่อน และหากไม่พบ ก็จะค้นหาในไฟล์ conftest.py เรียกใช้การทดสอบด้วยคำสั่ง py.test -k test_comparewith -v เพื่อดูผลลัพธ์ด้านล่าง
test_basic_fixture.py::test_comparewithAA FAILED test_basic_fixture.py::test_comparewithBB PASSED test_basic_fixture.py::test_comparewithCC FAILED test_basic_fixture2.py::test_comparewithAA_file2 PASSED test_basic_fixture2.py::test_comparewithBB_file2 FAILED test_basic_fixture2.py::test_comparewithCC_file2 FAILED
การทดสอบแบบกำหนดพารามิเตอร์ของไพเทสต์
จุดประสงค์ของการกำหนดพารามิเตอร์ให้กับการทดสอบคือการรันการทดสอบกับชุดอาร์กิวเมนต์หลายชุด เราสามารถทำได้โดยใช้ `@pytest.mark.parametrize` เราจะเห็นได้จากตัวอย่าง pytest ด้านล่างนี้ ในที่นี้เราจะส่งอาร์กิวเมนต์สามตัวไปยังเมธอดทดสอบ เมธอดทดสอบนี้จะบวกอาร์กิวเมนต์สองตัวแรกและเปรียบเทียบผลลัพธ์กับอาร์กิวเมนต์ตัวที่สาม สร้างไฟล์ทดสอบ `test_addition.py` ด้วยโค้ดด้านล่างนี้
import pytest @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)]) def test_add(input1, input2, output): assert input1+input2 == output,"failed"
เมธอดทดสอบนี้รับอาร์กิวเมนต์สามตัว ได้แก่ input1, input2 และ output โดยจะนำค่า input1 และ input2 มาบวกกัน แล้วเปรียบเทียบผลรวมกับค่า output ลองรันการทดสอบด้วยคำสั่ง py.test -k test_add -v แล้วดูผลลัพธ์กัน
test_addition.py::test_add[5-5-10] PASSED
test_addition.py::test_add[3-5-12] FAILED
============================================== FAILURES ==============================================
__________________________________________ test_add[3-5-12] __________________________________________
input1 = 3, input2 = 5, output = 12
@pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
def test_add(input1, input2, output):
> assert input1+input2 == output,"failed"
E AssertionError: failed
E assert (3 + 5) == 12
test_addition.py:5: AssertionError
คุณจะเห็นว่ามีการทดสอบสองครั้ง ครั้งแรกตรวจสอบว่า 5+5 ==10 และครั้งที่สองตรวจสอบว่า 3+5 ==12
test_addition.py::test_add[5-5-10] ผ่านแล้ว
test_addition.py::test_add[3-5-12] ล้มเหลว
การทดสอบ Xfail และ Skip ของ Pytest
จะมีบางสถานการณ์ที่เราไม่ต้องการทำการทดสอบ หรือ กรณีทดสอบ ไม่เกี่ยวข้องในเวลาใดเวลาหนึ่ง ในสถานการณ์เหล่านั้น เรามีตัวเลือกที่จะ xfail การทดสอบหรือข้ามการทดสอบ การทดสอบที่ xfailed จะถูกดำเนินการ แต่จะไม่ถูกนับรวมเป็นส่วนหนึ่งของการทดสอบที่ล้มเหลวหรือผ่าน จะไม่มี traceback จะแสดงขึ้นหากการทดสอบนั้นล้มเหลว เราสามารถ xfail การทดสอบได้โดยใช้ @pytest.mark.xfail ข้ามไปping การทดสอบนี้จะไม่ดำเนินการ เราสามารถข้ามการทดสอบได้โดยใช้ `@pytest.mark.skip` แก้ไขไฟล์ test_addition.py ด้วยโค้ดด้านล่างนี้
import pytest @pytest.mark.skip def test_add_1(): assert 100+200 == 400,"failed" @pytest.mark.skip def test_add_2(): assert 100+200 == 300,"failed" @pytest.mark.xfail def test_add_3(): assert 15+13 == 28,"failed" @pytest.mark.xfail def test_add_4(): assert 15+13 == 100,"failed" def test_add_5(): assert 3+2 == 5,"failed" def test_add_6(): assert 3+2 == 6,"failed"
ที่นี่:
- test_add_1 และ test_add_2 ถูกข้ามไปและจะไม่ถูกดำเนินการ
- test_add_3 และ test_add_4 ถูกจัดอยู่ในสถานะ xfailed การทดสอบเหล่านี้จะถูกดำเนินการและจะเป็นส่วนหนึ่งของการทดสอบ xfailed (เมื่อการทดสอบล้มเหลว) หรือ xpassed (เมื่อการทดสอบผ่าน) จะไม่มีการทดสอบใดๆ เพิ่มเติม traceback สำหรับความล้มเหลว
- คำสั่ง test_add_5 และ test_add_6 จะถูกเรียกใช้งาน และ test_add_6 จะรายงานความล้มเหลวพร้อมข้อความแสดงข้อผิดพลาด traceback ในขณะที่ test_add_5 ผ่าน
เรียกใช้การทดสอบด้วยคำสั่ง `py.test test_addition.py -v` แล้วดูผลลัพธ์
test_addition.py::test_add_1 SKIPPED
test_addition.py::test_add_2 SKIPPED
test_addition.py::test_add_3 XPASS
test_addition.py::test_add_4 xfail
test_addition.py::test_add_5 PASSED
test_addition.py::test_add_6 FAILED
============================================== FAILURES ==============================================
_____________________________________________ test_add_6 _____________________________________________
def test_add_6():
> assert 3+2 == 6,"failed"
E AssertionError: failed
E assert (3 + 2) == 6
test_addition.py:24: AssertionError
================ 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.07 seconds =================
ผลลัพธ์ในรูปแบบ XML
เราสามารถสร้างผลลัพธ์การทดสอบในรูปแบบ XML ซึ่งเราสามารถป้อนให้กับเซิร์ฟเวอร์ Continuous Integration เพื่อประมวลผลต่อไปได้ สามารถทำได้โดยใช้คำสั่ง `py.test test_sample1.py -v –junitxml=”result.xml”` ไฟล์ `result.xml` จะบันทึกผลลัพธ์การทดสอบ ตัวอย่างไฟล์ `result.xml` อยู่ด้านล่าง
<?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="1" name="pytest" skips="0" tests="2" time="0.046"> <testcase classname="test_sample1" file="test_sample1.py" line="3" name="test_file1_method1" time="0.001384973526"> <failure message="AssertionError:test failed because x=5 y=6 assert 5 ==6"> @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed because x=" + str(x) + " y=" + str(y) E AssertionError: test failed because x=5 y=6 E assert 5 == 6 test_sample1.py:9: AssertionError </failure> </testcase> <testcase classname="test_sample1" file="test_sample1.py" line="10" name="test_file1_method2" time="0.000830173492432" /> </testsuite>
จาก เราจะเห็นการทดสอบทั้งหมดสองรายการ ซึ่งหนึ่งในนั้นล้มเหลว ด้านล่างนั้น คุณจะเห็นรายละเอียดเกี่ยวกับการทดสอบแต่ละรายการที่ดำเนินการไปแล้ว แท็ก
เฟรมเวิร์ก Pytest สำหรับทดสอบ API
ต่อไปนี้เราจะสร้างเฟรมเวิร์ก pytest ขนาดเล็กเพื่อทดสอบ API โดย API ที่ใช้ในที่นี้เป็น API ฟรีจาก [ชื่อแพลตฟอร์ม API] ความต้องการ.ในเว็บไซต์นี้เป็นเพียง API ที่สามารถทดสอบได้ และไม่ได้จัดเก็บข้อมูลของเรา ต่อไปนี้เราจะเขียนการทดสอบสำหรับหัวข้อต่อไปนี้:
- แสดงรายชื่อผู้ใช้บางส่วน
- เข้าสู่ระบบด้วยชื่อผู้ใช้
สร้างไฟล์ต่อไปนี้โดยใช้โค้ดที่ให้มา ก่อนอื่น ไฟล์ conftest.py จะมีฟิกซ์เจอร์ที่จะให้ข้อมูลพื้นฐาน URL สำหรับวิธีการทดสอบทั้งหมด
import pytest @pytest.fixture def supply_url(): return "https://reqres.in/api"
ถัดไป ไฟล์ test_list_user.py จะมีเมธอดทดสอบสำหรับแสดงรายชื่อผู้ใช้ที่ถูกต้องและไม่ถูกต้อง
- test_list_valid_user ทดสอบการดึงข้อมูลผู้ใช้ที่ถูกต้องและตรวจสอบการตอบกลับ
- test_list_invaliduser ทดสอบการดึงข้อมูลผู้ใช้ที่ไม่ถูกต้องและตรวจสอบความถูกต้องของผลลัพธ์
import pytest import requests import json @pytest.mark.parametrize("userid, firstname",[(1,"George"),(2,"Janet")]) def test_list_valid_user(supply_url,userid,firstname): url = supply_url + "/users/" + str(userid) resp = requests.get(url) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['data']['id'] == userid, resp.text assert j['data']['first_name'] == firstname, resp.text def test_list_invaliduser(supply_url): url = supply_url + "/users/50" resp = requests.get(url) assert resp.status_code == 404, resp.text
จากนั้น ไฟล์ test_login_user.py จะมีเมธอดทดสอบสำหรับทดสอบฟังก์ชันการเข้าสู่ระบบ
- test_login_valid จะทดสอบการเข้าสู่ระบบที่ถูกต้องโดยใช้ที่อยู่อีเมลและรหัสผ่าน
- test_login_no_password ทดสอบการพยายามเข้าสู่ระบบที่ไม่ถูกต้องโดยไม่ใส่รหัสผ่าน
- test_login_no_email จะทดสอบการพยายามเข้าสู่ระบบที่ไม่ถูกต้องโดยไม่ระบุอีเมล
import pytest import requests import json def test_login_valid(supply_url): url = supply_url + "/login/" data = {'email':'test@test.com','password':'something'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['token'] == "QpwL5tke4Pnpja7X", resp.text def test_login_no_password(supply_url): url = supply_url + "/login/" data = {'email':'test@test.com'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing password", resp.text def test_login_no_email(supply_url): url = supply_url + "/login/" data = {} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing email or username", resp.text
เรียกใช้การทดสอบโดยใช้คำสั่ง py.test -v และดูผลลัพธ์ดังต่อไปนี้
test_list_user.py::test_list_valid_user[1-George] PASSED test_list_user.py::test_list_valid_user[2-Janet] PASSED test_list_user.py::test_list_invaliduser PASSED test_login_user.py::test_login_valid PASSED test_login_user.py::test_login_no_password PASSED test_login_user.py::test_login_no_email PASSED
อัปเดตการทดสอบและลองใช้ผลลัพธ์ต่างๆ




