XCUITest无法加载Main.Storyboard问题咨询:已添加至测试Target仍触发Bundle查找失败错误
嘿,我帮你排查下这个问题!你遇到的找不到Storyboard的错误,核心原因是你用错了Bundle对象,另外还有个小误区是测试target的选择,咱们一步步来解决:
1. 为什么会找不到Storyboard?
你现在用Bundle(for: type(of: self))获取的是UITest Runner的Bundle(也就是错误信息里的QuizAppUITests-Runner.app),而你的Main.storyboard实际是在主App的Bundle(QuizApp.app)里。哪怕你把Storyboard加到了UITest target,这种手动实例化ViewController的方式也不该用UITest的Bundle来加载主App的资源。
2. 修正Bundle的获取方式
既然你已经通过@testable import QuizApp导入了主App的代码,直接用主App里的类来获取对应的Bundle就好,把makeSUT()方法里的Bundle替换成这样:
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: QuizViewController.self))
这样就能准确拿到主App的Bundle,自然能找到Main.storyboard了。
3. 关于测试Target的小建议
看你的测试代码是在验证ViewController的属性逻辑,这种测试其实更适合放在单元测试Target(比如默认的QuizAppTests)里,而不是UI测试Target(QuizAppUITests)。UI测试Target的定位是模拟真实用户操作,测试整个App的交互流程(比如用XCUIApplication()启动App,点击按钮等),而单个ViewController的逻辑测试放在单元测试里更合适,也能避免Bundle混淆的问题。
4. 确认Build Settings(可选检查)
如果你坚持要在UI测试Target里做这个测试,除了修正Bundle,再确认下:
- 打开
Main.storyboard的右侧检查器,确认它的Target Membership里已经勾选了QuizAppUITests - 进入
QuizAppUITests的Build Settings,搜索Copy Bundle Resources,确认Main.storyboard在这个列表里(不过其实用主App的Bundle的话,这一步不是必须的)
修改后的测试代码示例:
import XCTest @testable import QuizApp class QuizViewControllerUITests: XCTestCase { func makeSUT() -> QuizViewController { // 改用主App的Bundle let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: QuizViewController.self)) let sut = storyboard.instantiateViewController(withIdentifier: "QuizViewController") as! QuizViewController _ = sut.view return sut } func test_loadQuizViewController() { let sut = makeSUT() sut.headerQuestion = "Q1" XCTAssertEqual(sut.headerQuestion, "Q1") } }
这样应该就能解决找不到Storyboard的问题啦!
内容的提问来源于stack exchange,提问作者Hitesh

