有没有人在他们的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类中设置的,而不是测试本身。有没有人能够解决这个问题?
答案 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")