Xamarin.UITest

Importante

Visual Studio App Center está programado para la retirada el 31 de marzo de 2025. Aunque puede seguir usando Visual Studio App Center hasta que se retire por completo, hay varias alternativas recomendadas a las que puede considerar la posibilidad de migrar.

Obtenga más información sobre las escalas de tiempo de soporte técnico y las alternativas.

Xamarin.UITest es un marco de pruebas de C# mediante NUnit para pruebas de aceptación de iu en aplicaciones iOS y Android. Se integra estrechamente con proyectos de Xamarin.iOS y Xamarin.Android, pero también se puede usar con proyectos nativos de iOS y Android. Xamarin.UITest es la biblioteca de automatización que permite que las pruebas de NUnit se ejecuten en dispositivos Android e iOS. Las pruebas interactúan con la interfaz de usuario como haría un usuario: escribir texto, pulsar botones y gestos, como deslizar el dedo.

Normalmente, cada Xamarin.UITest se escribe como un método denominado [Test]. La clase que contiene la prueba se conoce como [TestFixture]. El accesorio de prueba contiene una sola prueba o un grupo de pruebas. El accesorio también es responsable de la instalación para hacer que la prueba se ejecute y limpie que debe realizarse cuando finalice la prueba. Cada prueba debe seguir el patrón Arrange-Act-Assert :

  1. Organizar: la prueba configurará las condiciones e inicializará las cosas para que se pueda realizar la prueba.
  2. Acto: la prueba interactuará con la aplicación, escribirá texto, pulsar botones, etc.
  3. Aserción: la prueba examina los resultados de las acciones ejecutadas en el paso Act para determinar la corrección. Por ejemplo, la aplicación puede comprobar que se muestra un mensaje de error determinado.

El mejor momento para empezar a trabajar con Xamarin.UITest es durante el desarrollo de una aplicación móvil. Las pruebas automatizadas se escriben como una característica que se está desarrollando según los pasos descritos en la lista siguiente:

  1. Desarrolle la característica en la aplicación Android o iOS.
  2. Escriba las pruebas y ejecútelas localmente para comprobar la funcionalidad.
  3. Cree una nueva ejecución de pruebas en App Center Test o use una serie de pruebas existente.
  4. Compile el IPA o el APK y cárguelo junto con las pruebas en App Center Test.
  5. Corrija los problemas o errores expuestos por La prueba de App Center.
  6. Repita el proceso pasando a la siguiente característica de la aplicación.

En el caso de las aplicaciones existentes que ya no están en desarrollo activo, puede que no sea rentable agregar pruebas automatizadas de forma retroactiva. En su lugar, un mejor enfoque es usar Xamarin.UITest al corregir errores. Por ejemplo, considere una aplicación que no tiene pruebas automatizadas y un usuario notifica un error. Un desarrollador asignado para corregir ese error podría realizar algunas (o todas) de las siguientes acciones:

  • Compruebe el error o la regresión manualmente.
  • Escriba una prueba mediante Xamarin.UITest que muestre el error.
  • Envíe la prueba a la prueba de App Center para obtener información sobre el ámbito y el impacto del error en los dispositivos pertinentes.
  • Se corrige el error.
  • Compruebe que el error se ha corregido con un paso de Xamarin.UITest.
  • Envíe las correcciones y la prueba a App Center Test para comprobar que el error se ha corregido en los dispositivos pertinentes.
  • Compruebe el paso de pruebas al control de versiones.

Las pruebas automatizadas de iu se basan en gran medida en la localización e interacción con vistas en la pantalla. Xamarin.UITest aborda este requisito con dos conjuntos importantes de API que funcionan entre sí:

  1. Acciones que se pueden realizar en vistas: Xamarin.UITest proporciona API que permiten a una prueba simular acciones comunes del usuario, como pulsar en la vista, escribir texto o deslizar el dedo en la vista.
  2. Consultas para buscar vistas en la pantalla: parte del marco Xamarin.UITest son API que ubicarán las vistas en una pantalla. Las consultas localizan vistas en tiempo de ejecución inspeccionando los atributos de la vista y devolviendo un objeto en el que las acciones pueden funcionar. La consulta de tal manera es una técnica eficaz que permite escribir pruebas para interfaces de usuario, independientemente del tamaño, la orientación o el diseño de la pantalla.

Para ayudar con la escritura de pruebas, Xamarin.UITest proporciona un bucle read-eval-print-loop (REPL). RePL permite a los desarrolladores y evaluadores interactuar con una pantalla mientras se ejecuta la aplicación y simplifica la creación de las consultas.

Introducción a la API de Xamarin.UITest

Todas las interacciones de prueba con la aplicación móvil se producen a través de una instancia de Xamarin.UITest.IApp. Esta interfaz define los métodos cruciales para que la prueba colabore con la aplicación e interactúe con la interfaz de usuario. Hay dos implementaciones concretas de esta interfaz:

  • Xamarin.UITest.iOS.iOSApp Esta clase automatizará las pruebas en iOS.
  • Xamarin.UITest.Android.AndroidApp Esta clase es para automatizar pruebas en Android.

iOSApp y AndroidApp los objetos no se crean instancias directamente. En su lugar, se crean con la clase auxiliar ConfigureApp . Esta clase es un generador que garantiza que se iOSApp cree una instancia correcta de o AndroidApp .

Se recomienda usar una nueva IApp instancia para cada prueba. Una nueva instancia impide que el estado se desborde una prueba en otra. Hay dos lugares donde una prueba de NUnit podría inicializar una instancia de IApp:

  • En el SetUp método Normalmente, un accesorio de prueba es una agrupación lógica de pruebas relacionadas, cada una de ellas que se ejecuta independientemente de la otra. En este escenario, IApp se debe inicializar en el SetUp método , asegurándose de que hay un nuevo IApp disponible para cada prueba.
  • En el TestFixtureSetup método En algunas situaciones, una sola prueba puede requerir su propio accesorio de prueba. En este caso, puede tener más sentido inicializar el IApp objeto una vez en el TestFixtureSetup método .

Una vez IApp configurado, una prueba puede empezar a interactuar con la aplicación que se está probando. Para ello, es necesario obtener referencias a las vistas visibles en la pantalla. Muchos métodos de Xamarin.UITest toman un Func<AppQuery, AppQuery> parámetro para localizar las vistas. Por ejemplo, el fragmento de código siguiente muestra cómo pulsar en un botón:

app.Tap(c=>c.Button("ValidateButton"));

Hay dos implementaciones de la IApp interfaz dentro del marco Xamarin.UITest, una para iOS y otra para Android.

Inicializar IApp para aplicaciones iOS

Cuando Xamarin.UITest ejecuta una prueba en iOS, inicia una instancia del simulador de iOS, implementa la aplicación, la inicia y comienza a ejecutar las pruebas. La aplicación de iOS ya debe compilarse. Xamarin.UITest no compilará la aplicación y creará el paquete de aplicaciones automáticamente.

El AppBundle método se puede usar para especificar dónde se puede encontrar en el sistema de archivos que se puede encontrar la agrupación de aplicaciones. Hay dos maneras de hacerlo, con una ruta de acceso absoluta o una ruta de acceso relativa. Este fragmento de código muestra el uso de una ruta de acceso absoluta a la agrupación de aplicaciones:

IApp app = ConfigureApp
    .iOS
    .AppBundle("/path/to/iosapp.app")
    .StartApp();

Las rutas de acceso parciales deben ser relativas al ensamblado Xamarin.UITest. Este fragmento de código es un ejemplo:

IApp app = ConfigureApp
    .iOS
    .AppBundle("../../../iOSAppProject/bin/iPhoneSimulator/Debug/iosapp.app")
    .StartApp();

En el ejemplo de ruta de acceso relativa se indica AppBundle que sube tres directorios desde el ensamblado Xamarin.UITest y, a continuación, desplácese por el árbol de proyecto del proyecto de aplicación de iOS para buscar la agrupación de aplicaciones.

ConfigureApp tiene otros métodos para ayudar a configurar IApp. Consulte la clase iOSAppConfigurator para obtener más información. Algunos de los métodos más interesantes se describen en la tabla siguiente:

Método Descripción
AppBundle Este método especifica la ruta de acceso a la agrupación de aplicaciones que se va a usar al probar.
Debug Este método habilitará los mensajes de registro de depuración en el ejecutor de pruebas. Este método es útil para solucionar problemas con la ejecución de la aplicación en el simulador.
DeviceIdentifier Configura el dispositivo que se va a usar con el identificador del dispositivo. Este método se describirá con más detalle a continuación.
EnableLocalScreenshots Habilite capturas de pantalla al ejecutar pruebas localmente. Las capturas de pantalla siempre están habilitadas cuando las pruebas se ejecutan en la nube.

Para obtener más información sobre cómo ejecutar pruebas de iOS en un simulador de iOS específico, consulte Determinar el identificador de dispositivo para un simulador de iOS.

Inicialización de IApp para aplicaciones Android

Xamarin.UITest implementará un APK existente en un dispositivo conectado o una instancia del emulador de Android que ya se está ejecutando. Se iniciará la aplicación y, a continuación, se ejecutará la prueba. Xamarin.UITest no puede compilar el APK ni puede iniciar una instancia del emulador de Android.

El ApkFile método de se usa para especificar dónde se puede encontrar en el sistema de IApp archivos el APK. Hay dos maneras de hacerlo, con una ruta de acceso absoluta o una ruta de acceso relativa. Este fragmento de código muestra el uso de una ruta de acceso absoluta al APK:

IApp app = ConfigureApp
    .Android
    .ApkFile("/path/to/android.apk")
    .StartApp();

Las rutas de acceso parciales deben ser relativas al ensamblado Xamarin.UITest. Este fragmento de código es un ejemplo:

IApp app = ConfigureApp
    .Android
    .ApkFile("../../../AndroidProject/bin/Debug/android.apk")
    .StartApp();

El ejemplo de ruta de acceso relativa indica ApkFile que suba tres directorios del ensamblado Xamarin.UITest y, a continuación, desplácese por el árbol de proyecto del proyecto de aplicación de Android para buscar el archivo apk.

Si hay más de un dispositivo o emulador conectado, Xamarin.UITest detendrá la ejecución de la prueba y mostrará un mensaje de error, ya que no puede resolver cuál es el destino previsto para la prueba. En este caso, es necesario proporcionar el identificador de serie del dispositivo o emulador para ejecutar la prueba. Por ejemplo, considere la siguiente salida del adb devices comando que enumera todos los dispositivos (o emuladores) conectados al equipo (junto con su identificador de serie):

$ adb devices
List of devices attached
192.168.56.101:5555 device
03f80ddae07844d3    device

El dispositivo se puede especificar mediante el DeviceSerial método :

IApp app = ConfigureApp.Android.ApkFile("/path/to/android.apk")
                               .DeviceSerial("03f80ddae07844d3")
                               .StartApp();

Interacción con la interfaz de usuario

Para interactuar con vistas, muchos IApp métodos toman un Func<AppQuery, AppQuery> delegado para buscar la vista. Este delegado usa AppQuery que se encuentra en el núcleo de cómo Xamarin.UITest localiza las vistas.

AppQuery es una interfaz fluida para compilar las consultas para buscar vistas. De los métodos que AppQuery proporciona, el Marked método es uno de los más sencillos y flexibles. Este método usa una heurística para intentar localizar vistas y se describirá con más detalle en la sección siguiente. Por ahora, es importante comprender que IApp tiene muchos métodos para interactuar con una aplicación. Estos métodos usan para Func<AppQuery, AppQuery> obtener una referencia a la vista con la que interactuar. A continuación se enumeran algunos de los métodos más interesantes proporcionados por AppQuery :

Método Descripción
Button Buscará uno o varios botones en la pantalla.
Class Intentará buscar vistas que son de una clase especificada.
Id Intentará buscar una vista con el identificador especificado.
Index . Devolverá una vista de una colección de vistas coincidentes. Normalmente se usa junto con otros métodos. Toma un índice de base cero.
Marked Devolverá una vista según la heurística que se describe a continuación.
Text Coincidirá con las vistas que contienen el texto proporcionado.
TextField Coincidirá con un dispositivo Android EditText o iOS UITextField.

Por ejemplo, el método siguiente muestra cómo simular una pulsación en un botón denominado "SaveUserdataButton":

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

Dado que AppQuery es una interfaz fluida, es posible encadenar varias invocaciones de método juntas. Considere este ejemplo más complicado de pulsar en una vista:

app.Tap(c=>c.Marked("Pending")
            .Parent()
            .Class("AppointmentListCell").Index(0));

Aquí, primero encontrará una vista marcada Pendingy, a continuación, AppQuery seleccionará el primer elemento primario de esa vista que es un AppointmentListCell tipo.

Puede resultar complicado intentar crear estas consultas examinando una aplicación móvil. Xamarin.UITest proporciona una REPL que se puede usar para explorar la jerarquía de vistas de una pantalla, experimentar con la creación de consultas y usarlas para interactuar con una aplicación.

Uso de REPL

La única manera de iniciar el REPL es invocar el IApp.Repl método dentro de una prueba existente. Esto requiere la creación de un objeto NUnit TestFixture, que configura una instancia de IApp que se puede usar en un Test método . En el fragmento de código siguiente se muestra un ejemplo de cómo hacerlo:

[TestFixture]
public class ValidateCreditCard
{
    IApp app;

    [SetUp]
    public void Setup()
    {
        app = ConfigureApp.Android.ApkFile("/path/to/application.apk").StartApp();
    }
    [Test]
    public void CreditCardNumber_TooLong_DisplayErrorMessage()
    {
        app.Repl();
    }
}

Para ejecutar la prueba, haga clic con el botón derecho en el medianil de Visual Studio y seleccione Ejecutar:

Captura de pantalla del menú emergente con las opciones de ejecución de una prueba

La prueba se ejecutará y, cuando se invoque el Repl método, Xamarin.UITest iniciará el REPL en una sesión de terminal, como se muestra en la captura de pantalla siguiente:

Captura de pantalla del terminal macOS que ejecuta repl de Xamarin.UITest

REPL ha inicializado una instancia de IApp denominada , que appinteractúa con la aplicación. Una de las primeras cosas que hay que hacer es explorar la interfaz de usuario. Repl tiene un tree comando para hacerlo. Imprimirá la jerarquía de vistas en la pantalla mostrada. Por ejemplo, considere la siguiente captura de pantalla de una aplicación:

Captura de pantalla de una aplicación de ejemplo que se ejecuta en un iPhone

Podemos usar el tree comando para mostrar la siguiente jerarquía de esta pantalla:

App has been initialized to the 'app' variable.
Exit REPL with ctrl-c or see help for more commands.

>>> tree
[UIWindow > UILayoutContainerView]
  [UINavigationTransitionView > ... > UIView]
    [UITextView] id: "CreditCardTextField"
      [_UITextContainerView]
    [UIButton] id: "ValidateButton"
      [UIButtonLabel] text: "Validate Credit Card"
    [UILabel] id: "ErrorrMessagesTestField"
  [UINavigationBar] id: "Credit Card Validation"
    [_UINavigationBarBackground]
      [_UIBackdropView > _UIBackdropEffectView]
      [UIImageView]
    [UINavigationItemView]
      [UILabel] text: "Credit Card Validation"
>>>

Podemos ver que hay un UIButton elemento en esta vista con el de idValidateButton. Podemos usar la información mostrada por el tree comando para ayudar a crear las consultas necesarias para buscar e interactuar con vistas. Por ejemplo, el código siguiente simula una pulsación en el botón:

app.Tap(c=>c.Marked("ValidateButton"))

A medida que se escriben los comandos, el REPL los recuerda en un búfer. REPL proporciona un copy comando que copiará el contenido de este búfer en el Portapapeles. Esto nos permite crear prototipos de una prueba. Podemos copiar el trabajo realizado en REPL en el Portapapeles con copyy, a continuación, pegar esos comandos dentro de .[Test]

Uso de marcado para buscar vistas

El método AppQuery.Marked es una forma cómoda y eficaz de consultar vistas en pantalla. Funciona inspeccionando la jerarquía de vistas de una vista en la pantalla, intentando buscar coincidencias con las propiedades de la vista con la cadena proporcionada. Marked funciona de forma diferente en función del sistema operativo.

Búsqueda de vistas de iOS con marcado

Las vistas de iOS se ubicarán con uno de los siguientes atributos:

  • de AccessibilityIdentifier la vista
  • de AccessibilityLabel la vista

Por ejemplo, considere el siguiente fragmento de código de C# que crea y UILabel establece :AccessibilityLabel

UILabel errorMessagesTextField = new UILabel(new RectangleF(10, 210, 300, 40));
errorMessagesTextField.AccessibilityLabel = "ErrorMessagesTextField";
errorMessagesTextField.Text = String.Empty;

Esta vista se puede encontrar mediante la siguiente consulta:

AppResult[] results = app.Marked("ErrorMessagesTextField");

Búsqueda de vistas de Android con marcado

Las vistas de Android se ubicarán en función de una de las siguientes propiedades:

  • de Id la vista
  • de ContentDescription la vista
  • de Text una vista

Por ejemplo, considere un diseño de Android que tenga definido el botón siguiente:

<Button
    android:text="Action 1"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/action1_button"
    android:layout_weight="1"
    android:layout_marginLeft="5dp" />

Podemos ver que el android:id de este botón es action1_button y que es android:textacción 1. Cualquiera de las dos consultas siguientes buscará el botón en la pantalla:

  • app.Query(c=>c.Marked("action1_button"));
  • app.Query(c=>c.Marked("Action 1"));

Controlar la aplicación con Xamarin.UITest.IApp

Una vez IApp configurado e inicializado, la prueba puede empezar a interactuar con la aplicación. Un ejemplo de un método que usa Func<AppQuery, AppQuery> es el IApp.Query() método . Este método ejecutará la consulta y devolverá los resultados. El ejemplo más sencillo se muestra en el fragmento de código siguiente, que devuelve una lista de todas las vistas que están visibles en la pantalla:

AppResult[] results = app.Query(c=>c.All())

En la tabla siguiente se muestran algunos otros ejemplos de uso AppQuery para buscar vistas en la pantalla:

Sintaxis Results
app.Query(c=>c.Class("UILabel")) El .Class() método consultará las vistas que son una subclase de un iOS UILabel.
app.Query(c=>c.Id("txtUserName")) El .Id() método consultará las vistas con un Id de txtUserName.
app.Query(c=>c.Class("UILabel").Text("Hello, World")) Busca todas las UILabel clases que tienen el texto "Hello, World".
results = app.Query(c=>c.Marked("ValidateButton")) Devuelve todas las vistas marcadas con el texto especificado. El Marked método es un método útil que puede simplificar las consultas. Se tratará en la sección siguiente.

En la tabla siguiente se enumeran algunos (pero no todos) de los métodos proporcionados por IApp que se pueden usar para interactuar o manipular vistas en la pantalla:

Ejemplo Descripción
PressEnter Presione la tecla Entrar en la aplicación.
Tap Simula un gesto táctil o de pulsación en el elemento coincidente.
EnterText Escribe texto en la vista. En una aplicación iOS, Xamarin.UITest escribirá el texto mediante el teclado flexible. Por el contrario, Xamarin.UITest no usará el teclado Android, y escribirá directamente el texto en la vista.
WaitForElement Detiene la ejecución de la prueba hasta que las vistas aparecen en la pantalla.
Screenshot(String) Toma una captura de pantalla de la aplicación en su estado actual y la guarda en el disco. Devuelve un FileInfo objeto con información sobre la captura de pantalla tomada.
Flash Este método hará que la vista seleccionada "parpadee" o "parpadee" en la pantalla.

Para obtener más información sobre la IApp interfaz, consulte la documentación de la API para IApp, AndroidAppy iOSApp.

Como ejemplo de cómo usar estos métodos, considere la siguiente prueba para la captura de pantalla que se mostró anteriormente. Esta prueba escribirá un número de 17 dígitos para una tarjeta de crédito en un campo de texto y, a continuación, pulsará un botón en la pantalla. A continuación, inspeccionará la pantalla para ver un mensaje de error que informa al usuario de que el número es demasiado largo para ser un número de tarjeta de crédito válido:

[Test]
public void CreditCardNumber_TooLong_DisplayErrorMessage()
{
    /* Arrange - set up our queries for the views */
    // Nothing to do here, app has been instantiated in the [SetUp] method.

    /* Act */
    app.EnterText(c => c.Marked("CreditCardTextField"), new string('9', 17));
    // Screenshot can be used to break this test up into "steps".
    // The screenshot can be inspected after the test run to verify
    // the visual correctness of the screen.
    app.Screenshot("Entering a 17 digit credit card number.");

    app.Tap(c => c.Marked("ValidateButton"));
    app.Screenshot("The validation results.");

    /* Assert */
    AppResult[] result = app.Query(c => c.Class("UILabel").Text("Credit card number is too long."));
    Assert.IsTrue(result.Any(), "The error message isn't being displayed.");
}

Esta prueba también usa el Screenshot método para tomar imágenes en puntos clave durante la ejecución de la prueba. Cuando se ejecute esta prueba, App Center tomará las capturas de pantalla y las mostrará en los resultados de la prueba. El método permite dividir una prueba en pasos y proporcionar descripciones para las capturas de pantalla.