Testes em Swift: unit, integration, e2e do A ao Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que os testes são a base de um aplicativo Swift confiável

O desenvolvimento para iOS e macOS exige não apenas uma interface bonita, mas também uma lógica estável. Testes em Swift não são uma opção, mas uma necessidade. Sem testes, até mesmo uma pequena alteração pode quebrar funcionalidades que funcionavam há anos. Neste artigo, vamos analisar três níveis de teste: unit (teste de unidade), integration (teste de integração) e e2e (teste ponta a ponta). Você aprenderá como configurá-los, escrevê-los e executá-los corretamente nas plataformas Apple. No final — dicas práticas para organizar a arquitetura de testes.



Nível 1: Testes unitários — a base de tudo

Testes unitários verificam funções, métodos ou classes individuais de forma isolada. Em Swift, o framework principal é o XCTest. Ele está integrado ao Xcode, não requer dependências de terceiros e é ideal para testar a lógica de negócios.



Como escrever seu primeiro teste unitário

Crie um novo Unit Test Target no Xcode (File → New → Target → Unit Testing Bundle). Em seguida, adicione a classe de teste:

import XCTest@testable import MyApp

final class CalculatorTests: XCTestCase { var sut: Calculator! override func setUpWithError() throws { sut = Calculator() } override func tearDownWithError() throws { sut = nil } func testAddition() { // Given let a = 5 let b = 3 // When let result = sut.add(a, b) // Then XCTAssertEqual(result, 8, "A adição deve estar correta") }}


Melhores práticas de teste unitário

  • Isolamento: cada teste testa apenas uma unidade de código. Use setUp e tearDown para redefinir o estado.
  • Nomenclatura: use o padrão test[Method]_[Condition]_[ExpectedResult].
  • Mocks e stubs: para dependências externas (rede, banco de dados), use protocolos e substitua-os nos testes.
  • Cobertura: busque 70-80% de cobertura de código, mas não persiga 100% — teste os caminhos críticos.


Exemplo com mock

protocol NetworkServiceProtocol {    func fetchData(completion: @escaping (Result<Data, Error>) -> Void)}

class MockNetworkService: NetworkServiceProtocol { var shouldReturnError = false func fetchData(completion: @escaping (Result<Data, Error>) -> Void) { if shouldReturnError { completion(.failure(NSError(domain: "test", code: 1))) } else { completion(.success(Data())) } }}

func testFetchDataSuccess() { let mock = MockNetworkService() let viewModel = ViewModel(networkService: mock) mock.shouldReturnError = false viewModel.loadData() XCTAssertTrue(viewModel.isDataLoaded)}


Nível 2: Testes de integração — verificando a interação

Testes de integração verificam como diferentes módulos do sistema funcionam juntos: banco de dados + rede, UI + lógica de negócios, vários serviços. Em Swift, usa-se XCTest com dependências reais (ou in-memory) para isso.



Cenário típico: Core Data + Network

import XCTest@testable import MyApp

class UserServiceIntegrationTests: XCTestCase { var coreDataStack: CoreDataStack! var networkService: NetworkService! var userService: UserService! override func setUp() { coreDataStack = CoreDataStack(inMemory: true) // in-memory para testes networkService = NetworkService() userService = UserService(coreDataStack: coreDataStack, networkService: networkService) } func testSaveUserFromNetwork() { // Criamos uma expectativa para a requisição assíncrona let expectation = self.expe

Blogs

Book Recommendations