系統測試是指使用 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
端對端測試
檔案名稱:
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