Freelancing for Pale Blue

Looking for flexible work opportunities that fit your schedule?


How to clear the state of the app in Maestro tests (iOS)

iOS Jul 19, 2024

While UI testing may seem straightforward at first glance, it can quickly become complex, especially when dealing with various app states. One of the main challenges is preparing the app for different test scenarios.

The Issue with Clear State

Many developers resort to using -clearState, but this approach has limitations. It not only removes essential properties that indicate the app's current state (such as showOnboarding or askUserForRating) but can also be unreliable. As a result, we must account for numerous scenarios in our UI tests. This method may work for small, simple apps, but it becomes unmanageable as the application grows in complexity.

A More Effective Solution

To address this problem, we can leverage the launchArguments property. By passing a flag to the app, we can indicate that it's running in UI test mode. This approach allows us to:

  1. Maintain better control over the app's state during testing
  2. Avoid clearing crucial state indicators
  3. Improve test reliability and maintainability

Implementing this solution involves catching the launch argument in the app's initialization process, enabling us to set up the desired state for each test scenario more effectively.

Implementing the Launch Arguments Solution

To address the state management issue in UI testing, we utilize the launchArguments property. This allows us to pass a flag to the app, indicating that it's running in UI test mode. We can intercept this flag in the app's launch cycle, specifically in the application(_:didFinishLaunchingWithOptions:) method.

In the YAML File: We define the launch arguments for our UI tests. This configuration tells the testing framework to launch the app with a specific flag:

appId: com.example.staging
---
- launchApp:
    appId: com.example.staging
    arguments: 
        isUITestRunning: true

In the App's AppDelegate: We then handle this flag in our app's launch cycle. The app checks for the presence of the isUITestRunning argument and resets the state accordingly:

func application(
    _ application: UIApplication, didFinishLaunchingWithOptions
    launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    resetStateIfUITestIsRunning()
    return true
}

private func isUITestRunning() {
    if ProcessInfo.processInfo.arguments.contains("isUITestRunning") {
        // Set or delete your settings here
    }
}

And that's it.

Happy coding!

Tags

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.