Android Quickstart for Xamarin.UITest

PDF for offline use
Related APIs:
Related Links:

Let us know how you feel about this

Translation Quality


0/250

last updated: 2016-12

Overview

In this quick start we'll add a UITest to an Android application and run the test locally and in Xamarin Test Cloud. The test will confirm that the application will display the correct error message when the user enters a credit card number that is too short. Conceptually, the test will be compromised of the following steps:

  1. Wait for the Activity to load – Typically an Activity is quick to load, but to be safe the test should wait for the Activity to load, rather than blindly assuming.
  2. Enter 15 digits for the credit card number – The test must simulate data entry.
  3. Tap the Validate Credit Card button – Simulate what a user would do to call the validation logic.
  4. Confirm the Error Message – Finally, the test should assert the application has displayed the correct error message.

For each of these steps, we will use the UITest REPL to create queries for each step and to test out the UITest APIs involved.

To save time, download the ZIP file that contains the sample application.

Open the solution in Xamarin Studio. Notice that this solution contains the Xamarin.Android project and the default Xamarin.UITest project from the Xamarin template for UITest projects. There are no tests in the UITest project, one will be added as we go through this Quickstart. If necessary, go ahead and update the Xamarin Test Cloud Agent NuGet and the Xamarin.UITest packages to the most recent versions.

Xamarin.UITest requires NUnit 2.6.x, so do not update NUnit to NUnit 3.0 or higher. Xamarin.UITest and Xamarin Studio are not compatible with NUnit 3.x.

Finally, run the Xamarin.Android app to confirm that the application builds and runs in your development environment.

Open the solution in Visual Studio. Notice that this solution contains the Xamarin.Android project and the default Xamarin.UITest project from the Xamarin template for UITest projects. There are no tests in the UITest project, one will be added as we go through this Quickstart. If necessary, go ahead and update the Xamarin Test Cloud Agent NuGet and the Xamarin.UITest packages to the most recent versions.

Xamarin.UITest requires NUnit 2.6.x, so do not update NUnit to NUnit 3.0 or higher. Xamarin.UITest and Xamarin Studio are not compatible with NUnit 3.x.

Finally, run the Xamarin.Android app to confirm that the application builds and runs in your development environment.

Also, recall that Android applications must request the INTERNET permission in order to communicate with the test server APK. This permission has been added to the project for you.

Run the application to confirm that the application builds and runs in your development environment.

Creating the First Test

Before we get started, open the file Tests.cs in the UITest project, and delete the first test case, ClickingButtonTwiceShouldChangeItsLabel that was created by the UITest template.

Then edit the file Test.cs and add a stub for the first test, as shown in the following code snippet:

[Test]
public void CreditCardNumber_TooShort_DisplayErrorMessage()
{
    // Invoke the REPL so that we can explore the user interface
    app.Repl();
}

Initially, all we are doing in this test is invoking the REPL so that we can explore the user interface and gather some information on the views that are displayed on screen. To start the REPL, we will have to run the test.

Select View > Pads > Unit Tests to display the Unit Tests pad. Ensure that you have a device connected or an emulator started, and run the first test by right clicking on the CreditCardValidator.Droid.UITests node in the Unit Tests pane and selecting Run Test:

Xamarin Studio should compile the APK and run it on the selected device or emulator. The UITest REPL window should appear. Type the tree command in the REPL to see a hierarchical list of the views on the screen:

Ensure that you have a device connected or an emulator running. Select TEST > Run > All Tests to run the tests.

Visual Studio should compile the APK and run it on the selected device. The UITest REPL window should appear. Type tree command in the REPL to see a heirarchical list of the views on the screen:

The results of the tree can be seen below:

>>> tree                                                                                                                
[[object CalabashRootView] > PhoneWindow$DecorView]                                                                     
  [ActionBarOverlayLayout] id: "decor_content_parent"
    [FrameLayout > LinearLayout] id: "content"
      [EditText] id: "creditCardNumberText"
      [Button] id: "validateButton" text: "Validate Credit Card"
      [TextView] id: "errorMessagesText"
    [ActionBarContainer] id: "action_bar_container"
      [ActionBarView > LinearLayout] id: "action_bar"
        [ActionBarView$HomeView]
          [ImageView] id: "home"
        [LinearLayout]
          [TextView] id: "action_bar_title" text: "Enter Credit Card Number"

We will use the information about the views as we complete each step in the test.

Waiting for the Screen to Load

We can tell if the Activity has loaded by checking for the text Enter Credit Card Number< in the Action Bar. We will use the following API's to perform this check:

  • IApp.WaitForElement – This will cause a test to pause until the specified query is satisified, i.e. returns some results. If the query is not satisified within the time limit, an exception will be thrown.
  • AppQuery.Marked – On Android, this method will find any view that matches the provided text by examining the id, contentDescription, or text property of the view.
  • AppQuery.Text – The AppQuery.Text method can be used as filter to check a string displayed by a particular view.

We will test out the API calls and queries in the REPL before adding them to a test. To help identify UI elements on the screen, UITest provides the IApp.Flash method which will cause a view to blink on the screen. Lets see how to use Flash and the REPL to create our test.

If we examine our tree output, we can see that there is a TextView with the ID action_bar_title. We want to create a query that locate this TextView based on the text it is displaying.

Look at the following snippet, where the Flash command is issued with a query. You can see that UITest managed to find the TextView and return some results from that query:

>>> app.Flash(c=>c.Marked("action_bar_title").Text("Enter Credit Card Number"))                                         
Flashing query for Marked("action_bar_title").Text("Enter Credit Card Number") gave 1 results.                          [                                                                                                                           [0] {                                                                                                                       Id => "action_bar_title",                                                                                               Description => "android.widget.TextView{56d9e56 V.ED..... ........ 0,0-613,73 #10202e8 android:id/action_bar_title}",                                                                                                                           Rect => {                                                                                                      
            Width => 613,
            Height => 73,
            X => 145,
            Y => 107,
            CenterX => 451,
            CenterY => 143
        },
        Label => null,
        Text => "Enter Credit Card Number",
        Class => "android.widget.TextView",
        Enabled => true
    }
]

You should see the TextView in the title bar flash briefly. We will use this query in our test to wait for the Activity to load. Edit the test so that it contains the code in the following snippet:

[Test]
public void CreditCardNumber_TooShort_DisplayErrorMessage()
{
    app.WaitForElement(c => c.Marked("action_bar_title").Text("Enter Credit Card Number"));
}

Enter the Credit Card Number

The IApp.EnterText method will simulate text entry. We will use that along with a new UITest query to reference the Credit Card Number< field.

If we examine the tree output, we can see that there is a EditText with the ID creditCardNumberText. Lets validate the next step of our test in the REPL window by typing in this snippet:

app.EnterText(c => c.Marked("creditCardNumberText"), new string('9', 15));

The following screenshot shows the contents of the REPL window and the Android application - notice how the EditText was populated with the string "999999999999999":

The following screenshot shows the contents of the REPL window:

Now that we know this step works, update the test method so that it resembles this snippet of code

[Test]
public void CreditCardNumber_TooShort_DisplayErrorMessage()
{
    app.WaitForElement(c => c.Marked("action_bar_title").Text("Enter Credit Card Number"));

    app.EnterText(c => c.Marked("creditCardNumberText"), new string('9', 15));
}

Our test will now wait for the Activity to load, and then enter a credit card number, just like a human user would do.

Tap the Button

Next we need to simulate the user tapping the Validate Credit Card< button using IApp.Tap.

If we look at the tree output above, we can see that the ID of this button is validateButton. Enter the following text in the REPL:

app.Tap(c=>c.Marked("validateButton"));

Observe how UITest simulates a tap on the button for us, triggering the validation logic.

Update the test method so that it resembles the following:

[Test]
public void CreditCardNumber_TooShort_DisplayErrorMessage()
{
    app.WaitForElement(c => c.Marked("action_bar_title").Text("Enter Credit Card Number"));
    app.EnterText(c => c.Marked("creditCardNumberText"), new string('9', 15));

    app.Tap(c=>c.Marked("validateButton"));
}

Verify the Error Message

The final step of the test is to verify that the correct error message is displayed to the user. We will use the IApp.WaitForElement method for this:

app.WaitForElement(c => c.Marked("errorMessagesText").Text("Credit card number is too short."));

Add this line to the test. The completed test should resemble the following:

[Test]
public void CreditCardNumber_TooShort_DisplayErrorMessage()
{
    app.WaitForElement(c => c.Marked("action_bar_title").Text("Enter Credit Card Number"));
    app.EnterText(c=>c.Marked("creditCardNumberText"), new string('9', 15));
    app.Tap(c => c.Marked("validateButton"));

    app.WaitForElement(c => c.Marked("errorMessagesText").Text("Credit card number is too short."));
}

Run the Test

Now that the code for the test is complete, let's run the test in Xamarin Studio. You should the see the test automating the user interface and run to successful completion. Ensure that you only have one instance of an emulator running or one device attached to your computer.

Next, submit the test to Xamarin Test Cloud:

  • Change the build configuration to Release.

  • Right click on the CreditCardValidator.Droid.UITests< project in the Unit Tests< pad and selecting Run in Test Cloud<.

Xamarin Studio will build your APK, upload it and the tests to Xamarin Test Cloud. Use the web interface to specify the team, select the devices, and provide some meta-data on how the test will run. Please see the Submitting UITests to Xamarin Test Cloud for more details.

Now that the code for the test is complete, let's run the test in Visual Studio. You should the see the test automating the user interface and run to successful completion. Ensure that you only have one instance of an emulator running or one device attached to your computer.

Next, submit the test to Xamarin Test Cloud:

  • Change the build configuration to Release.

    • Right click on the CreditCardValidator.Droid.UITests< project in the Unit Tests< pad and selecting Run in Test Cloud.

Visual Studio will build your APK, upload it and the tests to Xamarin Test Cloud. Use the web interface to specify the team, select the devices, and provide some meta-data on how the test will run. Please see the guide Submitting UITests to Xamarin Test Cloud for more details.

Running Android 6.0 Applications from the IDE

When the IDE installs an Android 6.0 app for the first time, it does not grant all permissions required by the application. The workaround for this is to use UITest to install and start the application:

ConfigureApp.Android.Debug().ApkFile(apkpath).StartApp ()

Do use ApkFile() and do not use PreferIdeSettings(). This will force UITest to install instead of the IDE.

Summary

At this point you have finished this quick start. For practice, why not try to write a UITest for when a user enters a valid credit card number?

Xamarin Workbook

If it's not already installed, install the Xamarin Workbooks app first. The workbook file should download automatically, but if it doesn't, just click to start the workbook download manually.