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

3
我的最终问题是关于使用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个回答

2

您可以将附件添加到测试用例并保存到磁盘中。问题在于容器中可能尚未存在 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


截图的一个目的是为了比较一段时间内不同截图之间的差异。测试用例针对视频流,当暂停时,相隔几秒钟拍摄的两个截图应该是相同的。理想情况下,我想使用ImageMagick进行比较(如果Swift允许我这样做),但是如果我甚至无法将文件保存到我想要的位置,那么似乎这是不可能的。 - HalJor
我改口了。你可以将屏幕截图保存到磁盘上,并且也可以将其附加到测试报告中。 - Code Different
保存到磁盘是我的问题——这是我一直无法解决的部分。 - HalJor
尝试使用更新的代码时,在createDirectory步骤上遇到了致命错误:Thread 1: Fatal error: 'try!'表达式意外引发了一个错误:Error Domain = NSCocoaErrorDomain Code = 513“您没有权限在文件夹”B9C0B1FD-14D2-4986-9775-B6EF76E4EC37“中保存文件”Downloads“。” UserInfo = {NSFilePath = /var/mobile/Containers/Data/Application/B9C0B1FD-14D2-4986-9775-B6EF76E4EC37/Downloads,NSUnderlyingError = 0x283bf6df0 {Error Domain = NSPOSIXErrorDomain Code = 1”操作不允许“}}这是我早先遇到的相同错误,试图在/var/mobile下创建文件夹。 - HalJor
你没有权限将文件保存到磁盘。请记住,这里的bundle是测试bundle,而不是应用程序bundle。 - Code Different
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接