遗留 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 下(详情如下)。我正在尝试进行最小的结构更改以恢复测试,以便为接下来的重构提供安全网。在采取了在我看来明显的第一步之后,测试无法构建(下面再次详细说明)。
我对以下任何一个感兴趣
- 原始问题的解决方案(在混乱的设置中再次获得测试 运行ning)
- 重构后问题的解决方案(在更简洁的设置中构建重构测试)
- 构建设置的建议以验证或包含在此处的描述中,以更清楚地了解问题所在
我对有关如何构建新项目或创建具有更合理配置的新目标的建议不感兴趣:从这些目标中提取代码也很重要,所以我真的需要测试覆盖率回来之前 我开始任何重构。
原来的情况(很乱)
- 项目
myCompany
- 构建模块
MyCompany
的应用程序目标 app
- 同时包含 Swift 和 ObjC 代码,两者都具有依赖关系
- 定义模块 = 是,产品模块名称 =
MyCompany
- 测试目标
myCompanyTests
- 定义模块 = 否,产品模块名称 =
MyCompany
- 还包含 Swift 和 ObjC 代码
- 用于外部依赖的 CocoaPods,还有一堆内部 Swift 模块,具有手动管理的依赖关系
测试文件仅包含在 myCompanyTests
目标中,但许多代码文件包含在 app
和 myCompanyTests
目标中。我认为这个和定义相同模块名称的两个目标可能是为了避免必须将应用程序目标导入测试,因为 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"
作为对整理内容的第一次尝试,我做了以下工作:
- 从
myCompanyTests
目标中删除所有非测试文件
- 将
myCompanyTests
产品模块名称重命名为 MyCompanyTests
- 在大量 swift 测试中添加
@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
#import "MyCompanyTests-Swift.h"
在所有需要访问应用程序目标的 objc .m 测试文件中
- 生成的文件
MyCompanyTests-Swift.h
包含一行 @import MyCompany;
看起来很有前途!
- 但是该行失败并出现错误
Module 'MyCompany' not found
特别是最后一个对我来说看起来很可疑,因为我希望 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 互操作)。
可能还有更简单的方法来整理它,但至少这个方法被证明是有效的。
我有一个混合的 ObjC/Swift 代码库,其结构非常混乱,并且测试不再 运行 在 Xcode 10.2 下(详情如下)。我正在尝试进行最小的结构更改以恢复测试,以便为接下来的重构提供安全网。在采取了在我看来明显的第一步之后,测试无法构建(下面再次详细说明)。
我对以下任何一个感兴趣
- 原始问题的解决方案(在混乱的设置中再次获得测试 运行ning)
- 重构后问题的解决方案(在更简洁的设置中构建重构测试)
- 构建设置的建议以验证或包含在此处的描述中,以更清楚地了解问题所在
我对有关如何构建新项目或创建具有更合理配置的新目标的建议不感兴趣:从这些目标中提取代码也很重要,所以我真的需要测试覆盖率回来之前 我开始任何重构。
原来的情况(很乱)
- 项目
myCompany
- 构建模块
MyCompany
的应用程序目标app
- 同时包含 Swift 和 ObjC 代码,两者都具有依赖关系
- 定义模块 = 是,产品模块名称 =
MyCompany
- 测试目标
myCompanyTests
- 定义模块 = 否,产品模块名称 =
MyCompany
- 还包含 Swift 和 ObjC 代码
- 定义模块 = 否,产品模块名称 =
- 用于外部依赖的 CocoaPods,还有一堆内部 Swift 模块,具有手动管理的依赖关系
测试文件仅包含在 myCompanyTests
目标中,但许多代码文件包含在 app
和 myCompanyTests
目标中。我认为这个和定义相同模块名称的两个目标可能是为了避免必须将应用程序目标导入测试,因为 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"
作为对整理内容的第一次尝试,我做了以下工作:
- 从
myCompanyTests
目标中删除所有非测试文件 - 将
myCompanyTests
产品模块名称重命名为MyCompanyTests
- 在大量 swift 测试中添加
@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
#import "MyCompanyTests-Swift.h"
在所有需要访问应用程序目标的 objc .m 测试文件中- 生成的文件
MyCompanyTests-Swift.h
包含一行@import MyCompany;
看起来很有前途! - 但是该行失败并出现错误
Module 'MyCompany' not found
- 生成的文件
特别是最后一个对我来说看起来很可疑,因为我希望 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 互操作)。
可能还有更简单的方法来整理它,但至少这个方法被证明是有效的。