如何在Swift / XCTest中写入本地文件?

时间:2018-09-19 17:30:59

标签: swift file-io xctest

我的最终问题是要使用XCTest和Swift4(在与电视设备配对的MacBook上运行)从AppleTV应用程序保存屏幕截图,但是我什至无法将简单的文本字符串写入本地文件。如果我可以使用这种简单的文件保存功能,希望可以解决屏幕截图问题。 (很抱歉,这看起来像两个问题,但它们似乎是相关的,并且是我的故障排除工作所致。)

首先,这是我要根据我在网上某个地方找到的示例代码对屏幕截图进行的处理:

let appshot = XCUIApplication().windows.firstMatch.screenshot()
let shotpath = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask)[0].appendingPathComponent("appshot.png")
let shotpathUrl = URL(string: "file://\(shotpath)")
print("Saving to: \(shotpath)")

do {
    try appshot.pngRepresentation.write(to: shotpathUrl!)
} catch {
    print("Failed saving screenshot due to \(error)")
}

这给了我以下输出:

Saving to: file:///var/mobile/Containers/Data/Application/77D52C66-353B-4029-97D5-48E6BAE35C92/Downloads/appshot.png
Failed saving screenshot due to Error Domain=NSCocoaErrorDomain Code=4 "The file “appshot.png” doesn’t exist." UserInfo={NSFilePath=///var/mobile/Containers/Data/Application/77D52C66-353B-4029-97D5-48E6BAE35C92/Downloads/appshot.png, NSUnderlyingError=0x1c405bc60 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

当然,该文件不存在,因为那是我要创建的文件。但是/ var / mobile在我的笔记本电脑上也不存在-看起来FileManager正在构建的路径可能在AppleTV设备上存在,但是我希望在我的执行测试脚本的笔记本电脑上使用它。

所以我退出了一个更简单的案例,即使这样也给我带来了问题:

let str = "This is a test"
let path = "file:///Users/haljor/foo.txt"
let pathUrl = URL(string: path)!
print("Path: \(path)")
print("URL: \(pathUrl)")

do {
    try str.write(to: pathUrl, atomically: true, encoding: .utf8)
} catch {
    print("Caught error writing to \(pathUrl): \(error)")
}

这是输出:

Path: file:///Users/haljor/foo.txt
URL: file:///Users/haljor/foo.txt
Caught error writing to file:///Users/haljor/foo.txt: Error Domain=NSCocoaErrorDomain Code=4 "The folder “foo.txt” doesn’t exist." UserInfo={NSURL=file:///Users/haljor/foo.txt, NSUserStringVariant=Folder, NSUnderlyingError=0x1c40553f0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

在这里,它似乎正在尝试以我指定的路径而不是文件写入文件夹。显然,在每种情况下我都不了解。

对于使用完整指定的路径还是使用FileManager进行的操作,我并没有真正的偏好-它只需要放在笔记本电脑的某个位置即可(而不是电视设备)。我想念什么?

1 个答案:

答案 0 :(得分:0)

您可以将附件添加到测试用例,也可以将其保存到磁盘。问题是Downloads文件夹可能尚未在容器中存在。最好的方法是通过init-once属性:

var downloadsFolder: URL = {
    let fm = FileManager.default
    let folder = fm.urls(for: .downloadsDirectory, in: .userDomainMask)[0]

    var isDirectory: ObjCBool = false
    if !(fm.fileExists(atPath: folder.path, isDirectory: &isDirectory) && isDirectory.boolValue) {
        try! fm.createDirectory(at: folder, withIntermediateDirectories: false, attributes: nil)
    }
    return folder
}()

func test() {
    let appshot = XCUIScreen.main.screenshot()
    let attachment = XCTAttachment(screenshot: appshot)
    attachment.lifetime = .keepAlways
    self.add(attachment)

    // Save to container
    let url = downloadsFolder.appendingPathComponent("appshot.png")
    try! appshot.pngRepresentation.write(to: url)
}

如果要查看附件,请右键单击测试用例,选择跳转到报告并展开树。您最终将看到屏幕截图:

Jump to test report