Setting Up App State for Efficient Functional Testing with Appium

Functional testing is crucial for ensuring the quality of mobile applications, but it comes with a ๐ฌ๐ฉ๐ž๐ž๐ ๐ฅ๐ข๐ฆ๐ข๐ญ due to the time required for taps, keystrokes, loading data from the network, and animations. While these delays ensure high-fidelity testing, simulating real-life scenarios as closely as possible, they can become a bottleneck when multiple tests require the same initial setup, such as logging in.

Lana Begunova
Women in Technology
5 min readMay 22, 2024

--

The Problem: Redundant App State Setup

High-fidelity testing becomes inefficient when many tests rely on the same starting point. For instance, logging into an app might involve filling out several text boxes, tapping buttons, and waiting for network verification. This process can take 20 to 25 seconds. For a suite of 50 tests, each requiring a login, this adds up to approximately 20 minutes of wasted time. Moreover, repeating this setup increases the risk of flaky tests.

State Setup: FAST vs SLOW

The main objective of testing is to make assertions about app behavior. To do this, we need to interact with the app via the UI, such as filling in a text field and tapping a button. However, these interactions often require a proper setup of the application state. For instance, if weโ€™re testing an e-commerce app, our assertion might involve the quantity of items in the shopping cart. To make this assertion, we need to add an item to the cart, which is an essential part of the test.

State vs Assertion

However, setting up the state often involves preliminary steps unrelated to the core functionality being tested, like creating a user account and logging in. This requirement introduces two main issues:

1. ๐˜Œ๐˜ฏ๐˜ด๐˜ถ๐˜ณ๐˜ช๐˜ฏ๐˜จ ๐˜ต๐˜ฉ๐˜ฆ ๐˜š๐˜ต๐˜ข๐˜ต๐˜ฆ ๐˜๐˜ด ๐˜™๐˜ฆ๐˜ข๐˜ฅ๐˜บ: We must ensure no interactions occur before the state is fully set up, or our assertions will likely fail. This involves using explicit waits to ensure the app is ready for interaction.

Explicit Wait

2. ๐˜›๐˜ช๐˜ฎ๐˜ฆ-๐˜Š๐˜ฐ๐˜ฏ๐˜ด๐˜ถ๐˜ฎ๐˜ช๐˜ฏ๐˜จ ๐˜š๐˜ฆ๐˜ต๐˜ถ๐˜ฑ: Setting up application state through the UI can be slow. While the actual test steps might take seconds, preparing the app state can take minutes, wasting time and increasing unreliability. This issue compounds when multiple tests require the same setup, leading to significant inefficiency.

Quick & Reliable Setup

While it might not be possible to speed up the login steps using Appium directly, there are strategies to bypass these repetitive setups and start tests in the desired state. To address these challenges, we need strategies to quickly and reliably set up the app state, ensuring efficient and effective testing.

Five Strategies to Set Up App State Instantly

Here are five techniques to help you set up your app state efficiently, minimizing repetitive tasks and enhancing test reliability.

1. Custom Android Activities (Android)

Android apps can use Activities to represent different parts of the application. You can design an Activity to set up the desired state.

https://github.com/appium/appium-uiautomator2-driver?tab=readme-ov-file#mobile-startactivity

Using Appiumโ€™s native mobile startActivity command, we can launch an Activity directly:

driver.execute_script("mobile: startActivity",
{"component": f"{package_id}/{activity_name}"})

We can also use the appPackage and appActivity capabilities to start the session in the specified Activity. Remember to remove any test-specific activities from the production build.

https://medium.com/@begunova/android-activity-management-with-appium-powerful-shortcut-to-mobile-automation-5252222621f9

2. Custom Launch Arguments (iOS)

For iOS apps, which lack Activities, you can use launch arguments โ€” command-line flags read by the running application. These flags can include data like usernames and passwords for an initial UI-less login, accessed via the processArguments capability in Appium:

{
"processArguments": "-view login -viewparams 'your_username,your_password'"
}
https://github.com/appium/python-client/blob/fa7e6d44e13ea586bcbe73a1ba4464b97516ff51/appium/options/ios/xcuitest/wda/process_arguments_option.py#L25

The app developer must configure the app to recognize and handle these flags and ensure the production build ignores them.

3. Test Nexus

The Test Nexus, a.k.a. Kitchen Sink, technique involves creating a special view in your app, available only in the test build, with links to various states. For example, links like Logged-in Home or Cart With 1 Item can take the app to the respective state. This approach is cross-platform and straightforward, saving time by bypassing repetitive setup steps.

https://medium.com/@begunova/test-nexus-kitchen-sink-for-fast-and-reliable-mobile-app-testing-ad5f830aa776

4. Deep Links

Deep Links are commonly used in marketing campaigns to direct users to specific pages within an app, provided the app is already installed on their device. In test automation, we can leverage this technique to save significant time on setup steps by directly navigating to the desired page.

Deep linking uses OS-level features where custom scheme URLs direct the app to a specific state. For example:

your_app://test/login/:username/:password

Clicking this URL or using Appiumโ€™s driver.get() command can launch the app in the desired state:

driver.get("your_app://test/login/your_username/your_password");

This method requires the app to have a custom scheme registered and a URL controller to parse and navigate accordingly.

5. Application Backdoors

This technique involves exposing internal methods of the application for testing purposes. These methods, accessible via a custom RPC channel, can set up the necessary state. With Appiumโ€™s Espresso Driver, we can interact with appโ€™s internal methods from within the automation context.

https://medium.com/@begunova/appium-backdoors-testing-technique-with-espresso-driver-238b4f16d22c

Conclusion

Implementing these techniques can significantly reduce the time and potential flakiness of your tests by eliminating redundant state setups. Collaboration with your development team to create these mechanisms will yield quicker and more reliable builds. Despite the initial effort, the long-term benefits for testing efficiency and application stability are substantial.

By optimizing the state setup process, you ensure that your functional tests are both high-fidelity and time-efficient, ultimately contributing to a smoother and more reliable testing workflow.

๐“—๐’ถ๐“…๐“…๐“Ž ๐“‰๐“ฎ๐“ˆ๐“‰๐’พ๐“ƒ๐“ฐ ๐’ถ๐“ƒ๐’น ๐’น๐“ฎ๐’ท๐“Š๐“ฐ๐“ฐ๐’พ๐“ƒ๐“ฐ!

I welcome any comments and contributions to the subject. Connect with me on LinkedIn, X , GitHub, or Insta. Check out my website.

If you find this post useful, please consider buying me a coffee.

--

--

Lana Begunova
Women in Technology

I am a QA Automation Engineer passionate about discovering new technologies and learning from it. The processes that connect people and tech spark my curiosity.