مزامنة الاختبارات

تتم مزامنة اختبارات Compose تلقائيًا مع واجهة المستخدم. عند استدعاء تأكيد أو إجراء باستخدام ComposeTestRule، تتم مزامنة الاختبار مسبقًا، بانتظار أن تصبح شجرة واجهة المستخدم غير نشطة.

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

عند مزامنة اختبار، يتم تقديم تطبيق Compose في الوقت باستخدام ساعة افتراضية. هذا يعني أنّ اختبارات Compose لا تعمل في الوقت الفعلي، وبالتالي يمكن تنفيذها بأقصى سرعة ممكنة.

ومع ذلك، إذا لم تستخدِم الطرق التي تتم فيها مزامنة اختباراتك، لن تتم إعادة التركيب، وسيبدو أنّ واجهة المستخدم متوقّفة مؤقتًا.

@Test
fun counterTest() {
    val myCounter = mutableStateOf(0) // State that can cause recompositions.
    var lastSeenValue = 0 // Used to track recompositions.
    composeTestRule.setContent {
        Text(myCounter.value.toString())
        lastSeenValue = myCounter.value
    }
    myCounter.value = 1 // The state changes, but there is no recomposition.

    // Fails because nothing triggered a recomposition.
    assertTrue(lastSeenValue == 1)

    // Passes because the assertion triggers recomposition.
    composeTestRule.onNodeWithText("1").assertExists()
}

يُرجى العِلم أنّ هذا الشرط ينطبق فقط على تسلسلات Compose الهرمية وليس على بقية التطبيق.

إيقاف المزامنة التلقائية

عند طلب تأكيد أو إجراء من خلال ComposeTestRule، مثل assertExists()، تتم مزامنة اختبارك مع واجهة مستخدم Compose. في بعض الحالات، قد تحتاج إلى إيقاف هذه المزامنة والتحكّم في الساعة بنفسك. على سبيل المثال، يمكنك ضبط الوقت لالتقاط لقطات شاشة دقيقة للرسوم المتحركة، بينما تكون واجهة المستخدم لا تزال مشغولة. لإيقاف المزامنة التلقائية، اضبط السمة autoAdvance في mainClock على false:

composeTestRule.mainClock.autoAdvance = false

بعد ذلك، عليك عادةً تقديم الوقت بنفسك. يمكنك تقديم الوقت بمقدار إطار واحد تمامًا باستخدام advanceTimeByFrame()، أو لفترة زمنية محددة باستخدام advanceTimeBy():

composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)

الموارد غير النشطة

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

أنشئ موارد غير نشطة وسجِّلها في الاختبار حتى يتم أخذها في الاعتبار عند تحديد ما إذا كان التطبيق قيد الاختبار مشغولاً أو غير نشط. ليس عليك اتّخاذ أي إجراء إلا إذا كنت بحاجة إلى تسجيل مصادر عدم النشاط، على سبيل المثال، إذا كنت تشغّل مهمة في الخلفية غير متزامنة مع Espresso أو Compose.

تشبه واجهة برمجة التطبيقات هذه إلى حد كبير مصادر عدم النشاط في Espresso للإشارة إلى ما إذا كان العنصر قيد الاختبار في وضع الخمول أو مشغولاً. استخدِم قاعدة اختبار Compose لتسجيل عملية تنفيذ IdlingResource.

composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)

المزامنة اليدوية

في بعض الحالات، عليك مزامنة واجهة مستخدم Compose مع أجزاء أخرى من الاختبار أو التطبيق الذي تختبره.

تنتظر الدالة waitForIdle() أن يصبح Compose غير نشط، ولكن تعتمد الدالة على السمة autoAdvance:

composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.

composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.

يُرجى العِلم أنّه في كلتا الحالتين، ينتظر waitForIdle() أيضًا عمليات الرسم والتنسيق المعلّقة.

يمكنك أيضًا تقديم الوقت حتى يتم استيفاء شرط معيّن باستخدام advanceTimeUntil().

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

يُرجى العِلم أنّ الشرط المحدّد يجب أن يتحقّق من الحالة التي يمكن أن تتأثّر بهذا المؤقت (لا يعمل إلا مع حالة Compose).

انتظار الشروط

يجب أن يستخدم أي شرط يعتمد على عمل خارجي، مثل تحميل البيانات أو قياس Android أو الرسم (أي القياس أو الرسم الخارجيان لـ Compose)، مفهومًا أكثر عمومية، مثل waitUntil():

composeTestRule.waitUntil(timeoutMs) { condition }

يمكنك أيضًا استخدام أي من waitUntil أدوات المساعدة:

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

مراجع إضافية

  • اختبار التطبيقات على Android: تقدّم صفحة Android الرئيسية الخاصة بالاختبار نظرة عامة على أساسيات الاختبار وأساليبه.
  • أساسيات الاختبار: مزيد من المعلومات عن المفاهيم الأساسية لاختبار تطبيق Android
  • الاختبارات المحلية: يمكنك إجراء بعض الاختبارات محليًا على محطة العمل الخاصة بك.
  • اختبارات لقياس حالة التطبيق: من الممارسات الجيدة أيضًا إجراء اختبارات لقياس حالة التطبيق. أي الاختبارات التي يتم إجراؤها مباشرةً على الجهاز.
  • التكامل المستمر: يتيح لك التكامل المستمر دمج اختباراتك في مسار النشر.
  • اختبار أحجام الشاشات المختلفة: بما أنّ المستخدمين يتوفّر لديهم العديد من الأجهزة، عليك اختبار أحجام الشاشات المختلفة.
  • Espresso: على الرغم من أنّ Espresso مُصمَّمة لواجهات المستخدم المستندة إلى العرض، إلا أنّ معرفة أدوات Espresso يمكن أن تكون مفيدة في بعض جوانب اختبار Compose.