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

如何在KMM中获取iOS TestRunner或TestBundle的随机文件路径?

在KMM iOS端UI测试中读取测试Bundle文件的正确方法

问题背景

在Xcode中进行UI测试时,可通过以下代码读取UITest Bundle下的文件:

func testReadFile() throws {
    // 获取UI测试目标的Bundle
    let testBundle = Bundle(for: XCTestBase.self)
    
    // 查找当前测试运行器下的文件
    if let filePath = testBundle.url(forResource: "good", withExtension: "txt") {
      print(filePath)
    }
}

通过LLDB的po命令可以看到,文件路径指向运行时生成的随机路径,关联到iosAppUITests-Runner实例:

(lldb) po testBundle.url(forResource: "good", withExtension: "txt")
▿ Optional<URL>
  ▿ some : file:///Users/haibozhou/Library/Developer/CoreSimulator/Devices/EFF818A9-6670-4635-9618-DEBFB2C15156/data/Containers/Bundle/Application/DA9E0623-D0DF-414C-A831-5654BBB64AF8/iosAppUITests-Runner.app/PlugIns/iosAppUITests.xctest/good.txt
    - _url : file:///Users/haibozhou/Library/Developer/CoreSimulator/Devices/EFF818A9-6670-4635-9618-DEBFB2C15156/data/Containers/Bundle/Application/DA9E0623-D0DF-414C-A831-5654BBB64AF8/iosAppUITests-Runner.app/PlugIns/iosAppUITests.xctest/good.txt

但在KMM项目的iOS Kotlin代码中尝试实现相同功能时遇到问题:

  • 无法解析测试类XCTestBase,推测是该类未暴露给KMM项目:
    val testBundle = NSBundle.bundleForClass(XCTestBase)
    
  • 尝试使用相对路径读取也失败:
    actual fun readFile(path: String): String {
        val string = NSString.stringWithContentsOfFile(
            "../iosAppUITests-Runner.app/PlugIns/iosAppUITests.xctest/good.txt",
            NSUTF8StringEncoding, null) ?: return "File not found!"
        // 省略其他代码...
        return string
    }
    

请问在KMM的iOS Kotlin代码中,获取iOS测试运行器文件路径的正确方法是什么?


解决方案

在KMM的iOS端测试代码中,可通过以下两种可靠方式获取测试Bundle并读取文件:

方法1:通过当前测试类获取Bundle

如果你的KMM测试类继承自XCTestCase,直接用当前类的javaClass即可定位到对应测试Bundle:

actual fun readFile(fileName: String, fileExtension: String): String {
    // 获取当前测试类对应的Bundle
    val testBundle = NSBundle.bundleForClass(this.javaClass)
    // 查找目标文件的URL
    val fileUrl = testBundle.URLForResource(fileName, withExtension = fileExtension) 
        ?: return "File not found!"
    // 读取文件内容
    return NSString.stringWithContentsOfURL(fileUrl, NSUTF8StringEncoding, null) 
        ?: "Failed to read file content!"
}

方法2:通过Bundle Identifier获取测试Bundle

如果无法通过类对象获取Bundle,可以直接使用测试Target的Bundle Identifier定位:

actual fun readFile(path: String): String {
    // 替换为你XCTest Target的Bundle Identifier
    val testBundle = NSBundle.bundleWithIdentifier("com.yourcompany.iosAppUITests") 
        ?: return "Test bundle not found!"
    val filePath = testBundle.pathForResource("good", ofType = "txt") 
        ?: return "File not found!"
    return NSString.stringWithContentsOfFile(filePath, NSUTF8StringEncoding, null) 
        ?: "Failed to read file!"
}

关键注意事项

  • 确保测试文件已添加到KMM的iOS测试Target中:在Xcode里找到目标文件,勾选对应的测试Target的"Target Membership";
  • 禁止硬编码相对路径:测试运行器的路径是随机生成的,硬编码路径会导致跨环境失效,必须用URLForResource或pathForResource方法动态查找;
  • 方法2中的Bundle Identifier必须与Xcode测试Target的配置完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:15:08