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

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

التقسيم هو أحد الحلول المتاحة في 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;
    }
    ...
}

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

الاستقلال

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

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

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