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

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

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

توضح هذه الصفحة كيفية جعل العداء قابلاً للتجزئة في 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/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;
    }
    ...
}

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

الاستقلال

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

يجب أن يكون تقسيم الأجزاء حتميًا! ويُعد هذا إلزاميًا أيضًا، نظرًا الشروط نفسها، يجب أن تعرض طريقة 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 لا تُجري أي تجميع لنتائج الاختبار لطلبات التنفيذ المقسّمة، عليك التأكّد من أنّ خدمة إعداد التقارير تتيح ذلك.