Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Explore top React Native best practices to boost Appium test automation efficiency, reliability, and cross-platform performance in mobile app testing.
Srinivasan Sekar
January 11, 2026
React Native has evolved into a pillar for creating cross-platform apps effectively in the fast-paced realm of mobile app creation. But as apps get more sophisticated, the challenges of implementing robust test automation increase.
Not following React Native best practices, like incorrectly identifying elements, having overly complicated DOM structures, and unintentional clashes between accessibility and testability, leads to unreliable tests, slower performance, and incorrect results in tools like Appium.
This blog explores three React Native development pillars directly influencing your Appium test suite dependability:
These battle-tested techniques will enable you to create apps that are both user-friendly and automation-friendly without sacrificing either front, regardless of your struggle with inconsistent test failures or slow-moving automation pipelines.
A well-structured Element Identification Hierarchy is crucial in React Native apps, as it directly impacts the reliability and precision of your Appium test suite.
On Android, both testID and accessibilityLabel map to different native properties, but developers often misuse them interchangeably. This leads to:
| Property | Android Native Property | iOS Native Property |
|---|---|---|
| testID | View Tag (view.setTag()) | accessibilityIdentifier |
| accessibilityLabel | contentDescription | accessibilityLabel |
<Button
testID="login-submit-btn" // For Appium
accessibilityLabel="Submit login form" // For screen readers
accessibilityRole="button"
/>
Configure Appium to use the correct property for each platform:
// Custom "test-id" locator strategy for Android - For Espresso
driver.findElement(AppiumBy.androidViewTag("login-submit-btn"));
// UIAutomator2
driver.findElement(AppiumBy.androidUIAutomator("new UIAutomator().description('login-submit-btn')"));
driver.findElement(AppiumBy.accessibilityId("login-submit-btn"))
adb shell uiautomator dump
adb shell cat /sdcard/window_dump.xml | grep 'login-submit-btn'
Here is another real-world example: below is a React component called Image with the testID set as react-logo and the accessibility label set as React Logo.

Let’s see how these attributes are being mapped in the Android app using Appium Inspector:

Let’s see how these attributes are being mapped in the iOS app using Appium Inspector:


| Platform | Appium Locates By | Screen Reader Announces |
|---|---|---|
| Android | testID → View Tag (via custom strategy) or Resource ID | accessibilityLabel → contentDescription |
| iOS | testID → accessibilityIdentifier | accessibilityLabel |
Outcome:
Note: Test React Native apps with Appium on real Android and iOS devices. Try TestMu AI Now!
Only combine testID and accessibilityLabel on the same element if:
<Button
testID="Submit login form" // For Appium
accessibilityLabel="Submit login form" // For screen readers
accessibilityRole="button"
/>
DOM Reduction Techniques help streamline the app’s UI structure, minimizing unnecessary nodes and making your Appium test suite faster, more stable, and easier to maintain.
Decorative elements (e.g., background images, separators) remain in the accessibility tree, causing:
Solution:
<Image
source={bg}
importantForAccessibility="no-hide-descendants" // Android
accessibilityElementsHidden={true} // iOS
/>
ScrollView with 1000 items creates 1000 DOM nodes immediately:
Solution:
Replacing ScrollView with FlatList reduces DOM nodes and improves Appium performance.
<FlatList
data={data}
renderItem={({item}) => (
<Item
testID={`item-${item.id}`} // Unique selector
accessibilityLabel={item.name} // Screen reader context
/>
)}
keyExtractor={item => item.id}
initialNumToRender={10} // Only 10 nodes mounted initially
windowSize={21} // 10 above + 10 below + 1 current
/>
React Navigation’s default behaviour keeps previous screens mounted:
Solution:
<Stack.Screen
name="Details"
component={DetailsScreen}
options={{
unmountOnBlur: true, // Full cleanup
detachPreviousScreen: true // Android-specific optimization
}}
/>
useEffect(() => {
const subscription = NetInfo.addEventListener(...);
return () => subscription.remove(); // Cleanup on unmount
}, []);
# Check Android DOM size
adb shell uiautomator dump && adb shell cat /sdcard/window_dump.xml | wc -l
# Check iOS DOM via WDA
appium:showIOSLog: true
The result: A 500-node screen, with these optimizations, achieves the following:
Deeply nested elements or large DOMs may cause Appium to truncate the element hierarchy during inspection.
driver.setSetting("snapshotMaxDepth", 60);
driver.setSetting("customSnapshotTimeout", 30000);
As per Appium, snapshotMaxDepth changes the value of maximum depth for traversing the elements in the source tree. It may help to prevent out-of-memory or timeout errors while getting the element’s source tree, but it might restrict its depth.
Please consider restricting this value if you observed an error like Timed out snapshotting com.apple.testmanagerd… message or The current application’s XML source cannot be retrieved from your Appium log, possibly due to a timeout. A part of the elements’ source tree might be lost if the value is too small. Defaults to 50
According to Appium, the customSnapshotTimeout parameter determines the maximum time in float seconds for resolving a single accessibility snapshot with custom attributes. Page source generation, XML lookup, and the retrieval of custom attributes (both visibility and accessibility) primarily use snapshots.
It might be necessary to increase this value if the actual page source is enormous and contains hundreds of UI elements. The default value is set to 15 seconds.
Since Appium 1.19.1, if this timeout expires and no custom snapshot can be made, then WDA tries to calculate the missing attributes using its own algorithms, so setting this value to zero might speed up, for example, page source retrieval, but at the cost of the precision of some element attributes.
Reduce XML size using Appium settings as below:
driver.setSetting("pageSourceExcludedAttributes", "type,index,visible"); // Exclude non-critical attributes
driver.setSetting("useJSONSource", true); // Use lightweight JSON instead of XML
The strategic use of the accessible property in React Native enhances both accessibility and test automation by enabling Appium to accurately identify and interact with UI elements.
When a parent container uses accessible={true}, React Native flattens its children into a single accessibility node. While this feature improves screen reader UX by grouping related elements, it hides individual child elements from Appium, making them untestable.
// BAD FOR TESTING: List items become untestable
function ShoppingCartScreen() {
const cartItems = [
{ id: 1, name: "Headphones", price: "$99" },
{ id: 2, name: "Phone Case", price: "$29" },
{ id: 3, name: "Charger", price: "$19" }
];
return (
<View accessible={true} accessibilityLabel="Shopping cart items">
{cartItems.map(item => (
<View key={item.id} testID={`cart-item-${item.id}`}>
<Text>{item.name}</Text>
<Text>{item.price}</Text>
<Button
testID={`remove-item-${item.id}`}
title="Remove"
onPress={() => removeItem(item.id)}
/>
</View>
))}
</View>
);
}
What happens:
Here’s an example of a React component named ThemedView with numerous components inside, set to accessible true.

Let’s see how the parent element blocks child elements in the DOM using Appium Inspector:

None of the child elements are accessible, and React Native flattens them into a single node.
For Lists:
// GOOD FOR TESTING: Each list item remains testable
function ShoppingCartScreen() {
const cartItems = [
{ id: 1, name: "Headphones", price: "$99" },
{ id: 2, name: "Phone Case", price: "$29" },
{ id: 3, name: "Charger", price: "$19" }
];
return (
<FlatList
data={cartItems}
renderItem={({item}) => (
<View
key={item.id}
testID={`cart-item-${item.id}`}
accessibilityLabel={`${item.name}, ${item.price}`}
>
<Text>{item.name}</Text>
<Text>{item.price}</Text>
<Button
testID={`remove-item-${item.id}`}
accessibilityLabel={`Remove ${item.name}`}
title="Remove"
onPress={() => removeItem(item.id)}
/>
</View>
)}
/>
);
}
FlatList, by default, exposes accessible elements within it.
What happens:
Key Behaviours:
Here is a real-world example again, with accessible property set to false for the themed view containing many child elements:

Let’s examine how Appium Inspector presents the parent element and child elements in the DOM.

Setting the accessible property of the parent view to false (default) clearly presents both the parent and child elements in the DOM.
By strategically limiting accessible=true usage, you maintain both accessibility compliance and test automation reliability.
Even with robust element identification and DOM optimizations, tests may fail on real devices due to platform fragmentation, OS-specific quirks, or hardware variations. Emulators/simulators cannot replicate real-world conditions like battery states, network fluctuations, or sensor interactions.
Solution: Integrate TestMu AI’s real device cloud into your React Native testing workflow to validate Appium scripts across 10,000+ real Android/iOS devices. This service ensures your optimizations hold up in production-like environments.
After auditing DOM nodes with React DevTools, run tests on TestMu AI to verify performance gains on low-memory devices (e.g., older Android models)
Designing with empathy for both your users and your QA processes is more than just a matter of writing better code; it is also a matter of mastering the nuances of React Native best practices with respect to test automation.
Remember this: what’s good for automation is frequently good for accessibility, and vice versa when you restructure your React Native components. Use the checklist on this site to audit your app right now and see for yourself how small changes can lead to significant improvements in quality and performance. The finest programs, after all, are created to be tested rather than merely created. 🚀
Are you prepared to modify the React Native testing process? Choose one section from this guide, apply it, and see how your Appium test starts to stabilize.
Co-Author: Sai Krishna
Sai Krishna is a Director of Engineering at TestMu AI. As an active contributor to Appium and a member of the Appium organization, he is deeply involved in the open-source community. He is passionate about innovative thinking and love to contribute to open-source technologies. Additionally, he is a blogger, community builder, mentor, international speaker, and conference organizer.
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance