Liên kết kiểm thử

Đây là phần giới thiệu ngắn về tính năng ánh xạ kiểm thử và giải thích cách bắt đầu định cấu hình các kiểm thử trong Dự án nguồn mở Android (AOSP).

Giới thiệu về tính năng kiểm thử ánh xạ

Ánh xạ kiểm thử là một phương pháp dựa trên Gerrit, cho phép nhà phát triển tạo các quy tắc kiểm thử trước khi gửi và sau khi gửi ngay trong cây nguồn Android, đồng thời để cơ sở hạ tầng kiểm thử đưa ra quyết định về các nhánh và thiết bị cần kiểm thử. Định nghĩa ánh xạ kiểm thử là các tệp JSON có tên TEST_MAPPING mà bạn có thể đặt trong bất kỳ thư mục nguồn nào.

Atest có thể sử dụng các tệp TEST_MAPPING để chạy các kiểm thử trước khi gửi trong các thư mục được liên kết. Với tính năng liên kết kiểm thử, bạn có thể thêm cùng một bộ kiểm thử vào các quy trình kiểm tra trước khi gửi với một thay đổi tối thiểu trong cây nguồn Android.

Hãy xem các ví dụ sau:

Hoạt động kiểm thử ánh xạ dựa vào Trade Federation (TF) test harness để thực thi các kiểm thử và báo cáo kết quả.

Xác định nhóm kiểm thử

Kiểm thử các nhóm ánh xạ bằng một nhóm kiểm thử. Tên của một nhóm kiểm thử có thể là bất kỳ chuỗi nào. Ví dụ: presubmit có thể là tên của một nhóm kiểm thử sẽ chạy khi xác thực các thay đổi. Và postsubmit có thể là các kiểm thử dùng để xác thực bản dựng sau khi các thay đổi được hợp nhất.

Quy tắc tập lệnh bản dựng gói

Để Trade Federation test harness chạy các mô-đun kiểm thử cho một bản dựng nhất định, các mô-đun này phải có test_suites được đặt cho Soong hoặc LOCAL_COMPATIBILITY_SUITE được đặt cho Make thành một trong hai bộ kiểm thử sau:

  • general-tests là dành cho các kiểm thử không phụ thuộc vào các chức năng dành riêng cho thiết bị (chẳng hạn như phần cứng dành riêng cho nhà cung cấp mà hầu hết các thiết bị không có). Hầu hết các kiểm thử đều phải nằm trong bộ general-tests, ngay cả khi chúng dành riêng cho một ABI hoặc độ rộng bit hoặc các tính năng phần cứng như HWASan (có một mục tiêu test_suites riêng cho mỗi ABI), và ngay cả khi chúng phải chạy trên một thiết bị.
  • device-tests là dành cho những kiểm thử phụ thuộc vào các chức năng dành riêng cho thiết bị. Thông thường, những kiểm thử này nằm trong vendor/. Dành riêng cho thiết bị chỉ đề cập đến những chức năng dành riêng cho một thiết bị, vì vậy, điều này cũng áp dụng cho các kiểm thử JUnit cũng như kiểm thử GTest (thường phải được đánh dấu là general-tests ngay cả khi chúng dành riêng cho ABI).

Ví dụ:

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

Định cấu hình các kiểm thử để chạy trong một bộ kiểm thử

Để một kiểm thử chạy trong một bộ kiểm thử, kiểm thử đó phải:

  • Không được có nhà cung cấp bản dựng nào.
  • Phải dọn dẹp sau khi hoàn tất, ví dụ: bằng cách xoá mọi tệp tạm thời được tạo trong quá trình kiểm thử.
  • Bạn phải thay đổi chế độ cài đặt hệ thống thành giá trị mặc định hoặc giá trị ban đầu.
  • Không nên giả định rằng thiết bị đang ở một trạng thái nhất định, chẳng hạn như đã sẵn sàng để truy cập vào hệ thống. Hầu hết các kiểm thử đều không yêu cầu đặc quyền root để chạy. Nếu một quy trình kiểm thử phải yêu cầu quyền truy cập vào root, thì quy trình đó phải chỉ định quyền truy cập đó bằng RootTargetPreparer trong AndroidTest.xml, như trong ví dụ sau:

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
    

Tạo tệp ánh xạ kiểm thử

Đối với thư mục yêu cầu mức độ bao phủ kiểm thử, hãy thêm một tệp JSON TEST_MAPPING tương tự như ví dụ. Những quy tắc này đảm bảo rằng các kiểm thử chạy trong quy trình kiểm tra trước khi gửi khi có bất kỳ tệp nào được sửa đổi trong thư mục đó hoặc bất kỳ thư mục con nào của thư mục đó.

Làm theo ví dụ

Dưới đây là tệp TEST_MAPPING mẫu (ở định dạng JSON nhưng có hỗ trợ nhận xét):

{
  "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": "CtsDeqpTestCases",
      "options": [
        {
          // Use regex in include-filter which is supported in AndroidJUnitTest
          "include-filter": "dEQP-EGL.functional.color_clears.*"
        }
      ]
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

Đặt thuộc tính

Trong ví dụ, presubmitpostsubmit là tên của từng nhóm thử nghiệm. Hãy xem phần Xác định nhóm kiểm thử để biết thêm thông tin về nhóm kiểm thử.

Bạn có thể đặt tên cho mô-đun kiểm thử hoặc tên kiểm thử tích hợp Trade Federation (đường dẫn tài nguyên đến tệp XML kiểm thử, ví dụ: uiautomator/uiautomator-demo) trong giá trị của thuộc tính name. Xin lưu ý rằng trường name không thể sử dụng lớp name hoặc phương thức kiểm thử name. Để thu hẹp phạm vi kiểm thử cần chạy, hãy sử dụng các tuỳ chọn như include-filter. Xem include-filter ví dụ về cách sử dụng.

Chế độ cài đặt host của một bài kiểm thử cho biết liệu bài kiểm thử đó có phải là bài kiểm thử không có thiết bị đang chạy trên máy chủ lưu trữ hay không. Giá trị mặc định là false, nghĩa là kiểm thử yêu cầu thiết bị chạy. Các loại kiểm thử được hỗ trợ là HostGTest cho các tệp nhị phân GTest và HostTest cho các kiểm thử JUnit.

Thuộc tính file_patterns cho phép bạn đặt một danh sách các chuỗi biểu thức chính quy để so khớp đường dẫn tương đối của mọi tệp mã nguồn (tương ứng với thư mục chứa tệp TEST_MAPPING). Trong ví dụ, thử nghiệm CtsWindowManagerDeviceTestCases chỉ chạy trong giai đoạn kiểm tra trước khi gửi khi một tệp Java bắt đầu bằng Window hoặc Activity, nằm trong cùng thư mục với tệp TEST_MAPPING hoặc bất kỳ thư mục con nào của tệp đó. Bạn cần thoát dấu gạch chéo ngược (\) vì chúng nằm trong tệp JSON.

Thuộc tính imports cho phép bạn thêm các kiểm thử vào các tệp TEST_MAPPING khác mà không cần sao chép nội dung. Các tệp TEST_MAPPING trong thư mục mẹ của đường dẫn đã nhập cũng được đưa vào. Hoạt động kiểm thử ánh xạ cho phép nhập lồng nhau; điều này có nghĩa là 2 tệp TEST_MAPPING có thể nhập lẫn nhau và hoạt động kiểm thử ánh xạ có thể hợp nhất các kiểm thử được đưa vào.

Thuộc tính options chứa các lựa chọn dòng lệnh bổ sung của Tradefed.

Để xem danh sách đầy đủ các lựa chọn có sẵn cho một kiểm thử nhất định, hãy chạy:

tradefed.sh run commandAndExit [test_module] --help

Tham khảo Xử lý lựa chọn trong Tradefed để biết thêm thông tin chi tiết về cách hoạt động của các lựa chọn.

Chạy kiểm thử bằng Atest

Cách thực thi các quy tắc kiểm thử trước khi gửi cục bộ:

  1. Chuyển đến thư mục chứa tệp TEST_MAPPING.
  2. Chạy lệnh:

    atest
    

Tất cả các kiểm thử trước khi gửi được định cấu hình trong các tệp TEST_MAPPING của thư mục hiện tại và các thư mục mẹ của thư mục đó đều được chạy. Atest xác định vị trí và chạy hai thử nghiệm để gửi trước (A và B).

Đây là cách đơn giản nhất để chạy các kiểm thử trước khi gửi trong các tệp TEST_MAPPING trong thư mục đang hoạt động (CWD) và các thư mục mẹ. Atest xác định vị trí và sử dụng tệp TEST_MAPPING trong CWD và tất cả các thư mục mẹ của tệp đó.

Cấu trúc mã nguồn

Ví dụ này cho thấy cách bạn có thể định cấu hình các tệp TEST_MAPPING trên cây nguồn:

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

Nội dung của src/TEST_MAPPING:

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

Nội dung của src/project_1/TEST_MAPPING:

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

Nội dung của src/project_2/TEST_MAPPING:

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

Chỉ định thư mục đích

Bạn có thể chỉ định một thư mục đích để chạy các kiểm thử trong tệp TEST_MAPPING trong thư mục đó. Lệnh sau đây chạy 2 kiểm thử (A, B):

atest --test-mapping src/project_1

Chạy các quy tắc kiểm thử sau khi gửi

Bạn cũng có thể dùng lệnh này để chạy các quy tắc kiểm thử sau khi gửi được xác định trong TEST_MAPPING trong src_path (mặc định là CWD) và các thư mục mẹ của nó:

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

Chỉ chạy những kiểm thử không yêu cầu thiết bị

Bạn có thể sử dụng lựa chọn --host cho Atest để chỉ chạy những kiểm thử được định cấu hình dựa trên máy chủ lưu trữ không yêu cầu thiết bị. Nếu không có lựa chọn này, Atest sẽ chạy cả hai kiểm thử, những kiểm thử yêu cầu một thiết bị và những kiểm thử chạy trên một máy chủ lưu trữ không yêu cầu thiết bị. Các kiểm thử được chạy trong 2 bộ kiểm thử riêng biệt:

atest [--test-mapping] --host

Xác định nhóm thử nghiệm

Bạn có thể chỉ định các nhóm kiểm thử trong lệnh Atest. Lệnh sau đây sẽ chạy tất cả các lượt kiểm thử postsubmit liên quan đến các tệp trong thư mục src/project_1. Thư mục này chỉ chứa một lượt kiểm thử (C).

Hoặc bạn có thể dùng :all để chạy tất cả các kiểm thử, bất kể nhóm nào. Lệnh sau đây chạy 4 kiểm thử (A, B, C, X):

atest --test-mapping src/project_1:all

Bao gồm thư mục con

Theo mặc định, việc chạy các kiểm thử trong TEST_MAPPING bằng Atest chỉ chạy các kiểm thử trước khi gửi được định cấu hình trong tệp TEST_MAPPING trong CWD (hoặc thư mục đã cho) và các thư mục mẹ của tệp đó. Nếu bạn muốn chạy các kiểm thử trong tất cả các tệp TEST_MAPPING trong các thư mục con, hãy sử dụng lựa chọn --include-subdir để buộc Atest đưa cả những kiểm thử đó vào.

atest --include-subdir

Nếu không có lựa chọn --include-subdir, Atest sẽ chỉ chạy kiểm thử A. Với lựa chọn --include-subdir, Atest sẽ chạy hai thử nghiệm (A, B).

Hỗ trợ bình luận ở cấp dòng

Bạn có thể thêm nhận xét định dạng // ở cấp dòng để bổ sung cho tệp TEST_MAPPING bằng nội dung mô tả về chế độ cài đặt tiếp theo. ATest và Trade Federation tiền xử lý TEST_MAPPING thành định dạng JSON hợp lệ mà không có nhận xét. Để giữ cho tệp JSON gọn gàng, chỉ có nhận xét ở định dạng // cấp dòng được hỗ trợ.

Ví dụ:

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