8.3 טסטים הרצאה
מבוא לטסטים בPython¶
- "סביבת פרודקשן" היא הסביבה שבה אנו מאחסנים את התוכנה שלנו כאשר אנו רוצים לפרסם אותה בפומבי, למפתחים אחרים או לאנשים כמוצר עובד, בפרודקשן צריך להיות 0 באגים ו-0 הפתעות.
- "סביבת אינטגרציה" היא המקום שבו אנו משלבים רכיבים שונים של התוכנה שלנו יחד ומוודאים שהכל עובד לפני העלת התוכנה לפרודקשן.
לפני השקת התוכנה שלך לפרודקשן אתה צריך לוודא שהתוכנית שלך עובדת ועושה בהצלחה מה שהיא צריכה לעשות.
טסטים היא חלק חיוני בפיתוח תוכנה המבטיח שהקוד שלך מתנהג כמצופה. טסטים הם מבחנים שאנחנו כותבים לתוכנה שלנו כדי לוודא שהיא עובדת. ב-Python, אתה יכול לכתוב טסטים באמצעות המודול המובנה unittest או עם מודול חיצוני כמו pytest. טסטים מתחלקים בדרך כלל לשתי קטגוריות:
- יוניט טסט - unit test: טסטים שמתמקדים בחלקים קטנים ומבודדים של פונקציונליות בתוך הקוד שלך. (לדוגמה פונקציות בסיסיות)
- טסטים לאינטגרציה - integration test: טסטים שמבטיחים שרכיבים שונים של התוכנה שלך פועלים יחד בצורה נכונה.
כתיבת הטסט הראשון שלך¶
כדי להתחיל בכתיבת טסטים, עליך להחליט היכן למקם אותם. בדרך כלל, הטסטים ממוקמים לצד הקוד שהם בודקים, בתקייה נפרדת בשם 'tests'.
הנה דוגמה ליוניט טסט בפייתון:
import unittest
from mymodule import MyClass
class MyTestClass(unittest.TestCase):
def test_my_method(self):
obj = MyClass()
result = obj.my_method()
self.assertEqual(result, 5)
if __name__ == '__main__':
unittest.main()
במקרה הזה שימו לב, כתבנו מחלקה וטסט למחלקה. הטסט יורש מ
unittest.TestCase, ובהגדרה כל מתודה שמתחילה עם test_ נחשבת כטסט.שימו לב שאנחנו קוראים למתודה של המחלקה המקורית ושומרים את הערך חזרה של הפונקציה, אחרכך אנחנו בודקים האם הערף חזרה של הפונקציה שווה לערך שאנחנו מצפים שהפונקציה תחזיר, אם הערך זהה הטסט יעבור בהצלחה, אם לא אז הוא יכשל.
קונספט - מוקים¶
- המון פעמים שנכתוב טסטים לפונקציות הפונקציות יקראו לפונקציות אחרות, ולפעמים הפונקציות שנקראות עלולות לעשות פעולות מסובכות וארוכות, כמו לפנות לאיזשהו API, או לשלוף מידע מDB. אז לפעמים אנחנו נרצה להגדיר בטסט ערך שאותם פונקציות יחזירו לפונקציה שאנחנו עושים לה טסט, כך גם אנחנו יכולים לעשות טסט רק לפונקציה אחת ספציפית.
מוקים בunittest¶
from unittest.mock import patch
import unittest
from mymodule import MyClass
class MyTestClass(unittest.TestCase):
@patch('MyClass.external_function')
def test_my_method(self, mock_external_function):
mock_external_function.return_value = "mocked data"
obj = MyClass()
result = obj.my_method()
self.assertEqual(result, 5)
if __name__ == '__main__':
unittest.main()
- בדוגמה הזו אנחנו משתמשים בדקורטור patch כדי לעשות מוק לפונקציה מסויימת.
- אנחנו מגדירים שהפונקציה "external_function" תמיד תחזיר "mocked data". אחרכך אנחנו קוראים לפונקציה שאנחנו עושים לה טסט - "my_method"
הרצת הטסטים עם unittest¶
- הרץ
python -m unittest discover, זה אוטמטית יחפש טסטים בפרויקט שלך ויריץ אותם. - שימו לב, עד כו עשינו טסטים למחלקות, אפשר גם לעשות טסטים לפונקציות יחידות עם
unittest.
מודול pytest¶
- יותר טוב ממודול
unittest - הרץ
pip install pytest
טסטים בסיסיים¶
# test_example.py
def add(x, y):
return x + y
def test_addition():
assert add(2, 3) == 5
def test_addition_negative():
assert add(-1, 1) == 0
- המילה השמורה assert בפייתון תקריס את התוכנה (תכשיל את הטסט) אם התנאי מחזיר false (משמע הטסט לא עבד)
- כדי להריץ את שני הטסטים שכתבנו הריצו
טסטים עם פרמטרים¶
# Test_example.py
import pytest
def multiply(x, y):
return x * y
@pytest.mark.parametrize("input_1, input_2, expected", [(2, 3, 6), (-1, 5, -5), (0, 100, 0)])
def test_multiplication(input_1, input_2, expected):
result = multiply(input_1, input_2)
assert result == expected
- הטסט שכתבנו מקבל 3 פרמטרים, זה אומר שבפועל יהיו 3 טסטים:
- טסט ראשון יבדוק האם 2 * 3 == 6
- טסט שני יבדוק האם 1- * 5 == 5-
- טסט שלישי יבדוק האם 0 * 100 == 0
דקורטור Fixture¶
- הדקרוטור Fixture מאפשר לנו להעביר פרמטרים למספר טסטים בצורה נוחה.
# Test_example.py import pytest class Calculator: def add(self, x, y): return x + y @pytest.fixture def calculator(): return Calculator() def test_fixture_addition(calculator): result = calculator.add(2, 3) assert result == 5 def test_fixture_addition_negative(calculator): result = calculator.add(-1, 1) assert result == 0