Answers:
当单元测试工具运行您的代码时,单元测试包不会主包。
即使您正在运行测试,而不是您的应用程序,您的应用程序包仍然是主要包。(大概是这样,可以防止正在测试的代码搜索错误的包。)因此,如果将资源文件添加到单元测试包中,则在搜索主包时将找不到它。如果将以上行替换为:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"foo" ofType:@"txt"];
然后,您的代码将搜索单元测试类所在的包,一切都会好起来。
self
指的是主包中的类,而不是测试用例类。替换[self class]
为主捆绑中的任何类。我将编辑我的示例。
bundleForClass:
与单元测试包中的类一起使用。您应该在单元测试代码中获取文件的路径,然后将路径字符串传递给其他代码。
一个Swift实现:
迅捷2
let testBundle = NSBundle(forClass: self.dynamicType)
let fileURL = testBundle.URLForResource("imageName", withExtension: "png")
XCTAssertNotNil(fileURL)
雨燕3,雨燕4
let testBundle = Bundle(for: type(of: self))
let filePath = testBundle.path(forResource: "imageName", ofType: "png")
XCTAssertNotNil(filePath)
捆绑包提供了发现配置主要路径和测试路径的方法:
@testable import Example
class ExampleTests: XCTestCase {
func testExample() {
let bundleMain = Bundle.main
let bundleDoingTest = Bundle(for: type(of: self ))
let bundleBeingTested = Bundle(identifier: "com.example.Example")!
print("bundleMain.bundlePath : \(bundleMain.bundlePath)")
// …/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Agents
print("bundleDoingTest.bundlePath : \(bundleDoingTest.bundlePath)")
// …/PATH/TO/Debug/ExampleTests.xctest
print("bundleBeingTested.bundlePath : \(bundleBeingTested.bundlePath)")
// …/PATH/TO/Debug/Example.app
print("bundleMain = " + bundleMain.description) // Xcode Test Agent
print("bundleDoingTest = " + bundleDoingTest.description) // Test Case Bundle
print("bundleUnderTest = " + bundleBeingTested.description) // App Bundle
在Xcode 6 | 7 | 8 | 9中,单元测试包路径将位于Developer/Xcode/DerivedData
...
/Users/
UserName/
Library/
Developer/
Xcode/
DerivedData/
App-qwertyuiop.../
Build/
Products/
Debug-iphonesimulator/
AppTests.xctest/
foo.txt
...与 Developer/CoreSimulator/Devices
常规(非单元测试)捆绑包路径:
/Users/
UserName/
Library/
Developer/
CoreSimulator/
Devices/
_UUID_/
data/
Containers/
Bundle/
Application/
_UUID_/
App.app/
另请注意,默认情况下,单元测试可执行文件与应用程序代码链接。但是,单元测试代码仅应在测试包中具有目标成员身份。应用程序代码应仅在应用程序捆绑包中具有目标成员资格。在运行时,将单元测试目标捆绑软件注入应用程序捆绑软件中以进行执行。
Swift Package Manager(SPM)4:
let testBundle = Bundle(for: type(of: self))
print("testBundle.bundlePath = \(testBundle.bundlePath) ")
注意:默认情况下,命令行将swift test
创建MyProjectPackageTests.xctest
测试包。并且,swift package generate-xcodeproj
将创建一个MyProjectTests.xctest
测试包。这些不同的测试包具有不同的路径。另外,不同的测试包可能会有一些内部目录结构和内容差异。
无论哪种情况, .bundlePath
and .bundleURL
都会返回当前在macOS上运行的测试包的路径。但是,Bundle
当前尚未为Ubuntu Linux实施。
另外,命令行 swift build
和swift test
当前不提供复制资源的机制。
但是,只要付出一些努力,就有可能在macOS Xcode,macOS命令行和Ubuntu命令行环境中,通过资源来设置使用Swift软件包管理器的过程。可以在这里找到一个示例: 004.4'2具有资源Qref的SW Dev Swift软件包管理器(SPM)
也可以看看: 通过Swift Package Manager在单元测试中使用资源
Swift套件管理员(SPM)4.2
Swift Package Manager PackageDescription 4.2引入了对本地依赖项的支持。
本地相关性是磁盘上的程序包,可以使用其路径直接引用。本地依赖项仅在根包中允许,它们会在包图中覆盖具有相同名称的所有依赖项。
注意:我希望但尚未经过测试,使用SPM 4.2应该可以进行以下操作:
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "MyPackageTestResources",
dependencies: [
.package(path: "../test-resources"),
],
targets: [
// ...
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage", "MyPackageTestResources"]
),
]
)