เขียนโปรแกรมรันไทม์การทดสอบ IRemoteTest แบบแยกกลุ่ม

เมื่อเขียนโปรแกรมเรียกใช้การทดสอบ สิ่งสำคัญคือต้องคำนึงถึงความสามารถในการปรับขนาด ลองถามตัวเองว่า "หากโปรแกรมเรียกใช้การทดสอบต้องเรียกใช้กรณีทดสอบ 200,000 รายการ" จะใช้เวลานานเท่าใด

การแบ่งพาร์ติชันเป็นหนึ่งในคำตอบที่มีอยู่ในสหพันธ์การค้า โดยต้องแบ่งการทดสอบทั้งหมดที่โปรแกรมเรียกใช้ต้องการออกเป็นหลายๆ ส่วนที่สามารถ ดำเนินการแบบขนานได้

หน้านี้จะอธิบายวิธีทำให้ Runner แยกส่วนได้สำหรับ Tradefed

อินเทอร์เฟซที่จะติดตั้งใช้งาน

อินเทอร์เฟซที่สำคัญที่สุดเพียงอย่างเดียวที่ต้องติดตั้งใช้งานเพื่อให้ TF พิจารณาว่าสามารถแยกส่วนได้คือ IShardableTest ซึ่งมี 2 วิธี ได้แก่ split(int numShard) และ split()

หากการแบ่งข้อมูลขึ้นอยู่กับจำนวน Shard ที่ขอ คุณควรใช้ split(int numShard) มิเช่นนั้น ให้ใช้ split()

เมื่อเรียกใช้คำสั่งทดสอบ TF ด้วยพารามิเตอร์การแบ่งกลุ่ม --shard-count และ --shard-index TF จะวนซ้ำผ่าน IRemoteTest ทั้งหมดเพื่อค้นหาพารามิเตอร์ที่ใช้ IShardableTest หากพบ ระบบจะเรียกใช้ split เพื่อ รับออบเจ็กต์ IRemoteTest ใหม่เพื่อเรียกใช้ชุดย่อยของกรณีทดสอบสำหรับ ชาร์ดที่เฉพาะเจาะจง

ฉันควรรู้อะไรเกี่ยวกับการติดตั้งใช้งานแบบแยก

  • Runner อาจแบ่งพาร์ติชันภายใต้เงื่อนไขบางอย่างเท่านั้น ในกรณีนี้ ให้ส่งคืน null เมื่อคุณไม่ได้แบ่งพาร์ติชัน
  • พยายามแยกส่วนให้มากที่สุดเท่าที่จะทำได้ โดยแยกโปรแกรมเรียกใช้เป็นหน่วยการดำเนินการที่เหมาะสม ซึ่งขึ้นอยู่กับโปรแกรมเรียกใช้ของคุณ ตัวอย่างเช่น HostTest จะมีการแบ่งที่ระดับคลาส โดยคลาสทดสอบแต่ละคลาสจะอยู่ใน Shard แยกต่างหาก
  • หากเป็นไปได้ ให้เพิ่มตัวเลือกบางอย่างเพื่อควบคุมการแบ่งข้อมูลเล็กน้อย เช่น AndroidJUnitTest มี ajur-max-shard เพื่อระบุจำนวนสูงสุดของ Shard ที่สามารถ แยกได้ ไม่ว่าจำนวนที่ขอจะเป็นเท่าใดก็ตาม

ตัวอย่างการใช้งานโดยละเอียด

ตัวอย่างข้อมูลโค้ดที่ใช้ IShardableTest ซึ่งคุณ อ้างอิงได้มีดังนี้ ดูโค้ดทั้งหมดได้ที่ (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;
    }
    ...
}

ตัวอย่างนี้เพียงสร้างอินสแตนซ์ใหม่ของตัวเองและตั้งค่าพารามิเตอร์ของ Shard ให้ อย่างไรก็ตาม ตรรกะการแยกอาจแตกต่างกันโดยสิ้นเชิงจากการทดสอบหนึ่งไปอีกการทดสอบหนึ่ง และตราบใดที่ตรรกะนั้นเป็นแบบดีเทอร์มินิสติกและให้ผลลัพธ์เป็นเซ็ตย่อยที่ครอบคลุมทั้งหมด ก็ถือว่าใช้ได้

ความเป็นอิสระ

Shards ต้องเป็นอิสระต่อกัน Shards 2 รายการที่สร้างขึ้นจากการติดตั้งใช้งาน split ใน Runner ไม่ควรมีทรัพยากรที่ขึ้นต่อกันหรือแชร์

การแยก Shard ต้องเป็นแบบดีเทอร์มินิสติก นอกจากนี้ยังเป็นข้อบังคับด้วย เนื่องจาก ภายใต้เงื่อนไขเดียวกัน splitเมธอดควรแสดงรายการ Shards เดียวกันทุกครั้งในลำดับเดียวกัน

หมายเหตุ: เนื่องจากแต่ละ Shard สามารถทำงานบนอินสแตนซ์ TF ที่แตกต่างกันได้ จึงจำเป็นอย่างยิ่งที่จะต้อง ตรวจสอบว่าตรรกะ split ให้ผลลัพธ์เป็นเซ็ตย่อยที่ไม่มีส่วนร่วมกันและ ครอบคลุมทั้งหมดในลักษณะที่กำหนดได้

แบ่งการทดสอบออกเป็นหลายๆ ส่วนในเครื่อง

หากต้องการแบ่งการทดสอบใน TF ในเครื่อง คุณเพียงแค่เพิ่มตัวเลือก --shard-count ลงในบรรทัดคำสั่ง

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

จากนั้น TF จะสร้างคำสั่งสำหรับแต่ละ Shard และเรียกใช้คำสั่งเหล่านั้นโดยอัตโนมัติ

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)

การรวบรวมผลการทดสอบ

เนื่องจาก TF ไม่ได้รวมผลการทดสอบใดๆ สำหรับการเรียกใช้ที่แยกส่วน คุณจึงต้องตรวจสอบว่าบริการรายงานรองรับการเรียกใช้ดังกล่าว