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

如何在Swift/XCTest中写入本地文件?,swift,file-io,xctest,Swift,File Io,Xctest,我的最终问题是如何使用XTest和Swift4(在与电视设备配对的MacBook上运行)保存AppleTV应用程序的屏幕截图,但我甚至无法将简单的文本字符串写入本地文件。如果我能让这个简单的文件保存工作,我希望我能解决屏幕截图的问题。(很抱歉让这看起来像两个问题,但它们似乎是相关的,是我排除故障的结果。) 首先,根据我在网上找到的示例代码,我尝试用一个屏幕截图做如下操作: let appshot = XCUIApplication().windows.firstMatch.screenshot(

我的最终问题是如何使用XTest和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——它只需要放在我笔记本电脑的某个地方(而不是电视设备)。我遗漏了什么?

您可以将附件添加到测试用例并将其保存到磁盘。问题是容器中可能还不存在
下载
文件夹。处理此问题的最佳方法是通过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)
}
如果要查看附件,请右键单击测试用例,选择“跳转到报告”并展开树。您最终将看到屏幕截图:


抓取屏幕截图的一个目的是比较不同时间截图之间的差异。测试用例针对的是一个视频流——暂停时,相隔几秒钟的两个快照应该是相同的。理想情况下,我会使用ImageMagick进行比较(如果Swift允许的话),但如果我甚至不能将文件保存到我想要的位置,这听起来是不可能的。我会更正的。您可以将屏幕截图保存到磁盘,并将其附加到测试报告。保存到磁盘是我的问题--这是我无法获得的部分。尝试此更新的代码时,我在createDirectory步骤中遇到一个致命错误:
Thread 1:致命错误:“try!”表达式意外引发错误:error Domain=nscocaerordomain Code=513“您没有权限将文件“Downloads”保存在文件夹“B9C0B1FD-14D2-4986-9775-B6EF76E4EC37”中。“UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/B9C0B1FD-14D2-4986-9775-B6EF76E4EC37/Downloads,NSUnderlyingError=0x283bf6df0”{Error Domain=NSPOSIXErrorDomain Code=1“不允许操作”}
这与我之前尝试在/var/mobile下创建文件夹时遇到的错误相同。我猜您当时正在设备上测试。我在模拟器中测试了此错误。iOS不允许您创建
下载
文件夹,默认情况下未创建任何文件夹。因此,请选择其他文件夹,如
文档