Xamarin UI Test – Testing State Management

State management, ensuring that an suspended app restarts to the same place, is one of the more challenging areas of mobile development. It’s a good idea to make sure it’s covered by your automated tests. Here’s how I managed this with Xamarin UITest…

The source code for this post is available here.

1 – Setup Tests to Run in Order

My example uses two tests, one to set the data up and one to make sure the same data is present in the restored app. The Order attribute in nunit ensures they run sequentially.

[Test, Order(1)]
public void StateTest()
{
    app = AppInitializer.StartApp(platform);
    app.Tap("Button");
    app.Tap("Button");
    app.EnterText("Text", "Some text");

    SaveAppState();
}

[Test, Order(2)]
public void StateTest2()
{
    app = AppInitializer.StartApp(platform, true);
    app.WaitForElement("Clicked 2 Times");
    app.WaitForElement(x => x.Marked("Text").Text("Some text"));
}

2 – Preserve Local Data Between Tests

In regular tests any local data will be wiped before the app is run, but here it needs to be preserved. A parameter added to the AppInitialiser controls this. This means that the local data from the first test is still in place for the second test.

public static IApp StartApp(Platform platform, bool preseveData = false)
{
    var dataMode = preseveData ? AppDataMode.DoNotClear : AppDataMode.Clear;

    if (platform == Platform.Android)
    {
        return ConfigureApp.Android
            .StartApp(dataMode);
    }
    else
    {
        return ConfigureApp.iOS
           .StartApp(dataMode);
    }
}

The documentation says that the AppDataMode attribute is only supported in test cloud, but I found it works with local tests as well.

3 – Suspend the App Programatically

When the app is stopped and restarted between tests it doesn’t get a chance to save state. To get round this the first test suspends the app programmatically. This is done via backdoor methods for each platform.

Here’s a way to suspend on iOS:

[Export("SuspendApp:")]
public void SuspendApp(NSString value)
{
    UIApplication.SharedApplication.PerformSelector(new ObjCRuntime.Selector("suspend"), null, 2.0);
}

Here’s a way to ‘suspend’ on Android (note this just triggers App.OnSleep, it doesn’t really suspend the app):

[Export("SuspendApp")]
public void SuspendApp()
{
    OnPause();
    OnStop();
}

Run the Tests!

With everything in place the last thing to do is run the tests – here’s how it looks on my machine 🙂

Advertisements
Xamarin UI Test – Testing State Management

4 thoughts on “Xamarin UI Test – Testing State Management

  1. I can see that you are using OrderAttribute from NUnit. But this class is only available in NUnit 3.x. Do you able to make Xamarin.UITest work with NUnit 3.x? As the xamarin documentation stated Xamarin.UITest is not compatible with NUnit 3.x.

    Like

    1. martynnw says:

      I’ve been running locally on my mac which works with NUnit 3.x.

      To get it working without the Order attribute you can just merge the two tests into one – calling StartApp a second time. Actually I think I like this way better!

      Like

    2. martynnw says:
      [Test]
      public void StateTest()
      {
          app = AppInitializer.StartApp(platform);
      
          // Set values
          app.Tap("Button");
          app.Tap("Button");
          app.EnterText("Text", "Some text");
      
          SaveAppState();
      
          // Restart the app
          app = AppInitializer.StartApp(platform, true);
      
          // Verify vlues
          app.WaitForElement("Clicked 2 Times");
          app.WaitForElement(x => x.Marked("Text").Text("Some text"));
      }
      

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s