Kiểm thử hệ thống là bất kỳ kiểm thử SDV nào được tạo bằng Khung kiểm thử SDV.
Tạo bài kiểm thử
Vị trí kiểm thử
<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
Kiểm tra tệp
README.md: Mọi bài kiểm thử đều phải có nội dung mô tả mục đích của bài kiểm thử và cách chạy bài kiểm thử.Tệp kiểm thử: Tất cả các quy trình kiểm thử đều tuân theo một cấu trúc tương tự:
"""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()
- Tệp bản dựng:
Android.bp. Cấu trúc tệp như sau:
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>",
}
Quy ước đặt tên
Để xác định và tìm các loại kiểm thử, bạn phải tạo kiểm thử theo một quy ước đặt tên cụ thể.
Kiểm thử mẫu
Tên tệp:
sdv_sample_<NAME>_test.pyTên lớp:
SdvSampleNameTest
Thử nghiệm E2E
Tên tệp:
sdv_e2e_<NAME>_test.pyTên lớp:
SdvE2ENameTest
Thử nghiệm kéo dài
Tên tệp:
sdv_long_running_<NAME>_test.pyTên lớp:
SdvLongRunningNameTest
Kiểm thử hiệu suất
Tên tệp:
sdv_performance_<NAME>_test.pyTên lớp:
SdvPerformanceNameTest
Kiểm thử phần cứng
Tên tệp:
sdv_hw_<NAME>_test.pyTên lớp:
SdvHWNameTest
Nguyên tắc về mã
Phần này cung cấp các nguyên tắc và phương pháp hay nhất để viết Kiểm thử hệ thống SDV.
Python và Mobly
Làm quen với hướng dẫn về kiểu Python và các phương pháp hay nhất của Mobly, đồng thời cân nhắc các đề xuất sau đây dành riêng cho SDV:
Tránh sử dụng trực tiếp các lệnh nhập Mobly, ngoại trừ các câu lệnh khẳng định. Khung kiểm thử SDV được xây dựng dựa trên khung này và tập trung vào SDV.
Xác nhận: Sử dụng trực tiếp các xác nhận của Mobly.
Kiểm thử SDV
Các phần sau đây trình bày các nguyên tắc cụ thể và phương pháp hay nhất để phát triển các bài kiểm thử trong Khung kiểm thử SDV.
Thiết lập và dọn dẹp
Mã thiết lập và mã dọn dẹp phải nằm bên ngoài các trường hợp kiểm thử. Các phương thức teardown được gọi ngay cả khi kiểm thử không thành công, để dọn dẹp thiết bị đúng cách.
Vị trí của mã thiết lập và mã huỷ bỏ phụ thuộc vào nhu cầu cụ thể của kiểm thử, ngay cả khi kiểm thử bị gián đoạn:
- Để chạy chỉ một lần ở đầu và cuối toàn bộ quá trình kiểm thử, hãy sử dụng
setup_classvàteardown_class. Ví dụ: lấy thiết bị, đặt các giá trị biến hoặc trạng thái không thay đổi giữa các trường hợp kiểm thử, định cấu hình các thuộc tính chung của thiết bị hoặc đặt cờ.
def setup_class(self):
super().setup_class()
# setup code
def teardown_class(self):
# teardown code
super().teardown_class()
- Để chạy giữa các trường hợp kiểm thử, trước và sau mỗi trường hợp. Ví dụ: phiên tương tác hoặc quá trình thực thi dịch vụ thông thường.
def setup_test(self):
super().setup_test()
# setup code
def teardown_test(self):
# teardown code
super().teardown_test()
Trường hợp kiểm thử được tham số hoá
Sử dụng các trường hợp kiểm thử được tham số hoá khi các bước là phổ biến trên nhiều trường hợp kiểm thử để tránh lặp lại mã.
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
Ví dụ này tạo ra 2 trường hợp kiểm thử test_name_ab và test_name_cd.
Một trường hợp kiểm thử để xác minh hành vi
Các trường hợp kiểm thử phải nhỏ gọn và tập trung vào một hành vi cụ thể. Nếu nhiều hành vi có chung các điều kiện tiên quyết hoặc bước, hãy cân nhắc việc chia chúng. Bạn có thể sử dụng setup_test hoặc tham số hoá để giảm thiểu lượng mã lặp lại.
Phương pháp này giúp bạn dễ dàng đọc và gỡ lỗi các kiểm thử vì phương pháp này cho biết rõ những bước và điều kiện nào không thành công.
Ví dụ
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()
Hành vi kiểm thử có tính xác định
Tránh thêm các điều kiện vào thử nghiệm để phân nhánh hành vi của thử nghiệm. Nếu cần chia một quy trình xác minh, hãy sử dụng hai trường hợp kiểm thử riêng biệt.
Không sử dụng các trường hợp ngoại lệ
Các kiểm thử và trình trợ giúp chung phải sử dụng các câu khẳng định thay vì các ngoại lệ. Điều này giúp gỡ lỗi và tuân theo các mẫu kiểm thử.
Ví dụ
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)
Ví dụ
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"
)
Không sử dụng chế độ ngủ
Tránh sử dụng sleep vì thao tác này làm tăng phiên chạy thử nghiệm và gây ra sự không ổn định.
Khi quy trình kiểm thử yêu cầu chờ một sự kiện hoặc quy trình xác minh để tiếp tục, hãy sử dụng Phương thức chờ được cung cấp trong khung.
Hãy sử dụng các phương thức chờ một cách cẩn thận vì phiên chạy thử nghiệm vẫn bị chặn cho đến khi điều kiện trùng khớp hoặc đạt đến thời gian chờ.
Khi bạn cần đợi một điều kiện hoàn tất trong một bài kiểm thử, hãy đặt những câu hỏi sau:
Thời gian chờ hợp lý là bao lâu?
Nếu một sự kiện dự kiến diễn ra trong một khung thời gian cụ thể, thì thời gian chờ phải khớp với kỳ vọng đó để đảm bảo kiểm thử nhanh chóng không thành công. Giảm thời gian chờ nếu cần (mặc định là 30 giây).
Thao tác do phương thức chờ thực hiện tốn bao nhiêu chi phí?
Tránh gọi các thao tác tốn kém thường xuyên. Tăng khoảng thời gian thăm dò nếu cần (mặc định là 0,5 giây).
Trường hợp kiểm thử có yêu cầu
Nếu một kiểm thử có các trường hợp kiểm thử có yêu cầu rõ ràng để hoạt động (ví dụ: đích đến mà kiểm thử đó sẽ chạy), bạn có thể bỏ qua các trường hợp đó nếu chúng không đáp ứng các yêu cầu:
def test_with_requirement():
self.get_test_validator().skip_if(expr, reason)
# Test case