多裝置測試

VTS 支援需要多部 Android 裝置互動的測試。

建築

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

圖 1. 通過 VTS 的裝置序號。

測試計畫設定中會指定裝置需求,例如裝置數量和裝置類型。舉例來說,您可以指定測試計畫,要求使用兩個以 Sailfish 建構目標為基礎的 Android 裝置。

裝置分配

測試基礎架構 (通常是測試排程器) 會將符合測試計畫設定中指定需求的可用裝置,分配給 VTS 架構。即使測試模組未使用已分配的裝置,這些裝置仍會保留給測試計畫。接著,VTS 代理程式二進位檔會推送至所有已分配的裝置並在這些裝置上執行 (除非特別指示不要執行)。這可確保測試指令碼中所有裝置的 Shell 指令和 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 存放區中的「下十億使用者」測試是主機端、應用程式型多裝置測試。

類型 3:目標端 HIDL 測試

在目標端,多裝置 HIDL 測試會將所有測試邏輯放在裝置端測試二進位檔,因此測試必須在執行期間同步處理裝置:

圖 4. 以目標為準的 HIDL 測試。

在此情境中:

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

範例:多裝置測試計畫

這個範例會指定兩部裝置的設定:

  • 裝置 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')