בדיקות מערכת הן כל בדיקות ה-SDV שנוצרו באמצעות SDV Test Framework.
יצירת בדיקה
מיקום הבדיקה
<test_repository_root>/sample_tests<test_repository_root>/e2e_tests<test_repository_root>/long_running_tests<test_repository_root>/performance_tests<test_repository_root>/hardware
קבצי בדיקה
README.md: כל הבדיקות חייבות לכלול תיאור של מטרת הבדיקה והוראות להרצת הבדיקה.קובץ בדיקה: לכל הבדיקות יש מבנה דומה:
"""SDV Name Test"""
from sdv_test_fw.test_execution import sdv_base_test, sdv_test_runner
class SdvTypeNameTest(sdv_base_test.SdvBaseTestClass):
def setup_class(self):
# Setup code. Executed only once at the beginning of the test.
super().setup_class()
self.sdv_device1 = self.get_device('device1')
self.sdv_device2 = self.get_device('device2')
...
# Remove if not needed.
def setup_test(self):
super().setup_test()
# Setup code. Executed before every test case.
# Remove override if not needed.
# Remove if not needed.
def teardown_test(self):
# Cleanup code. Executed after every test case.
super().teardown_test()
# Remove if not needed.
def teardown_class(self):
# Cleanup code. Executed once at the end of the test.
super().teardown_class()
def test_name_case1(self):
# Test case step
# Test case verification
def test_name_case2(self):
# Test case step
# Test case verification
if __name__ == '__main__':
# Start Test Execution Using SDV Test Framework
sdv_test_runner.run()
- קובץ build:
Android.bp. מבנה הקובץ הוא:
python_test_host {
name: "SdvTypeNameTest", // Should match the name of the test class.
main: "sdv_type_name_test.py",
srcs: [
"sdv_type_name_test.py",
],
data: [
":sdv_test_fw_device_configs",
],
test_options: {
unit_test: false,
},
defaults: [
"sdv_test_fw_defaults",
],
test_config_template: ":<DEFAULT_TEMPLATE_NAME>",
}
מוסכמה למתן שמות
כדי לזהות ולמצוא את סוגי הבדיקות השונים, צריך ליצור בדיקות בהתאם למוסכמות ספציפיות למתן שמות:
- בדיקה לדוגמה:
- שם הקובץ:
sdv_sample_<NAME>_test.py - שם הכיתה:
SdvSampleNameTest
- שם הקובץ:
- בדיקת E2E:
- שם הקובץ:
sdv_e2e_<NAME>_test.py - שם הכיתה:
SdvE2ENameTest
- שם הקובץ:
- בדיקה שנמשכת זמן רב:
- שם הקובץ:
sdv_long_running_<NAME>_test.py - שם הכיתה:
SdvLongRunningNameTest
- שם הקובץ:
- בדיקת ביצועים:
- שם הקובץ:
sdv_performance_<NAME>_test.py - שם הכיתה:
SdvPerformanceNameTest
- שם הקובץ:
- בדיקת חומרה:
- שם הקובץ:
sdv_hw_<NAME>_test.py - שם הכיתה:
SdvHWNameTest
- שם הקובץ:
הנחיות לגבי הקוד
בקטע הזה מפורטות הנחיות ושיטות מומלצות לכתיבת בדיקות מערכת של SDV.
Python ו-Mobly
כדאי להכיר את מדריך הסגנון של Python ואת השיטות המומלצות של Mobly, ולקחת בחשבון את ההמלצות הבאות שספציפיות ל-SDV:
אל תשתמשו בייבוא של Mobly באופן ישיר, למעט טענות נכונות (assertions). SDV Test Framework מבוסס על CTS ומתמקד ב-SDV.
טענות נכונות (assertions): משתמשים בטענות הנכונות של Mobly ישירות.
בדיקות SDV
בקטעים הבאים מפורטות הנחיות ספציפיות ושיטות מומלצות לפיתוח בדיקות ב-SDV Test Framework.
הגדרה וניקוי
קוד ההגדרה והניקוי צריך להיות מחוץ למקרי הבדיקה. שיטות הפירוק מופעלות גם אם הבדיקה נכשלת, כדי לנקות את המכשיר כמו שצריך.
המיקום של קוד ההגדרה והפירוק תלוי בצרכים הספציפיים של הבדיקה, גם אם הבדיקה מופסקת:
- כדי להריץ רק פעם אחת בתחילת הבדיקה כולה ובסופה, משתמשים ב-
setup_classוב-teardown_class. לדוגמה, קבלת מכשירים, הגדרת ערכי משתנים או מצב שלא משתנה בין מקרי בדיקה, הגדרת מאפייני מכשיר נפוצים או הגדרת דגלים.
def setup_class(self):
super().setup_class()
# setup code
def teardown_class(self):
# teardown code
super().teardown_class()
- כדי להריץ בין מקרי בדיקה, לפני ואחרי כל אחד מהם. לדוגמה, סשן אינטראקטיבי או הפעלה של שירות נפוץ.
def setup_test(self):
super().setup_test()
# setup code
def teardown_test(self):
# teardown code
super().teardown_test()
מקרי בדיקה עם פרמטרים
כדי להימנע מחזרה על קוד, השתמשו במקרי בדיקה עם פרמטרים כשהשלבים משותפים למקרי בדיקה שונים.
from absl.testing import parameterized
@parameterized.named_parameters(
{
'testcase_name': 'ab',
'input1': 'a',
'input2': 'b',
},
{
'testcase_name': 'cd',
'input1': 'c',
'input2': 'd',
},
)
def test_name(self, input1, input2):
# test
בדוגמה נוצרים שני מקרי בדיקה: test_name_ab ו-test_name_cd.
מקרה בדיקה אחד לאימות ההתנהגות
מקרי הבדיקה צריכים להיות קומפקטיים ולהתמקד בהתנהגות ספציפית אחת. אם לכמה התנהגויות יש תנאים מוקדמים או שלבים משותפים, כדאי לפצל אותן. כדי לצמצם את כמות הקוד שחוזר על עצמו, אתם יכולים להשתמש ב-setup_test או בפרמטריזציה.
כך קל יותר לקרוא את הבדיקות ולנפות מהן באגים, כי ברור אילו שלבים ותנאים נכשלו.
דוגמה
def test_verify_process(self):
self.device.start_process()
# precondition 1
self.device.send_signal1()
# verification signal1 received
...
# precondition 2
self.device.send_signal2()
# verification signal2 received
...
# precondition 3
self.device.start_agent()
# verification behavior
...
self.device.kill_process()
def setup_test(self):
super().setup_test()
self.device.start_process()
def test_signal1(self):
# precondition
self.device.send_signal1()
# verification signal1 received
...
def test_signal2(self):
# precondition
self.device.send_signal2()
# verification signal2 received
...
def test_agent(self):
# precondition
self.device.start_agent()
# verification behavior
...
def teardown_test(self):
self.device.kill_process()
super().teardown_test()
התנהגות דטרמיניסטית של בדיקות
אל תוסיפו לבדיקה תנאים שמפצלים את ההתנהגות שלה. אם צריך לפצל אימות, השתמשו בשני מקרי בדיקה שונים.
לא להשתמש בחריגים
בבדיקות ובכלי עזר נפוצים צריך להשתמש בטענות נכונות (assertions) במקום בחריגים (exceptions). כך קל יותר לנפות באגים ולעקוב אחרי דפוסי בדיקה.
דוגמה
result = self.some_calculations()
if result is None:
raise Exception("No result")
result = self.some_calculations()
self.get_test_validator().assert_is_not_none(result)
דוגמה
if not self.device.is_subprocess_running(
self.EXPECTED_PROCESS
):
raise Exception("Process is not running")
self.get_test_validator().assert_true(
self.device.is_subprocess_running(self.EXPECTED_PROCESS),
"Process is not running"
)
לא להשתמש במצב שינה
כדאי להימנע משימוש ב-sleep כי הוא מאריך את זמן ביצוע הבדיקה וגורם לחוסר יציבות.
אם הבדיקה דורשת המתנה לאירוע או לאימות כדי להמשיך, צריך להשתמש בשיטות ההמתנה שסופקו במסגרת.
חשוב להשתמש בשיטות המתנה בזהירות, כי ביצוע הבדיקה נשאר חסום עד שהתנאי מתקיים או עד שנגמר הזמן הקצוב לתפוגה.
כשצריך לחכות עד שתנאי מסוים יתקיים בבדיקה, כדאי לשאול את עצמכם את השאלות הבאות:
מהו זמן קצוב לתפוגה סביר?
אם אירוע צפוי להתרחש בפרק זמן מסוים, זמן הקצוב לתפוגה צריך להתאים לציפייה הזו כדי לוודא שהבדיקה תיכשל במהירות. אם צריך, מקצרים את הזמן הקצוב לתפוגה (ברירת המחדל היא 30 שניות).
כמה משאבים נדרשים כדי לבצע את הפעולה של שיטת ההמתנה?
הימנעו מהפעלה תכופה של פעולות שצורכות משאבים רבים. אם צריך, מגדילים את מרווח הזמן של הסקר (ברירת המחדל היא 0.5 שניות).
מקרי בדיקה עם דרישות
אם לבדיקה יש מקרי בדיקה עם דרישות מפורשות כדי לפעול (לדוגמה, היעד שבו היא אמורה לפעול), אתם יכולים לדלג עליהם אם הם לא תואמים לדרישות:
def test_with_requirement(self):
self.get_test_validator().skip_if(expr, reason)
# Test case