多設備測試

VTS 支持需要在多個 Android 設備之間進行交互的測試。

建築學

VTS 使用 TradeFed 框架來獲取設備序列並將其傳遞給測試模塊。

圖 1. VTS 傳遞設備序列號。

設備要求,例如設備數量和設備類型,在測試計劃配置中指定。例如,您可以指定需要兩個具有 Sailfish 構建目標的 Android 設備的測試計劃。

設備分配

測試基礎設施(通常是測試調度程序)將滿足測試計劃配置中指定要求的可用設備分配給 VTS 框架。即使測試模塊沒有使用分配的設備,也會為測試計劃保留分配的設備。然後將 VTS 代理二進製文件推送到所有分配的設備並在其上運行(除非特別指示不要運行)。這可確保 shell 命令和 HAL RPC 的 TCP 連接可用於測試腳本中的所有設備。

測試準備者

該框架為收到序列號的所有設備運行測試準備程序。目標準備者可以是單設備或多設備:

  • 單設備目標準備器( VtsDeviceInfoCollector中的示例):
    • 只能在具有所需設備列表的測試計劃配置中指定(未來版本將允許模塊級配置)。
    • 僅接收一個設備序列號。
    • 針對特定設備運行準備和清理任務。
  • 多設備目標準備器( VtsPythonVirtualenvPreparer中的示例):
    • 可以在測試計劃配置或測試模塊配置中指定
    • 接收所有設備序列號
    • 為每個設備或所有設備運行準備和清理任務。

測試模塊

在測試準備者完成主機/設備設置後,測試模塊會獲取設備列表。每個多設備測試模塊運行一個主機端 Python 測試模塊。分配的 Android 設備可以從 Python 測試模塊作為AndroidDevice對象列表訪問:

devices = self.android_devices
device1 = devices[0]
device1_serial = device1.serial

所有分配的設備都保留給測試計劃,即使計劃中的測試模塊只使用一個設備。

測試期間的設備通信

有效的多 Android 測試涉及分配的設備之間的通信。在開發此類測試時,您必須確定如何在分配的設備之間建立通信。以下部分提供了三個通信示例(但是,測試開發人員可以自由設計其他模型)。

類型 1:主機端 HAL 測試

主機端 HAL 測試可以使用默認推送到設備的 VTS HAL 驅動程序:

圖 2.主機端 HAL 測試。

在這種情況下:

  • 測試邏輯在主機上執行。
  • 主機端測試腳本向每個設備上的驅動程序發出 RPC 調用。
  • 主機端協調設備交互。

類型 2:基於主機端代理的測試

除了在設備上使用 VTS 代理,主機端測試還可以將自己的代理(應用程序或二進製文件)推送到每個設備:

圖 3.主機端、基於代理的測試。

在這種情況下:

  • 測試邏輯在主機上執行。
  • 代理應用程序(或二進制)安裝在每台設備上。
  • 主機端測試腳本向每台設備上的應用程序發出命令。
  • 主機端協調設備交互。

例如,當前 VTS 存儲庫中的Next Billion User 測試是主機端、基於應用程序的多設備測試。

類型 3:目標端 HIDL 測試

目標端、多設備 HIDL 測試將所有測試邏輯放在設備端測試二進製文件中,這要求測試在測試執行期間同步設備:

圖 4.基於目標的 HIDL 測試。

在這種情況下:

  • 測試邏輯在設備上執行。
  • 主機端框架提供初始設備識別。
  • 目標端測試二進製文件需要同步:
    • 所有設備的相同測試二進製文件。
    • 每個角色的不同測試二進製文件。

示例:多設備測試計劃

此示例指定兩個設備的配置:

  • 設備 1 包括構建提供程序和VtsDeviceInfoCollector目標準備程序。
  • 設備 2 包括一個附加的FilePusher準備程序,它將一組主機驅動的相關文件推送到設備。
<configuration description="VTS Codelab Plan">
  ...
<device name="device1">
<build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
<target_preparer class="com.android.tradefed.targetprep.VtsDeviceInfoCollector" />
</device>
<device name="device2" >
<build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
<target_preparer class="com.android.tradefed.targetprep.VtsDeviceInfoCollector" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
<option name="push-group" value="HostDrivenTest.push" />
</target_preparer>
</device>
<option name="compatibility:include-filter" value="VtsCodelabHelloWorldMultiDeviceTest" />
</configuration>

示例:主機端 Python 測試腳本

有關測試準備者的詳細信息和示例,請參閱測試準備者。有關完整的主機端多設備示例,請參閱hello_world_multi 代碼實驗室

def setUpClass(self):
logging.info('number of device: %s', self.android_devices)
asserts.assertEqual(len(self.android_devices), 2, 'number of device is wrong.')
self.dut1 = self.android_devices[0]
self.dut2 = self.android_devices[1]
self.shell1 = self.dut1.shell
self.shell2 = self.dut2.shell

def testSerialNotEqual(self):
'''Checks serial number from two device not being equal.'''
command = 'getprop | grep ro.serial'
res1 = self.shell1.Execute(command)
res2 = self.shell2.Execute(command)

def getSerialFromShellOutput(output):
'''Get serial from getprop query'''
return output[const.STDOUT][0].strip().split(' ')[-1][1:-1]
serial1 = getSerialFromShellOutput(res1)
serial2 = getSerialFromShellOutput(res2)

logging.info('Serial number of device 1 shell output: %s', serial1)
logging.info('Serial number of device 2 shell output: %s', serial2)
asserts.assertNotEqual(serial1, serial2, 'serials from two devices should not be the same')
asserts.assertEqual(serial1, self.dut1.serial, 'serial got from device system property is different from allocated serial')
asserts.assertEqual(serial2, self.dut2.serial, 'serial got from device system property is different from allocated serial')