多裝置測試

VTS 支援需要在多部 Android 裝置之間進行互動的測試。

建築

VTS 會使用 TradeFed 架構取得並傳遞裝置序號,以便測試模組。

圖 1. VTS 傳遞裝置序號。

裝置需求 (例如裝置數量和裝置類型) 會在測試計畫設定中指定。舉例來說,您可以指定測試計畫,要求使用兩部搭載 Sailfish 建構目標的 Android 裝置。

裝置分配

測試基礎架構 (通常是測試排程器) 會將符合測試計畫設定中指定需求的可用裝置,分配給 VTS 架構。即使測試模組未使用,系統也會為測試計畫保留已分配的裝置。接著,VTS 代理程式二進位檔會推送至所有已指派的裝置並執行 (除非明確指示不執行)。這可確保測試指令碼中的所有裝置都能使用殼層指令和 HAL RPC 的 TCP 連線。

測試準備人員

此架構會針對收到序號的所有裝置執行測試準備工具。目標準備工具可支援單一或多部裝置:

  • 單一裝置目標準備器 (範例位於 VtsDeviceInfoCollector):
    • 只能在測試計畫設定中指定,並提供必要的裝置清單 (日後版本將允許模組層級設定)。
    • 只接收一組裝置序號。
    • 針對特定裝置執行準備和清理工作。
  • 多裝置目標準備工具 (範例請見 VtsPythonVirtualenvPreparer):
    • 可在測試計畫設定或測試模組設定中指定
    • 接收所有裝置序號
    • 為每部或所有裝置執行準備和清理工作。

測試模組

測試準備人員完成主機/裝置設定後,測試模組會取得裝置清單。每個多裝置測試模組都會執行一個主機端 Python 測試模組。您可以透過 Python 測試模組存取已分配的 Android 裝置,做為 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 測試。

在這種情況下:

  • 測試邏輯會在裝置上執行。
  • 主機端架構會提供初始裝置 ID。
  • 目標端測試二進位檔需要同步處理:
    • 所有裝置都使用相同的測試二進位檔。
    • 為每個角色提供不同的測試二進位檔。

範例:多裝置測試計畫

以下範例會指定兩部裝置的設定:

  • 裝置 1 包含建構供應器和 VtsDeviceInfoCollector 目標準備工具。
  • Device 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')