تستهای سیستم به هر تست SDV که با استفاده از چارچوب تست SDV ایجاد شده باشد، اشاره دارد.
ایجاد تست
محل آزمایش
-
<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()
- فایل ساخت:
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 ارائه میدهد.
پایتون و موبلی
با راهنمای سبک پایتون و بهترین شیوههای Mobly آشنا شوید و توصیههای خاص SDV زیر را در نظر بگیرید:
از استفاده مستقیم از ایمپورتهای Mobly به جز برای assertionها خودداری کنید. چارچوب تست SDV بر اساس آن و با تمرکز بر SDV ساخته شده است.
ادعاها: مستقیماً از ادعاهای Mobly استفاده کنید.
آزمایشهای SDV
بخشهای زیر دستورالعملهای خاص و بهترین شیوهها را برای توسعه تستها در چارچوب تست SDV تشریح میکنند.
راهاندازی و پاکسازی
کد راهاندازی و پاکسازی باید خارج از موارد آزمایشی باشد. متدهای Teardown حتی اگر آزمایش با شکست مواجه شود، فراخوانی میشوند تا پاکسازی مناسب دستگاه انجام شود.
محل تنظیم و باز کردن کد به نیازهای خاص آزمایش بستگی دارد، حتی اگر آزمایش قطع شود:
- برای اینکه فقط یک بار در ابتدا و انتهای کل تست اجرا شود،
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 یا پارامترسازی برای به حداقل رساندن میزان کد تکراری استفاده کنید.
پیروی از این رویکرد، خواندن و اشکالزدایی تستها را آسانتر میکند، زیرا به وضوح نشان میدهد که کدام مراحل و شرایط با شکست مواجه شدهاند.
مثال
test_verify_process():
device.start_process()
# precondition 1
device.send_signal1()
# verification signal1 received
...
# precondition 2
device.send_signal2()
# verification signal2 received
...
# precondition 3
device.start_agent()
# verification behavior
...
device.kill_process()
test_setup_test():
super().setup_test()
device.start_process()
test_signal1():
# precondition
device.send_signal1()
# verification signal1 received
...
test_signal2():
# precondition
device.send_signal2()
# verification signal2 received
...
test_agent():
# precondition
device.start_agent()
# verification behavior
...
teardown_test():
device.kill_process()
super().teardown_test()
رفتار آزمون قطعی
از اضافه کردن شرطهایی که باعث شاخه شاخه شدن رفتار تست میشوند، خودداری کنید. اگر یک تأیید نیاز به تقسیم شدن دارد، به جای آن از دو مورد تست مختلف استفاده کنید.
از استثنائات استفاده نکنید
تستها و کمککنندههای رایج باید به جای استثناها از ادعاها (assertions) استفاده کنند. این کار اشکالزدایی را تسهیل میکند و از الگوهای تست پیروی میکند.
مثال
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() استفاده نکنید
از استفاده از sleep() خودداری کنید زیرا زمان اجرای تست را افزایش میدهد و باعث ایجاد ناپایداری میشود.
وقتی آزمایش نیاز به انتظار برای ادامه یک رویداد یا تأیید دارد، به جای آن از روشهای انتظار ارائه شده در چارچوب استفاده کنید.
از متدهای انتظار با دقت استفاده کنید زیرا اجرای تست تا زمانی که شرط مطابقت پیدا کند یا زمان انقضا فرا برسد، مسدود میماند.
وقتی لازم است منتظر بمانید تا یک شرط در یک تست کامل شود، سوالات زیر را بپرسید:
یک تایم اوت معقول چیست؟
اگر انتظار میرود رویدادی در یک بازه زمانی خاص رخ دهد، زمان انتظار باید با آن انتظار مطابقت داشته باشد تا از شکست سریع تست اطمینان حاصل شود. در صورت لزوم، زمان انتظار را کاهش دهید (پیشفرض 30 ثانیه است).
هزینه عمل جراحی که با روش انتظار انجام میشود چقدر است؟
از فراخوانی مکرر عملیات پرهزینه خودداری کنید. در صورت لزوم، فاصله زمانی نظرسنجی را افزایش دهید (پیشفرض 0.5 ثانیه است).
موارد آزمون با الزامات
اگر یک تست، موارد آزمایشی با الزامات صریح برای اجرا داشته باشد (مثلاً، هدفی که باید در آن اجرا شود)، در صورت عدم مطابقت با الزامات، میتوانید از آنها صرف نظر کنید:
def test_with_requirement():
self.get_test_validator().skip_if(expr, reason)
# Test case