सिस्टम टेस्ट, 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 सिस्टम टेस्ट लिखने के लिए दिशा-निर्देश और सबसे सही तरीके दिए गए हैं.
Python और Mobly
Python की स्टाइल गाइड और Mobly के सबसे सही तरीकों के बारे में जानें. साथ ही, SDV के लिए यहां दिए गए सुझावों पर ध्यान दें:
दावों के अलावा, Mobly के इंपोर्ट का सीधे तौर पर इस्तेमाल न करें. SDV टेस्ट फ़्रेमवर्क, SDV पर फ़ोकस करके बनाया गया है.
दावे: Mobly के दावों का सीधे तौर पर इस्तेमाल करें.
SDV टेस्ट
यहां दिए गए सेक्शन में, SDV टेस्ट फ़्रेमवर्क में टेस्ट डेवलप करने के लिए खास दिशा-निर्देश और सबसे सही तरीके बताए गए हैं.
सेटअप और क्लीनअप
सेटअप और क्लीनअप का कोड, टेस्ट केस से बाहर होना चाहिए. डिवाइस को सही तरीके से साफ़ करने के लिए, टेस्ट फ़ेल होने पर भी टियरडाउन के तरीके इस्तेमाल किए जाते हैं.
सेटअप और टियरडाउन कोड की जगह, टेस्ट की ज़रूरतों पर निर्भर करती है. भले ही, टेस्ट बीच में रुक जाए:
- पूरे टेस्ट की शुरुआत और आखिर में सिर्फ़ एक बार चलाने के लिए,
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()
टेस्ट के व्यवहार की जानकारी
टेस्ट में ऐसी शर्तें न जोड़ें जिनसे उसके व्यवहार में बदलाव हो. अगर किसी पुष्टि को अलग-अलग करना है, तो इसके बजाय दो अलग-अलग टेस्ट केस का इस्तेमाल करें.
अपवादों का इस्तेमाल न करें
टेस्ट और सामान्य हेल्पर में, अपवादों के बजाय दावों का इस्तेमाल करना ज़रूरी है. इससे डीबग करना आसान हो जाता है और टेस्टिंग पैटर्न का पालन किया जाता है.
उदाहरण
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.get_test_validator().skip_if(expr, reason)
# Test case