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 :
- Organizar: la prueba configurará las condiciones e inicializará las cosas para que se pueda realizar la prueba.
- Acto: la prueba interactuará con la aplicación, escribirá texto, pulsar botones, etc.
- 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:
- Desarrolle la característica en la aplicación Android o iOS.
- Escriba las pruebas y ejecútelas localmente para comprobar la funcionalidad.
- Cree una nueva ejecución de pruebas en App Center Test o use una serie de pruebas existente.
- Compile el IPA o el APK y cárguelo junto con las pruebas en App Center Test.
- Corrija los problemas o errores expuestos por La prueba de App Center.
- 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í:
- 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.
- 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 elSetUp
método , asegurándose de que hay un nuevoIApp
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 elIApp
objeto una vez en elTestFixtureSetup
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 Pending
y, 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:
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:
REPL ha inicializado una instancia de IApp
denominada , que app
interactú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:
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 id
ValidateButton. 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 copy
y, 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:text
acció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
, AndroidApp
y 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.