Тестирование на нескольких устройствах

VTS поддерживает тесты, требующие взаимодействия между несколькими устройствами Android.

Архитектура

VTS использует фреймворк TradeFed, чтобы получать и передавать серийные номера устройств в тестовые модули.

Рисунок 1. Серийные номера устройств, прошедших проверку VTS.

Требования к устройствам, такие как количество устройств и типы устройств, указаны в конфигурации плана тестирования. Например, вы можете указать план тестирования, для которого требуются два устройства Android с целевыми сборками Sailfish.

Распределение устройств

Инфраструктура тестирования (обычно планировщик тестирования) выделяет доступные устройства, соответствующие требованиям, указанным в конфигурации плана тестирования, для платформы VTS. Выделенные устройства резервируются для плана тестирования, даже если тестовый модуль их не использует. Затем двоичные файлы агента VTS отправляются на все выделенные устройства и запускаются на них (если не указано иное). Это гарантирует, что TCP-подключения для команд оболочки и HAL RPC будут доступны для всех устройств в тестовом скрипте.

Организаторы тестирования

Фреймворк запускает подготовительные тесты для всех устройств, серийные номера которых были получены. Целевые подготовители могут быть одно- или многоустройственными:

  • Подготовители целевых данных для одного устройства (пример: VtsDeviceInfoCollector):
    • Можно указать только в конфигурации плана тестирования с обязательным списком устройств (в будущих версиях можно будет задавать конфигурацию на уровне модуля).
    • Получать только один серийный номер устройства.
    • Выполнять задачи по подготовке и очистке на определенном устройстве.
  • Подготовка целевых устройств (пример: VtsPythonVirtualenvPreparer).
    • Можно указать в конфигурации плана тестирования или модуля тестирования.
    • Получить серийные номера всех устройств
    • Выполнять задачи по подготовке и очистке для каждого устройства или для всех устройств.

Тестовые модули

Тестовые модули получают список устройств после того, как средства подготовки тестов завершат настройку хоста и устройств. Для каждого модуля тестирования нескольких устройств запускается один модуль тестирования Python на стороне хоста. Выделенные устройства Android доступны из тестовых модулей Python в виде списка объектов AndroidDevice:

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

Все выделенные устройства резервируются для плана тестирования, даже если модуль тестирования в плане использует только одно устройство.

Обмен данными между устройствами во время тестирования

Эффективные тесты с несколькими устройствами Android включают связь между выделенными устройствами. При разработке таких тестов необходимо определить, как установить связь между выделенными устройствами. В следующих разделах приведены три примера общения (разработчики тестов могут использовать и другие модели).

Тип 1. Тесты HAL на стороне хоста

В тестах HAL на стороне хоста можно использовать драйверы HAL VTS, которые по умолчанию передаются на устройства:

Рисунок 2. Тест HAL на стороне хоста.

В этом случае:

  • Логика тестирования выполняется на хосте.
  • Тестовый скрипт на стороне хоста отправляет драйверам на каждом устройстве вызовы RPC.
  • Хост координирует взаимодействие устройств.

Тип 2: тестирование на основе агента на стороне хоста

Вместо того чтобы использовать агентов VTS на устройстве, хост-тест может отправить собственного агента (приложение или исполняемый файл) на каждое устройство:

Рисунок 3. Тест на стороне хоста с использованием агента.

В этом случае:

  • Логика тестирования выполняется на хосте.
  • Приложение агента (или двоичный файл) устанавливается на каждом устройстве.
  • Скрипт тестирования на стороне хоста отправляет команды приложениям на каждом устройстве.
  • Хост координирует взаимодействие устройств.

Например, тесты для следующего миллиарда пользователей в текущем репозитории VTS выполняются на хосте, в приложении и на нескольких устройствах.

Тип 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')