在我的应用程序中,我允许用户将项目从Finder (或任何其他基于URL的文件来源)拖放到我的应用程序中。我想要做的是添加一种机制,允许我在Xcode UI测试中对此进行测试。
我可以看到如何使用XCUIElement.press(forDuration:thenDragTo:)来测试源和目标在应用程序中的拖放,但我一直无法找到一种方法来测试拖放源是否在应用程序之外。
在一个相关的测试中,我测试了应用程序的复制和粘贴部分,方法是设置要粘贴到NSPasteboard.general中的字符串,然后使用XCUIElement.typeKey("v", modifierFlags: .command)将其粘贴到所需的元素中。这有点不太理想,因为它依赖于Command-v实际上是作为粘贴命令实现的,但这种情况不太可能改变,所以我的需要是可以接受的。(实际上,我已经编写了一个XCUIElement.paste(_ s: String)扩展,它使我可以轻松地将其添加到测试中。)
我相信拖放也是使用NSPasteboard进行通信的,所以只要稍微研究一下底层机制,我就应该能够将对象设置到正确的粘贴板中,就像对剪切和粘贴所做的那样。我相当确定我能弄清楚这一部分。但我还没有想出如何执行实际的drop。
我的目标是创建一个XCUIElement.drop(_ url),将正确的“proper .file-url”对象设置到正确的粘贴板中,然后模拟/执行拖放到元素中。
有什么想法吗?
我应该注意到,我已经尝试了以下两个项目:
首先,我确实使用了Xcode记录功能来尝试记录拖放操作,并查看它会给我带来什么事件。不幸的是,它完全没有记录任何东西。
其次,我确实有一个基于菜单的替代方案,用户可以通过文件选择器选择一个文件。因此,如果我可以模拟文件选择,这将是一个适合我的目的的测试替代方案。不幸的是,我在这条道路上也没有取得任何进展。当我使用Xcode记录事件时,它记录了菜单选择,对话框中实际上没有执行任何操作。
发布于 2020-07-14 17:40:30
根据您的评论,我建议您阅读这篇文章的文档部分https://developer.apple.com/documentation/xctest/xcuiapplication
请注意init(bundleIdentifier: String)和init(url: URL)方法。这些允许您与目标应用程序之外的应用程序进行交互。
然后,您可以使用XCUIElement.press(forDuration:thenDragTo:)
import XCTest
import XCTApps
import ScreenObject
let notes = XCTApps.notes.app
let photos = XCTApps.photos.app
class Tests: XCTestCase {
func testDragAndDrop() {
photos.launch()
notes.launch()
photos.images.lastMatch.press(forDuration: 1, thenDragTo: notes.textViews["Note Body Text View"])
}
}在这个例子中,我使用了XCTApps,因为我不想记住或者谷歌包标识符:D
发布于 2020-07-14 07:45:37
好吧,我还没有想出我的问题的答案(如何测试拖放),但我已经为我的测试提出了一个可以接受的变通办法。
特别是,当我更多地考虑粘贴板时,我意识到如果我允许用户将文件拖放到我的应用程序中,那么我也应该允许他们将文件剪切和粘贴到应用程序中。
一旦我意识到这一点,那么通过粘贴URL而不是拖放URL来测试我的应用程序的必要功能就是一个相当简单的过程。这有一个额外的好处,那就是我可以将必要的测试文件添加到我的测试包中,使所有内容保持良好的自包含状态。
为此,我在XCUIElement扩展中添加了以下函数:
extension XCUIElement {
func paste(url: URL) {
precondition(url.isFileURL, "This must be a file URL to match the pasteboard type.")
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(url.absoluteString, forType: .fileURL)
click()
typeKey("v", modifierFlags: .command)
}
}然后在我的测试代码中添加以下代码来触发事件:
let mainWindow = app.windows[/*...my main window name goes here...*/]
let testBundle = Bundle(for: type(of: self))
let fileURL = testBundle.url(forResource: "Resources/simple", withExtension: "json")
mainWindow.paste(url: fileURL!)诚然,这并不实际测试拖放,但它确实测试了我的代码的相同部分,因为在我的AppDelegate中,我的onPaste操作方法调用与我的performDrop方法相同的底层方法。
我将等待几天,看看是否有人提出了实际问题的答案(因为我仍然会发现这是有用的),但如果没有人这样做,我会接受我自己的答案。
https://stackoverflow.com/questions/62884594
复制相似问题