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

Khi viết trình chạy kiểm thử, điều quan trọng là bạn phải suy nghĩ về khả năng mở rộng. Hãy tự hỏi mình "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ì mất bao lâu?

Phân đoạn là một trong những giải pháp có trong Trade Federation. Phương thức này yêu cầu phân tách tất cả các chương trình kiểm thử mà trình chạy cần thành một số phần có thể được chạy song song.

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

Giao diệ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 hai phương thức: split(int numShard)split().

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

Khi 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 qua tất cả IRemoteTest để tìm những tham số triển khai IShardableTest. Nếu tìm thấy, lệnh này sẽ gọi split để lấy đối tượng IRemoteTest mới nhằm chạy một tập hợp con các trường hợp kiểm thử cho một phân đoạn cụ thể.

Tôi nên biết gì về việc triển khai phần phân tách?

  • Trình chạy của bạn chỉ có thể phân đoạn theo 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.
  • Hãy cố gắng phân chia càng nhiều càng tốt: chia trình chạy 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 vận động viên 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.
  • Nếu có thể, hãy thêm một số tuỳ chọn để kiểm soát việc phân đoạn một chút. Ví dụ: AndroidJUnitTestajur-max-shard để chỉ định số lượng mảnh tối đa có thể phân tách, bất kể số lượng được yêu cầu.

Triển khai ví dụ chi tiết

Dưới đây là đoạn mã mẫu triển khai IShardableTest mà bạn có thể tham khảo. Bạn có thể xem mã đầy đủ tại (https://android.googlesource.com/platform/tools/tradefederation/+/refs/heads/main/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 thực thể mới của chính nó và đặt các tham số phân đoạn cho thực thể đó. Tuy nhiên, logic phân tách có thể hoàn toàn khác nhau giữa các kiểm thử; và miễn là logic đó có tính xác định và mang lại tập hợp con toàn diện, thì bạn có thể sử dụng logic đó.

Độc lập

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

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

LƯU Ý: Vì mỗi phân mảnh 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 đủ một cách có định hướng.

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

Để phân đoạn một kiểm thử trên TF cục bộ, bạn chỉ cần thêm tuỳ 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ử nào 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.