IOS UI 测试 - 如何编写打开相机和文件选择器的测试用例
IOS UI Testing - How to write test cases for opening camera and file chooser
我正在使用 XCTest 框架为 IOS 编写测试用例。我想 select 一张照片用于设置用户配置文件,这可以通过两种方式完成:
1. 使用相机拍摄图像。
2. 从文件选择器中选择图像。
我遇到以下问题:
1.我在模拟器上运行这个测试。那么,如何访问相机?
2. 我可以通过单击 "Choose on Photo album" 打开页面文件选择器页面。但是,无法检测到点击页面文件选择器页面。
我的代码如下:
app.buttons["Choose from Photo Album"].tap()
app.tables.firstMatch.cells.element(boundBy: 0).tap()
第 2 行给我错误:
NSInternalInconsistencyException 无效参数不满足
未找到上述案例的单个文档。
我能够使用文件选择器解决第二个用例 i.e.Setting 图像的问题。这是我的代码。
app.tables.cells.element(boundBy: 1).tap()
app.collectionViews["PhotosGridView"].cells["Photo, Landscape, March 13, 2011, 5:47 AM"].tap()
app.buttons["Choose"].tap()
app.buttons["Confirm"].tap()
第 1 行选择两个选项中的一个,即 "Moments" 和 "Camera Roll"
第 2 行从列表中选择 1 个图像
第3、4行确认并设置图像。
但我想知道它是否适用于不同的模拟器,因为图像的日期和时间在该模拟器上可能不同。
我对@deepak-terse的回答有补充:
您可以使用索引代替字符串文件名,因此您不依赖于模拟器。
func selectFromCameraRoll(_ app: XCUIApplication, index: Int = 1) {
app.tables.cells.element(boundBy: 1).tap()
app.collectionViews.cells.element(boundBy: index).tap()
}
您甚至可以使用 arc4random_uniform()
随机化您选择的照片
更新
万一有人发现这个有用,这里是我在真实设备上测试时使用的 UI 测试中相机的辅助函数:
func addPhotoCamera(_ app: XCUIApplication) {
let pleaseSelectSheet = app.sheets.element
// Take Picture button, it is first:
pleaseSelectSheet.buttons.element(boundBy: 0).tap()
// this monstrosity finds Capture button
let element = app
.children(matching: .window).element(boundBy: 0)
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
let photoCapture = element.children(matching: .other).element
.children(matching: .other).element(boundBy: 1)
.children(matching: .other).element
photoCapture.tap()
// I have slow computer, so I need this so test does not fail
sleep(5)
app.buttons["Use Photo"].tap()
}
更新 2
在设备上,上面的相机胶卷不起作用,因为通常有很多照片,所以先点击不在屏幕上的照片无济于事。我最终使用了以下代码片段:
let photoCells = app.collectionViews.cells
if Platform.isSimulator {
photoCells.element(boundBy: index).tap()
} else {
photoCells.allElementsBoundByIndex.last!.firstMatch.tap()
}
其中 Platform.isSimulator
部分取自 :
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
和整段代码一起:
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
extension XCUIElement {
func tapIfExists() {
if exists {
tap()
}
}
}
// MARK: - Helper functions
extension XCTestCase {
func addPhotoCamera(_ app: XCUIApplication) {
let pleaseSelectSheet = app.sheets.element
// ["Take Picture"].tap()
pleaseSelectSheet.buttons.element(boundBy: 0).tap()
// use coordinates and tap on Take picture button
let element = app
.children(matching: .window).element(boundBy: 0)
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
let photoCapture = element.children(matching: .other).element
.children(matching: .other).element(boundBy: 1)
.children(matching: .other).element
photoCapture.tap()
sleep(5)
app.buttons["Use Photo"].tap()
}
func addPhotoLibrary(_ app: XCUIApplication, index: Int = 0) {
let pleaseSelectSheet = app.sheets["Add Photo"]
pleaseSelectSheet.buttons.element(boundBy: 1).tap()
sleep(10)
// Camera Roll
app.tables.cells.element(boundBy: 1).tap()
sleep(2)
let photoCells = app.collectionViews.cells
if Platform.isSimulator {
photoCells.element(boundBy: index).tap()
} else {
photoCells.allElementsBoundByIndex.last!.firstMatch.tap()
}
sleep(2)
app.buttons["Choose"].tapIfExists()
}
}
我正在使用 XCTest 框架为 IOS 编写测试用例。我想 select 一张照片用于设置用户配置文件,这可以通过两种方式完成: 1. 使用相机拍摄图像。 2. 从文件选择器中选择图像。
我遇到以下问题: 1.我在模拟器上运行这个测试。那么,如何访问相机? 2. 我可以通过单击 "Choose on Photo album" 打开页面文件选择器页面。但是,无法检测到点击页面文件选择器页面。
我的代码如下:
app.buttons["Choose from Photo Album"].tap()
app.tables.firstMatch.cells.element(boundBy: 0).tap()
第 2 行给我错误: NSInternalInconsistencyException 无效参数不满足
未找到上述案例的单个文档。
我能够使用文件选择器解决第二个用例 i.e.Setting 图像的问题。这是我的代码。
app.tables.cells.element(boundBy: 1).tap()
app.collectionViews["PhotosGridView"].cells["Photo, Landscape, March 13, 2011, 5:47 AM"].tap()
app.buttons["Choose"].tap()
app.buttons["Confirm"].tap()
第 1 行选择两个选项中的一个,即 "Moments" 和 "Camera Roll" 第 2 行从列表中选择 1 个图像 第3、4行确认并设置图像。
但我想知道它是否适用于不同的模拟器,因为图像的日期和时间在该模拟器上可能不同。
我对@deepak-terse的回答有补充:
您可以使用索引代替字符串文件名,因此您不依赖于模拟器。
func selectFromCameraRoll(_ app: XCUIApplication, index: Int = 1) {
app.tables.cells.element(boundBy: 1).tap()
app.collectionViews.cells.element(boundBy: index).tap()
}
您甚至可以使用 arc4random_uniform()
更新
万一有人发现这个有用,这里是我在真实设备上测试时使用的 UI 测试中相机的辅助函数:
func addPhotoCamera(_ app: XCUIApplication) {
let pleaseSelectSheet = app.sheets.element
// Take Picture button, it is first:
pleaseSelectSheet.buttons.element(boundBy: 0).tap()
// this monstrosity finds Capture button
let element = app
.children(matching: .window).element(boundBy: 0)
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
let photoCapture = element.children(matching: .other).element
.children(matching: .other).element(boundBy: 1)
.children(matching: .other).element
photoCapture.tap()
// I have slow computer, so I need this so test does not fail
sleep(5)
app.buttons["Use Photo"].tap()
}
更新 2
在设备上,上面的相机胶卷不起作用,因为通常有很多照片,所以先点击不在屏幕上的照片无济于事。我最终使用了以下代码片段:
let photoCells = app.collectionViews.cells
if Platform.isSimulator {
photoCells.element(boundBy: index).tap()
} else {
photoCells.allElementsBoundByIndex.last!.firstMatch.tap()
}
其中 Platform.isSimulator
部分取自 :
import Foundation
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
和整段代码一起:
struct Platform {
static var isSimulator: Bool {
return TARGET_OS_SIMULATOR != 0
}
}
extension XCUIElement {
func tapIfExists() {
if exists {
tap()
}
}
}
// MARK: - Helper functions
extension XCTestCase {
func addPhotoCamera(_ app: XCUIApplication) {
let pleaseSelectSheet = app.sheets.element
// ["Take Picture"].tap()
pleaseSelectSheet.buttons.element(boundBy: 0).tap()
// use coordinates and tap on Take picture button
let element = app
.children(matching: .window).element(boundBy: 0)
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
.children(matching: .other).element
let photoCapture = element.children(matching: .other).element
.children(matching: .other).element(boundBy: 1)
.children(matching: .other).element
photoCapture.tap()
sleep(5)
app.buttons["Use Photo"].tap()
}
func addPhotoLibrary(_ app: XCUIApplication, index: Int = 0) {
let pleaseSelectSheet = app.sheets["Add Photo"]
pleaseSelectSheet.buttons.element(boundBy: 1).tap()
sleep(10)
// Camera Roll
app.tables.cells.element(boundBy: 1).tap()
sleep(2)
let photoCells = app.collectionViews.cells
if Platform.isSimulator {
photoCells.element(boundBy: index).tap()
} else {
photoCells.allElementsBoundByIndex.last!.firstMatch.tap()
}
sleep(2)
app.buttons["Choose"].tapIfExists()
}
}