כתיבת הרצת בדיקה מפוצלת של IremoteTest

כשכותבים מפעיל בדיקות, חשוב להביא בחשבון את יכולת ההתאמה לעומס. כדאי לשאול את עצמכם: "אם הכלי להרצת הבדיקות שלי יצטרך להריץ 200,000 תרחישי בדיקה, כמה זמן זה ייקח?"

חלוקה למקטעים היא אחת מהתשובות הזמינות ב-Trade Federation. לשם כך צריך לפצל את כל הבדיקות שנדרשות למפעיל לכמה קטעים שאפשר לבצע במקביל.

בדף הזה נסביר איך להפוך את ה-runner לניתן לחלוקה לחלקים ב-Tradefed.

ממשק להטמעה

הממשק החשוב ביותר שצריך להטמיע כדי ש-TF יחשב את האובייקט כניתן לחלוקה הוא IShardableTest, שמכיל שתי שיטות: split(int numShard) ו-split().

אם חלוקת המשנה תלויה במספר פלחים המבוקשים, צריך להטמיע את split(int numShard). אחרת, צריך להטמיע את split().

כשמפעילים פקודת בדיקה של TF עם פרמטרים של חלוקה לפלחים --shard-count ו---shard-index, ‏TF מבצע חזרה על כל IRemoteTest כדי לחפש אלה שמטמיעים את IShardableTest. אם הוא ימצא, הוא יפעיל את split כדי לקבל אובייקט IRemoteTest חדש להרצת קבוצת משנה של מקרי בדיקה לשבר ספציפי.

מה חשוב לדעת על ההטמעה של חלוקת המודעות?

  • ה-runner יכול לפצל לפי תנאים מסוימים בלבד. במקרה כזה, צריך להחזיר את הערך null כשלא בוצע פיצול.
  • כדאי לחלק את הריצה כמה שיותר הגיוני: לחלק את הריצה ליחידת ביצוע שמתאימה לה. זה תלוי בגורם שמריץ את הבדיקה. לדוגמה: HostTest מחולק למקטעים ברמת הכיתה, כל כיתה של בדיקות מועברת למקטע נפרד.
  • אם הגיוני, הוסיפו כמה אפשרויות כדי לשלוט קצת בפיצול. לדוגמה: ל-AndroidJUnitTest יש את ajur-max-shard כדי לציין את המספר המקסימלי של פלחים שאפשר לפצל אותו אליהם, ללא קשר למספר המבוקש.

דוגמה מפורטת להטמעה

לפניכם קטע קוד לדוגמה שמטמיע את IShardableTest שאפשר להפנות אליו. הקוד המלא זמין בכתובת (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;
    }
    ...
}

בדוגמה הזו פשוט נוצרת מכונה חדשה של עצמה ומגדירים לה פרמטרים של פלחים. עם זאת, הלוגיקה של הפיצול יכולה להיות שונה לגמרי מבדיקת A/B לבדיקת A/B אחרת. כל עוד היא גורמת ליצירת קבוצות משנה מקיפות באופן קולקטיבי, היא תקינה.

עצמאות

אסור שהפלחים יהיו תלויים זה בזה! לשני שבבים שנוצרו על ידי ההטמעה של split ב-runner לא צריכות להיות יחסי תלות זה בזה או משאבים משותפים.

פיצול פיצולים צריך להיות דטרמיניסטי! זה חובה גם כי באותו מצב, שיטת split תמיד צריכה להחזיר את אותה רשימה של פלחים באותו סדר.

הערה: מאחר שכל שריד יכול לפעול במכונות TF שונות, חשוב לוודא שהלוגיקה של split מניבה קבוצות משנה שהן בלתי ניתנות להפרדה ומקיפות באופן דטרמיניסטי.

חלוקה של בדיקה למקטעים באופן מקומי

כדי לפצל בדיקה ב-TF מקומי, אפשר פשוט להוסיף את האפשרות --shard-count לשורת הפקודה.

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

לאחר מכן TF יפעיל פקודות לכל פיצול באופן אוטומטי ויריץ אותן.

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 לא מבצע צבירת תוצאות בדיקה להפעלות מחולקות, צריך לוודא ששירות הדיווח תומך בכך.