Pytest - คู่มือฉบับย่อ
Pytest เป็นเฟรมเวิร์กการทดสอบที่ใช้ Python ซึ่งใช้ในการเขียนและรันโค้ดทดสอบ ในปัจจุบันของบริการ REST pytest ส่วนใหญ่จะใช้สำหรับการทดสอบ API แม้ว่าเราจะสามารถใช้ pytest เพื่อเขียนการทดสอบแบบง่ายไปจนถึงซับซ้อนได้เช่นเราสามารถเขียนโค้ดเพื่อทดสอบ API ฐานข้อมูล UI และอื่น ๆ
ข้อดีของ Pytest
ข้อดีของ Pytest มีดังนี้ -
Pytest สามารถเรียกใช้การทดสอบหลายรายการพร้อมกันซึ่งจะช่วยลดเวลาในการดำเนินการของชุดทดสอบ
Pytest มีวิธีของตัวเองในการตรวจจับไฟล์ทดสอบและทดสอบฟังก์ชันโดยอัตโนมัติหากไม่ได้ระบุไว้อย่างชัดเจน
Pytest ช่วยให้เราสามารถข้ามการทดสอบบางส่วนระหว่างการดำเนินการได้
Pytest ช่วยให้เราสามารถเรียกใช้ชุดทดสอบย่อยทั้งหมดได้
Pytest เป็นโอเพ่นซอร์สฟรี
เนื่องจากไวยากรณ์ที่เรียบง่าย pytest จึงเริ่มต้นได้ง่ายมาก
ในบทช่วยสอนนี้เราจะอธิบายถึงปัจจัยพื้นฐานที่ยิ่งใหญ่ที่สุดด้วยโปรแกรมตัวอย่าง
ในบทนี้เราจะเรียนรู้วิธีการติดตั้ง pytest
ในการเริ่มการติดตั้งให้ดำเนินการคำสั่งต่อไปนี้ -
pip install pytest == 2.9.1
เราสามารถติดตั้ง pytest เวอร์ชันใดก็ได้ นี่ 2.9.1 คือเวอร์ชันที่เรากำลังติดตั้ง
ในการติดตั้ง pytest เวอร์ชันล่าสุดให้ดำเนินการคำสั่งต่อไปนี้ -
pip install pytest
ยืนยันการติดตั้งโดยใช้คำสั่งต่อไปนี้เพื่อแสดงส่วนวิธีใช้ของ pytest
pytest -h
การเรียกใช้ pytest โดยไม่กล่าวถึงชื่อไฟล์จะเรียกใช้ไฟล์ทุกรูปแบบ test_*.py หรือ *_test.pyในไดเร็กทอรีปัจจุบันและไดเร็กทอรีย่อย Pytest จะระบุไฟล์เหล่านั้นโดยอัตโนมัติว่าเป็นไฟล์ทดสอบ เราcan ทำให้ pytest เรียกใช้ชื่อไฟล์อื่นโดยกล่าวถึงอย่างชัดเจน
Pytest ต้องการให้ชื่อฟังก์ชันทดสอบขึ้นต้นด้วย test. ชื่อฟังก์ชันที่ไม่ใช่รูปแบบtest*ไม่ถือว่าเป็นฟังก์ชันทดสอบโดย pytest เราcannot ทำให้ pytest พิจารณาฟังก์ชันใด ๆ ที่ไม่ได้ขึ้นต้นด้วย test เป็นฟังก์ชันทดสอบ
เราจะเข้าใจการดำเนินการทดสอบในบทต่อ ๆ ไปของเรา
ตอนนี้เราจะเริ่มต้นด้วยโปรแกรม pytest แรกของเรา ก่อนอื่นเราจะสร้างไดเร็กทอรีจากนั้นสร้างไฟล์ทดสอบของเราในไดเร็กทอรี
ให้เราทำตามขั้นตอนที่แสดงด้านล่าง -
สร้างไดเร็กทอรีใหม่ชื่อ automation และไปที่ไดเร็กทอรีในบรรทัดคำสั่งของคุณ
สร้างไฟล์ชื่อ test_square.py และเพิ่มรหัสด้านล่างลงในไฟล์นั้น
import math
def test_sqrt():
num = 25
assert math.sqrt(num) == 5
def testsquare():
num = 7
assert 7*7 == 40
def tesequality():
assert 10 == 11
ทำการทดสอบโดยใช้คำสั่งต่อไปนี้ -
pytest
คำสั่งดังกล่าวจะสร้างผลลัพธ์ต่อไปนี้ -
test_square.py .F
============================================== FAILURES
==============================================
______________________________________________ testsquare
_____________________________________________
def testsquare():
num=7
> assert 7*7 == 40
E assert (7 * 7) == 40
test_square.py:9: AssertionError
================================= 1 failed, 1 passed in 0.06 seconds
=================================
ดูบรรทัดแรกของผลลัพธ์ จะแสดงชื่อไฟล์และผลลัพธ์ F หมายถึงความล้มเหลวในการทดสอบและจุด (.) แสดงถึงความสำเร็จในการทดสอบ
ด้านล่างนี้เราสามารถดูรายละเอียดของการทดสอบที่ล้มเหลว จะแสดงข้อความที่การทดสอบล้มเหลว ในตัวอย่างของเรา 7 * 7 ถูกเปรียบเทียบเพื่อความเท่าเทียมกับ 40 ซึ่งไม่ถูกต้อง ในท้ายที่สุดเราจะเห็นสรุปการดำเนินการทดสอบ 1 ล้มเหลวและ 1 ผ่าน
ฟังก์ชัน tesequality จะไม่ถูกเรียกใช้เนื่องจาก pytest จะไม่ถือว่าเป็นการทดสอบเนื่องจากชื่อของมันไม่ใช่รูปแบบ test*.
ตอนนี้ดำเนินการคำสั่งด้านล่างและดูผลลัพธ์อีกครั้ง -
pytest -v
-v เพิ่มความฟุ่มเฟื่อย
test_square.py::test_sqrt PASSED
test_square.py::testsquare FAILED
============================================== FAILURES
==============================================
_____________________________________________ testsquare
_____________________________________________
def testsquare():
num = 7
> assert 7*7 == 40
E assert (7 * 7) == 40
test_square.py:9: AssertionError
================================= 1 failed, 1 passed in 0.04 seconds
=================================
ตอนนี้ผลลัพธ์อธิบายได้มากขึ้นเกี่ยวกับการทดสอบที่ล้มเหลวและการทดสอบที่ผ่าน
Note - คำสั่ง pytest จะเรียกใช้ไฟล์รูปแบบทั้งหมด test_* หรือ *_test ในไดเร็กทอรีปัจจุบันและไดเร็กทอรีย่อย
ในบทนี้เราจะเรียนรู้วิธีเรียกใช้ไฟล์ทดสอบไฟล์เดียวและไฟล์ทดสอบหลายไฟล์ เรามีไฟล์ทดสอบแล้วtest_square.pyสร้างขึ้น สร้างไฟล์ทดสอบใหม่test_compare.py ด้วยรหัสต่อไปนี้ -
def test_greater():
num = 100
assert num > 100
def test_greater_equal():
num = 100
assert num >= 100
def test_less():
num = 100
assert num < 200
ตอนนี้เพื่อเรียกใช้การทดสอบทั้งหมดจากไฟล์ทั้งหมด (2 ไฟล์ที่นี่) เราต้องเรียกใช้คำสั่งต่อไปนี้ -
pytest -v
คำสั่งดังกล่าวจะเรียกใช้การทดสอบจากทั้งสองอย่าง test_square.py และ test_compare.py. ผลลัพธ์จะถูกสร้างขึ้นดังนี้ -
test_compare.py::test_greater FAILED
test_compare.py::test_greater_equal PASSED
test_compare.py::test_less PASSED
test_square.py::test_sqrt PASSED
test_square.py::testsquare FAILED
================================================ FAILURES
================================================
______________________________________________ test_greater
______________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
_______________________________________________ testsquare
_______________________________________________
def testsquare():
num = 7
> assert 7*7 == 40
E assert (7 * 7) == 40
test_square.py:9: AssertionError
=================================== 2 failed, 3 passed in 0.07 seconds
===================================
ในการดำเนินการทดสอบจากไฟล์เฉพาะให้ใช้ไวยากรณ์ต่อไปนี้ -
pytest <filename> -v
ตอนนี้เรียกใช้คำสั่งต่อไปนี้ -
pytest test_compare.py -v
คำสั่งดังกล่าวจะดำเนินการทดสอบจากไฟล์เท่านั้น test_compare.py. ผลลัพธ์ของเราจะเป็น -
test_compare.py::test_greater FAILED
test_compare.py::test_greater_equal PASSED
test_compare.py::test_less PASSED
============================================== FAILURES
==============================================
____________________________________________ test_greater
____________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
================================= 1 failed, 2 passed in 0.04 seconds
=================================
ในสถานการณ์จริงเราจะมีไฟล์ทดสอบหลายไฟล์และแต่ละไฟล์จะมีการทดสอบจำนวนหนึ่ง การทดสอบจะครอบคลุมโมดูลและฟังก์ชันต่างๆ สมมติว่าเราต้องการเรียกใช้การทดสอบเฉพาะชุดหนึ่ง เราจะไปต่อได้อย่างไร
Pytest มีสองวิธีในการเรียกใช้ชุดย่อยของชุดทดสอบ
- เลือกการทดสอบที่จะเรียกใช้ตามการจับคู่สตริงย่อยของชื่อการทดสอบ
- เลือกกลุ่มการทดสอบที่จะเรียกใช้ตามเครื่องหมายที่ใช้
เราจะอธิบายสองสิ่งนี้พร้อมตัวอย่างในบทต่อ ๆ ไป
ในการดำเนินการทดสอบที่มีสตริงในชื่อเราสามารถใช้ไวยากรณ์ต่อไปนี้ -
pytest -k <substring> -v
-k <substring> แทนสตริงย่อยที่จะค้นหาในชื่อการทดสอบ
ตอนนี้เรียกใช้คำสั่งต่อไปนี้ -
pytest -k great -v
การดำเนินการนี้จะเรียกใช้ชื่อการทดสอบทั้งหมดที่มีคำ ‘great’ในชื่อของมัน ในกรณีนี้คือtest_greater() และ test_greater_equal(). ดูผลลัพธ์ด้านล่าง
test_compare.py::test_greater FAILED
test_compare.py::test_greater_equal PASSED
============================================== FAILURES
==============================================
____________________________________________ test_greater
____________________________________________
def test_greater():
num = 100
> assert num > 100
E assert 100 > 100
test_compare.py:3: AssertionError
========================== 1 failed, 1 passed, 3 deselected in 0.07 seconds
==========================
ในผลลัพธ์นี้เราจะเห็นการทดสอบ 3 รายการที่ยกเลิกการเลือก เนื่องจากชื่อการทดสอบเหล่านั้นไม่มีคำว่าgreat ในพวกเขา
Note - ชื่อของฟังก์ชันการทดสอบควรยังคงขึ้นต้นด้วย 'test'
ในบทนี้เราจะเรียนรู้วิธีจัดกลุ่มการทดสอบโดยใช้เครื่องหมาย
Pytest อนุญาตให้เราใช้เครื่องหมายในฟังก์ชันทดสอบ เครื่องหมายใช้เพื่อตั้งค่าคุณสมบัติ / คุณลักษณะต่างๆเพื่อทดสอบฟังก์ชัน Pytest มีเครื่องหมาย inbuilt จำนวนมากเช่น xfail, skip และ parametrize นอกเหนือจากนั้นผู้ใช้สามารถสร้างชื่อเครื่องหมายของตนเองได้ เครื่องหมายถูกนำไปใช้กับการทดสอบโดยใช้ไวยากรณ์ที่ระบุด้านล่าง -
@pytest.mark.<markername>
ในการใช้เครื่องหมายเราต้อง import pytestโมดูลในไฟล์ทดสอบ เราสามารถกำหนดชื่อเครื่องหมายของเราเองในการทดสอบและเรียกใช้การทดสอบด้วยชื่อเครื่องหมายเหล่านั้น
ในการเรียกใช้การทดสอบที่ทำเครื่องหมายไว้เราสามารถใช้ไวยากรณ์ต่อไปนี้ -
pytest -m <markername> -v
-m <markername> แสดงถึงชื่อเครื่องหมายของการทดสอบที่จะดำเนินการ
อัปเดตไฟล์ทดสอบของเรา test_compare.py และ test_square.pyด้วยรหัสต่อไปนี้ เรากำลังกำหนด 3 เครื่องหมาย– great, square, others.
test_compare.py
import pytest
@pytest.mark.great
def test_greater():
num = 100
assert num > 100
@pytest.mark.great
def test_greater_equal():
num = 100
assert num >= 100
@pytest.mark.others
def test_less():
num = 100
assert num < 200
test_square.py
import pytest
import math
@pytest.mark.square
def test_sqrt():
num = 25
assert math.sqrt(num) == 5
@pytest.mark.square
def testsquare():
num = 7
assert 7*7 == 40
@pytest.mark.others
def test_equality():
assert 10 == 11
ตอนนี้เพื่อเรียกใช้การทดสอบที่ทำเครื่องหมายเป็น othersเรียกใช้คำสั่งต่อไปนี้ -
pytest -m others -v
ดูผลลัพธ์ด้านล่าง ดำเนินการทดสอบ 2 รายการที่ทำเครื่องหมายว่าothers.
test_compare.py::test_less PASSED
test_square.py::test_equality FAILED
============================================== FAILURES
==============================================
___________________________________________ test_equality
____________________________________________
@pytest.mark.others
def test_equality():
> assert 10 == 11
E assert 10 == 11
test_square.py:16: AssertionError
========================== 1 failed, 1 passed, 4 deselected in 0.08 seconds
==========================
ในทำนองเดียวกันเราสามารถเรียกใช้การทดสอบกับเครื่องหมายอื่น ๆ ได้เช่นกัน - เยี่ยมมากเปรียบเทียบได้
ส่วนควบเป็นฟังก์ชันซึ่งจะทำงานก่อนการทดสอบแต่ละฟังก์ชันที่จะใช้ การแข่งขันใช้เพื่อป้อนข้อมูลบางส่วนไปยังการทดสอบเช่นการเชื่อมต่อฐานข้อมูล URL ที่จะทดสอบและข้อมูลอินพุตบางประเภท ดังนั้นแทนที่จะเรียกใช้รหัสเดียวกันสำหรับการทดสอบทุกครั้งเราสามารถแนบฟังก์ชันฟิกซ์เจอร์เข้ากับการทดสอบและจะเรียกใช้และส่งคืนข้อมูลไปยังการทดสอบก่อนดำเนินการทดสอบแต่ละครั้ง
ฟังก์ชันถูกทำเครื่องหมายว่าเป็นฟิกซ์เจอร์โดย -
@pytest.fixture
ฟังก์ชันทดสอบสามารถใช้ฟิกซ์เจอร์ได้โดยระบุชื่อฟิกซ์เจอร์เป็นพารามิเตอร์อินพุต
สร้างไฟล์ test_div_by_3_6.py และเพิ่มรหัสด้านล่างลงไป
import pytest
@pytest.fixture
def input_value():
input = 39
return input
def test_divisible_by_3(input_value):
assert input_value % 3 == 0
def test_divisible_by_6(input_value):
assert input_value % 6 == 0
ที่นี่เรามีฟังก์ชันติดตั้งชื่อ input_valueซึ่งให้ข้อมูลเข้าในการทดสอบ ในการเข้าถึงฟังก์ชันฟิกซ์เจอร์การทดสอบต้องระบุชื่อฟิกซ์เจอร์เป็นพารามิเตอร์อินพุต
Pytest ในขณะที่กำลังดำเนินการทดสอบจะเห็นชื่อฟิกซ์เจอร์เป็นพารามิเตอร์อินพุต จากนั้นเรียกใช้ฟังก์ชันฟิกซ์เจอร์และค่าที่ส่งคืนจะถูกเก็บไว้ในพารามิเตอร์อินพุตซึ่งสามารถใช้โดยการทดสอบได้
ดำเนินการทดสอบโดยใช้คำสั่งต่อไปนี้ -
pytest -k divisible -v
คำสั่งดังกล่าวจะสร้างผลลัพธ์ต่อไปนี้ -
test_div_by_3_6.py::test_divisible_by_3 PASSED
test_div_by_3_6.py::test_divisible_by_6 FAILED
============================================== FAILURES
==============================================
________________________________________ test_divisible_by_6
_________________________________________
input_value = 39
def test_divisible_by_6(input_value):
> assert input_value % 6 == 0
E assert (39 % 6) == 0
test_div_by_3_6.py:12: AssertionError
========================== 1 failed, 1 passed, 6 deselected in 0.07 seconds
==========================
อย่างไรก็ตามแนวทางดังกล่าวมาพร้อมกับข้อ จำกัด ของตัวเอง ฟังก์ชันฟิกซ์เจอร์ที่กำหนดไว้ภายในไฟล์ทดสอบมีขอบเขตภายในไฟล์ทดสอบเท่านั้น เราไม่สามารถใช้ฟิกซ์เจอร์นั้นในไฟล์ทดสอบอื่นได้ ในการทำให้ฟิกซ์เจอร์พร้อมใช้งานกับไฟล์ทดสอบหลายไฟล์เราต้องกำหนดฟังก์ชันฟิกซ์เจอร์ในไฟล์ที่เรียกว่า conftest.pyconftest.py จะอธิบายในบทถัดไป
เราสามารถกำหนดฟังก์ชันฟิกซ์เจอร์ในไฟล์นี้เพื่อให้เข้าถึงได้จากไฟล์ทดสอบหลายไฟล์
สร้างไฟล์ใหม่ conftest.py และเพิ่มรหัสด้านล่างเข้าไป -
import pytest
@pytest.fixture
def input_value():
input = 39
return input
แก้ไขไฟล์ test_div_by_3_6.py เพื่อลบฟังก์ชันการติดตั้ง -
import pytest
def test_divisible_by_3(input_value):
assert input_value % 3 == 0
def test_divisible_by_6(input_value):
assert input_value % 6 == 0
สร้างไฟล์ใหม่ test_div_by_13.py -
import pytest
def test_divisible_by_13(input_value):
assert input_value % 13 == 0
ตอนนี้เรามีไฟล์ test_div_by_3_6.py และ test_div_by_13.py ใช้ประโยชน์จากฟิกซ์เจอร์ที่กำหนดไว้ใน conftest.py.
เรียกใช้การทดสอบโดยดำเนินการคำสั่งต่อไปนี้ -
pytest -k divisible -v
คำสั่งดังกล่าวจะสร้างผลลัพธ์ต่อไปนี้ -
test_div_by_13.py::test_divisible_by_13 PASSED
test_div_by_3_6.py::test_divisible_by_3 PASSED
test_div_by_3_6.py::test_divisible_by_6 FAILED
============================================== FAILURES
==============================================
________________________________________ test_divisible_by_6
_________________________________________
input_value = 39
def test_divisible_by_6(input_value):
> assert input_value % 6 == 0
E assert (39 % 6) == 0
test_div_by_3_6.py:7: AssertionError
========================== 1 failed, 2 passed, 6 deselected in 0.09 seconds
==========================
การทดสอบจะค้นหาฟิกซ์เจอร์ในไฟล์เดียวกัน เนื่องจากไม่พบฟิกซ์เจอร์ในไฟล์มันจะตรวจสอบฟิกซ์เจอร์ในไฟล์ conftest.py ในการค้นหาวิธีการติดตั้งจะถูกเรียกใช้และผลลัพธ์จะถูกส่งกลับไปยังอาร์กิวเมนต์อินพุตของการทดสอบ
การกำหนดพารามิเตอร์ของการทดสอบทำขึ้นเพื่อรันการทดสอบกับอินพุตหลายชุด เราสามารถทำได้โดยใช้เครื่องหมายต่อไปนี้ -
@pytest.mark.parametrize
คัดลอกโค้ดด้านล่างลงในไฟล์ที่เรียกว่า test_multiplication.py -
import pytest
@pytest.mark.parametrize("num, output",[(1,11),(2,22),(3,35),(4,44)])
def test_multiplication_11(num, output):
assert 11*num == output
ที่นี่การทดสอบจะคูณอินพุตด้วย 11 และเปรียบเทียบผลลัพธ์กับผลลัพธ์ที่คาดหวัง การทดสอบมีอินพุต 4 ชุดแต่ละชุดมี 2 ค่า - หนึ่งคือจำนวนที่จะคูณด้วย 11 และอีกชุดคือผลลัพธ์ที่คาดหวัง
ดำเนินการทดสอบโดยรันคำสั่งต่อไปนี้ -
Pytest -k multiplication -v
คำสั่งดังกล่าวจะสร้างผลลัพธ์ต่อไปนี้ -
test_multiplication.py::test_multiplication_11[1-11] PASSED
test_multiplication.py::test_multiplication_11[2-22] PASSED
test_multiplication.py::test_multiplication_11[3-35] FAILED
test_multiplication.py::test_multiplication_11[4-44] PASSED
============================================== FAILURES
==============================================
_________________ test_multiplication_11[3-35] __________________
num = 3, output = 35
@pytest.mark.parametrize("num, output",[(1,11),(2,22),(3,35),(4,44)])
def test_multiplication_11(num, output):
> assert 11*num == output
E assert (11 * 3) == 35
test_multiplication.py:5: AssertionError
============================== 1 failed, 3 passed, 8 deselected in 0.08 seconds
==============================
ในบทนี้เราจะเรียนรู้เกี่ยวกับการทดสอบ Skip และ Xfail ใน Pytest
ตอนนี้พิจารณาสถานการณ์ด้านล่าง -
- การทดสอบไม่เกี่ยวข้องในบางครั้งเนื่องจากสาเหตุบางประการ
- กำลังมีการใช้งานคุณลักษณะใหม่และเราได้เพิ่มการทดสอบสำหรับคุณลักษณะนั้นแล้ว
ในสถานการณ์เหล่านี้เรามีตัวเลือกในการ xfail การทดสอบหรือข้ามการทดสอบ
Pytest จะดำเนินการทดสอบ xfailed แต่จะไม่ถือว่าเป็นส่วนที่ล้มเหลวหรือผ่านการทดสอบ รายละเอียดของการทดสอบเหล่านี้จะไม่ถูกพิมพ์แม้ว่าการทดสอบจะล้มเหลวก็ตาม (โปรดจำไว้ว่า pytest มักจะพิมพ์รายละเอียดการทดสอบที่ล้มเหลว) เราสามารถ xfail การทดสอบโดยใช้เครื่องหมายต่อไปนี้ -
@pytest.mark.xfail
การข้ามการทดสอบหมายความว่าการทดสอบจะไม่ถูกดำเนินการ เราสามารถข้ามการทดสอบโดยใช้เครื่องหมายต่อไปนี้ -
@pytest.mark.skip
หลังจากนั้นเมื่อการทดสอบมีความเกี่ยวข้องเราสามารถลบเครื่องหมายออกได้
แก้ไขไฟล์ test_compare.py เราต้องรวมเครื่องหมาย xfail และข้ามไว้แล้ว -
import pytest
@pytest.mark.xfail
@pytest.mark.great
def test_greater():
num = 100
assert num > 100
@pytest.mark.xfail
@pytest.mark.great
def test_greater_equal():
num = 100
assert num >= 100
@pytest.mark.skip
@pytest.mark.others
def test_less():
num = 100
assert num < 200
ดำเนินการทดสอบโดยใช้คำสั่งต่อไปนี้ -
pytest test_compare.py -v
เมื่อดำเนินการคำสั่งดังกล่าวจะสร้างผลลัพธ์ต่อไปนี้ -
test_compare.py::test_greater xfail
test_compare.py::test_greater_equal XPASS
test_compare.py::test_less SKIPPED
============================ 1 skipped, 1 xfailed, 1 xpassed in 0.06 seconds
============================
ในสถานการณ์จริงเมื่อโค้ดเวอร์ชันใหม่พร้อมใช้งานแล้วโค้ดจะถูกปรับใช้ในสภาพแวดล้อมแบบ pre-prod / staging ก่อน จากนั้นชุดทดสอบจะทำงาน
รหัสนี้มีคุณสมบัติสำหรับการปรับใช้กับการใช้งานจริงเมื่อชุดทดสอบผ่าน หากมีความล้มเหลวในการทดสอบไม่ว่าจะเป็นรหัสเดียวหรือหลายรหัสยังไม่พร้อมใช้งานจริง
ดังนั้นจะเกิดอะไรขึ้นถ้าเราต้องการหยุดการทำงานของชุดทดสอบในไม่ช้าหลังจาก n จำนวนการทดสอบล้มเหลว สามารถทำได้ใน pytest โดยใช้ maxfail
ไวยากรณ์เพื่อหยุดการทำงานของชุดทดสอบในไม่ช้าหลังจาก n จำนวนการทดสอบล้มเหลวมีดังนี้ -
pytest --maxfail = <num>
สร้างไฟล์ test_failure.py ด้วยรหัสต่อไปนี้
import pytest
import math
def test_sqrt_failure():
num = 25
assert math.sqrt(num) == 6
def test_square_failure():
num = 7
assert 7*7 == 40
def test_equality_failure():
assert 10 == 11
การทดสอบทั้ง 3 ครั้งจะล้มเหลวในการเรียกใช้ไฟล์ทดสอบนี้ ที่นี่เราจะหยุดการดำเนินการทดสอบหลังจากความล้มเหลวหนึ่งครั้งโดย -
pytest test_failure.py -v --maxfail = 1
test_failure.py::test_sqrt_failure FAILED
=================================== FAILURES
=================================== _______________________________________
test_sqrt_failure __________________________________________
def test_sqrt_failure():
num = 25
> assert math.sqrt(num) == 6
E assert 5.0 == 6
E + where 5.0 = <built-in function sqrt>(25)
E + where <built-in function sqrt>= math.sqrt
test_failure.py:6: AssertionError
=============================== 1 failed in 0.04 seconds
===============================
จากผลลัพธ์ข้างต้นเราจะเห็นการดำเนินการหยุดลงในความล้มเหลวครั้งเดียว
โดยค่าเริ่มต้น pytest จะรันการทดสอบตามลำดับ ในสถานการณ์จริงชุดทดสอบจะมีไฟล์ทดสอบจำนวนหนึ่งและแต่ละไฟล์จะมีการทดสอบมากมาย ซึ่งจะนำไปสู่การดำเนินการครั้งใหญ่ เพื่อเอาชนะสิ่งนี้ pytest มีตัวเลือกให้เราทำการทดสอบควบคู่กันไป
สำหรับสิ่งนี้เราต้องติดตั้งปลั๊กอิน pytest-xdist ก่อน
ติดตั้ง pytest-xdist โดยรันคำสั่งต่อไปนี้ -
pip install pytest-xdist
ตอนนี้เราสามารถเรียกใช้การทดสอบโดยใช้ไวยากรณ์ pytest -n <num>
pytest -n 3
-n <num> รันการทดสอบโดยใช้คนงานหลายคนนี่คือ 3
เราจะไม่มีความแตกต่างของเวลามากนักเมื่อมีการทดสอบเพียงเล็กน้อยเท่านั้น อย่างไรก็ตามจะมีความสำคัญเมื่อชุดทดสอบมีขนาดใหญ่
เราสามารถสร้างรายละเอียดของการดำเนินการทดสอบในไฟล์ xml ไฟล์ xml นี้มีประโยชน์เป็นหลักในกรณีที่เรามีแดชบอร์ดที่แสดงผลการทดสอบ ในกรณีเช่นนี้สามารถแยกวิเคราะห์ xml เพื่อดูรายละเอียดของการดำเนินการได้
ตอนนี้เราจะดำเนินการทดสอบจาก test_multiplcation.py และสร้าง xml โดยเรียกใช้
pytest test_multiplication.py -v --junitxml="result.xml"
ตอนนี้เราสามารถเห็น result.xml ถูกสร้างขึ้นด้วยข้อมูลต่อไปนี้ -
<?xml version = "1.0" encoding = "utf-8"?>
<testsuite errors = "0" failures = "1"
name = "pytest" skips = "0" tests = "4" time = "0.061">
<testcase classname = "test_multiplication"
file = "test_multiplication.py"
line = "2" name = "test_multiplication_11[1-11]"
time = "0.00117516517639>
</testcase>
<testcase classname = "test_multiplication"
file = "test_multiplication.py"
line = "2" name = "test_multiplication_11[2-22]"
time = "0.00155973434448">
</testcase>
<testcase classname = "test_multiplication"
file = "test_multiplication.py"
line = "2" name = "test_multiplication_11[3-35]" time = "0.00144290924072">
failure message = "assert (11 * 3) == 35">num = 3, output = 35
@pytest.mark.parametrize("num,
output",[(1,11),(2,22),(3,35),(4,44)])
def test_multiplication_11(num, output):>
assert 11*num == output
E assert (11 * 3) == 35
test_multiplication.py:5: AssertionErro
</failure>
</testcase>
<testcase classname = "test_multiplication"
file = "test_multiplication.py"
line = "2" name = "test_multiplication_11[4-44]"
time = "0.000945091247559">
</testcase>
</testsuite>
ที่นี่แท็ก <testsuit> สรุปมีการทดสอบ 4 ครั้งและจำนวนข้อผิดพลาดคือ 1
แท็ก <testcase> ให้รายละเอียดของการทดสอบที่ดำเนินการแต่ละครั้ง
แท็ก <failure> ให้รายละเอียดของรหัสทดสอบที่ล้มเหลว
ในบทช่วยสอน pytest นี้เราได้กล่าวถึงประเด็นต่อไปนี้ -
- กำลังติดตั้ง pytest ..
- การระบุไฟล์ทดสอบและฟังก์ชันการทดสอบ
- การเรียกใช้ไฟล์ทดสอบทั้งหมดโดยใช้ pytest –v
- การเรียกใช้ไฟล์เฉพาะ usimng pytest <filename> -v.
- ดำเนินการทดสอบโดยสตริงย่อยที่ตรงกับ pytest -k <substring> -v
- ดำเนินการทดสอบตามเครื่องหมาย pytest -m <marker_name> -v
- การสร้างการแข่งขันโดยใช้ @ pytest.fixture
- conftest.py อนุญาตให้เข้าถึงส่วนควบจากไฟล์หลายไฟล์
- การทดสอบ Parametrizing โดยใช้ @ pytest.mark.parametrize
- Xfailing การทดสอบโดยใช้ @ pytest.mark.xfail
- ข้ามการทดสอบโดยใช้ @ pytest.mark.skip
- หยุดการดำเนินการทดสอบกับ n ความล้มเหลวโดยใช้ pytest --maxfail = <num>
- รันการทดสอบแบบขนานโดยใช้ pytest -n <num>
- การสร้างผลลัพธ์ xml โดยใช้ pytest -v --junitxml = "result.xml"
บทช่วยสอนนี้แนะนำให้คุณรู้จักกับ pytest framework ตอนนี้คุณควรจะเริ่มเขียนแบบทดสอบโดยใช้ pytest ได้แล้ว
เป็นแนวทางปฏิบัติที่ดี -
- สร้างไฟล์ทดสอบต่างๆตามฟังก์ชันการทำงาน / โมดูลที่กำลังทดสอบ
- ตั้งชื่อที่มีความหมายเพื่อทดสอบไฟล์และวิธีการ
- มีเครื่องหมายเพียงพอที่จะจัดกลุ่มการทดสอบตามเกณฑ์ต่างๆ
- ใช้อุปกรณ์ติดตั้งเมื่อจำเป็น