You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让XCUITest应用访问照片库并获取添加的图片上传服务器?

解决XCUITest应用自身访问照片库并上传图片的问题

我来帮你搞定这个问题!因为XCUITest的测试应用和你的被测试应用(SUT)是完全独立的沙盒环境,所以你得单独给测试应用配置权限、处理访问逻辑,而不是依赖SUT的配置。下面一步步来:

一、先给XCUITest测试Target配置照片库权限

测试应用要访问照片库,得先在它的Info.plist里加权限描述,操作步骤如下:

  • 打开Xcode项目,在左侧导航栏找到你的XCUITest Target(一般叫[你的App名]UITests)
  • 选中这个Target,切换到Info标签页
  • 点击+号添加权限键:
    • 如果只需要读取照片,加Privacy - Photo Library Usage Description,填写描述文本(比如"测试需要读取照片库")
    • 如果是iOS 14及以上,要是需要读取所有照片,还要加Privacy - Photo Library Limited Usage Description,同样填描述
    • 要是需要写入照片(比如上传后存回相册),再加Privacy - Photo Library Additions Usage Description

二、在测试代码里请求权限并访问照片

默认情况下测试应用不会自动获得权限,得主动请求,然后才能读取你用simctl addmedia添加的图片:

  1. 先导入必要的框架:
import XCTest
import Photos
  1. 在测试类的setUp里请求权限(用XCTestExpectation等待异步操作完成,避免测试跑飞):
override func setUp() {
    super.setUp()
    continueAfterFailure = false
    
    // 请求照片库读取权限
    let permissionExpectation = expectation(description: "等照片库权限请求完成")
    PHPhotoLibrary.requestAuthorization { status in
        switch status {
        case .authorized, .limited:
            print("权限拿到啦!")
        default:
            print("权限被拒了,没法访问照片库哦")
        }
        permissionExpectation.fulfill()
    }
    waitForExpectations(timeout: 5, handler: nil)
}
  1. 编写测试用例读取照片并上传:
func testFetchPhotoAndUploadToServer() {
    // 从照片库获取最新的图片
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    let imageAssets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
    
    guard let targetAsset = imageAssets.firstObject else {
        XCTFail("照片库没找到图片!你是不是用simctl加错模拟器了?")
        return
    }
    
    // 把PHAsset转成可以上传的Data
    let loadImageExpectation = expectation(description: "等图片加载完成")
    var imageData: Data?
    
    let imageManager = PHImageManager.default()
    imageManager.requestImageDataAndOrientation(for: targetAsset, options: nil) { data, _, _, _ in
        imageData = data
        loadImageExpectation.fulfill()
    }
    waitForExpectations(timeout: 10, handler: nil)
    
    guard let uploadData = imageData else {
        XCTFail("没法获取图片数据")
        return
    }
    
    // 调用上传方法把图片发到服务器
    uploadImage(data: uploadData)
}

// 写个简单的上传示例(根据你的服务器接口调整参数和格式)
private func uploadImage(data: Data) {
    guard let uploadURL = URL(string: "https://your-server-endpoint.com/upload") else {
        XCTFail("服务器URL无效")
        return
    }
    
    var request = URLRequest(url: uploadURL)
    request.httpMethod = "POST"
    
    // 构建multipart/form-data请求(大多数文件上传接口用这个格式)
    let boundary = "TestUploadBoundary-\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
    var requestBody = Data()
    // 添加上传字段
    requestBody.append("--\(boundary)\r\n".data(using: .utf8)!)
    requestBody.append("Content-Disposition: form-data; name=\"image\"; filename=\"test-photo.jpg\"\r\n".data(using: .utf8)!)
    requestBody.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
    requestBody.append(data)
    requestBody.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
    
    request.httpBody = requestBody
    
    // 等待上传完成
    let uploadExpectation = expectation(description: "等图片上传完成")
    URLSession.shared.dataTask(with: request) { data, response, error in
        defer { uploadExpectation.fulfill() }
        
        if let err = error {
            XCTFail("上传失败:\(err.localizedDescription)")
            return
        }
        
        guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
            XCTFail("服务器返回错误状态码")
            return
        }
        
        print("图片上传成功啦!")
    }.resume()
    
    waitForExpectations(timeout: 30, handler: nil)
}

三、关于xcrun simctl addmedia的小提醒

你用这个命令加图片的时候,要确保是给当前运行测试的模拟器加的:

  • 先通过xcrun simctl list查看所有模拟器的UDID
  • 指定UDID添加图片:xcrun simctl addmedia <你的模拟器UDID> /path/to/your/image.jpg
  • 加完之后,测试应用必须拿到权限才能看到这些图片,因为权限是测试应用单独的,和SUT没关系

四、常见坑排查

  • 还是看不到图片?去模拟器的设置->隐私与安全性->照片里看看测试应用的权限是不是开着的,或者检查Info.plist里的权限描述有没有加对
  • 上传失败?先确认服务器URL能正常访问,要是用HTTPS,检查证书是不是信任的;另外测试里的网络请求一定要用XCTestExpectation等待,不然测试会提前结束
  • 异步操作出问题?所有涉及权限请求、图片加载、网络请求的异步操作,都要用waitForExpectations等待完成,不然测试会直接跳过这些逻辑

内容的提问来源于stack exchange,提问作者ablarg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:08:47