การทดสอบระบบหมายถึงการทดสอบ 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 Test Framework สร้างขึ้นบนพื้นฐานนี้โดยมุ่งเน้นที่ 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
ตัวอย่างนี้สร้างกรณีทดสอบ 2 รายการ test_name_ab และ test_name_cd
กรณีทดสอบ 1 รายการสำหรับการยืนยันลักษณะการทำงาน
กรณีทดสอบควรมีขนาดกะทัดรัดและมุ่งเน้นที่ลักษณะการทำงานที่เฉพาะเจาะจง หากลักษณะการทำงานหลายอย่างมีข้อกำหนดเบื้องต้นหรือขั้นตอนที่เหมือนกัน ให้พิจารณาแยกข้อกำหนดเบื้องต้นหรือขั้นตอนเหล่านั้น คุณสามารถ
ใช้ 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()
ลักษณะการทำงานของการทดสอบที่แน่นอน
หลีกเลี่ยงการเพิ่มเงื่อนไขในการทดสอบที่แยกพฤติกรรม หากต้องแยกการยืนยัน ให้ใช้กรณีทดสอบ 2 กรณีที่แตกต่างกันแทน
อย่าใช้ข้อยกเว้น
การทดสอบและตัวช่วยทั่วไปต้องใช้การยืนยันแทนข้อยกเว้น ซึ่งจะช่วยให้การแก้ไขข้อบกพร่องง่ายขึ้นและเป็นไปตามรูปแบบการทดสอบ
ตัวอย่าง
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