Ios 从js到目标C的谓词

Ios 从js到目标C的谓词,ios,objective-c,xcode-ui-testing,Ios,Objective C,Xcode Ui Testing,我在Instruments.app中有一个用于屏幕截图自动化的.js文件,我在其中查找具有以下谓词的单元格: var classScheduleCell = classScheduleTableView.cells().firstWithPredicate("isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'").withValueForKey(1, "isVisible"); 我想将该谓词转换为一个

我在Instruments.app中有一个用于屏幕截图自动化的.js文件,我在其中查找具有以下谓词的单元格:

var classScheduleCell = classScheduleTableView.cells().firstWithPredicate("isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'").withValueForKey(1, "isVisible");
我想将该谓词转换为一个objective C UI测试,因为我用于截图的ruby脚本现在使用UI测试而不是工具。使用相同的谓词失败

XCUIElement *firstCell = [classScheduleTableView.cells elementMatchingPredicate:[NSPredicate predicateWithFormat:@"isEnabled == 1 && NONE staticTexts.value BEGINSWITH 'No classes'"]];
看起来我可以改变谓词的第一部分

isEnabled == 1
为了


关于如何使另一部分工作,有什么想法吗?

我不相信您的确切谓词在UI测试中是可能的

UI测试与UI自动化 将谓词与UI测试(UIT)匹配的行为与UI自动化(UIA)稍有不同。UIA可以更多地访问实际的UIKit元素。UIT是一种更黑的方法,只能通过可访问性API与元素交互

谓词 分解查询,我假设第二部分尝试查找第一个未命名为“No class”的单元格。首先,让我们只匹配
statictext

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
如注释中所述,尝试点击“第一个”单元格会引发异常。这是因为以“无类”开头的文本标签有多个匹配项

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()
希望predict返回单个实例,而不是数组或集合。我不知道如何让查询选择第一个元素。一旦你得到一个
xguielement
,就没有办法进一步限制它了

不同的方法 也就是说,我建议你采取稍微不同的测试方法。如果您的测试是确定性的,并且应该是确定性的,只需点击第一个已知单元。这意味着您不必担心不明确的匹配器或链接谓词

let firstCell = app.staticTexts["Biology"]
XCTAssert(firstCell.exists)
firstCell.tap()

我找到了一个解决方案,虽然不是最优雅的。我找不到一种方法使谓词像UI自动化中的谓词那样工作,所以我使用了两个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;
    }
}
NSPredicate*enabledCellsPredicate=[NSPredicate predicateWithFormat:@“enabled==true”];
XUIElementQuery*enabledCellsQuery=[classScheduleTableView.cells matchingPredicate:enabledCellsPredicate];
int cellCount=enabledCellsQuery.count;
对于(int i=0;i

无论如何,谢谢乔·马西洛蒂的帮助

如果将谓词一分为二,您可能会指出(&&case)的哪一部分不起作用?我不使用
xguielement
,而是使用
statictext.text
我不知道什么是
statictext
?如果我将它分成两部分,我可以使第一部分工作,将isEnabled==1更改为enabled==true。staticText.value是使用Instruments.app在.js中查找标签值的谓词。问题是,我需要找到第一个启用的单元格,其中没有“No class”文本。单元格内容是动态的,经常变化。我将使用您的第一个谓词重试,但是使用
matchingPredicate
而不是
elementMatchingPredicate
,因此如果我得到
xguielementquery
,那么我就可以使用
elementBoundByIndex
获得第一个元素。我会让你知道这是否有效
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;
    }
}