تتيح لك وظيفة Compose Offers ComposeTestRule كتابة اختبارات للصور المتحركة
بطريقة حتمية مع التحكّم الكامل في ساعة الاختبار. يتيح لك ذلك التحقّق من قيم الرسوم المتحركة الوسيطة. بالإضافة إلى ذلك، يمكن أن يتم تشغيل الاختبار بشكل أسرع من المدة الفعلية للحركة.
تعرض ComposeTestRule ساعة الاختبار على النحو mainClock. يمكنك ضبط قيمة السمة
autoAdvance على false للتحكّم في الساعة في رمز الاختبار. بعد بدء الحركة التي تريد اختبارها، يمكن تقديم الساعة باستخدام advanceTimeBy.
يُرجى العِلم أنّ advanceTimeBy لا ينقل الساعة بالضبط بالمدة المحدّدة. بل يتم تقريبه إلى أقرب مدة زمنية تكون مضاعفًا لمدة عرض اللقطة.
@get:Rule val rule = createComposeRule() @Test fun testAnimationWithClock() { // Pause animations rule.mainClock.autoAdvance = false var enabled by mutableStateOf(false) rule.setContent { val color by animateColorAsState( targetValue = if (enabled) Color.Red else Color.Green, animationSpec = tween(durationMillis = 250) ) Box(Modifier.size(64.dp).background(color)) } // Initiate the animation. enabled = true // Let the animation proceed. rule.mainClock.advanceTimeBy(50L) // Compare the result with the image showing the expected result. // `assertAgainGolden` needs to be implemented in your code. rule.onRoot().captureToImage().assertAgainstGolden() }
تحسين اختبارات الصور المتحركة
عند اختبار الرسوم المتحركة عالية الدقة، عليك غالبًا إيقاف التقدّم التلقائي
والانتقال يدويًا بين اللقطات لتأكيد حالات واجهة المستخدم الوسيطة. بالنسبة إلى حلقات التكرار المحدّدة هذه، استخدِم طريقة runWithoutImplicitWait لتنفيذ تأكيداتك. تؤدي طلبات البحث عن العُقد العادية (مثل onNodeWithTag أو fetchSemanticsNode) إلى عمليات مزامنة ضمنية تكون غير ضرورية عند التحكّم في الساعة يدويًا، لذا فإنّ تجاوزها يؤدي إلى تسريع أوقات تشغيل الاختبار بشكل كبير.
إرشادات الاستخدام
- الإدارة اليدوية للساعة: استخدِم واجهة برمجة التطبيقات هذه عندما يكون
mainClock.autoAdvanceمضبوطًا علىfalseوتكون واجهة المستخدم في حالة معروفة وثابتة للإطار الحالي. - تنفيذ سلسلة واجهة المستخدم: لضمان استقرار شجرة واجهة المستخدم، استدعِ
runWithoutImplicitWaitفي سلسلة واجهة المستخدم، مثلاً باستخدامrunOnUiThread. يؤدي تشغيل الاختبار خارج سلسلة التعليمات الخاصة بواجهة المستخدم إلى تعريض الاختبار لحالات التنافس وقراءات الحالة القديمة. - تأكيدات للقراءة فقط: يجب أن يحتوي الحظر على تأكيدات للقراءة فقط. يجب تنفيذ أي إجراءات تغيّر الحالة خارج هذا القسم.
مثال
@Test fun runWithoutImplicitWaitSample() = runComposeUiTest { setContent { MainScreen() } mainClock.autoAdvance = false // Trigger an animation onNodeWithText("Start Animation").performClick() // Step through the animation frame-by-frame while (hasPendingWork()) { mainClock.advanceTimeByFrame() waitForIdle() runOnUiThread { // Suppress implicit synchronization inside this block to avoid redundant // waits on each node query, making the frame assertions execute much faster. runWithoutImplicitWait { val box1 = onNodeWithTag("Box1").fetchSemanticsNode() val box2 = onNodeWithTag("Box2").fetchSemanticsNode() val box3 = onNodeWithTag("Box3").fetchSemanticsNode() // Assert the exact intermediate state of all three properties for this frame assert(box1.boundsInRoot.right <= box2.boundsInRoot.left) assert(box2.boundsInRoot.right <= box3.boundsInRoot.left) } } } }
مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة
- اختبار تصميم Compose
- اعتبارات أخرى
- تخصيص الصور المتحركة