问题
I am new to the Swift Package Manager but with its integration into Xcode 11 it is time to give it a try. I have a new application and SPM library within a new workspace. I have a working library with tests and have successfully imported the library into the application.
I need to extend the SPM library with new tests that parse json files. I have learned that a resources directory feature is not supported. The only workable scheme seems to be a file copy step added to the library build process so that the resource files can be discovered by the executable.
I could figure out how to do this from the command line but not with Xcode running the build and test. There is no Copy Bundle Resources, build phase for swift packages. In fact everything appears to be hidden by Xcode.
I have looked within the SPM for Makefile type files that would allow me to edit default command line actions thereby circumventing Xcode; but I am not seeing them.
Is there some way to interact/control how Xcode 11 builds SPM targets so that I can copy non-code files to test targets?
回答1:
Got it working!!!
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)
}
}
Usage:
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)
}
}
I found the key of using #file
here
回答2:
This is another workaround to provide access to test resources. Hopefully an answer to the OP's question will be forthcoming.
Using the code below, an extension is created to allow callers to create URL's to test resources like this.
let url = URL(forResource: "payload", type: "json")
This code requires that all resource files be located in a flat directory named "Resources" just under the test target.
// MARK: - ./Resources/ Workaround
// URL of the directory containing non-code, test resource fi;es.
//
// It is required that a directory named "Resources" be contained immediately below the test target.
// Root
// Package.swift
// Tests
// (target)
// Resources
//
fileprivate let _resources: URL = {
func packageRoot(of file: String) -> URL? {
func isPackageRoot(_ url: URL) -> Bool {
let filename = url.appendingPathComponent("Package.swift", isDirectory: false)
return FileManager.default.fileExists(atPath: filename.path)
}
var url = URL(fileURLWithPath: file, isDirectory: false)
repeat {
url = url.deletingLastPathComponent()
if url.pathComponents.count <= 1 {
return nil
}
} while !isPackageRoot(url)
return url
}
guard let root = packageRoot(of: #file) else {
fatalError("\(#file) must be contained in a Swift Package Manager project.")
}
let fileComponents = URL(fileURLWithPath: #file, isDirectory: false).pathComponents
let rootComponenets = root.pathComponents
let trailingComponents = Array(fileComponents.dropFirst(rootComponenets.count))
let resourceComponents = rootComponenets + trailingComponents[0...1] + ["Resources"]
return URL(fileURLWithPath: resourceComponents.joined(separator: "/"), isDirectory: true)
}()
extension URL {
init(forResource name: String, type: String) {
let url = _resources.appendingPathComponent("\(name).\(type)", isDirectory: false)
self = url
}
}
来源:https://stackoverflow.com/questions/57693818/copying-resource-files-for-xcode-spm-tests