NSURL到XCTest的测试包中的文件路径

Edu*_*ada 71 tdd nsbundle ios xctest

我正在尝试使用TDD和新的XCTest框架编写iOS应用程序.我的一个方法从Internet检索文件(给定NSURL对象)并将其存储在用户的文档中.该方法的签名类似于:

- (void) fetchAndStoreImage:(NSURL *)imageUrl
Run Code Online (Sandbox Code Playgroud)

我正在尝试为这种方法编写测试,如果没有连接到互联网就不会失败.我的方法(取自上一个问题)是使用NSURL将方法调用到本地文件系统中的图像.

当创建启用了单元测试的新项目时,Tests目录有一个名为"Supporting Files"的子目录.我想这是我的测试图像应该去的地方.我的问题是如何获得指向此目录中的图像的NSURL对象,因为我不希望测试图像与应用程序捆绑在一起.任何帮助表示赞赏.

Ben*_*ton 124

实际上,[NSBundle mainBundle]运行UnitTest时不是应用程序的路径,而是/ Developer/usr/bin,所以这不起作用.

在单元测试中获取资源的方法是:OCUnit和NSBundle

简而言之,使用:

[[NSBundle bundleForClass:[self class]] resourcePath]
Run Code Online (Sandbox Code Playgroud)

或者在你的情况下:

[[NSBundle bundleForClass:[self class]] resourceURL]
Run Code Online (Sandbox Code Playgroud)

  • 这非常有帮助.顺便说一句,在Swift中它是`NSBundle(forClass:self.dynamicType)` (18认同)

l -*_*c l 45

斯威夫特2:

let testBundle = Bundle(for: type(of: self))
guard let fileURL = testBundle.url(forResource: "imageName", withExtension: "png") 
  else { fatalError() }

// path approach
guard let filePath = bundle.path(forResource: "dataName", ofType: "csv")
  else { fatalError() }
let fileUrl = URL(fileURLWithPath: filePath)
Run Code Online (Sandbox Code Playgroud)

斯威夫特3,4:

@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
Run Code Online (Sandbox Code Playgroud)

Bundle提供了发现配置的主路径和测试路径的方法:

file:///Users/
  UserName/
    Library/
      Developer/
        Xcode/
          DerivedData/
            App-qwertyuiop.../
              Build/
                Products/
                  Debug-iphonesimulator/
                    AppTests.xctest/
                      imageName.png
Run Code Online (Sandbox Code Playgroud)

Xcode 6 | 7 | 8 URL将是Developer/Xcode/DerivedData......

file:///Users/
  UserName/
    Library/
    Developer/
      CoreSimulator/
        Devices/
          _UUID_/
            data/
              Containers/
                Bundle/
                  Application/
                    _UUID_/
                      App.app/
Run Code Online (Sandbox Code Playgroud)

...与Developer/CoreSimulator/DevicesURL 分开

let testBundle = Bundle(for: type(of: self)) 
print("testBundle.bundlePath = \(testBundle.bundlePath) ")
Run Code Online (Sandbox Code Playgroud)

另请注意,默认情况下,单元测试可执行文件与应用程序代码链接.但是,单元测试代码应仅在测试包中具有目标成员资格.应用程序代码应仅在应用程序包中具有目标成员身份.在运行时,将单元测试目标包注入应用程序包中以供执行.

Swift Package Manager(SPM)4:

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    name: "MyPackageTestResources",
    dependencies: [
        .package(path: "../test-resources"),
    ],
    targets: [
        // ...
        .testTarget(
            name: "MyPackageTests",
            dependencies: ["MyPackage", "MyPackageTestResources"]
        ),
    ]
)
Run Code Online (Sandbox Code Playgroud)

注意:默认情况下,命令行将swift test创建MyProjectPackageTests.xctest测试包.并且,swift package generate-xcodeproj将创建一个MyProjectTests.xctest测试包.这些不同的测试包具有不同的路径.此外,不同的测试包可能具有一些内部目录结构和内容差异.

在任何一种情况下,.bundlePath.bundleURL将返回当前在macOS上运行的测试包的路径.但是,Bundle目前还没有为Ubuntu实现.

此外,命令行swift buildswift test目前不提供复制资源的机制.

但是,通过一些努力,可以设置使用Swift Package Manger和macOS Xcode,macOS命令行和Ubuntu命令行环境中的资源的过程.可以在这里找到一个例子:004.4'2 SW Dev Swift Package Manager(SPM)With Resources Qref

Swift Package Manager(SPM)4.2

Swift Package Manager PackageDescription 4.2引入了对本地依赖项的支持.

本地依赖项是磁盘上的包,可以使用它们的路径直接引用.仅在根包中允许本地依赖性,并且它们将覆盖包图中具有相同名称的所有依赖项.

注意:我希望,但尚未测试,SPM 4.2应该可以使用以下内容:

let testBundle = Bundle(for: type(of: self))
guard let fileURL = testBundle.url(forResource: "imageName", withExtension: "png") 
  else { fatalError() }

// path approach
guard let filePath = bundle.path(forResource: "dataName", ofType: "csv")
  else { fatalError() }
let fileUrl = URL(fileURLWithPath: filePath)
Run Code Online (Sandbox Code Playgroud)


wzb*_*zon 13

只是为了附加正确答案,这是如何获取UnitTests/Supporting Files中文件的filePath的示例:

NSString *filePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"YourFileName.json"];
XCTAssertNotNil(filePath);
Run Code Online (Sandbox Code Playgroud)

这可能对某人有用.