Xcode 7 UI测试的页面对象模式

时间:2016-05-02 18:09:47

标签: xcode-ui-testing pageobjects

有没有人在他们的UI测试中成功实现了Page Object模式?我试了一下,遇到了一个问题。当我使用谓词来等待元素存在时,我会在日志中收到警告。这是Page Object类的代码片段:

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]

当超时超时时,我在日志中看到错误,但测试本身并没有真正失败。我假设这是因为谓词是在Page Object类中设置的,而不是测试本身。有没有人能够解决这个问题?

2 个答案:

答案 0 :(得分:1)

从这个问题来看,我假设waitForExpection是在Page Objects类中编写的。

一般来说,页面对象不是从XCTestCase继承的,因为它们仅用于保存页面中可能存在的所有UI元素的引用。因此它们不能有断言操作(在这种情况下为waitForExpectation)

如果你正在尝试编写一个可重用的函数,它可以在PageObject类中有waitForExpectation等断言,那么你需要将测试用例作为参数传递给函数(你的函数应该接受一个测试用例)< / p>

对于这种情况,我建议你在XCTestCase上用XCUIElement编写一个类别(swift中的扩展名)作为输入参数,它使用waitsForTheElementToExist而不是在pageobject类中编写。你可以避免在所有页面对象中复制相同的代码。

示例代码

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

答案 1 :(得分:0)

我使用了通过参数传递testCase的相同想法,但后来变得非常难看。 PageObjects的一种方法(我喜欢的方法)说你不应该在Pages上有断言。

所以我想出了这个实现:

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

然后,您可以将新的XCode9 API用于 XCUIElement waitForExpectation(或waitForExistence(timeout:) if,而不是使用需要XCTestCase的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: "solid@snake.com")