Xamarin.UITest
In this article I will tell you about Xamarin.UITest - a framework for acceptance UI testing from Xamarin.
Xamarin.UITest is based on Calabash and has a similar operating principle. However, tests on this framework are written in C # and NUnit (unlike Calabash, which uses Gherkin + Ruby). The framework is cross-platform and, therefore, it allows you to write tests for both the iOS platform and Android. Windows Phone is not supported, which I personally consider a drawback of this tool. But it fully supports testing of native applications in Java and Objective-C.

Of course, many of you can object, they say, for Java and Objective-C there are native frameworks that perfectly cope with the task assigned to them. But if you need to write acceptance UI tests simultaneously for two platforms, Xamarin.UITest will come in handy. Moreover, it has box support for the Xamarin Test Cloud . Testcloud itself is a very useful thing, but quite expensive.
The mechanism of operation on iOS and Android is different. On iOS, a Nuget package is built into the application that raises the http server inside your application. Here's how it works on iOS:

When working with Android, things are a little different. In fact, when building and running tests, two applications are installed on the device: yours and Test Cloud server. Both of them are signed with the same key, therefore Test Cloud server has the rights to manage your application. It looks like this:

Xamarin.UITest is built into the solution quite simply, in almost a couple of clicks. All you need is to create another project for UI tests.

After these simple steps, a project with an initialization template and installed packages is added. Then, in the iOS project, you need to add the Nuget package Xamarin Test Cloud Agent NuGet, and in AppDelegate we write the following lines:
If you use the Zamarin's IDE, then the integration process can be considered complete. For Visual studio you have to do everything manually, but here everything is quite simple. In addition to manipulating the iOS project, you need to add a PCL project and install the Nunit and Xamarin.UITest packages in it.
We will be interested in two classes: Tests and Appinitializer. Let's start with the second:
In addition to the path to the apk and ipa files specified in TODO, there are a number of parameters, for example, the identifier of the device on which the tests will be run, the api key for Xamarin Test Cloud, and others. The class itself defines the platform to run and starts the tests on the selected platform. Now let's look at the Tests class:
The method with the SetUp attribute will run our tests, passing the form to StartApp. Unfortunately, the “out-of-box” option will only work for a project on Xamarin.Forms. And on MVVM-Cross you can somehow get out like this:
Accordingly, you need to create the TestiOS and TestDroid targets.
Tests usually have a very standard Arrange-Act-Assert structurethe same Nunit, only in profile . You should start by creating a test containing the Repl method (read-eval-print-loop). It launches a console in which with the help of queries we can see the structure of the visible part of our application. This is done like this:
This method calls the REPL console. For clarity, I executed the tree command in it, which displays information on all visible elements:

And the application itself looks like this:

In order to interact with controls, we need to use the IApp interface methods. In this article, we will consider only three of them: Tap (), WaitForElement () and Query (). Although they are much larger, and a complete list with all the properties can be found here .
First, we need to get the identifiers of elements of type AppQuery. This is done like this:
So, we got AppQuery for all elements and now we can interact with them. Let's validate the start message, tap on the button and validate the received message.
As you can see from the example, IApp methods (the instance in this case is app) take data of type AppQuery as input parameters and return a result of type AppResult []. In this case, Linq expressions are applicable only to AppResult [], and therefore the assertions look as follows. And AppResult [] itself looks like this:

In this example, when running locally, tests can run in parallel on both platforms, and all the results will be poured into one console (which, IMHO, is not very convenient). In addition, you can integrate the Zamarin Marine TestCloud service in a couple of clicks and run tests in the cloud. The tests are launched from the unit test panel, which is quite convenient.
In addition to the agent, to run tests in TestCloud, you need to add an api key (I did not add it in this sample). How to get it and apply it is described in detail here .
On this, perhaps, it is worth completing our brief excursion to Xamarin.UITest. I hope my review was useful to you. Thank you all for your attention.
Link to the sample used in the article.
Useful links on the topic:
developer.xamarin.com/api/namespace/Xamarin.UITest
developer.xamarin.com/guides/testcloud/uitest/intro-to-uitest
www.nunit.org/index.php?p=quickStart&r=2.6.3
msdn.microsoft .com / ru-ru / library / bb397926.aspx
What is it and how to cook it
Xamarin.UITest is based on Calabash and has a similar operating principle. However, tests on this framework are written in C # and NUnit (unlike Calabash, which uses Gherkin + Ruby). The framework is cross-platform and, therefore, it allows you to write tests for both the iOS platform and Android. Windows Phone is not supported, which I personally consider a drawback of this tool. But it fully supports testing of native applications in Java and Objective-C.

Why Xamarin.UITest?
Of course, many of you can object, they say, for Java and Objective-C there are native frameworks that perfectly cope with the task assigned to them. But if you need to write acceptance UI tests simultaneously for two platforms, Xamarin.UITest will come in handy. Moreover, it has box support for the Xamarin Test Cloud . Testcloud itself is a very useful thing, but quite expensive.
Learn more about how it works.
The mechanism of operation on iOS and Android is different. On iOS, a Nuget package is built into the application that raises the http server inside your application. Here's how it works on iOS:

When working with Android, things are a little different. In fact, when building and running tests, two applications are installed on the device: yours and Test Cloud server. Both of them are signed with the same key, therefore Test Cloud server has the rights to manage your application. It looks like this:

Xamarin.UITest is built into the solution quite simply, in almost a couple of clicks. All you need is to create another project for UI tests.

After these simple steps, a project with an initialization template and installed packages is added. Then, in the iOS project, you need to add the Nuget package Xamarin Test Cloud Agent NuGet, and in AppDelegate we write the following lines:
#if DEBUG
Xamarin.Calabash.Start();
#endif
return true;
If you use the Zamarin's IDE, then the integration process can be considered complete. For Visual studio you have to do everything manually, but here everything is quite simple. In addition to manipulating the iOS project, you need to add a PCL project and install the Nunit and Xamarin.UITest packages in it.
Now let's talk about configuring our tests.
We will be interested in two classes: Tests and Appinitializer. Let's start with the second:
public class AppInitializer
{
public static IApp StartApp (Platform platform)
{
// TODO: If the iOS or Android app being tested is included in the solution
// then open the Unit Tests window, right click Test Apps, select Add App Project
// and select the app projects that should be tested.
if (platform == Platform.Android) {
return ConfigureApp
.Android
// TODO: Update this path to point to your Android app and uncomment the
// code if the app is not included in the solution.
//.ApkFile ("../../../Droid/bin/Debug/xamarinforms.apk")
.StartApp ();
}
return ConfigureApp
.iOS
// TODO: Update this path to point to your iOS app and uncomment the
// code if the app is not included in the solution.
//.AppBundle ("../../../iOS/bin/iPhoneSimulator/Debug/XamarinForms.iOS.app")
.StartApp ();
}
}
In addition to the path to the apk and ipa files specified in TODO, there are a number of parameters, for example, the identifier of the device on which the tests will be run, the api key for Xamarin Test Cloud, and others. The class itself defines the platform to run and starts the tests on the selected platform. Now let's look at the Tests class:
public class Tests
{
IApp app;
Platform platform;
public Tests(Platform platform)
{
this.platform = platform;
}
[SetUp]
public void BeforeEachTest()
{
app = AppInitializer.StartApp(platform);
}
[Test]
public void AppLaunches()
{
app.Repl();
}
}
The method with the SetUp attribute will run our tests, passing the form to StartApp. Unfortunately, the “out-of-box” option will only work for a project on Xamarin.Forms. And on MVVM-Cross you can somehow get out like this:
public void SetUp ()
{
#if TestiOS
Path = "path/to/app";
_app = ConfigureApp.iOS
.AppBundle(Path)
//Xcode ->Window ->Devices -> Identifier
.DeviceIdentifier("Identifier")
.StartApp();
#else
Path = "path/to/apk";
_app = ConfigureApp
.Android
.ApkFile (Path)
//.EnableLocalScreenshots ()
.StartApp ();
#endif
}
Accordingly, you need to create the TestiOS and TestDroid targets.
Well ... configured, launched, it's time to start writing tests!
Tests usually have a very standard Arrange-Act-Assert structure
[Test]
public void AppLaunches()
{
app.Repl();
}
This method calls the REPL console. For clarity, I executed the tree command in it, which displays information on all visible elements:

And the application itself looks like this:

In order to interact with controls, we need to use the IApp interface methods. In this article, we will consider only three of them: Tap (), WaitForElement () and Query (). Although they are much larger, and a complete list with all the properties can be found here .
First, we need to get the identifiers of elements of type AppQuery. This is done like this:
static readonly Func InitialMessage = c => c.Marked("MyLabel").Text("Hello, Habrahabr!");
static readonly Func Button = c => c.Marked("MyButton");
static readonly Func DoneMessage = c => c.Marked("MyLabel").Text("Was clicked");
So, we got AppQuery for all elements and now we can interact with them. Let's validate the start message, tap on the button and validate the received message.
[Test]
public void AppLaunches()
{
app.Repl();
// Arrange - Nothing to do because the queries have already been initialized.
AppResult[] result = app.Query(InitialMessage);
Assert.IsTrue(result.Any(), "The initial message string isn't correct - maybe the app wasn't re-started?");
// Act
app.Tap(Button);
app.WaitForElement (DoneMessage, "Timeout", TimeSpan.FromSeconds (2));
// Assert
result = app.Query(DoneMessage);
Assert.IsTrue(result.Any (), "The 'clicked' message is not being displayed.");
}
As you can see from the example, IApp methods (the instance in this case is app) take data of type AppQuery as input parameters and return a result of type AppResult []. In this case, Linq expressions are applicable only to AppResult [], and therefore the assertions look as follows. And AppResult [] itself looks like this:

In this example, when running locally, tests can run in parallel on both platforms, and all the results will be poured into one console (which, IMHO, is not very convenient). In addition, you can integrate the Zamarin Marine TestCloud service in a couple of clicks and run tests in the cloud. The tests are launched from the unit test panel, which is quite convenient.
In addition to the agent, to run tests in TestCloud, you need to add an api key (I did not add it in this sample). How to get it and apply it is described in detail here .
On this, perhaps, it is worth completing our brief excursion to Xamarin.UITest. I hope my review was useful to you. Thank you all for your attention.
Link to the sample used in the article.
Useful links on the topic:
developer.xamarin.com/api/namespace/Xamarin.UITest
developer.xamarin.com/guides/testcloud/uitest/intro-to-uitest
www.nunit.org/index.php?p=quickStart&r=2.6.3
msdn.microsoft .com / ru-ru / library / bb397926.aspx