我有一个非常简单的
XCTestCase
实现,它测试按钮上的点击并期望出现警报控制器。问题是 tap()
方法不起作用。在关联按钮的 IBAction 中放置一个断点,我意识到逻辑甚至没有被调用。
class uitestsampleUITests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
continueAfterFailure = false
app = XCUIApplication()
app.launch()
}
func testButton() {
let button = app.buttons["Button"]
button.tap()
expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5.0, handler: nil)
}
}
此外,复制
button.tap()
指令可使测试通过,如下所示:
func testButton() {
let button = app.buttons["Button"]
button.tap()
button.tap()
expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil)
waitForExpectationsWithTimeout(5.0, handler: nil)
}
我在 Xcode 7.3.1 中遇到这个问题,我是否遗漏了什么?这是一个错误吗?
因此,一位 Apple 工程师对我的错误报告做出了回应:
第二种可能性是你遇到了一个问题 有时会发生在应用程序完成启动但 启动画面不会立即消失,事件会发送到 该应用程序没有得到正确处理。
要尝试解决该问题,请考虑稍微延迟 测试开始(睡眠(1)应该足够了)。
所以我做到了,现在它可以工作了:
override func setUp() {
super.setUp()
continueAfterFailure = false
app = XCUIApplication()
app.launch()
sleep(1)
}
对于可击中的
UIWebView
,在我通过坐标完成之前,水龙头无法工作:
extension XCUIElement {
func forceTap() {
coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap()
}
}
希望对某人有帮助
附注也适用于不可击中的项目,例如标签等。
我也有类似的经历。对我来说,问题是我尝试点击的元素有时由于某种原因不是
hittable
。
来自Apple的文档:
将点击事件发送到为元素计算的可命中点。
因此,如果某个元素不是
hittable
,则点击操作不会执行太多操作,这会破坏测试用例的逻辑。
为了解决这个问题,在点击某些内容之前,我会等到相应的元素变得可点击。非常简单。
#import <XCTest/XCTest.h>
@interface XCUIElement (Tap)
- (void)tapInTestCase:(XCTestCase *)testCase;
@end
@implementation XCUIElement (Tap)
- (void)tapInTestCase:(XCTestCase *)testCase
{
// wait until the element is hittable
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hittable == true"];
[testCase expectationForPredicate:predicate evaluatedWithObject:element handler:nil];
[testCase waitForExpectationsWithTimeout:5.0f handler:nil];
// and then tap
[self tap];
}
@end
您可以在元素加载时
wait
,我创建了这个扩展:
import XCTest
extension XCUIElement {
func tap(wait: Int, test: XCTestCase) {
if !isHittable {
test.expectation(for: NSPredicate(format: "hittable == true"), evaluatedWith: self, handler: nil)
test.waitForExpectations(timeout: TimeInterval(wait), handler: nil)
}
tap()
}
}
像这样使用:
app.buttons["start"].tap(wait: 20, test: self)
对我来说,最可靠的方法是在元素未正确点击的地方添加
sleep(1)
。使用值小于 usleep
的 1000
函数会导致不可靠的行为,例如正确的测试随机失败。
就我而言,问题在于按钮样式。 我正在使用 SUI 并将 ButtonStyle 设置为
.borderless
。在我的列表中(我猜)系统点击不可点击区域。但
XCTAssertTrue(app.buttons["myButton"].isHittable)
不要抛出错误。
可能对某人有帮助
我的按钮位于 LabeledContent 内,可点击,但我的点击未注册。我猜测系统正在点击 LabeledContent 的中心点,而不是按钮本身。以下解决了我的布局问题:
button.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.95)).tap()