旧版ObjC / Swift代码库使“ swift_checkMetadataState”中的测试崩溃:如何解开应用/测试目标?

时间:2019-04-22 09:58:30

标签: ios swift xcode unit-testing xcode10

我有一个混合结构的ObjC / Swift代码库,并且测试不再在Xcode 10.2下运行(详细信息如下)。我正在尝试进行最小的结构更改以恢复测试,以便为下一步的重构提供一个安全网。在采取我认为显而易见的第一步之后,测试无法建立(下面再次详细介绍)。

我对以下任何一项感兴趣

  • 原始问题的解决方案(以使测试在混乱的设置中再次运行)
  • 重构后问题的解决方案(以在稍微整齐的设置中构建重构测试)
  • 构建设置的建议,以验证或包括在此处的描述中,以更清楚地了解发生了什么问题

我对如何构造一个新项目或创建具有更合理配置的新目标的建议不感兴趣:从这些目标中提取代码也不是一件容易的事,因此我确实需要在之前进行测试覆盖我开始任何重构。

原始情况(非常混乱)

  • 项目myCompany
  • 构建模块app
  • 应用目标MyCompany
    • 同时包含Swift和ObjC代码,并且都具有依赖性
    • 定义模块=是,产品模块名称= MyCompany
  • 测试目标myCompanyTests
    • 定义模块=否,产品模块名称= MyCompany
    • 还包含Swift和ObjC代码
  • 用于外部依赖的CocoaPods,也是一堆内部Swift模块,具有手动管理的依赖

测试文件仅包含在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成功构建,但是运行测试失败,并且在EXC_BAD_ACCESS调用内某处的swift_checkMetadataState中有UIApplicationMain。我的 guess 是,这与模块名/目标中的文件名都有关。

首次尝试“解决明显的错误”

作为整理事情的第一次尝试,我做了以下工作:

  • myCompanyTests目标中删除所有非测试文件
  • myCompanyTests产品模块名称重命名为MyCompanyTests
  • 在许多快速测试中添加@testable import MyCompany

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

  • #import "MyCompany-Swift.h"在objc .m测试文件中
    • 'MyCompany-Swift.h' file not found
  • #import <MyCompany-Swift.h>在objc .m测试文件中
    • 'MyCompany-Swift.h' file not found
  • #import <MyCompany/MyCompany-Swift.h>在objc .m测试文件中(是​​的,您可以看到我实际上并不了解这种机制)
    • 'MyCompany/MyCompany-Swift.h' file not found
  • 需要访问应用程序目标的所有objc .m测试文件中的
  • #import "MyCompanyTests-Swift.h"
    • 生成的文件MyCompanyTests-Swift.h包含一行@import MyCompany;,看起来很有希望!
    • 但该行失败,并显示错误Module 'MyCompany' not found

尤其是最后一个对我来说似乎很可疑,因为我希望Xcode生成的文件应该“正常工作”。我想我已经覆盖了一些麻烦的用户设置:我很乐意为检查位置提供任何建议。

2 个答案:

答案 0 :(得分:0)

由于此信息尚不完整,我不会接受(但),但我至少相信,我知道为什么固定版本会失败:MyCompany-Swift.h的位置不在单元测试中目标的标头搜索路径,因为它是 app 目标。参考例如https://github.com/jeremy-w/MixedLanguageTesting(建议在标题搜索路径中添加临时条目)。

答案 1 :(得分:0)

我认为问题在于,只有 framework 目标会自动创建swift-to-objc头文件Module-Swift.h:应用目标和测试目标都没有这样做

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

仍然可以使用更简单的方法来解决此问题,但至少已证明该方法可行。