Я испробовал все другие доступные способы представления открытой панели, а именно:
panel.begin { (response) in
switch response {
case NSApplication.ModalResponse.OK:
self.openPanelDidSelectURL(panel.urls[0])
default:
return
}
}
... а также:
panel.beginSheetModal(for: view.window!) { (response) in
switch response {
case NSApplication.ModalResponse.OK:
self.openPanelDidSelectURL(panel.urls[0])
default:
return
}
}
... но результатвсегда одно и то же: Весь код сразу после представления панели не покрывается во время тестов.
В конце я понял, что мои тесты пользовательского интерфейса не могут полагаться на некоторыеВыбираемая пользователем папка присутствует везде, где находится открытая панель (последний посещенный каталог?), поэтому я выбрал вместо этого mocking .
Во-первых, в моих тестовых классах пользовательского интерфейса Я применил эту логику настройки:
override func setUp() {
continueAfterFailure = false
let app = XCUIApplication()
app.launchArguments.append("-Testing")
app.launch()
}
(дефис перед «Testing» является обязательным, в противном случае мое основанное на документе приложение macOS будет считать, что я запускаю его, чтобы открыть документ с именем «Testing»", и не в состоянии это сделать)
Далее, на стороне приложения, Я определил глобальное вычисляемое свойство, чтобы определить, выполняем ли мы тест или нет:
public var isTesting: Bool {
return ProcessInfo().arguments.contains("-Testing")
}
Наконец, также на стороне приложения Я завернул все NSOpenPanel
звонкина два метода: один для запроса пользователю на чтение входных файлов, а другой - на запрос пользователя на выходной каталог, в который нужно записать результирующие файлы (это все, что нужно моему приложению с NSOpenPanel
):
public func promptImportInput(completionHandler: @escaping (([URL]) -> Void)) {
guard isTesting == false else {
/*
Always returns the URLs of the bundled resource files:
- 01@2x.png,
- 02@2x.png,
- 03@2x.png,
...
- 09@2x.png,
*/
let urls = (1 ... 9).compactMap { (index) -> URL? in
let fileName = String(format: "%02d", index) + "@2x"
return Bundle.main.url(forResource: fileName, withExtension: "png")
}
return completionHandler(urls)
}
// (The code below cannot be covered during automated testing)
let panel = NSOpenPanel()
panel.canChooseFiles = true
panel.canChooseDirectories = true
panel.canCreateDirectories = false
panel.allowsMultipleSelection = true
let response = panel.runModal()
switch response {
case NSApplication.ModalResponse.OK:
completionHandler(panel.urls)
default:
completionHandler([])
}
}
public func promptExportDestination(completionHandler: @escaping((URL?) -> Void)) {
guard isTesting == false else {
// Testing: write output to the temp directory
// (works even on sandboxed apps):
let tempPath = NSTemporaryDirectory()
return completionHandler(URL(fileURLWithPath: tempPath))
}
// (The code below cannot be covered during automated testing)
let panel = NSOpenPanel()
panel.canChooseFiles = false
panel.canChooseDirectories = true
panel.canCreateDirectories = true
panel.allowsMultipleSelection = false
let response = panel.runModal()
switch response {
case NSApplication.ModalResponse.OK:
completionHandler(panel.urls.first)
default:
completionHandler(nil)
}
}
Части этих двух функций, которые используют фактический NSOpenPanel
вместо насмешки по выбранным пользователем файлам / каталогам , по-прежнему исключены из сбора статистики покрытия кода (но на этот раз это сделано по замыслу),
Но, по крайней мере, сейчас это просто два места.Остальная часть моего кода просто вызывает эти две функции и больше не взаимодействует с NSOpenPanel
напрямую.Я "абстрагировал" интерфейс просмотра файлов ОС от моего приложения ...