← Back to blog

UI Tests para Apps iOS — Básicos

Una guía introductoria sobre cómo implementar pruebas de interfaz de usuario en aplicaciones iOS utilizando XCTest.

Después de cubrir pruebas unitarias y de integración, llegamos a la cúspide de la pirámide de pruebas: los UI Tests. Estas pruebas utilizan la interfaz de usuario para verificar que todo funcione como se espera, a un nivel más cercano a la experiencia real del usuario.

El principal inconveniente es que son significativamente más lentos en ejecución comparados con otros tipos de pruebas. También se conocen como pruebas End-to-End (E2E) porque abarcan un flujo completo: desde que el usuario realiza una acción hasta que se recibe la respuesta y se muestra en pantalla.

Características de los UI Tests

Se utiliza el framework XCTest extendiendo clases de test con XCTestCase. A diferencia de pruebas unitarias y de integración, los UI Tests requieren interacción con la interfaz de usuario ya que no hay acceso directo al código.

Ejecución de los Tests

Para ejecutar UI tests, XCTest instala dos aplicaciones en el dispositivo:

  • La aplicación a probar
  • Una aplicación que simula los inputs del usuario

Se ejecuta la aplicación con:

let app = XCUIApplication()
app.launch()

Acceso a Elementos de la UI

En lugar de usar coordenadas (x, y), Apple proporciona acceso a elementos mediante referencias como texto, títulos o placeholders:

let nameTextField = app.textFields["Name"]

Grabación de UI Tests

Xcode proporciona una herramienta de grabación automática. Para usarla:

  1. Crear un target de tipo UI Testing Bundle
  2. Crear una clase de test: final class ContentViewUITests: XCTestCase
  3. Crear una función de test
  4. Activar "Record UI Tests"
  5. Ejecutar acciones en la aplicación

Ejemplo registrado:

func testStartAndSelectNameTextField() throws {
    let app = XCUIApplication()
    app.launch()

    app.textFields["Name"].tap()

    let vKey = app.keys["V"]
    vKey.tap()

    let iKey = app.keys["i"]
    iKey.tap()

    let cKey = app.keys["c"]
    cKey.tap()

    let tKey = app.keys["t"]
    tKey.tap()

    let oKey = app.keys["o"]
    oKey.tap()

    app.keys["r"].tap()
}

Aserciones en UI Tests

Ejemplo de test con validación:

func testSaveButtonEnabledAfterFillAllTextFields() throws {
    let app = XCUIApplication()
    app.launch()

    app.textFields["Name"].tap()
    app.typeText("Test")

    app.textFields["Surname"].tap()
    app.typeText("Test")

    app.textFields["Email"].tap()
    app.typeText("Test")

    app.textFields["Phone"].tap()
    app.typeText("Test")

    XCTAssertTrue(app.buttons["Save"].isEnabled)
}

Uso de Identificadores de Accesibilidad

Un problema con referenciar elementos por texto es que fallan si el contenido cambia. La solución es usar accessibilityIdentifier:

Button {
    // Action
} label: {
    Text("Guardar")
}
.accessibilityIdentifier("SaveButton")
.disabled(name.count == 0 || surname.count == 0 || email.count == 0 || phoneNumber.count == 0)

Luego se puede hacer la aserción sin depender del texto:

XCTAssertTrue(app.buttons["SaveButton"].isEnabled)

Los UI Tests en iOS permiten validar la experiencia completa del usuario interactuando con la interfaz. Aunque más lentos que otras pruebas, son esenciales para garantizar que la aplicación funcione correctamente desde la perspectiva del usuario final.