4

我正在寻找一种XCTestCase从不依赖于Bundle.

Bundle从 Xcode(或在终端上)运行测试时效果很好xcodebuild,但捆绑包是 Xcode 项目的一部分,并且不适用于 Swift 包管理器(运行时swift test),无论是在 Mac 上还是在 Linux 上。

有没有办法指定应该在所有平台上运行测试的当前目录?或者也许有一种方法可以确定测试的位置,也适用于所有平台?

FileManager.default.currentDirectoryPath只返回当前执行路径(工作目录)。

4

2 回答 2

7

这种方法似乎对我有用,并且应该适用于 Xcode 11 和命令行。我刚刚在这里写的答案的副本。

struct Resource {
  let name: String
  let type: String
  let url: URL

  init(name: String, type: String, sourceFile: StaticString = #file) throws {
    self.name = name
    self.type = type

    // The following assumes that your test source files are all in the same directory, and the resources are one directory down and over
    // <Some folder>
    //  - Resources
    //      - <resource files>
    //  - <Some test source folder>
    //      - <test case files>
    let testCaseURL = URL(fileURLWithPath: "\(sourceFile)", isDirectory: false)
    let testsFolderURL = testCaseURL.deletingLastPathComponent()
    let resourcesFolderURL = testsFolderURL.deletingLastPathComponent().appendingPathComponent("Resources", isDirectory: true)
    self.url = resourcesFolderURL.appendingPathComponent("\(name).\(type)", isDirectory: false)
  }
}

用法:

final class SPMTestDataTests: XCTestCase {
  func testExample() throws {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct
    // results.
    XCTAssertEqual(SPMTestData().text, "Hello, World!")

    let file = try Resource(name: "image", type: "png")
    let image = UIImage(contentsOfFile: file.url.path)
    print(image)
  }
}

在此处输入图像描述

我在#file 这里找到了使用的关键

于 2019-08-29T15:14:23.393 回答
1

似乎在使用 Swift Package Manager ( swift test) 运行测试时,工作目录是项目的根目录。这允许使用相对路径(例如。./Tests/Resources)轻松地从磁盘加载资源。

在评估了不同的选项之后,我编写了以下类来从测试包(如果可用)或给定路径中检索路径。

class Resource {
    static var resourcePath = "./Tests/Resources"

    let name: String
    let type: String

    init(name: String, type: String) {
        self.name = name
        self.type = type
    }

    var path: String {
        guard let path: String = Bundle(for: Swift.type(of: self)).path(forResource: name, ofType: type) else {
            let filename: String = type.isEmpty ? name : "\(name).\(type)"
            return "\(Resource.resourcePath)/\(filename)"
        }
        return path
    }
}

资源必须添加到所有测试目标才能在捆绑包中可用。例如,可以通过文件扩展名更新上述类以支持多个资源路径。

然后可以XCTest根据需要从 a 加载资源:

let file = Resource(name: "datafile", type: "csv")
let content = try String(contentsOfFile: file)
let image = try UIImage(contentsOfFile: Resource(name: "image", type: "png"))

可以添加扩展Resource以加载不同格式的内容。

extension Resource {
    var content: String? {
        return try? String(contentsOfFile: path).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }

    var base64EncodedData: Data? {
        guard let string = content, let data = Data(base64Encoded: string) else {
            return nil
        }
        return data
    }

    var image: Image? {
        return try? UIImage(contentsOfFile: path)
    }
}

并用作:

let json = Resource(name: "datafile", type: "json").contents
let image = Resource(name: "image", type: "jpeg").image
于 2017-09-25T20:48:07.993 回答