테스트 매핑

테스트 매핑을 간단하게 소개하고 Android 오픈소스 프로젝트(AOSP)에서 테스트를 쉽게 구성하는 방법을 설명합니다.

테스트 매핑 소개

테스트 매핑은 Gerrit 기반 접근 방식으로, 개발자는 Android 소스 트리에서 사전 제출 및 사후 제출 테스트 규칙을 직접 만들고 테스트할 브랜치와 기기의 결정을 테스트 인프라에 맡길 수 있습니다. 테스트 매핑의 정의는 모든 소스 디렉터리에 배치할 수 있는 TEST_MAPPING이라는 이름의 JSON 파일입니다.

Atest는 TEST_MAPPING 파일을 사용하여 관련 디렉터리에서 사전 제출 테스트를 실행할 수 있습니다. 테스트 매핑을 사용하면 Android 소스 트리 내에서 간단히 변경하여 사전 제출 검사에 동일한 테스트 세트를 추가할 수 있습니다.

다음 예를 참고하세요.

services.core의 TEST_MAPPING에 사전 제출 테스트 추가

가져오기를 통해 도구/덱스터용 TEST_MAPPING에 사전 제출 테스트 추가

테스트 매핑은 테스트 실행 및 결과 보고를 위해 Trade Federation(TF) 테스트 하네스를 사용합니다.

테스트 그룹 정의

테스트 매핑은 테스트 그룹을 통해 테스트를 그룹화합니다. 테스트 그룹의 이름은 임의의 문자열일 수 있습니다. 예를 들어 presubmit은 변경사항을 확인할 때 실행할 테스트 그룹에 사용될 수 있습니다. postsubmit 테스트는 변경사항을 병합한 후 빌드를 확인하는 데 사용할 수 있습니다.

빌드 스크립트 규칙 패키징

Trade Federation 테스트 하네스에서 특정 빌드에 테스트 매핑의 테스트 모듈을 실행하려면 이러한 모듈에는 Soongtest_suite 세트와 Make의 LOCAL_COMPATIBILITY_SUITE 세트가 다음 두 모음 중 하나에 있어야 합니다.

  • general-tests: 기기별 기능에 종속되지 않는 테스트(예: 대부분의 기기에 없는 공급업체별 하드웨어)입니다. 대부분의 테스트는 하나의 ABI나 비트율 또는 HWASan과 같은 하드웨어 기능(ABI마다 별도의 test_suites 타겟이 있음)과 관련된 경우 및 기기에서 실행해야 하는 경우에도 general-tests 모음에 있어야 합니다.
  • device-tests: 기기별 기능에 종속되는 테스트입니다. 일반적으로 이러한 테스트는 vendor/ 아래에 있습니다. '기기별'은 다른 기기에 있거나 없을 수 있는 ABI 또는 SoC 기능을 의미하는 것이 아니고 기기에 고유한 기능만 의미하므로, GTest 네이티브 테스트(ABI 전용이더라도 일반적으로 general-tests임)만큼 JUnit 테스트에 적용됩니다.

예:

Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests

테스트 모음에서 실행되도록 테스트 구성

테스트 모음 내에서 테스트가 실행되려면 테스트는 다음을 충족해야 합니다.

  • 빌드 제공업체가 없어야 합니다.
  • 작업이 완료된 후에는 정리해야 합니다(예: 테스트 중에 생성된 임시 파일 삭제).
  • 시스템 설정을 기본값 또는 원래 값으로 변경합니다.
  • 기기가 특정 상태에 있는 것으로 가정해서는 안 됩니다(예: 루트 준비). 대부분의 테스트는 실행하는 데 루트 권한이 필요하지 않습니다. 테스트에 루트가 있어야 하는 경우 다음 예와 같이 AndroidTest.xmlRootTargetPreparer를 사용하여 지정해야 합니다.
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>

테스트 매핑 파일 만들기

테스트 범위가 필요한 디렉터리의 경우 아래와 같이 TEST_MAPPING JSON 파일을 추가하면 됩니다. 이러한 규칙은 디렉터리 또는 하위 디렉터리에서 파일이 터치될 때 사전 제출 검사에서 테스트가 실행되도록 합니다.

예제 따르기

다음은 샘플 TEST_MAPPING 파일(JSON 형식이지만 주석이 지원됨)입니다.

{
  "presubmit": [
    // JUnit test with options and file patterns.
    {
      "name": "CtsWindowManagerDeviceTestCases",
      "options": [
        {
          "include-annotation": "android.platform.test.annotations.RequiresDevice"
        }
      ],
      "file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
    },
    // Device-side GTest with options.
    {
      "name" : "hello_world_test",
      "options": [
        {
          "native-test-flag": "\"servicename1 servicename2\""
        },
        {
          "native-test-timeout": "6000"
        }
      ]
    }
    // Host-side GTest.
    {
      "name" : "net_test_avrcp",
      "host" : true
    }
  ],
  "postsubmit": [
    {
      "name": "CtsWindowManagerDeviceTestCases"
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

속성 설정

위의 예에서 presubmitpostsubmit은 각 테스트 그룹의 이름입니다. 테스트 그룹에 관한 자세한 내용은 테스트 그룹 정의를 참고하세요.

테스트 모듈이름 또는 Trade Federation 통합 테스트 이름(테스트 XML 파일 리소스 경로, 예: uiautomator/uiautomator-demo)은 name 속성의 값으로 설정할 수 있습니다. name 필드는 name 클래스 또는 name 테스트 메서드를 사용할 수 없습니다. 실행할 테스트의 범위를 좁히려면 여기 include-filter와 같은 옵션을 사용할 수 있습니다. include-filter 샘플 사용법을 참고하세요.

host 설정은 테스트가 기기 없이 호스트에서 실행되는 테스트인지를 나타냅니다. 기본값은 false이며 테스트를 실행하려면 기기가 필요합니다. 지원되는 테스트 유형은 GTest 바이너리의 경우 HostGTest이고, JUnit 테스트의 경우 HostTest입니다.

file_patterns 속성을 사용하면 TEST_MAPPING 파일이 포함된 디렉터리를 기준으로 소스 코드 파일의 상대 경로와 일치하는 정규식 문자열 목록을 설정할 수 있습니다. 위의 예에서 테스트 CtsWindowManagerDeviceTestCases는 TEST_MAPPING 파일 또는 하위 디렉터리와 동일한 디렉터리에 있는 Window 또는 Activity로 시작하는 자바 파일이 변경될 때만 사전 제출로 실행됩니다. 백슬래시(\)는 JSON 파일에 있으므로 이스케이프 처리되어야 합니다.

imports 속성을 사용하면 콘텐츠를 복사하지 않고 다른 TEST_MAPPING 파일에 테스트를 포함할 수 있습니다. 가져온 경로의 상위 디렉터리에 있는 TEST_MAPPING 파일도 포함됩니다. 테스트 매핑은 중첩 가져오기를 허용합니다. 즉, 두 TEST_MAPPING 파일이 서로를 가져올 수 있기 때문에 포함된 테스트를 테스트 매핑을 통해 적절하게 병합할 수 있습니다.

options 속성에는 추가 TradeFed 명령줄 옵션이 있습니다.

테스트에 사용할 수 있는 옵션의 전체 목록을 보려면 다음을 실행합니다.

tradefed.sh run commandAndExit [test_module] --help

옵션의 작동 방식에 관한 자세한 내용은 TradeFed 옵션 처리를 참고하세요.

Atest로 테스트 실행

사전 제출 테스트 규칙을 로컬에서 실행하려면 다음 단계를 따르세요.

  1. TEST_MAPPING 파일이 있는 디렉터리로 이동합니다.
  2. 다음 명령어를 실행합니다.
atest

현재 디렉터리와 상위 디렉터리의 TEST_MAPPING 파일에 구성된 모든 사전 제출 테스트가 실행됩니다. Atest는 사전 제출에 관한 두 개의 테스트(A 및 B)를 찾아 실행합니다.

현재 작업 디렉터리(CWD) 및 상위 디렉터리의 TEST_MAPPING 파일에서 사전 제출 테스트를 실행하는 가장 간단한 방법입니다. Atest는 CWD 및 모든 상위 디렉터리에서 TEST_MAPPING 파일을 찾아 사용합니다.

소스 코드 구성

다음 예는 소스 트리 전체에 TEST_MAPPING 파일을 구성하는 방법을 보여줍니다.

src
├── project_1
│   └── TEST_MAPPING
├── project_2
│   └── TEST_MAPPING
└── TEST_MAPPING

src/TEST_MAPPING의 콘텐츠

{
  "presubmit": [
    {
      "name": "A"
    }
  ]
}

src/project_1/TEST_MAPPING의 콘텐츠

{
  "presubmit": [
    {
      "name": "B"
    }
  ],
  "postsubmit": [
    {
      "name": "C"
    }
  ],
  "other_group": [
    {
      "name": "X"
    }
  ]}

src/project_2/TEST_MAPPING의 콘텐츠

{
  "presubmit": [
    {
      "name": "D"
    }
  ],
  "import": [
    {
      "path": "src/project_1"
    }
  ]}

타겟 디렉터리 지정

타겟 디렉터리를 지정하여 디렉터리의 TEST_MAPPING 파일에서 테스트를 실행할 수 있습니다. 다음 명령어는 두 개의 테스트(A, B)를 실행합니다.

atest --test-mapping src/project_1

사후 제출 테스트 규칙 실행

또한 이 명령어를 사용하여 src_path(기본값은 CWD)와 상위 디렉터리의 TEST_MAPPING에 정의된 사후 제출 테스트 규칙을 실행할 수 있습니다.

atest [--test-mapping] [src_path]:postsubmit

기기가 필요 없는 테스트만 실행

Atest에 --host 옵션을 사용하면 호스트에 구성된 테스트 중 기기가 필요 없는 테스트만 실행할 수 있습니다. 이 옵션이 없으면 Atest는 기기가 필요한 테스트와 호스트에서 실행되고 기기가 필요 없는 테스트를 모두 실행합니다. 테스트는 두 개의 개별 모음에서 실행됩니다.

atest [--test-mapping] --host

테스트 그룹 식별

Atest 명령어에서 테스트 그룹을 지정할 수 있습니다. 다음 명령어는 src/project_1 디렉터리의 파일과 관련된 모든 사후 제출 테스트를 실행합니다. 해당 파일에는 하나의 테스트(C)만 포함되어 있습니다.

또는 :all을 사용하여 그룹과 관계없이 모든 테스트를 실행할 수 있습니다. 다음 명령어는 A, B, C, X 등 4개의 테스트를 실행합니다.

atest --test-mapping src/project_1:all

하위 디렉터리 포함

기본적으로 TEST_MAPPING에서 Atest로 테스트를 실행하면 CWD(또는 지정된 디렉터리) 및 상위 디렉터리에 있는 TEST_MAPPING에 구성된 사전 제출 테스트만 실행됩니다. 하위 디렉터리의 모든 TEST_MAPPING 파일에서 테스트를 실행하려면 --include-subdir 옵션을 사용하여 강제로 Atest가 이러한 테스트도 포함하도록 합니다.

atest --include-subdir

--include-subdir 옵션이 없으면 Atest는 A 테스트만 실행합니다. --include-subdir 옵션이 있으면 Atest는 테스트 두 개(A, B)를 실행합니다.

행 수준 주석 지원

행 수준 //-format 주석을 추가하여 TEST_MAPPING 파일을 만들고 잇따른 설정에 관한 설명을 추가할 수 있습니다. ATest 및 Trade Federation은 TEST_MAPPING을 주석 없이 유효한 JSON 형식으로 사전 처리합니다. JSON 파일을 깨끗하고 읽기 쉽게 유지하기 위해 행 수준의 //-format 주석만 지원됩니다.

예:

{
  // For presubmit test group.
  "presubmit": [
    {
      // Run test on module A.
      "name": "A"
    }
  ]
}