Compose ऐप्लिकेशन को टेस्ट करने के लिए, पहले से मौजूद तरीकों और पैटर्न का इस्तेमाल किया जा सकता है.
अलग से टेस्ट करना
ComposeTestRule की मदद से, किसी भी कंपोज़ेबल को दिखाने वाली गतिविधि शुरू की जा सकती है:
आपका पूरा ऐप्लिकेशन, एक स्क्रीन या कोई छोटा एलिमेंट. यह भी एक अच्छी प्रैक्टिस है कि आप यह जांच लें कि आपके कंपोज़ेबल सही तरीके से एनकैप्सुलेट किए गए हैं और वे अलग-अलग काम करते हैं. इससे यूज़र इंटरफ़ेस (यूआई) की जांच करना आसान और ज़्यादा फ़ोकस हो जाता है.
इसका मतलब यह नहीं है कि आपको सिर्फ़ यूनिट यूज़र इंटरफ़ेस (यूआई) टेस्ट बनाने चाहिए. यूज़र इंटरफ़ेस के बड़े हिस्सों को टेस्ट करना भी बहुत ज़रूरी है.
अपना कॉन्टेंट सेट करने के बाद, गतिविधि और संसाधनों को ऐक्सेस करना
अक्सर आपको composeTestRule.setContent का इस्तेमाल करके, टेस्ट किए जा रहे कॉन्टेंट को सेट करना पड़ता है. साथ ही, आपको गतिविधि के संसाधनों को ऐक्सेस करना पड़ता है. उदाहरण के लिए, यह दावा करने के लिए कि दिखाया गया टेक्स्ट, स्ट्रिंग रिसॉर्स से मैच करता है. हालांकि, createAndroidComposeRule() की मदद से बनाए गए नियम पर setContent को कॉल नहीं किया जा सकता. ऐसा तब होता है, जब गतिविधि पहले से ही इसे कॉल करती हो.
ऐसा करने का एक सामान्य तरीका यह है कि ComponentActivity जैसी खाली गतिविधि का इस्तेमाल करके, AndroidComposeTestRule बनाया जाए.
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
ध्यान दें कि ComponentActivity को आपके ऐप्लिकेशन की AndroidManifest.xml फ़ाइल में जोड़ना होगा. इस सुविधा को चालू करने के लिए, अपने मॉड्यूल में यह डिपेंडेंसी जोड़ें:
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
कस्टम सिमैंटिक प्रॉपर्टी
टेस्ट के लिए जानकारी दिखाने के लिए, कस्टम सिमैंटिक प्रॉपर्टी बनाई जा सकती हैं.
इसके लिए, एक नया SemanticsPropertyKey तय करें और SemanticsPropertyReceiver का इस्तेमाल करके इसे उपलब्ध कराएं.
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
अब उस प्रॉपर्टी को semantics मॉडिफ़ायर में इस्तेमाल करें:
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
टेस्ट से, प्रॉपर्टी की वैल्यू को तय करने के लिए SemanticsMatcher.expectValue का इस्तेमाल करें:
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
स्टेट रीस्टोरेशन की पुष्टि करना
पुष्टि करें कि गतिविधि या प्रोसेस को फिर से बनाने पर, आपके Compose एलिमेंट की स्थिति सही तरीके से वापस आ गई है. StateRestorationTester क्लास की मदद से, गतिविधि को फिर से बनाने पर भरोसा किए बिना, इस तरह की जांच करें.
इस क्लास की मदद से, कंपोज़ेबल को फिर से बनाने की प्रोसेस को सिम्युलेट किया जा सकता है. यह खास तौर पर, rememberSaveable के लागू होने की पुष्टि करने के लिए मददगार है.
class MyStateRestorationTests {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun onRecreation_stateIsRestored() {
val restorationTester = StateRestorationTester(composeTestRule)
restorationTester.setContent { MainScreen() }
// TODO: Run actions that modify the state
// Trigger a recreation
restorationTester.emulateSavedInstanceStateRestore()
// TODO: Verify that state has been correctly restored.
}
}
अलग-अलग डिवाइस कॉन्फ़िगरेशन की जांच करना
Android ऐप्लिकेशन को कई तरह की स्थितियों के हिसाब से अडजस्ट होना पड़ता है. जैसे, विंडो के साइज़, स्थानीय भाषाएं, फ़ॉन्ट के साइज़, गहरे और हल्के रंग वाली थीम वगैरह. इनमें से ज़्यादातर शर्तें, डिवाइस-लेवल की वैल्यू से तय होती हैं. इन वैल्यू को उपयोगकर्ता कंट्रोल करता है और इन्हें मौजूदा Configuration इंस्टेंस के साथ दिखाया जाता है. किसी टेस्ट में अलग-अलग कॉन्फ़िगरेशन को सीधे तौर पर टेस्ट करना मुश्किल होता है. इसकी वजह यह है कि टेस्ट को डिवाइस-लेवल की प्रॉपर्टी कॉन्फ़िगर करनी होती हैं.
DeviceConfigurationOverride, सिर्फ़ टेस्ट के लिए इस्तेमाल किया जाने वाला एपीआई है. इसकी मदद से, टेस्ट किए जा रहे @Composable कॉन्टेंट के लिए, डिवाइस के अलग-अलग कॉन्फ़िगरेशन को स्थानीय तौर पर सिम्युलेट किया जा सकता है.
DeviceConfigurationOverride के कंपैनियन ऑब्जेक्ट में ये एक्सटेंशन फ़ंक्शन होते हैं. ये फ़ंक्शन, डिवाइस-लेवल की कॉन्फ़िगरेशन प्रॉपर्टी को बदल देते हैं:
DeviceConfigurationOverride.DarkMode(): यह सिस्टम की थीम को गहरे रंग वाली थीम या हल्के रंग वाली थीम में बदल देता है.DeviceConfigurationOverride.FontScale(): सिस्टम के फ़ॉन्ट स्केल को बदलता है.DeviceConfigurationOverride.FontWeightAdjustment(): सिस्टम के फ़ॉन्ट की मोटाई में किए गए बदलाव को बदल देता है.DeviceConfigurationOverride.ForcedSize(): डिवाइस के साइज़ के बावजूद, स्पेस की तय संख्या को लागू करता है.DeviceConfigurationOverride.LayoutDirection(): यह लेआउट की दिशा (बाएं से दाएं या दाएं से बाएं) को बदल देता है.DeviceConfigurationOverride.Locales(): भाषा को बदलता है.DeviceConfigurationOverride.RoundScreen(): अगर स्क्रीन गोल है, तो यह ओवरराइड हो जाती है.
किसी खास बदलाव को लागू करने के लिए, टेस्ट किए जा रहे कॉन्टेंट को DeviceConfigurationOverride() टॉप-लेवल फ़ंक्शन के कॉल में रैप करें. साथ ही, बदलाव को पैरामीटर के तौर पर पास करें.
उदाहरण के लिए, यहां दिया गया कोड DeviceConfigurationOverride.ForcedSize() ओवरराइड को लागू करता है, ताकि डेंसिटी को स्थानीय तौर पर बदला जा सके. इससे MyScreen कंपोज़ेबल को बड़ी लैंडस्केप विंडो में रेंडर करने के लिए मजबूर किया जाता है. भले ही, जिस डिवाइस पर टेस्ट चल रहा है वह उस विंडो साइज़ के साथ सीधे तौर पर काम न करता हो:
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
एक साथ कई बदलाव लागू करने के लिए, DeviceConfigurationOverride.then() का इस्तेमाल करें:
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
टेस्ट में गड़बड़ी को हैंडल करने के लिए कस्टम कोड
यूज़र इंटरफ़ेस (यूआई) टेस्ट को डीबग करने के लिए, अक्सर स्क्रीन की स्थिति और कंपोज़िशन की हैरारकी की जांच करनी पड़ती है. ऐसा तब होता है, जब कोई दावा पूरा नहीं होता.
Compose, गड़बड़ी को ठीक करने के लिए नेटिव पाइपलाइन उपलब्ध कराता है, ताकि गड़बड़ी का पता लगाने की प्रोसेस को आसान बनाया जा सके. जांच के दौरान गड़बड़ी होने पर, स्क्रीनशॉट और यूज़र इंटरफ़ेस (यूआई) की हैरारकी अपने-आप कैप्चर हो सकती है. इसके अलावा, क्रैश टेलीमेट्री को बाहरी टूल पर भेजने के लिए, कस्टम हैंडलर रजिस्टर किए जा सकते हैं.
गड़बड़ी की जानकारी की सेटिंग कॉन्फ़िगर करें
गड़बड़ी को मैनेज करने की सुविधा को कॉन्फ़िगर करने के लिए, ComposeUiTestConfig को TestFailurePolicy ऑब्जेक्ट पास करें.
गड़बड़ी के आर्टफ़ैक्ट कैप्चर करने की सुविधा
टेस्ट फ़ेलियर होने पर स्क्रीनशॉट और यूज़र इंटरफ़ेस (यूआई) की हैरारकी कैप्चर करने के लिए, TestFailurePolicy में screenshotCaptureMode और uiHierarchyCaptureMode प्रॉपर्टी सेट करें.
class MyComposeTest { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled ) ) @Test fun myFirstTest() = runComposeUiTest(config = customConfig) { // ... } }
कस्टम फ़ेलियर हैंडलर का इस्तेमाल करना
टेस्ट फ़ेलियर के लिए कस्टम व्यवहार तय करने के लिए, failureHandlers सूची में TestFailureHandler जोड़ें. हर हैंडलर को एक FailureContext ऑब्जेक्ट मिलता है. इसमें ओरिजनल गड़बड़ी और पिछले पाइपलाइन हैंडलर से जनरेट किए गए आर्टफ़ैक्ट की सूची होती है.
class MyComposeTestWithHandler { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, failureHandlers = listOf( TestFailureHandler { context -> val screenshot = context.artifacts.firstOrNull { it.type == FailureArtifact.Type.Screenshot } // ... } ) ) ) @get:Rule val rule = createComposeRule(config = customConfig) // ... }
पूरे टेस्ट सुइट के लिए कैप्चर कॉन्फ़िगर करना
अपने मॉड्यूल की build.gradle फ़ाइल में इंस्ट्रुमेंटेशन रनर आर्ग्युमेंट पास करके, पूरे टेस्ट सुइट के लिए फ़ेलियर आर्टफ़ैक्ट कैप्चर करने की सुविधा चालू की जा सकती है. इससे, हर टेस्ट फ़ाइल को अपडेट करने की ज़रूरत नहीं पड़ती.
// build.gradle.kts
android {
defaultConfig {
// ...
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
}
}
कॉन्फ़िगरेशन लागू होने का क्रम
यह फ़्रेमवर्क, लोकल TestFailurePolicy और सुइट-लेवल, दोनों के रनर आर्ग्युमेंट का आकलन करता है:
- अगर आपने अपने टेस्ट
failurePolicyमें किसी मोड को साफ़ तौर परCaptureMode.Enabled/Disabledपर सेट किया है, तो यह रनर आर्ग्युमेंट को बदल देता है. - अगर आपने किसी मोड को
CaptureMode.Unspecifiedपर सेट किया है याfailurePolicyकोnullके तौर पर छोड़ा है, तो फ़्रेमवर्क, रनर आर्ग्युमेंट पर वापस चला जाता है.
अतिरिक्त संसाधन
- Android पर ऐप्लिकेशन की टेस्टिंग: Android टेस्टिंग का मुख्य लैंडिंग पेज, टेस्टिंग की बुनियादी बातों और तकनीकों के बारे में ज़्यादा जानकारी देता है.
- टेस्टिंग की बुनियादी बातें: Android ऐप्लिकेशन की टेस्टिंग से जुड़े मुख्य कॉन्सेप्ट के बारे में ज़्यादा जानें.
- लोकल टेस्ट: अपने वर्कस्टेशन पर, कुछ टेस्ट लोकल तौर पर चलाए जा सकते हैं.
- इंस्ट्रुमेंटेड टेस्ट: इंस्ट्रुमेंटेड टेस्ट चलाना भी एक अच्छा तरीका है. इसका मतलब है कि ये टेस्ट सीधे तौर पर डिवाइस पर चलाए जाते हैं.
- लगातार इंटिग्रेशन: लगातार इंटिग्रेशन की मदद से, टेस्ट को डिप्लॉयमेंट पाइपलाइन में इंटिग्रेट किया जा सकता है.
- अलग-अलग स्क्रीन साइज़ पर टेस्ट करें: उपयोगकर्ताओं के पास कई तरह के डिवाइस होते हैं. इसलिए, आपको अलग-अलग स्क्रीन साइज़ पर टेस्ट करना चाहिए.
- Espresso: Espresso को व्यू-आधारित यूज़र इंटरफ़ेस (यूआई) के लिए डिज़ाइन किया गया है. हालांकि, Espresso की जानकारी, Compose की टेस्टिंग के कुछ पहलुओं के लिए अब भी मददगार हो सकती है.