2016-05-02 3 views
1

Кто-нибудь успешно реализовал шаблон объекта страницы в своих тестах пользовательского интерфейса? Я попробовал и столкнулся с проблемой. Когда я использую предикат для ожидания существования элемента, я получаю предупреждение в журнале. Вот фрагмент кода из класса Page объекта:Page Object Pattern for Xcode 7 UI Tests

XCUIElement *myCoolButton = self.app.buttons[@"Super Cool Button"]; 
[self expectationForPredicate:self.existsPredicate evaluatedWithObject:myCoolButton handler:nil]; 
[self waitForExpectationsWithTimeout:5.0f handler:nil]; 

При выполнении этого кода, я вижу следующее в журнале:

Questionable API usage: creating XCTestExpectation for test case -[MyPageObject (null)] which is not the currently running test case -[MyTestCase test] 

и когда превышено время ожидания, я вижу ошибку в log, но сам тест на самом деле не сработает. Я предполагаю, что это происходит потому, что предикат настроен в классе Object Object, а не сам тест. Кто-нибудь мог обойти это?

ответ

1

Из вопроса, я полагаю, waitForExpection записывается в классе Page Objects.

Обычно страница Объекты не наследуются от XCTestCase, так как они используются только для хранения ссылок всех элементов пользовательского интерфейса, возможно, в page.Hence они не могут иметь утверждать действия (waitForExpectation в данном случае)

Если то, что вы пытается написать повторно используемую функцию, которая может иметь такие утверждения, как waitForExpectation в классе PageObject, тогда вам нужно передать тестовый пример в качестве параметра функции (ваша функция должна принять тестовый пример)

Для этого случая, Я предлагаю вам написать категорию (расширение в swift) на XCTestCase с XCUIElement в качестве входного параметра, который ждетForElementToExist вместо записи в pageobject class. Вы можете избежать повторения одного и того же кода во всех объектах страниц.

Пример кода здесь

class LoginPageObect { 
let userNameTextField = XCUIApplication().textFields["UserName"] 
let passwordTextField = XCUIApplication().textFields["Password"] 

    func loginUser(testcase: XCTestCase) { 
    testcase.waitForElementToAppear(userNameTextField) 
    testcase.waitForElementToAppear(passwordTextField) 
    //Do rest of things here 
    } 
} 
extension XCTestCase { 
    func waitForElementToAppear(element: XCUIElement) { 
    let existsPredicate = NSPredicate(format: "exists == true") 
    expectationForPredicate(existsPredicate, 
          evaluatedWithObject: element, handler: nil) 
    waitForExpectationsWithTimeout(5, handler: nil) 
    } 
} 
+0

Спасибо, Shahid. Вы правы, я унаследовал свой класс Object Object от XCTestCase. Я дам продление выстрела. Однако мы бы столкнулись с той же проблемой тайм-аута, что и не сбой теста, поскольку я буду использовать расширение XCUIElement в классе объектов страницы (а не сам тест)? – ryasui

+0

@ryasui: Извините ryasui, означало написать расширение на XCTestCase, которое принимает XCUIElement. Соответственно ответил ответ – Shahid

+0

@ryasui: Объекты страницы не должны делать никаких утверждений. Таким образом, вам не нужно будет писать waitForExpection в классе объектов страницы. В идеале он должен иметь только ссылки на объекты представления, которые используются в классе testcase для записи соответствующих тестов и утверждений. – Shahid

0

Я использовал ту же самую идею прохождения TestCase параметром, но это стало довольно некрасиво позже. Один из подходов (тот, который я предпочитаю) для PageObjects говорит, что у вас не должно быть утверждений на страницах.

Так что я пришел с этой реализации:

class Page { 
    required init(_ c: ((Bool) -> Void)? = nil) { 
     c?(waitForExistence()) 
    } 
    func waitForExistence() -> Bool { 
     fatalError("Subclass of Page should override \(#function)") 
    } 
} 

Затем, вместо того, чтобы использовать waitForExpectation, который требовал бы XCTestCase, вы можете использовать новый XCode9 API для XCUIElement: waitForExistence(timeout:) (или XCTWaiter если вы нужен более сложный ожидания)

class LoginPage: Page { 
    override func waitForExistence() -> Bool { 
     return XCUIApplication().otherElements["view_login"].waitForExistence(timeout: 10) 
    } 

И использование будет:

LoginPage { 
    XCTAssertTrue($0, "Login page not shown") 
} 
.type(email: "[email protected]")