从 js 到 objective C 的谓词
predicate from js to objective C
我有一个 .js 文件用于我的屏幕截图自动化 Instruments.app 我在其中查找具有以下谓词的单元格:
var classScheduleCell = classScheduleTableView.cells().firstWithPredicate("isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'").withValueForKey(1, "isVisible");
我想将该谓词转换为 objective C UI 测试,因为我用于屏幕截图的 ruby 脚本现在使用 UI 测试而不是 Instruments .使用相同的谓词失败
XCUIElement *firstCell = [classScheduleTableView.cells elementMatchingPredicate:[NSPredicate predicateWithFormat:@"isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'"]];
看来我可以使谓词的第一部分发生变化
isEnabled == 1
为
enabled == true
关于如何使另一部分工作的任何想法?
我认为 UI 测试无法实现您的确切谓词。
UI 测试与 UI 自动化
匹配谓词与 UI 测试 (UIT) 的行为与 UI 自动化 (UIA) 的行为略有不同。 UIA 可以更多地访问实际的 UI 工具包元素。 UIT 是一种更 black-box 的方法,只能通过可访问性 API 与元素交互。
NOT
谓词
分解您的查询我假设第二部分试图找到标题为 'No classes' 的第一个 而不是 的单元格。首先,让我们匹配 staticTexts
.
let predicate = NSPredicate(format: "NOT label BEGINSWITH 'No classes'")
let firstCell = app.staticTexts.elementMatchingPredicate(predicate)
XCTAssert(firstCell.exists)
firstCell.tap() // UI Testing Failure: Multiple matches found
如评论中所述,尝试点击 "first" 单元格会引发异常。这是因为以 "No classes".
开头的文本标签有多个匹配项
NONE
谓词
使用 NSPredicate 的 NONE
运算符让我们走上了不同的道路。
let predicate = NSPredicate(format: "NONE label BEGINSWITH 'No classes'")
let firstCell = app.staticTexts.elementMatchingPredicate(predicate)
XCTAssert(firstCell.exists)// XCTAssertTrue failed: throwing "The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet." -
这种方法甚至找不到单元格。这是因为 elementMatchingPredicate()
期望预测为 return 单个实例,而不是数组或集合。我不知道如何使查询 select 成为第一个元素。一旦你得到 XCUIElement
就没有办法进一步限制它了。
不同的方法
也就是说,我建议您对测试采取稍微不同的方法。如果您的测试是确定性的,而且它们应该是,只需点击第一个已知单元格。这意味着您不必担心不明确的匹配器或链接谓词。
let firstCell = app.staticTexts["Biology"]
XCTAssert(firstCell.exists)
firstCell.tap()
我找到了一个解决方案,虽然不是最优雅的。我找不到使谓词像我在 UI Automation 中那样工作的方法,所以我使用了几个 for 循环来检查单元格标签的值。
NSPredicate *enabledCellsPredicate = [NSPredicate predicateWithFormat:@"enabled == true "];
XCUIElementQuery *enabledCellsQuery = [classScheduleTableView.cells matchingPredicate:enabledCellsPredicate];
int cellCount = enabledCellsQuery.count;
for (int i = 0; i < cellCount; i++) {
XCUIElement *cellElement = [enabledCellsQuery elementBoundByIndex:i];
XCUIElementQuery *cellStaticTextsQuery = cellElement.staticTexts;
int textCount = cellStaticTextsQuery.count;
BOOL foundNoClasses = NO;
for (int j = 0; j < textCount; j++) {
XCUIElement *textElement = [cellStaticTextsQuery elementBoundByIndex:j];
if (textElement.value && [textElement.value rangeOfString:NSLocalizedString(@"No classes", nil) options:NSCaseInsensitiveSearch].location != NSNotFound) {
foundNoClasses = YES;
break;
}
}
if (foundNoClasses == NO) {
[cellElement tap];
break;
}
}
感谢@joe-masilotti 的帮助。
我有一个 .js 文件用于我的屏幕截图自动化 Instruments.app 我在其中查找具有以下谓词的单元格:
var classScheduleCell = classScheduleTableView.cells().firstWithPredicate("isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'").withValueForKey(1, "isVisible");
我想将该谓词转换为 objective C UI 测试,因为我用于屏幕截图的 ruby 脚本现在使用 UI 测试而不是 Instruments .使用相同的谓词失败
XCUIElement *firstCell = [classScheduleTableView.cells elementMatchingPredicate:[NSPredicate predicateWithFormat:@"isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'"]];
看来我可以使谓词的第一部分发生变化
isEnabled == 1
为
enabled == true
关于如何使另一部分工作的任何想法?
我认为 UI 测试无法实现您的确切谓词。
UI 测试与 UI 自动化
匹配谓词与 UI 测试 (UIT) 的行为与 UI 自动化 (UIA) 的行为略有不同。 UIA 可以更多地访问实际的 UI 工具包元素。 UIT 是一种更 black-box 的方法,只能通过可访问性 API 与元素交互。
NOT
谓词
分解您的查询我假设第二部分试图找到标题为 'No classes' 的第一个 而不是 的单元格。首先,让我们匹配 staticTexts
.
let predicate = NSPredicate(format: "NOT label BEGINSWITH 'No classes'")
let firstCell = app.staticTexts.elementMatchingPredicate(predicate)
XCTAssert(firstCell.exists)
firstCell.tap() // UI Testing Failure: Multiple matches found
如评论中所述,尝试点击 "first" 单元格会引发异常。这是因为以 "No classes".
开头的文本标签有多个匹配项NONE
谓词
使用 NSPredicate 的 NONE
运算符让我们走上了不同的道路。
let predicate = NSPredicate(format: "NONE label BEGINSWITH 'No classes'")
let firstCell = app.staticTexts.elementMatchingPredicate(predicate)
XCTAssert(firstCell.exists)// XCTAssertTrue failed: throwing "The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet." -
这种方法甚至找不到单元格。这是因为 elementMatchingPredicate()
期望预测为 return 单个实例,而不是数组或集合。我不知道如何使查询 select 成为第一个元素。一旦你得到 XCUIElement
就没有办法进一步限制它了。
不同的方法
也就是说,我建议您对测试采取稍微不同的方法。如果您的测试是确定性的,而且它们应该是,只需点击第一个已知单元格。这意味着您不必担心不明确的匹配器或链接谓词。
let firstCell = app.staticTexts["Biology"]
XCTAssert(firstCell.exists)
firstCell.tap()
我找到了一个解决方案,虽然不是最优雅的。我找不到使谓词像我在 UI Automation 中那样工作的方法,所以我使用了几个 for 循环来检查单元格标签的值。
NSPredicate *enabledCellsPredicate = [NSPredicate predicateWithFormat:@"enabled == true "];
XCUIElementQuery *enabledCellsQuery = [classScheduleTableView.cells matchingPredicate:enabledCellsPredicate];
int cellCount = enabledCellsQuery.count;
for (int i = 0; i < cellCount; i++) {
XCUIElement *cellElement = [enabledCellsQuery elementBoundByIndex:i];
XCUIElementQuery *cellStaticTextsQuery = cellElement.staticTexts;
int textCount = cellStaticTextsQuery.count;
BOOL foundNoClasses = NO;
for (int j = 0; j < textCount; j++) {
XCUIElement *textElement = [cellStaticTextsQuery elementBoundByIndex:j];
if (textElement.value && [textElement.value rangeOfString:NSLocalizedString(@"No classes", nil) options:NSCaseInsensitiveSearch].location != NSNotFound) {
foundNoClasses = YES;
break;
}
}
if (foundNoClasses == NO) {
[cellElement tap];
break;
}
}
感谢@joe-masilotti 的帮助。