Writing automated UI tests for your iOS and Android apps might not be as difficult as you think. Learn how to set up tests for your apps with Xamarin.UITest.

  • By Greg Shackles02/17/2015

Previously in this column, I’ve written about unit testing iOS apps, but what can you do when unit tests just won’t cut it? If you’re a Web developer you’re probably already familiar with libraries like Selenium, which allow you to drive automated testing of your Web app’s front-end.

Xamarin offers a library named Xamarin.UITest that enable the similar possibilities for your iOS and Android apps. In addition to being able to run those tests locally on an emulator or device, you can even push the same tests out to Xamarin’s Test Cloud, allowing you to validate your tests across more than a thousand different devices.

Setting Up Your Tests

Getting started is as easy as it gets. Start out by creating a normal .NET 4.5 class library, just like you would for any other test project, and then add the NuGet packages for NUnit and Xamarin.UITest. That’s everything you need for your test project! Android apps already have enough accessibility hooks in them out of the box to allow Xamarin.UITest to interact with them, but there’s one small thing you need to do in your iOS app to open up the required hooks. In your Xamarin.iOS app, install the Xamarin.TestCloud.Agent NuGet package. Once that is installed, add the following code to the app’s AppDelegate class:

#if DEBUG
Xamarin.Calabash.Start();
#endif

When this runs, a small HTTP server will be started inside the app using the open source library Calabash, which allows Xamarin.UITest to interact with the app. This is not something that should be left in builds of the app meant for release, which is why in this example I’ve surrounded the call with a #if DEBUG directive to make sure it’s only included in debug builds.

One of the great things about Xamarin.UITest is that if you set your tests up properly, you can share the exact same tests across both iOS and Android. The one part that needs to be slightly different is where you tell Xamarin.UITest which app to use for this test run. Each platform-specific setup object implements a common IApp interface that contains all the methods you’ll want to call in your tests. If tests are written against this interface instead of the platform classes they’ll be portable across both platforms.

One pattern I’ve found useful is to put test builds in known folder that my test fixture can scan and determine which app it is meant to use. That tends to end up looking something like this:

[TestFixture]
public class TipCalculationTests
{
   private IApp _app;

   [SetUp]
   public void SetUp()
   {
      switch (TestEnvironment.Platform)
      {
         case TestPlatform.Local:
            var appFile = 
               new DirectoryInfo("some/path/goes/here")
                  .GetFileSystemInfos()
                  .OrderByDescending(file => file.LastWriteTimeUtc)
                  .First(file => file.Name.EndsWith(".app") || file.Name.EndsWith(".apk"));

            _app = appFile.Name.EndsWith(".app")
               ? ConfigureApp.iOS.AppBundle(appFile.FullName).StartApp() as IApp
               : ConfigureApp.Android.ApkFile(appFile.FullName).StartApp();
            break;
         case TestPlatform.TestCloudiOS:
            _app = ConfigureApp.iOS.StartApp();
            break;
         case TestPlatform.TestCloudAndroid:
            _app = ConfigureApp.Android.StartApp();
            break;
      }
   }
}

For local runs it scans a known folder, chooses the latest file with an extension of .app or .apk, and initializes Xamarin.UITest with it. For TestCloud builds you don’t need to specify a file path since it will be provided automatically, so all that’s necessary is calling StartApp() and it’s good to go. There are more options that can be customized as well, such as specifying a specific device or emulator to run the tests on, but this is the basic set of methods to call to wire up a new test fixture.

#ios

Write Automated UI Tests for iOS and Android Apps
1.35 GEEK