Having problems with your account or logging in?
A lot of changes are happening in the community right now. Some may affect you. READ MORE HERE

Creating testable React Native apps

Micro Focus Expert
Micro Focus Expert
1 0 1,382

React Native provides users with the ability to build mobile apps using only Java Script. The apps built using this framework are indistinguishable from an app built using Objective-C or Java and uses the same fundamental building blocks as regular iOS and Android apps. When creating an app using React Native, the properties that are specified on the elements of the app can have different effects on how the application behaves for automation tools such as Silk Test. This blog will look at the impact of setting these properties and how we can leverage them to create testable apps.

Firstly, we can take a look at the source code for a simple React Native application below:

render(){
return(
     <View style={styles.container}>
          
<Text style={styles.welcome}>
               
Silk Test React Native Demo!
          
</Text>

          <Button title="Press Me" onPress={doSomething} color="#10c600" />
     
</View>
);
}

From this single piece of source code, React Native allows a user to build an app that will run on both Android and iOS:

Android iOS

We can also now use Silk Tests mobile automation capabilities to identify and inspect the React Native app on both Android and iOS. Using the Locator Spy, we can observe the differences in the attributes that are available for identification purposes for each platform. In the screenshots below, I have used Silk Test to identify the “Silk Test React Native Demo” label:

Android iOS

In the above images, we can see that there is some correlation in the attributes available on the Android and iOS platforms. Using the Silk Test Locator Spy we have been able to identify the label control using the caption attribute. However, the question remains if this is the best attribute to use for automation?

Let us consider that the app in question could be distributed in many locales, where the application text is localized. For example, the English text is substituted for German/Portuguese/French/etc equivalents. In this particular scenario, using the caption is likely not the ideal solution, as we may have the requirement to test the mobile app for various locales.

So, are any of the other attributes usable?

  • className
    • This attribute has different values for each platform.
    • May not be unique, as there could be multiple instances of this type of control displayed at any particular time.
  • content-desc
    • Android specific locator attribute.
    • Currently empty.
  • IsEnabled
    • This attribute is common to all mobile controls and will therefore not provide a unique way to identify a control of interest.
  • IsFocused
    • This attribute is common to all mobile controls and will therefore not provide a unique way to identify a control of interest.
  • IsSelected
    • This attribute is common to all mobile controls and will therefore not provide a unique way to identify a control of interest.
  • label
    • Appears to have the same limitations as the caption attribute.
  • package
    • Android specific locator attribute.
    • This attribute is common to all mobile controls and will therefore not provide a unique way to identify a control of interest.
  • resource-id
    • Android specific locator attribute.
    • This attribute is cannot be set by React Native and therefore not of use.
  • name
    • iOS specific locator attribute.
    • Appears to have the same limitations as the caption attribute.
  • Text
    • Appears to have the same limitations as the caption attribute.

After evaluating the available locator attributes, none currently appear to be ideal.

In a scenario such as this, the use of a unique identifier or automation identifier would be of great help. An automation identifier is a means by which a developer will assign a unique value to a UI element for the purposes of identifying that element during testing, it is generally a stable value and not prone to change. If we look at the React Native documentation for the Text element we find that it provides a testID property, the purpose of which is as follows:

Let us adjust our React Native app to set the testID property on the available UI elements and the impact this has on Silk Tests recognition of the label:

render(){
return(
     <View style={styles.container}>
          
<Text style={styles.welcome} testID="demoMsg">
               
Silk Test React Native Demo!
          
</Text>

          <Button title="Press Me" testID="pressMeBtn" onPress={doSomething} color="#10c600" />
     
</View>
);
}

Using the Silk Test Locator Spy we can now verify the effects of setting the testID property on the recognition of the label element:

Android iOS

In the above images we can see that setting the testID property has affected the recognition of the label element for the iOS app version, we can now identify this element uniquely using the name attribute. Therefore, if the text changes for any reason (such as localization) it will not impact the recognition of the element. Unfortunately there has been no recognition change for the Android version and we currently have to rely on the caption attribute.

If we look at the attribute available on Android version of the app, we can see that 2 attributes have no value. As discussed earlier, the resource-id attribute cannot be set by React Native which leaves the content-desc as the only attribute where an automation identifier could possibly be assigned. To set the content-desc attribute, we use the React Native accessibilityLabel property. Let us adjust the source code for our React Native application to supply the Android version of the app with automation identifiers and view the impact this has on Silk Tests recognition.

render(){
return(
     <View style={styles.container}>
          
<Text style={styles.welcome} testID="demoMsg" accessibilityLabel={'demoMsg'}>
               
Silk Test React Native Demo!
          
</Text>

          <Button title="Press Me" testID="pressMeBtn" accessibilityLabel={'pressMeBtn'onPress={doSomething} color="#10c600" />
     
</View>
);
}


Using the Silk Test Locator Spy we can now verify the effects of setting the accessibilityLabel property on the recognition of the label element:

Android iOS

In the above images we can now see that the label element for the Android and iOS versions of the app can now be identified using a unique automation identifier. However, by setting the accessibilityLabel property we have also introduced some undesired behaviour on iOS, as it appears that the accessibilityLabel value of 'demoMsg' has replaced the expected value of 'Silk Test React Native Demo!' for the caption, label and Text attributes. This is a problem as it affects Silk Tests ability to verify the actual display text of the label element. For example, consider the following Silk4J test to verify that the label has the correct display text on an iOS device:

@test
public void verifyLabelMessage() {
     MobileObject lbl = desktop.<MobileObject>find("/MobileDevice//MobileObject[@name='demoMsg' or @content-desc='demoMsg']");
     Assert.assertEquals("Silk Test React Native Demo!", lbl.getText());
}

Results in the following error:

Based on the above results we are left with the assumption that it may not be possible to assign automation identifiers to UI elements via React Native without affecting the automation capabilities or recognition on the Android and iOS platforms. React Native, however, understands that there may be scenario’s where a developer may have or want to provide platform specific code/values. One such method that React Native provides, is the Platform.select method.

Per the React Native documentation the Platform.select method, given an object containing Platform.OS as keys, returns the value for the platform you are currently running on.”.

Based on the behaviors that we have observed in setting the testID and accessibilityLabel React Native properties, we can determine that we should only supply an accessibilityLabel value should the platform be Android. This should therefore negate the impact this property has on the iOS platform. Let us implement this change in our React Native app and view the impact on both Silk Test recognition and the test we previously executed.

The React Native source now appears as follows:

render(){
return(
     <View style={styles.container}>
          
<Text style={styles.welcome} testID="demoMsg" accessibilityLabel={Platform.select({andoird:'demoMsg'})}>
               
Silk Test React Native Demo!
          
</Text>

          <Button title="Press Me" testID="pressMeBtn" accessibilityLabel={Platform.select({android:'pressMeBtn'})} onPress={doSomething} color="#10c600" />
     
</View>
);
}

Using the Silk Test Locator Spy we can now verify the effects of setting the accessibilityLabel property on the recognition of the label element:

Android iOS

We can see that the caption, label and Text locator attributes have been restored to their expected values on iOS, whilst on the Android platform, the automation identifiers have now been retained. If we now execute the “verifyLabelMessage” from earlier, the test now passes.

We now also have the ability to build cross platform compatible tests for React Native apps, where the locator attributes:

  • name; Will be used to identify elements on iOS
  • content-desc; Will be used to identify elements on Android

For example:

@test
public void xPlatformTest() {
     MobileDevice device = desktop.<MobileDevice>find("/MobileDevice");

     
//Verify the label has the correct display text
     
MobileObject lbl = device.<MobileObject>find("//MobileObject[@name='demoMsg' or @content-desc='demoMsg']");
     
Assert.assertEquals("Silk Test React Native Demo!", lbl.getText());

     //Click the Press Me button
     
MobileButton pressMeBtn = device.<MobileButton>find("//MobileButton[@name='pressMeBtn' or @content-desc='pressMeBtn']");
     
pressMeBtn.click();

     //Dismiss the mobile Alert
     device.<MobileButton>find("//MobileButton[@name='OK']").click();
}

About the Author
Silk Test Functional Testing Test Management Mobile Center TestPartner
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.