كتابة أداة تشغيل اختبار IRemoteTest مجزّأة

عند كتابة أداة لتشغيل الاختبارات، من المهم التفكير في قابلية التوسّع. اسأل نفسك، "إذا كان على أداة تشغيل الاختبار تنفيذ 200 ألف حالة اختبار"، كم من الوقت سيستغرق ذلك؟

التجزئة هي إحدى الإجابات المتاحة في Trade Federation. ويتطلّب ذلك تقسيم جميع الاختبارات التي يحتاجها أداة التشغيل إلى عدة أجزاء يمكن تنفيذها بشكل موازٍ.

توضّح هذه الصفحة كيفية تقسيم برنامج التشغيل إلى أقسام لاستخدامه مع Tradefed.

الواجهة المطلوب تنفيذها

الواجهة الأكثر أهمية التي يجب تنفيذها لكي يتم اعتبارها قابلة للتقسيم من قِبل TF هي IShardableTest، التي تحتوي على طريقتَين: split(int numShard) وsplit().

إذا كان تقسيم البيانات سيعتمد على عدد الأجزاء المطلوبة، عليك تنفيذ split(int numShard). بخلاف ذلك، نفِّذ split().

عند تنفيذ أمر اختبار TF باستخدام مَعلمتَي التجزئة --shard-count و --shard-index، ينتقل TF إلى جميع IRemoteTest للبحث عن IShardableTest التي يتم تنفيذها. وفي حال العثور عليه، سيتمّ استدعاء split للحصول على عنصر IRemoteTest جديد لتنفيذ مجموعة فرعية من حالات الاختبار لشريحة معيّنة.

ما هي المعلومات التي يجب أن أعرفها عن التنفيذ المُقسَّم؟

  • قد يقسّم برنامج التشغيل البيانات إلى شرائح استنادًا إلى بعض الشروط فقط، وفي هذه الحالة، يمكنك عرض null عندما لا يتم تقسيم البيانات إلى شرائح.
  • حاوِل تقسيم الإجراء إلى أجزاء منطقية: قسِّم الإجراء إلى وحدات تنفيذ منطقية. يعتمد ذلك حقًا على عداءك. على سبيل المثال: تتم تجزئة HostTest على مستوى الفئة، ويتم وضع كل فئة اختبار في شريحة منفصلة.
  • أضِف بعض الخيارات للتحكّم في التجزئة قليلاً إذا كان ذلك منطقيًا. على سبيل المثال: يحتوي AndroidJUnitTest على ajur-max-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;
    }
    ...
}

ينشئ هذا المثال ببساطة مثيلًا جديدًا من نفسه ويضبط مَعلمات القسم عليه. ومع ذلك، يمكن أن يختلف منطق التقسيم تمامًا من اختبار إلى آخر، طالما أنّه حتمي وينتج بشكل جماعي مجموعات فرعية شاملة، فلا بأس بذلك.

الاستقلال

يجب أن تكون الشرائح مستقلة. يجب ألا تكون هناك تبعيات بين الشرحتَين اللتين تم إنشاؤهما من خلال تنفيذ split في أداة التشغيل أو أن تشتركا في الموارد.

يجب أن يكون تقسيم الشرائح حتميًا. هذا الإجراء إلزامي أيضًا، فوفقًا لل conditions نفسها، يجب أن تعرض طريقة split دائمًا القائمة نفسها بالfragments بالترتيب نفسه.

ملاحظة: بما أنّه يمكن تشغيل كل شريحة على نُسخ مختلفة من TensorFlow، من المهم ضمان أن يؤدي منطق 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 لا تُجري أي تجميع لنتائج الاختبار لطلبات التنفيذ المقسّمة، عليك التأكّد من أنّ خدمة إعداد التقارير تتيح ذلك.