ios - 从分割 View Controller 内部测试 UITableViewCell 是否存在失败

标签 ios swift xctest ui-testing

我正在测试表格 View 单元是否存在,以下代码在 iPhone 7 上运行得非常好:

let complaintCell = self.app.tables.cells.element(boundBy: 0)
XCTAssert(complaintCell.exists)
complaintCell.tap()

现在的问题是,如果我在 View Controller 嵌入到 Split View Controller 中的 iPad 上运行相同的测试,则测试会失败:

enter image description here

TableView 在主视图 Controller 上仍然可见:

enter image description here

所以我找不到测试失败的原因,即使 TableView 是唯一可见的。有什么提示吗?

完整代码:

func testNavigation() {
    let complaintCell = self.app.tables.cells.element(boundBy: 0)
    XCTAssert(complaintCell.exists)
    complaintCell.tap()

    XCTAssert(self.app.navigationBars["Complaint #100"].exists)
    XCTAssertFalse(self.app.navigationBars["Complaint #99"].exists)

    let editButton = self.app.buttons["editComplaint"]
    XCTAssert(editButton.exists)
    editButton.tap()

    XCTAssert(self.app.navigationBars["Complaint #100"].exists)
    XCTAssertFalse(self.app.navigationBars["Complaint #99"].exists)

    let saveButton = self.app.buttons["Save"]
    XCTAssert(saveButton.exists)
    saveButton.tap()

    let okButton = self.app.buttons["Ok"]
    XCTAssert(okButton.exists)
    okButton.tap()
}

更新

我能够隔离问题:如果我只是创建一个新项目、一个主详细信息应用程序,然后设置主 TableView 的可访问性标识符,然后测试它的存在,则测试失败:

let table = self.app.tables["TableView"]
XCTAssert(table.waitForExistence(timeout: 5.0))

重现此问题所需的步骤非常简单,您只需创建一个主详细信息应用程序,设置 TableView 的辅助功能标识符,然后运行上面的代码。但如果您愿意,您也可以克隆此存储库,我将其用作演示来隔离问题:https://github.com/ralzuhouri/tableViewTestDemo

最佳答案

当我尝试在模拟器上测试 tableview 单元格是否存在时,我遇到了同样的问题。在模拟 iPhone 设备上测试会成功,而在 iPad 设备上测试会失败。

我发现问题在于,如果应用程序的当前 View 没有您想要测试其数据的 TableView ,则引用表的 UITest 将失败。在 iPhone 上,默认情况下 View 有一个后退按钮,可以将应用程序从其详细 View 转换回包含表格 View 的主视图 Controller 。在 iPad 模拟器上,这个后退按钮不存在,因此它无法正确转换到 tableview 的 View ,从而导致整个测试失败。

func testTableCellsExist() {

    let app = XCUIApplication()
    app.launch()

    app.navigationBars["AppName.DetailView"].buttons["Root View Controller"].tap()

    let tablesQuery = app.tables["MasterTable"]

    let testCell = tablesQuery.cells.element(boundBy: 49)
    XCTAssert(tablesQuery.cells.count == 50)
    XCTAssert(testCell.exists)
}

为了使 iPad 和 iPhone 设备模拟测试都取得成功,我所做的就是让应用程序一开始就启动并显示 tableview 的 View Controller 。这是通过将此代码添加到 UISplitViewController swift 文件来完成的:

class SplitViewController: UISplitViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self
    self.preferredDisplayMode = .allVisible
}

}

extension SplitViewController: UISplitViewControllerDelegate {
    func splitViewController(
             _ splitViewController: UISplitViewController,
             collapseSecondary secondaryViewController: UIViewController,
             onto primaryViewController: UIViewController) -> Bool {
        // Return true to prevent UIKit from applying its default behavior
        return true
    }

}

以上代码的解释可以在这里找到:

Open UISplitViewController to Master View rather than Detail

无论如何,经过上述修改后,即使在 iPad 上, TableView 单元存在的断言现在也应该成功,因为 View 现在已正确设置为正在查询 TableView 的 View 。

如果您不希望应用程序默认从此 View 启动,则必须确保测试代码在做出断言之前转换到表格 View 的 View 。

此外,如果您按照我的示例进行操作,请务必删除测试用例中的这一行,因为修改 UISplitViewController 代码后不再需要导航到 tableview 的 VC:

app.navigationBars["AppName.DetailView"].buttons["Root View Controller"].tap()

更新(10 月 25 日):Master Detail 应用项目 - 基本 TableView 存在测试

我尝试按照您的建议创建一个基本的主详细信息应用程序,并尝试了测试。当我选择 iPad 设备进行模拟时,表格 View 的基本测试再次失败,因为它仅显示详细 View (没有表格)。我修改了我的测试,以便如果设备是 iPad,它将检查其方向,并根据需要设置横向方向,然后再检查 table 是否存在。我只修改了测试,没有做其他任何事情,之前的失败变成了成功。我还在MasterVC的viewDidLoad中设置了tableview的可访问性标识符,但我相信无论我们是否设置标识符,结果都是相同的。测试代码如下:

func testExample() {
    // UI tests must launch the application that they test.
    let app = XCUIApplication()
    app.launch()

    // Use recording to get started writing UI tests.
    // Use XCTAssert and related functions to verify your tests produce the correct results.

    if UIDevice.current.userInterfaceIdiom == .pad {

        print("TESTING AN IPAD\n")
        print(XCUIDevice.shared.orientation.rawValue)

        // For some reason isPortrait returns false
        // If rawValue == 0 it also seems to indicate iPad in portrait mode
        if (XCUIDevice.shared.orientation.isPortrait || XCUIDevice.shared.orientation.rawValue == 0){
            XCUIDevice.shared.orientation = .landscapeRight
        }
        XCTAssert(app.tables["MyTable"].exists)
        //XCTAssert(app.tables["MyTable"].waitForExistence(timeout: 5.0))
    } else if UIDevice.current.userInterfaceIdiom == .phone {
        print("TESTING AN IPHONE\n")
        XCTAssert(app.tables["MyTable"].exists)
    }


    // XCTAssert(app.tables["MyTable"].exists)

}

我为 iPhone 外壳添加了 else,并打印日志来说明正在测试哪种类型的设备。无论使用 .exists 还是 .waitForExistence,测试都应该始终成功。但正如所指出的,在 TableView 需要时间加载的情况下,.waitForExistence 更好。

希望这有帮助。干杯!

更新(10 月 27 日):在真实 iPad 上测试失败

OP 发现该测试(在模拟 iPhone 和 iPad 设备上成功)在真实设备上失败(有关更多信息,请查看下面他对这个答案的信息评论)。由于测试在已处于横向模式的真实 iPad 上失败(请参见屏幕截图),因此可以假设 XC UITest 功能在这方面已损坏。

无论如何,我希望这些测试和结果对其他人也有帮助(它们确实教会了我一两件事)。

干杯:D

关于ios - 从分割 View Controller 内部测试 UITableViewCell 是否存在失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58475394/

相关文章:

iphone - 钥匙串(keychain)访问中找不到公钥和私钥

iphone - 在 Objective-C 中跟踪类实例的最佳方法是什么?

swift - 'for index'与传统 'for loop'的区别

ios - 服务器到服务器的响应主体是什么样的?

iOS 警告 GLES-Render 和其他

ios - 如何以编程方式使电影播放器​​居中?

ios - 如何调整正在打印在另一个图像上的图像的大小(swift3)

swift - 如何使用 XCTest 测试线程安全

ios - 使用捆绑资源进行测试的最简单方法

ios - rootViewController 呈现 View 时进行单元测试?