系统测试是指使用 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()
避免使用 sleep(),因为这会增加测试作业时间并导致测试不稳定。
如果测试需要等待事件或验证才能继续,请改用框架中提供的等待方法。
请谨慎使用等待方法,因为在条件匹配或达到超时时间之前,测试作业会一直处于阻塞状态。
在测试中需要等待某个条件完成时,请考虑以下问题:
什么是合理的超时时间?
如果预期在特定时间范围内发生某个事件,则超时时间应与该预期相符,以确保测试快速失败。根据需要缩短超时时间(默认值为 30 秒)。
等待方法执行的操作的开销有多大?
避免频繁调用开销大的操作。如有必要,请增加轮询间隔(默认值为 0.5 秒)。
包含要求的测试用例
如果测试的测试用例明确要求在特定条件下运行(例如,应在哪个目标平台上运行),那么如果测试用例不符合这些要求,您可以跳过它们:
def test_with_requirement():
self.get_test_validator().skip_if(expr, reason)
# Test case