UITesting,XCTest 当前 ViewController Class

UITesting, XCTest current ViewController Class

简单的问题。我得到了执行 segue 到下一个视图控制器的按钮。 我想写 UI XCTest 来告诉我它是否打开了我想要的视图控制器。

UI 测试框架无法访问您的应用程序代码,这使得 class 无法对实例进行断言。您无法直接告诉屏幕上控制器的class。

但是,如果您以稍微不同的方式考虑您的测试,您可以做出非常相似的断言。 编写您的测试,就好像您是用户一样。您的用户不关心 he/she 正在查看 ItemDetailViewController 还是 ItemListTableViewController,所以两者都不关心你应该测试。

用户关心屏幕上显示的内容。标题是什么?或者,这些按钮的名称是什么?按照该逻辑,您将重写测试以根据这些项目进行断言,而不是编码 class.

的名称

例如,如果您在导航堆栈中展示您的控制器,您可以声明标题。

let app = XCUIApplication()
app.buttons["View Item"].tap()

XCTAssert(app.navigationBars["Some Item"].exists)

或者,如果屏幕以模态方式呈现,但您知道一些静态文本或按钮,请使用它们。

let app = XCUIApplication()
app.buttons["View Item"].tap()

XCTAssert(app.staticTexts["Item Detail"].exists)
XCTAssert(app.buttons["Remove Item"].exists)

Matt Green 的评论给了我一个好主意。我们可以定义一个未使用的 label/button,理想情况下是在基本视图控制器内,并为其分配一个可访问性标签以执行查询以找出显示的视图控制器。

public class BaseViewController: UIViewController {

    let button = UIButton(frame: CGRect(x: 0, y: 0, width: 1, height: 1))

    public override func viewDidLoad() {
        super.viewDidLoad()
        if let identifier = self.theClassName.split(separator: ".").last {
            button.accessibilityIdentifier = String(identifier)
            view.addSubview(button)
        }
    }
}

public class DatePickerViewController: BaseViewController {
   ...
}

func testExample() {
    let app = XCUIApplication()
    app.launch()
    app.navigationBars.buttons["DateSelector"].tap()
    XCTAssertTrue(app.buttons["DatePickerViewController"].exists)
}

请注意,为了使这种方法起作用,您必须添加用于标识视图控制器的视图,在本例中为按钮,应添加为子视图并且必须具有非零框架。