다중 기기 테스트

VTS는 다중 Android 기기 간의 상호 작용이 필요한 테스트를 지원합니다.

아키텍처

VTS는 TradeFed 프레임워크를 사용하여 기기 일련 번호를 가져와 테스트 모듈에 전달합니다.

그림 1. 기기 일련 번호를 전달하는 VTS

기기 수, 기기 유형과 같은 기기 필수사항은 테스트 계획 구성 시 지정됩니다. 예를 들어 Sailfish 빌드 타겟과 함께 두 대의 Android 기기를 요구하는 테스트 계획을 지정할 수 있습니다.

기기 할당

테스트 인프라(일반적으로 테스트 스케줄러)는 사용 가능한 기기 중 테스트 계획 구성에 지정된 필수사항을 충족하는 기기를 VTS 프레임워크에 할당합니다. 할당된 기기는 테스트 모듈에 사용되지 않더라도 테스트 계획에 사용되도록 예약됩니다. 그런 다음 VTS 에이전트 바이너리가 할당된 모든 기기에 푸시되어 실행됩니다. 단, 실행되지 않도록 별도로 지정된 경우에는 예외입니다. 이를 통해 테스트 스크립트의 모든 기기에 셸 명령어와 HAL RPC의 TCP 연결이 가능합니다.

테스트 준비자

프레임워크는 일련번호를 받은 모든 기기를 대상으로 테스트 준비자를 실행합니다. 타겟 준비자는 단일 기기이거나 다중 기기일 수 있습니다.

  • 단일 기기 타겟 준비자( VtsDeviceInfoCollector에 있는 예):
    • 필수 기기 목록이 있는 테스트 계획 구성에서만 지정할 수 있습니다(향후 버전에서는 모듈 수준 구성이 허용됨).
    • 기기 일련번호를 하나만 수신합니다.
    • 특정 기기를 대상으로 준비 작업과 정리 작업을 실행합니다.
  • 다중 기기 타겟 준비자(VtsPythonVirtualenvPreparer에 있는 예):
    • 테스트 계획 구성 또는 테스트 모듈 구성에서 지정할 수 있습니다.
    • 모든 기기 일련번호를 수신합니다.
    • 각 기기 또는 모든 기기를 대상으로 준비 작업과 정리 작업을 실행합니다.

테스트 모듈

테스트 준비자가 호스트/기기 설정을 마치면 테스트 모듈이 기기 목록을 가져옵니다. 각 다중 기기 테스트 모듈을 대상으로 하나의 호스트 측 Python 테스트 모듈이 실행됩니다. 할당된 Android 기기에는 AndroidDevice 객체 목록인 Python 테스트 모듈에서 액세스할 수 있습니다.

    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 codelab을 참조하세요.

    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')