遗留 ObjC/Swift 代码库在 `swift_checkMetadataState` 中崩溃测试:如何解开 app/test 目标?

Legacy ObjC/Swift codebase crashes tests in `swift_checkMetadataState`: how to disentangle app/test targets?

我有一个混合的 ObjC/Swift 代码库,其结构非常混乱,并且测试不再 运行 在 Xcode 10.2 下(详情如下)。我正在尝试进行最小的结构更改以恢复测试,以便为接下来的重构提供安全网。在采取了在我看来明显的第一步之后,测试无法构建(下面再次详细说明)。

我对以下任何一个感兴趣

我对有关如何构建新项目或创建具有更合理配置的新目标的建议不感兴趣:从这些目标中提取代码也很重要,所以我真的需要测试覆盖率回来之前 我开始任何重构。

原来的情况(很乱)

测试文件仅包含在 myCompanyTests 目标中,但许多代码文件包含在 appmyCompanyTests 目标中。我认为这个和定义相同模块名称的两个目标可能是为了避免必须将应用程序目标导入测试,因为 Swift/ObjC 互操作存在问题(请参阅下一节)。构建测试会在两个地方产生关于 类 的警告:

objc[9724]: Class _TtC12MyCompany12DiaryFetcher is implemented in both
/Users/tikitu/Library/Developer/CoreSimulator/Devices/556CAC28-B90B-4B6B-A87C-1A1450795051/data/Containers/Bundle/Application/495F33C2-F7FC-4AE6-B3FE-6908D6361B55/mycompany-develop.app/mycompany-develop (0x10d724060) 
and 
/Users/tikitu/Library/Developer/Xcode/DerivedData/mycompany-bifciplpbqaeqqdrmhivpjgnojri/Build/Products/Debug-iphonesimulator/mycompany-develop.app/PlugIns/myCompanyTests.xctest/myCompanyTests (0x13566dc38). 
One of the two will be used. Which one is undefined.

从 Xcode 10.2 开始,myCompanyTests 构建成功但 运行 测试失败,swift_checkMetadataState 中的 EXC_BAD_ACCESS 在 [=26] 的某处=] 打电话。我的 猜测 是这与 module-name/files-in-both-targets 恶作剧有关。

第一次尝试 "fix the obvious mistakes"

作为对整理内容的第一次尝试,我做了以下工作:

然后我开始 运行 解决 Swift/ObjC 互操作问题,因为我需要从测试目标中的 ObjC 代码调用应用程序目标中的 Swift 代码。我尝试过的事情:

特别是最后一个对我来说看起来很可疑,因为我希望 Xcode 生成的文件应该 "just work"。我想我已经在某处覆盖了一些用户设置,这妨碍了我:如果有任何关于要检查的地方的建议,我会很高兴。

我不会(还)接受这个,因为它是不完整的信息,但我相信至少我知道 fixed-up 版本失败的原因:MyCompany-Swift.h 的位置不在unit-test 目标的 header 搜索路径,因为它是 app 目标。参考例如https://github.com/jeremy-w/MixedLanguageTesting(建议在 header 搜索路径中添加一个 ad-hoc 条目)。

我认为问题是只有 框架 目标 auto-creates swift-to-objc 头文件 Module-Swift.h:既不是应用程序目标也不是一个测试目标似乎这样做了。

我通过创建两个新的框架目标成功解决了这些问题 * MyCompanyStuffThatUsedToBeInApp(包含应用目标中除 main.h 之外的所有内容),它执行双向 swift/objc 互操作和 * MyCompanyTesting(测试导入的框架目标,同样为 test-only 代码执行双向 swift/objc 互操作)。

可能还有更简单的方法来整理它,但至少这个方法被证明是有效的。