اكتب عداء اختبار 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 لا يقوم بأي تجميع لنتائج الاختبار للاستدعاءات المجزأة، فأنت بحاجة للتأكد من أن خدمة التقارير الخاصة بك تدعمها.