Viết trình chạy kiểm thử IRemoteTest được phân đoạn

Khi viết một trình chạy kiểm thử, điều quan trọng là bạn phải nghĩ đến khả năng mở rộng. Hãy tự hỏi bản thân: "Nếu trình chạy kiểm thử của tôi phải chạy 200.000 trường hợp kiểm thử, thì sẽ mất bao lâu?"

Phân đoạn là một trong những câu trả lời có trong Trade Federation. Việc này đòi hỏi bạn phải chia tất cả các kiểm thử mà trình chạy cần thành nhiều khối có thể song song hoá.

Trang này mô tả cách tạo trình chạy có thể phân đoạn cho Tradefed.

Giao diện cần triển khai

Giao diện quan trọng nhất cần triển khai để được TF coi là có thể phân đoạn là IShardableTest, chứa 2 phương thức: split(int numShard)split().

Nếu việc phân đoạn của bạn sẽ phụ thuộc vào số lượng phân đoạn được yêu cầu, thì bạn nên triển khai split(int numShard). Nếu không, hãy triển khai split().

Khi một lệnh kiểm thử TF được thực thi bằng các tham số phân đoạn --shard-count--shard-index, TF sẽ lặp lại tất cả IRemoteTest để tìm những tham số triển khai IShardableTest. Nếu tìm thấy, phương thức này sẽ gọi split để lấy một đối tượng IRemoteTest mới nhằm chạy một nhóm nhỏ các trường hợp kiểm thử cho một phân đoạn cụ thể.

Tôi cần biết những gì về việc triển khai phân chia?

  • Bạn có thể chỉ phân đoạn trình chạy trong một số điều kiện; trong trường hợp đó, hãy trả về null khi bạn không phân đoạn.
  • Cố gắng chia nhỏ càng nhiều càng tốt: chia runner của bạn thành đơn vị thực thi phù hợp. Điều này thực sự phụ thuộc vào trình chạy của bạn. Ví dụ: HostTest được phân đoạn ở cấp độ Lớp, mỗi lớp kiểm thử được đặt trong một phân đoạn riêng biệt.
  • Nếu có thể, hãy thêm một số lựa chọn để kiểm soát việc phân đoạn một chút. Ví dụ: AndroidJUnitTest có một ajur-max-shard để chỉ định số lượng phân đoạn tối đa mà nó có thể chia tách, bất kể số lượng được yêu cầu.

Ví dụ chi tiết về cách triển khai

Sau đây là một đoạn mã mẫu triển khai IShardableTest mà bạn có thể tham khảo. Bạn có thể xem toàn bộ mã tại (https://android.googlesource.com/platform/tools/tradefederation/+/refs/heads/android16-release/test_framework/com/android/tradefed/testtype/InstalledInstrumentationsTest.java)

/**
 * Runs all instrumentation found on current device.
 */
@OptionClass(alias = "installed-instrumentation")
public class InstalledInstrumentationsTest
        implements IDeviceTest, IResumableTest, IShardableTest {
    ...

    /** {@inheritDoc} */
    @Override
    public Collection<IRemoteTest> split(int shardCountHint) {
        if (shardCountHint > 1) {
            Collection<IRemoteTest> shards = new ArrayList<>(shardCountHint);
            for (int index = 0; index < shardCountHint; index++) {
                shards.add(getTestShard(shardCountHint, index));
            }
            return shards;
        }
        // Nothing to shard
        return null;
    }

    private IRemoteTest getTestShard(int shardCount, int shardIndex) {
        InstalledInstrumentationsTest shard = new InstalledInstrumentationsTest();
        try {
            OptionCopier.copyOptions(this, shard);
        } catch (ConfigurationException e) {
            CLog.e("failed to copy instrumentation options: %s", e.getMessage());
        }
        shard.mShardIndex = shardIndex;
        shard.mTotalShards = shardCount;
        return shard;
    }
    ...
}

Ví dụ này chỉ tạo một phiên bản mới của chính nó và đặt các tham số phân đoạn cho phiên bản đó. Tuy nhiên, logic phân chia có thể hoàn toàn khác nhau giữa các phép kiểm thử; và miễn là logic đó mang tính xác định và tạo ra các tập hợp con đầy đủ, thì không sao cả.

Độc lập

Các phân đoạn cần phải độc lập! Hai phân đoạn do quá trình triển khai split trong trình chạy của bạn tạo ra không được có sự phụ thuộc lẫn nhau hoặc chia sẻ tài nguyên.

Việc phân chia các phân đoạn cần phải mang tính xác định! Đây cũng là điều bắt buộc, trong cùng điều kiện, phương thức split của bạn phải luôn trả về danh sách mảnh chính xác theo cùng một thứ tự.

LƯU Ý: Vì mỗi phân đoạn có thể chạy trên các phiên bản TF khác nhau, nên điều quan trọng là phải đảm bảo logic split tạo ra các tập hợp con loại trừ lẫn nhau và đầy đủ theo cách xác định.

Phân đoạn một bài kiểm thử cục bộ

Để phân đoạn một bài kiểm thử trên TF cục bộ, bạn chỉ cần thêm lựa chọn --shard-count vào dòng lệnh.

tf >run host --class com.android.tradefed.UnitTests --shard-count 3

Sau đó, TF sẽ tự động tạo các lệnh cho từng phân đoạn và chạy các lệnh đó.

tf >l i
Command Id  Exec Time  Device          State
3           0m:03      [null-device-2]  running stub on build 0 (shard 1 of 3)
3           0m:03      [null-device-1]  running stub on build 0 (shard 0 of 3)
3           0m:03      [null-device-3]  running stub on build 0 (shard 2 of 3)

Tổng hợp kết quả kiểm thử

Vì TF không tổng hợp kết quả kiểm thử cho các lệnh gọi được phân đoạn, nên bạn cần đảm bảo dịch vụ báo cáo của mình hỗ trợ tính năng này.