Introdução aos testes de interface (UI) no iOS
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
- 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.