Тест на существование UITableViewCell, терпящий неудачу изнутри контроллера разделенного представления - PullRequest
1 голос
/ 20 октября 2019

Я проверяю наличие ячейки табличного представления, и следующий код отлично работает на iPhone 7:

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

Теперь проблема заключается в том, что если я запускаю тот же тест на iPad, гдеконтроллер представления встроен в контроллер разделения представления, тест не пройден:

enter image description here

Представление таблицы все еще отображается на главном контроллере представления:

enter image description here

Так что я не могу понять, почему тест не пройден, даже если представление таблицы является единственным видимым. Есть подсказка?

Полный код:

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()
}

Обновление

Мне удалось выделить проблему: если я просто создаю новый проект,приложение основной детали, и я устанавливаю идентификатор доступности основного представления таблицы, а затем проверяю его существование, проверка не выполняется:

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

Шаги, необходимые для воспроизведения этой проблемы, очень просты,вам просто нужно создать приложение с основными данными, установить идентификатор доступности табличного представления, а затем запустить приведенный выше код. Но если вы хотите, вы также можете клонировать этот репозиторий, который я использовал в качестве демонстрации, чтобы изолировать проблему: https://github.com/ralzuhouri/tableViewTestDemo

Ответы [ 4 ]

0 голосов
/ 25 октября 2019

Я скачал ваше демо.

Когда приложение iPhone запускается с Master View, приложение iPad поставляется с SplitView или Detail View (в портретной ориентации).

Портретное представление должно начинаться с Master + Detail View. Другой вариант изменить тесты пользовательского интерфейса следующим образом:

func testExample() {
    let table = self.app.tables["TableView"]
    if !table.waitForExistence(timeout: 1) {
        app.navigationBars.element.swipeRight()
        XCTAssert(table.waitForExistence(timeout: 2))
    }
    ...
}
0 голосов
/ 23 октября 2019

Ваша проблема, кажется, связана с ориентацией устройства, как я заметил, когда пробовал его в своем тестовом проекте. Мне удалось придумать два решения, оба работают отлично, выбирая между 1 или 1а согласно комментариям в коде. Вариант 1 будет работать как на iPhone, так и на iPad. Вариант 1a зависит от iPad или более крупных iPhone, которые также отображают мастер в альбомной ориентации.

Сначала задайте идентификатор доступности tableViews в своем коде, чтобы легко ссылаться на правильный tableView:

complaintTableView.accessibilityIdentifier = "ComplaintsTableView"

Тогда в ваших тестах просто укажите идентификатор - вот полный тест в соответствии с вашим вопросом выше:

func testNavigation() {
    // 1 - Hit the back button on the collapset master view
    let masterButton = app.navigationBars.buttons.element(boundBy: 0)
    if masterButton.exists {
        masterButton.tap()
        print("BACK TAPPED")
    }
    // 1a - Or just use the line below to rotate the view to landscape which will automatically show the master view
    XCUIDevice.shared.orientation = UIDeviceOrientation.landscapeRight

    let complaintsTable = app.tables["ComplaintsTableView"]
    XCTAssertTrue(complaintsTable.exists, "Table does not exist")
    let complaintCell = complaintsTable.cells.firstMatch
    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()
}
0 голосов
/ 23 октября 2019

Вы, вероятно, будете использовать waitForExistence() вместо .exists

.exists выполняется, как только он будет вызван. Ваш TableView может быть не готов к тестированию в данный момент.

Я бы попытался заменить .exists на waitForExistence()

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

Также вы можете отказаться от этого XCTAssert.

tap() будет ждать существования для3 секунды, а затем выдайте сообщение об ошибке, если ячейка не существует.

Сокращенная версия будет:

app.tables.cells.firstMatch.tap()
0 голосов
/ 21 октября 2019

Я столкнулся с той же проблемой при попытке проверить наличие ячеек таблицы в симуляторе. На смоделированном устройстве iPhone тест прошел бы успешно, тогда как на устройстве iPad он не прошел бы.

Я обнаружил, что проблема заключается в том, что UITest, который ссылается на таблицу, потерпит неудачу, если текущее представление приложения не будет выполнено. есть табличное представление, данные которого вы хотели бы проверить. На iPhone в представлении по умолчанию была кнопка «Назад», которая переводила приложение из подробного представления обратно в главный контроллер представления, который содержал табличное представление. На симуляторе iPad этой кнопки «назад» не было, и поэтому она не могла правильно перейти к представлению таблицы, что привело к провалу всего теста.

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, так и для iPad. Имитация устройства iPhone должна была сделать так, чтобы приложение запускалось и отображало контроллер представления таблицы в самом начале. Это было сделано путем добавления этого кода в swift-файл UISplitViewController:

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
    }

}

Объяснение приведенного выше кода можно найти здесь:

Откройте UISplitViewController в Master View, а не в Detail

Несмотря на это, после вышеупомянутой модификации утверждения о существовании ячейки табличного представления теперь должны успешно выполняться даже на iPad, потому что представление теперь правильно установлено на представление, у которого запрашивается табличное представление.

Если вы не хотите, чтобы ваше приложение запускалось с этим представлением по умолчанию, вам нужно будет убедиться, что ваш тестовый код переходит в представление табличного представления, прежде чем будут сделаны утверждения.

Кроме того, еслиследуйте моему примеру до конца, обязательно удалите эту строку в тестовом примере, потому что больше нет необходимости переходить к VC табличного представления после внесения изменений в код UISplitViewController:

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

UPDATE(25 октября): проект приложения Master Detail - базовый тест существования TableView

Я попытался создать базовое приложение Master Detail, как вы предложили, и также попробовал тест. Базовый тест для просмотра таблицы снова провалился со мной, когда я выбрал устройство iPad для имитации, потому что он показывает только подробный вид (без таблицы). Я изменил свой тест таким образом, чтобы, если устройство представляет собой iPad, оно проверяло его ориентацию и устанавливало альбомную ориентацию по мере необходимости, прежде чем проверять наличие таблицы. Я только изменил тест и ничего больше, и то, что раньше было неудачей, стало успешным. Я также установил идентификатор доступности для табличного представления в viewDidLoad MasterVC, но я считаю, что результаты будут одинаковыми, независимо от того, установим мы идентификатор или нет. Вот тестовый код:

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 и распечатывал логи, чтобы сообщить, какой тип устройства тестируется. Независимо от того, используется ли .exists или .waitForExistence, тесты всегда должны быть успешными. Но, как было отмечено, .waitForExistence лучше в случае, когда табличное представление требует времени для загрузки.

Надеюсь, это поможет. Приветствия!

ОБНОВЛЕНИЕ (27 ОКТЯБРЯ): тест не пройден на реальном iPad

OP обнаружил, что тест - который успешно выполняется для имитированных устройств iPhone и iPad -не удается на реальном устройстве (для получения дополнительной информации, пожалуйста, проверьте его информативный комментарий для этого ответа ниже). Поскольку тест не прошел на реальном iPad, который уже находился в ландшафтном режиме (см. Скриншот), можно предположить, что функциональность XC UITest в этом отношении нарушена.

В любом случае, я надеюсь, что эти тесты и результаты окажутся полезнымиполезно (они, конечно, научили меня одной или двум вещам) и другим.

Приветствия: D

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...