在 XCUI TestCase 期间最后停止在 UITableView 上滚动

Posted

技术标签:

【中文标题】在 XCUI TestCase 期间最后停止在 UITableView 上滚动【英文标题】:Stop scrolling on UITableView at last during XCUI TestCase 【发布时间】:2018-01-24 09:24:17 【问题描述】:

在我的UITableView 之一中有超过 10 行。我想在UITestCase 运行时滚动到最后一行。

我已经写了下面的代码来滚动到最后一行。

-(void)scrollToElement:(XCUIElement *)element application:(XCUIApplication *)app
    while ([self visible:element withApplication:app]) 
        XCUIElement *searchResultTableView = app.tables[@"searchResultView"];
        XCUICoordinate *startCoord = [searchResultTableView coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
        XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, -262)];
        [startCoord pressForDuration:0.01 thenDragToCoordinate:endCoord];
    

-(BOOL)visible:(XCUIElement *)element withApplication:(XCUIApplication *)app
    if (element.exists && !CGRectIsEmpty(element.frame) && element.isHittable) 
        return CGRectContainsRect([app.windows elementBoundByIndex:0].frame, element.frame);
     else 
        return FALSE;
    

我通过下面的代码在我的UITestCase 方法中调用了上述方法

XCUIElement *searchResultTableView = app.tables[@"searchResultView"];
[self waitForElementToAppear:searchResultTableView withTimeout:30];


XCUIElement *table = [app.tables elementBoundByIndex:0];
XCUIElement *lastCell = [table.cells elementBoundByIndex:table.cells.count - 1];
[self scrollToElement:lastCell application:app];

通过此代码,我可以滚动到最后一行,但到达最后一行后,它继续滚动意味着无法停止滚动。

请帮我滚动到最后一行,然后它应该停止滚动,以便我可以执行下一个动作事件。

我参考了*** 的答案,但没有一个符合我的要求。

提前致谢。

【问题讨论】:

visible 的实现只返回element.exists && element.isHittable 的结果就足够了...对你有用吗? 感谢@Oletha 的重播。我已经尝试过 element.exists && element.isHittable,但仍然无法正常工作。 【参考方案1】:

我在我的一个项目中遇到了类似的问题。 我想通过 TestKit 框架测试“加载更多”功能。

这是实现相同场景的一些解决方法。

//app           : is your current instance of appliaction
//listTable     : is a Table which you've found via accessibility identifier
//loadMoreTest  : is a parameter to determine whether code should perform test for loadmore feature or not

- (void)testScrollableTableForApplication:(XCUIApplication *)app
                                 forTable:(XCUIElement *)listTable
                         withLoadMoreTest:(BOOL)loadMoreTest 

    [listTable accessibilityScroll:UIAccessibilityScrollDirectionUp];
    [listTable swipeUp];

    if (loadMoreTest) 
        __block BOOL isLoadMoreCalled;
        __block XCUIElement *lastCell;
        __block __weak void (^load_more)();
        void (^loadMoreCall)();
        load_more = loadMoreCall = ^() 
            XCUIElementQuery *tablesQuery = app.tables;
            XCUIElementQuery *cellQuery = [tablesQuery.cells containingType:XCUIElementTypeCell identifier:@"LoadMoreCell"];
            lastCell = cellQuery.element;
            if ([lastCell elementIsWithinWindowForApplication:app]) 
                [self waitForElementToAppear:lastCell withTimeout:2];
                [lastCell tap];
                isLoadMoreCalled = true;
                [self wait:2];
            
            [listTable swipeUp];
            if (!isLoadMoreCalled) 
                load_more();
            
        ;
        loadMoreCall();
    



- (void)waitForElementToAppear:(XCUIElement *)element withTimeout:(NSTimeInterval)timeout

    NSUInteger line = __LINE__;
    NSString *file = [NSString stringWithUTF8String:__FILE__];

    NSPredicate *existsPredicate = [NSPredicate predicateWithFormat:@"exists == 1"];
    [self expectationForPredicate:existsPredicate evaluatedWithObject:element handler:nil];

    [self waitForExpectationsWithTimeout:timeout handler:^(NSError * _Nullable error) 
        if (error != nil) 
            NSString *message = [NSString stringWithFormat:@"Failed to find %@ after %f seconds",element,timeout];
            [self recordFailureWithDescription:message inFile:file atLine:line expected:YES];
        
    ];

为 XCUIElement 创建一个类别 XCUIElement+Helper.m 并将其导入到您各自的 Test 类中。

#import <XCTest/XCTest.h>

@interface XCUIElement (Helper)

/// Check whether current XCUIElement is within current window or not
- (BOOL)elementIsWithinWindowForApplication:(XCUIApplication *)app ;

@end

@implementation XCUIElement (Helper)

/// Check whether current XCUIElement is within current window or not
/*
@description: we need to check particular element's frame and window's frame is intersecting or not, to get perfectly outcome whether element is currently visible on screen or not, because if element has not yet appeared on screen then also the flag frame, exists and hittable can become true
*/
- (BOOL)elementIsWithinWindowForApplication:(XCUIApplication *)app 
    if (self.exists && !CGRectIsEmpty(self.frame) && self.hittable)
        return CGRectContainsRect(app.windows.allElementsBoundByIndex[0].frame, self.frame);
    else
        return false;


@end

为了获得“加载更多”单元格,我给出了

cell.accessibilityIdentifier = @"LoadMoreCell";

其余代码是 testScrollableTableForApplication 中的递归函数,以使 Tableview 滚动到底部,这样我就可以访问加载更多单元格(在您的情况下是最后一个单元格)。然后我正在执行操作 Tap 从服务器获取新记录。然后我再次滚动表格以验证是否已从服务器获取新记录。

提示:您可以将递归函数替换为 do whilewhile 循环来实现相同的效果。

希望这会有所帮助!

编码愉快!!

【讨论】:

以上是关于在 XCUI TestCase 期间最后停止在 UITableView 上滚动的主要内容,如果未能解决你的问题,请参考以下文章

Jenkins 服务在节点 js 构建期间完全停止,在 Ubuntu 上使用 nginx 设置获得 502 错误网关

如何在Laravel中检测TestCase的最后一次测试?

在真实设备上的 XCUI 测试中检测暗模式

在 XCUI 测试中终止时未调用 applicationWillTerminate

如何在 XCUI 测试自动化框架中组织和分组测试用例

XCUI 测试:如何单击运行时填充的标签