Introdução aos testes de interface (UI) no iOS

Giovanna Moeller
3 min readSep 20, 2024

--

Photo by Christopher Gower on Unsplash

Os testes de interface de usuário (UI) no iOS são fundamentais para garantir que a interação do usuário com o aplicativo funcione conforme o esperado. Eles simulam as ações do usuário e verificam se a interface responde corretamente.

Neste artigo, vou mostrar como você pode testar a interface de uma aplicação iOS.

Mas antes, por que escrever testes de UI é importante?

Os testes de UI te ajudam a:

  • Garantir uma experiência de usuário consistente;
  • Detectar problemas de layout e interação;
  • Manter a qualidade do aplicativo durante atualizações;
  • Realizar testes de regressão;
  • Reduzir custos de manutenção e identificar falhas antes de uma versão ser lançada.

No entanto, é importante ter em mente que testes de UI podem ser mais lentos do que testes unitários e de integração. Ele está posicionado no topo da pirâmide de testes.

Adicionando testes de UI no seu projeto

  1. No Xcode, selecione File > New > Target;
    2. Escolha iOS UI Testing Bundle;
    3. Configure o novo target para seu projeto.

Estrutura básica

Para começar, precisamos criar uma instância de XCUIApplication, que representa a nossa aplicação:

import XCTest

class MyAppUITests: XCTestCase {
var app: XCUIApplication!
override func setUpWithError() throws {
continueAfterFailure = false
app = XCUIApplication()
XCUIApplication().launch()
}
func testExample() throws {
// Interações com a UI e asserções
}
}

Adicionando uma identificação aos elementos

Para o teste de UI funcionar e saber qual elemento está interagindo, é preciso adicionar um identificador para o componente que você deseja acessar.

No SwiftUI, você pode adicionar o modificador accessibilityIdentifier:

TextField("Username", text: $username) 
.accessibilityIdentifier("usernameTextField")
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()

No UIKit, pode usar a propriedade accessibilityIdentifier:

class ViewController: UIViewController { 
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var loginButton: UIButton!

override func viewDidLoad() {
super.viewDidLoad()
// Configurando accessibilityIdentifier para os elementos de UI
usernameTextField.accessibilityIdentifier = "usernameTextField"
passwordTextField.accessibilityIdentifier = "passwordTextField"
loginButton.accessibilityIdentifier = "loginButton"
}

@IBAction func loginButtonTapped(_ sender: Any) { // Lógica de login aqui } }

Acessando os elementos de UI

Para encontrar e acessar um elemento, como um texto, podemos usar:

app.staticTexts["Welcome"]

Se você possui apenas um elemento na sua interface, pode usar:

app.scrollViews.element

Alguns dos elementos disponíveis são:

app.alerts.element
app.buttons.element
app.collectionViews.element
app.images.element
app.maps.element
app.navigationBars.element
app.pickers.element
app.progressIndicators.element
app.scrollViews.element
app.segmentedControls.element
app.staticTexts.element
app.switches.element
app.tabBars.element
app.tables.element
app.textFields.element
app.textViews.element
app.webViews.element

Queries avançadas

Você pode executar queries avançadas para achar elementos específicos:

// O único botão
app.buttons.element

// O botão com o título "Help"
app.buttons["Help"]

// Todos os botões dentro de uma scroll view específica (apenas subviews diretas)
app.scrollViews["Main"].children(matching: .button)

// Todos os botões em qualquer lugar dentro de uma scroll view específica (subviews, sub-subviews, sub-sub-subviwes, etc)
app.scrollViews["Main"].descendants(matching: .button)

// Encontrar o primeiro e o quarto botões
app.buttons.element(boundBy: 0)
app.buttons.element(boundBy: 3)

// Encontrar o primeiro botão, mesmo se houver mais (mais rápido que element porque não verifica duplicatas)
app.buttons.firstMatch

Interagindo com elementos de UI

O XCTest nos oferece diversas maneiras de acionar interações:

app.buttons["Login"].doubleTap()
app.textFields["Username"].tap()
app.textFields["Username"].typeText("user@example.com")
app.secureTextFields["Password"].typeText("password")

Asserções

Uma vez que você encontrou o elemento que deseja testar, pode fazer verificações em relação a ele usando as funções regulares do XCTest:

XCTAssert(app.staticTexts["Welcome"].exists)
XCTAssertEqual(app.tables.cells.count, 5)
XCTAssertEqual(app.buttons.element.title, "Buy")
XCTAssertEqual(app.staticTexts.element.label, "test")
XCTAssertTrue(app.alerts["Warning"].waitForExistence(timeout: 1))

// Swift Testing (novo framework de testes da Apple)
#expect(app.staticTexts["Welcome"].exists == true)
#expect(app.tables.cells.count == 5)

Outras técnicas de teste de UI

Teste de acessibilidade

Verificando se o aplicativo é acessível:

XCTAssert(app.buttons["Login"].isAccessibilityElement)
XCTAssertNotNil(app.buttons["Login"].accessibilityLabel)

Teste de rotação do dispositivo

Simule a rotação do dispositivo para testar o layout:

XCUIDevice.shared.orientation = .landscapeLeft
// Verifique o layout após a rotação
XCUIDevice.shared.orientation = .portrait

Use o Xcode’s Device Configuration para testar em diferentes dispositivos.

Conclusão

Os testes de interface de usuário são essenciais para garantir que seu aplicativo ofereça uma experiência de usuário de alta qualidade e sem falhas.

Ao automatizar as interações, você pode identificar problemas de layout, bugs em funcionalidades e garantir que atualizações futuras não quebrem partes cruciais da interface.

Incorporar testes de UI no seu fluxo de desenvolvimento não só mantém a qualidade do produto, mas também economiza tempo e esforços durante o ciclo de vida do aplicativo.

Lembre-se de sempre executar testes em múltiplos dispositivos e cenários, garantindo a consistência da experiência para todos os usuários.

Referências

--

--