在XCTest的@testable幕后发生了什么?

dim*_*ura 6 macos ios xctest swift

我知道

@testable import MyModule
Run Code Online (Sandbox Code Playgroud)

能够MyModule从"测试"(使用"testTarget"构建)模块探索非公共成员MyModuleTests.

我的"非测试"模块中需要相同的功能.不在生产中,只是在调试模式下.

我的问题是:你知道怎么做吗?

并且相关(我认为,更难的问题):背后真正发生了什么魔法@testable

Rob*_*gos 17

要回答您的问题,出于调试目的,您实际上可以使用它.假设你有一个工作区MyAwesomeWkspace和一个项目MyAwesomeProject.

现在,创建一个新framework又名moduleMyAwesomeModule.在该模块内部创建一个名为的非公共类Person.

如果你尝试在Person里面使用这个类,那么像你MyAwesomeProject这样的import MyAwesomeModule东西let p = Person()就会出错.

但是,如果你这样做@testable import MyAwesomeModule,魔术就会发生,你现在可以使用这个类了.

基本上@testable允许您测试未公开声明的内容.注释仅适用于import在此处看到的内容.

因此,为了工作,编译目标,-enable-testing以便您可以访问非公共成员.至少基于这里的内容

因为,默认情况下,debug编译构建配置-enable-testing,我展示的示例您将工作.但是如果你将构建配置改为release,你会看到一个错误,Module .. was not compiled for testing因为release配置不是用标志构建的.

Swift访问控制模型,如Swift编程语言(Swift 4)的访问控制部分所述,可防止外部实体访问在应用程序或框架中声明为内部的任何内容.默认情况下,为了能够从测试代码中访问这些项目,您需要将其访问级别提升至至少公开,从而降低Swift类型安全性的好处.

Xcode为这个问题提供了一个由两部分组成的解决方案:

将Enable Testability构建设置设置为Yes时,默认情况下,对于新项目中的测试构建,Xcode会在编译期间包含-enable-testing标志.这使得在已编译模块中声明的Swift实体有资格获得更高级别的访问权限.将@testable属性添加到已启用测试编译的模块的import语句时,将激活该范围内该模块的提升访问权限.标记为内部或公共的类和类成员的行为就像它们被标记为打开一样.标记为内部的其他实体就像宣布公开一样.

更多这里

延迟编辑:swift的一个很酷的部分是开源.因此,如果你想深入了解"神奇",请查看:https://github.com/apple/swift