- import SwiftUI
-
- /// 界面测试 ViewModel
- class UITestingBootcampViewModel: ObservableObject{
- let placeholderText: String = "Add name here..."
- @Published var textFiledText: String = ""
- @Published var currentUserIsSignedIn: Bool
-
- init(currentUserIsSignedIn: Bool) {
- self.currentUserIsSignedIn = currentUserIsSignedIn
- }
-
- /// 登录按钮处理,模拟测试
- func signUpButtonPressed() {
- guard !textFiledText.isEmpty else { return }
- currentUserIsSignedIn = true
- }
- }
-
- /// 界面测试
- struct UITestingBootcampView: View {
- @StateObject private var viewModel: UITestingBootcampViewModel
-
- init(currentUserIsSignedIn: Bool) {
- //"_" 下划线表示: 正在引用状态对象 wrappedValue: 表示包装值
- _viewModel = StateObject(wrappedValue: UITestingBootcampViewModel(currentUserIsSignedIn: currentUserIsSignedIn))
- print("description: " + currentUserIsSignedIn.description)
- }
-
- var body: some View {
- ZStack {
- LinearGradient(
- gradient: Gradient(colors: [Color.blue, Color.black]),
- startPoint: .topLeading,
- endPoint: .bottomTrailing)
- .ignoresSafeArea()
-
- ZStack {
- if viewModel.currentUserIsSignedIn {
- SignedInHomeView()
- .frame(maxWidth:.infinity, maxHeight: .infinity)
- .transition(.move(edge: .trailing))
- }
-
- if !viewModel.currentUserIsSignedIn{
- signUpLayer
- .frame(maxWidth:.infinity, maxHeight: .infinity)
- .transition(.move(edge: .leading))
- }
- }
- }
- }
- }
-
- /// 扩展 View
- extension UITestingBootcampView{
- // 登录布局
- private var signUpLayer: some View{
- VStack {
- TextField(viewModel.placeholderText, text: $viewModel.textFiledText)
- .font(.headline)
- .padding()
- .frame(height: 55)
- .background(Color.white)
- .cornerRadius(10)
- .accessibilityIdentifier("SignUpTextField")
- Button {
- withAnimation(.spring()) {
- viewModel.signUpButtonPressed()
- }
- } label: {
- Text("Sign Up")
- .font(.headline)
- .padding()
- .frame(maxWidth: .infinity)
- .foregroundColor(.white)
- .background(Color.accentColor)
- .cornerRadius(10)
- }
- .accessibilityIdentifier("SignUpButton")
- }
- .padding()
- }
- }
-
- /// 登录入主页
- struct SignedInHomeView: View{
- @State private var showAlert: Bool = false
-
- var body: some View{
- NavigationView {
- VStack(spacing: 20) {
- Button {
- showAlert.toggle()
- } label: {
- Text("Show welcome alert!")
- .font(.headline)
- .padding()
- .frame(maxWidth: .infinity)
- .foregroundColor(.white)
- .background(Color.red)
- .cornerRadius(10)
- }
- .accessibilityIdentifier("ShowAlertButton")
- .alert(isPresented: $showAlert) {
- return Alert(title: Text("Welcome to the app!"))
- }
-
- NavigationLink(destination: Text("Destination")) {
- Text("Navigate")
- .font(.headline)
- .padding()
- .frame(maxWidth: .infinity)
- .foregroundColor(.white)
- .background(Color.blue)
- .cornerRadius(10)
- }
- .accessibilityIdentifier("NavigationLinkToDestination")
- }
- .padding()
- .navigationTitle("Welcome")
- }
- }
- }
-
- struct UITestingBootcampView_Previews: PreviewProvider {
- static var previews: some View {
- UITestingBootcampView(currentUserIsSignedIn: true)
- }
- }
添加方法与单元测试类添加方法一样,注意的是 Test 栏下 选择 UI Testing Bundle。
创建界面测试文件 UITestingBootcampView_UITests.swift
- import XCTest
-
- // 《Testing Swift》 测试书籍
- // 书籍网址: https://www.hackingwithswift.com/store/testing-swift
- // Naming Structure: test_UnitOfWork_StateUnderTest_ExpectedBehavior - 结构体命名: 测试_工作单元_测试状态_预期的行为
- // Naming Structure: test_[struct]_[ui component]_[expected result] - 测试_[结构体]_[界面 组件]_[预期结果 预期值]
- // Testing Structure: Given, When, Then - 测试结构: 给定,什么时候,然后
-
- final class UITestingBootcampView_UITests: XCTestCase {
- let app = XCUIApplication()
-
- override func setUpWithError() throws {
- continueAfterFailure = false
- //app.launchArguments = ["-UITest_startSignedIn"]
- //app.launchEnvironment = ["-UITest_startSignedIn2" : "true"]
- app.launch()
- }
-
- override func tearDownWithError() throws {
- }
-
- /// 测试_界面测试视图_注册按钮_不能登录
- func test_UITestingBootcampView_signUpButton_shouldNotSignIn(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: false)
-
- // When
- let navBar = app.navigationBars["Welcome"]
-
- // Then 断言导航栏不存在
- XCTAssertFalse(navBar.exists)
- }
-
- /// 测试_界面测试视图_注册按钮_能登录
- func test_UITestingBootcampView_signUpButton_shouldSignIn(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: true)
-
- // When
- let navBar = app.navigationBars["Welcome"]
-
- // Then 断言导航栏存在
- XCTAssertTrue(navBar.exists)
- }
-
- /// 测试_登录到主页_显示警告按钮_能显示警告弹框
- func test_SignedInHomeView_showAlertButton_shouldDisplayAlert(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: true)
-
- // When
- tapAlertButton(shouldDismissAlert: false)
-
- // Then
- // 查找第一个警告框
- let alert = app.alerts.firstMatch
- // 警告框是否存在
- XCTAssertTrue(alert.exists)
- }
-
- /// 测试_登录到主页_显示警告按钮_能显示并关闭警告弹框
- func test_SignedInHomeView_showAlertButton_shouldDisplayAndDismissAlert(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: true)
-
- // When
- tapAlertButton(shouldDismissAlert: true)
-
- // Then 断言
- // sleep(1)
- // 查找第一个警告框,存不存在
- let alertExists = app.alerts.firstMatch.waitForExistence(timeout: 5)
- XCTAssertFalse(alertExists)
- }
-
- /// 测试_登录到主页_导航连接器_能够跳转到
- func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestination(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: true)
-
- // When
- tapNavigationLink(shouldDismissDestination: false)
- //then 断言文本是否存在
- let destinationText = app.staticTexts["Destination"]
- XCTAssertTrue(destinationText.exists)
- }
-
- /// 测试_登录到主页_导航连接到目标视图_能显示并关闭警告弹框
- func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestinationAndGoBack(){
- // Given
- signUpAndSignIn(shouldTypeOnKeyboard: true)
-
- // When
- tapNavigationLink(shouldDismissDestination: true)
-
- //then 断言 Home View 导航栏是否存在
- let navBar = app.navigationBars["Welcome"]
- // 导航栏是否存在
- XCTAssertTrue(navBar.exists)
- }
-
- /// 测试_登录到主页_导航连接到目标视图_能显示并关闭警告弹框
- // func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestinationAndGoBack2(){
- // // Given
- //
- // // When
- // tapNavigationLink(shouldDismissDestination: true)
- //
- // //then 断言 Home View 导航栏是否存在
- // let navBar = app.navigationBars["Welcome"]
- // // 导航栏是否存在
- // XCTAssertTrue(navBar.exists)
- // }
- }
-
- // MARK: 也许可能函数
- extension UITestingBootcampView_UITests{
-
- /// 提取公共部分代码 注册并登录,键盘输入: trur false
- func signUpAndSignIn(shouldTypeOnKeyboard: Bool){
- let textfield = app.textFields["SignUpTextField"]
- textfield.tap()
-
- if shouldTypeOnKeyboard {
- let keyA = app.keys["A"]
- keyA.tap()
- let keyA1 = app.keys["a"]
- keyA1.tap()
- keyA1.tap()
-
- let returnButton = app.buttons["Return"]
- returnButton.tap()
- }
-
- let signUpButton = app.buttons["SignUpButton"]
- signUpButton.tap()
- }
-
- /// 提取提示框按钮,是否关闭提示框
- func tapAlertButton(shouldDismissAlert: Bool){
- let showAlertButton = app.buttons["ShowAlertButton"]
- showAlertButton.tap()
-
- if shouldDismissAlert{
- // 查找第一个警告框 中的 OK 按钮
- let alertOKButton = app.alerts.firstMatch.buttons["OK"]
- // sleep(1)
- // 等待至少 5 秒,让 alertOKButton 存在
- let alertPKButtonExists = alertOKButton.waitForExistence(timeout: 5)
- // 断言按钮是否存在
- XCTAssertTrue(alertPKButtonExists)
- alertOKButton.tap()
- }
- }
-
- /// 提取导航连接器 ,是否关闭目标视图
- func tapNavigationLink(shouldDismissDestination: Bool){
- // 导航器按钮
- let navLinkButton = app.buttons["NavigationLinkToDestination"]
- navLinkButton.tap()
-
- if shouldDismissDestination{
- // 返回按钮
- let backButton = app.navigationBars.buttons["Welcome"]
- backButton.tap()
- }
- }
- }



- import SwiftUI
-
- @main
- struct SwiftfulThinkingAdvancedLearningApp: App {
- let currentUserIsSignedIn: Bool
-
- init() {
- // 获取启动参数,判断是否有此字符串: UITestingBootcampView
- // let userIsSignedIn:Bool = CommandLine.arguments.contains("-UITest_startSignedIn") ? true : false
- let userIsSignedIn:Bool = ProcessInfo.processInfo.arguments.contains("-UITest_startSignedIn") ? true : false
- // 获取环境变量配置值
- // let value = ProcessInfo.processInfo.environment["-UITest_startSignedIn2"]
- // let userIsSignedIn:Bool = value == "true" ? true : false
- self.currentUserIsSignedIn = userIsSignedIn
- //print("USER IS SIGNED IN: \(userIsSignedIn)")
- //print("USER IS SIGNED IN2: \(value ?? "")")
- }
-
- var body: some Scene {
- WindowGroup {
- UITestingBootcampView(currentUserIsSignedIn: self.currentUserIsSignedIn)
- }
- }
- }