Как перетащить внешний элемент для Xcode-ui-testing - PullRequest
1 голос
/ 14 июля 2020

В моем приложении я разрешаю пользователю перетаскивать элементы из Finder (или любого другого источника URL-адреса на основе файла) в мое приложение. Я хочу добавить механизм, который позволит мне проверить это в тестировании пользовательского интерфейса Xcode.

Я вижу, как использовать XCUIElement.press(forDuration:thenDragTo:) для проверки перетаскивания источника и места назначения внутри приложение, но мне не удалось найти способ проверить, когда источник перетаскивания находится за пределами приложения.

В несколько похожем тесте я тестирую часть приложения для копирования и вставки, установив строку, которую я хочу вставить в NSPasteboard.general, а затем используя XCUIElement.typeKey("v", modifierFlags: .command), чтобы вставить ее в нужный элемент. Это немного меньше, чем идеально, поскольку это зависит от того, действительно ли Command-v реализована как команда paste, но вряд ли это изменится, поэтому это приемлемо для моих нужд. (На самом деле я написал расширение XCUIElement.paste(_ s: String), которое упрощает мне добавление его в тест.)

Я считаю, что перетаскивание также использует NSPasteboard для обмена данными, поэтому После небольшого исследования механизма, лежащего в основе, я смогу поместить свой объект на правильный монтажный стол, как я это делаю для вырезания и вставки. Я достаточно уверен, что смогу понять эту часть. Но я не понял, как выполнить сброс.

Моей целью было бы создать XCUIElement.drop(_ url), который установил бы правильный объект «publi c .file-url» на правильном монтажном столе. , а затем смоделировать / выполнить падение в элемент.

Есть идеи?

Следует отметить, что я уже пробовал следующие два элемента:

Во-первых, я сделал используйте функцию записи Xcode, чтобы попытаться записать операцию перетаскивания и посмотреть, какие события она мне даст. К сожалению, он абсолютно ничего не записывает.

Во-вторых, у меня есть альтернатива на основе меню, когда пользователь выбирает файл с помощью селектора файлов. Так что, если бы я мог смоделировать выбор файла, это было бы подходящей альтернативой тестирования для моих целей. К сожалению, я тоже не продвинулся по этому пути. Когда я использовал Xcode для записи событий, он записывал выбор меню, ничего, что на самом деле не было сделано в диалоговом окне.

Ответы [ 2 ]

1 голос
/ 14 июля 2020

Основываясь на ваших комментариях, я бы рекомендовал вам прочитать часть документации к этой статье. 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"])
    }
}

PS В этом примере я использую XCTApps, потому что я не хочу запоминать или идентификаторы пакетов Google: D

https://github.com/rzakhar/XCTApps

0 голосов
/ 14 июля 2020

Хорошо, поэтому я еще не нашел ответа на свой вопрос (как протестировать перетаскивание), но я нашел приемлемый обходной путь для моего теста.

В частности, как Я больше думал о монтажном столе. Я понял, что если я разрешаю пользователю перетаскивать файл в мое приложение, то я также должен позволить им вырезать и вставлять файл в приложение.

Один раз У меня было такое осознание, тогда это был достаточно простой процесс для проверки необходимой функции моего приложения путем вставки 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 метод.

Я подожду пару дней, чтобы узнать, придет ли кто-нибудь ответ на собственно вопрос (поскольку я все равно считаю это полезным), но если никто не ответит, я приму свой ответ.

...