Swift 测试:单元测试、集成测试、端到端测试——高级水平

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 高级测试:单元测试、集成测试和端到端测试



测试不仅仅是检查,更是可靠代码的基础。在高级水平上,Swift 开发者不仅要编写测试,还要巧妙地构建测试金字塔:从快速的单元测试到复杂的端到端(e2e)场景。在本文中,我们将深入探讨 iOS/macOS 项目的高级技术:依赖管理、CoreData 集成测试和 UI 自动化。



1. 单元测试:依赖管理和模拟



在高级水平上,单元测试必须是隔离的。关键技术是 依赖注入(DI)。我们不测试真实的网络层或数据库,而是用模拟对象来替代它们。



示例:协议和 DI

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

class ViewModel { private let networkService: NetworkServiceProtocol init(networkService: NetworkServiceProtocol) { self.networkService = networkService } func loadData() { networkService.fetchData { result in // 处理结果 } }}

// 用于测试的模拟对象class MockNetworkService: NetworkServiceProtocol { var shouldReturnError = false func fetchData(completion: @escaping (Result<String, Error>) -> Void) { if shouldReturnError { completion(.failure(NSError(domain: "test", code: -1))) } else { completion(.success("Mock data")) } }}


在测试中,您创建 MockNetworkService 并将其传递给 ViewModel。这允许您在不使用真实 API 的情况下测试错误和成功场景。



用于异步的 XCTestExpectation

func testViewModelLoadDataSuccess() {    let mock = MockNetworkService()    let viewModel = ViewModel(networkService: mock)        let expectation = self.expectation(description: "Data loaded")        viewModel.loadData()        // 模拟异步调用    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {        expectation.fulfill()    }        waitForExpectations(timeout: 1.0)    // 检查 ViewModel 的状态}


2. 集成测试:CoreData 和真实数据处理



集成测试检查组件之间的交互。对于 CoreData,我们使用 内存容器,以避免污染主数据库。



配置内存 CoreData

class CoreDataTestStack {    lazy var persistentContainer: NSPersistentContainer = {        let container = NSPersistentContainer(name: "MyModel")        let description = NSPersistentStoreDescription()        description.type = NSInMemoryStoreType        container.persistentStoreDescriptions = [description]        container.loadPersistentStores { _, error in            if let error = error {                fatalError("Failed to load store: \\(error)")            }        }        return container    }()        var context: NSManagedObjectContext {        return persistentContainer.viewContext    }}


集成测试示例

func testSaveAndFetchUser() {    let stack = CoreDataTestStack()    let repository = UserRepository(context: stack.context)        // 创建用户    let user = User(context: stack.context)    user.name = "Test User"    user.age = 30        try? stack.context.save()        // 检查数据是否已保存    let fetchRequest: NSFetchRequest<User> = User.fetchRequest()    let users = try? stack.context.fetch(fetchRequest)        XCTAssertEqual(users?.count, 1)    XCTAssertEqual(users?.first?.name, "Test User")}


重要提示:每次测试后请清除上下文,以确保测试之间不会相互影响。

博客

书籍推荐