• UITesting 界面测试


    1. 创建界面测试视图 UITestingBootcampView.swift

    1. import SwiftUI
    2. /// 界面测试 ViewModel
    3. class UITestingBootcampViewModel: ObservableObject{
    4. let placeholderText: String = "Add name here..."
    5. @Published var textFiledText: String = ""
    6. @Published var currentUserIsSignedIn: Bool
    7. init(currentUserIsSignedIn: Bool) {
    8. self.currentUserIsSignedIn = currentUserIsSignedIn
    9. }
    10. /// 登录按钮处理,模拟测试
    11. func signUpButtonPressed() {
    12. guard !textFiledText.isEmpty else { return }
    13. currentUserIsSignedIn = true
    14. }
    15. }
    16. /// 界面测试
    17. struct UITestingBootcampView: View {
    18. @StateObject private var viewModel: UITestingBootcampViewModel
    19. init(currentUserIsSignedIn: Bool) {
    20. //"_" 下划线表示: 正在引用状态对象 wrappedValue: 表示包装值
    21. _viewModel = StateObject(wrappedValue: UITestingBootcampViewModel(currentUserIsSignedIn: currentUserIsSignedIn))
    22. print("description: " + currentUserIsSignedIn.description)
    23. }
    24. var body: some View {
    25. ZStack {
    26. LinearGradient(
    27. gradient: Gradient(colors: [Color.blue, Color.black]),
    28. startPoint: .topLeading,
    29. endPoint: .bottomTrailing)
    30. .ignoresSafeArea()
    31. ZStack {
    32. if viewModel.currentUserIsSignedIn {
    33. SignedInHomeView()
    34. .frame(maxWidth:.infinity, maxHeight: .infinity)
    35. .transition(.move(edge: .trailing))
    36. }
    37. if !viewModel.currentUserIsSignedIn{
    38. signUpLayer
    39. .frame(maxWidth:.infinity, maxHeight: .infinity)
    40. .transition(.move(edge: .leading))
    41. }
    42. }
    43. }
    44. }
    45. }
    46. /// 扩展 View
    47. extension UITestingBootcampView{
    48. // 登录布局
    49. private var signUpLayer: some View{
    50. VStack {
    51. TextField(viewModel.placeholderText, text: $viewModel.textFiledText)
    52. .font(.headline)
    53. .padding()
    54. .frame(height: 55)
    55. .background(Color.white)
    56. .cornerRadius(10)
    57. .accessibilityIdentifier("SignUpTextField")
    58. Button {
    59. withAnimation(.spring()) {
    60. viewModel.signUpButtonPressed()
    61. }
    62. } label: {
    63. Text("Sign Up")
    64. .font(.headline)
    65. .padding()
    66. .frame(maxWidth: .infinity)
    67. .foregroundColor(.white)
    68. .background(Color.accentColor)
    69. .cornerRadius(10)
    70. }
    71. .accessibilityIdentifier("SignUpButton")
    72. }
    73. .padding()
    74. }
    75. }
    76. /// 登录入主页
    77. struct SignedInHomeView: View{
    78. @State private var showAlert: Bool = false
    79. var body: some View{
    80. NavigationView {
    81. VStack(spacing: 20) {
    82. Button {
    83. showAlert.toggle()
    84. } label: {
    85. Text("Show welcome alert!")
    86. .font(.headline)
    87. .padding()
    88. .frame(maxWidth: .infinity)
    89. .foregroundColor(.white)
    90. .background(Color.red)
    91. .cornerRadius(10)
    92. }
    93. .accessibilityIdentifier("ShowAlertButton")
    94. .alert(isPresented: $showAlert) {
    95. return Alert(title: Text("Welcome to the app!"))
    96. }
    97. NavigationLink(destination: Text("Destination")) {
    98. Text("Navigate")
    99. .font(.headline)
    100. .padding()
    101. .frame(maxWidth: .infinity)
    102. .foregroundColor(.white)
    103. .background(Color.blue)
    104. .cornerRadius(10)
    105. }
    106. .accessibilityIdentifier("NavigationLinkToDestination")
    107. }
    108. .padding()
    109. .navigationTitle("Welcome")
    110. }
    111. }
    112. }
    113. struct UITestingBootcampView_Previews: PreviewProvider {
    114. static var previews: some View {
    115. UITestingBootcampView(currentUserIsSignedIn: true)
    116. }
    117. }

    2. 测试类及自动操作效果图

      2.1 添加界面测试类

          添加方法与单元测试类添加方法一样,注意的是 Test 栏下 选择 UI Testing Bundle。

          创建界面测试文件 UITestingBootcampView_UITests.swift

    1. import XCTest
    2. // 《Testing Swift》 测试书籍
    3. // 书籍网址: https://www.hackingwithswift.com/store/testing-swift
    4. // Naming Structure: test_UnitOfWork_StateUnderTest_ExpectedBehavior - 结构体命名: 测试_工作单元_测试状态_预期的行为
    5. // Naming Structure: test_[struct]_[ui component]_[expected result] - 测试_[结构体]_[界面 组件]_[预期结果 预期值]
    6. // Testing Structure: Given, When, Then - 测试结构: 给定,什么时候,然后
    7. final class UITestingBootcampView_UITests: XCTestCase {
    8. let app = XCUIApplication()
    9. override func setUpWithError() throws {
    10. continueAfterFailure = false
    11. //app.launchArguments = ["-UITest_startSignedIn"]
    12. //app.launchEnvironment = ["-UITest_startSignedIn2" : "true"]
    13. app.launch()
    14. }
    15. override func tearDownWithError() throws {
    16. }
    17. /// 测试_界面测试视图_注册按钮_不能登录
    18. func test_UITestingBootcampView_signUpButton_shouldNotSignIn(){
    19. // Given
    20. signUpAndSignIn(shouldTypeOnKeyboard: false)
    21. // When
    22. let navBar = app.navigationBars["Welcome"]
    23. // Then 断言导航栏不存在
    24. XCTAssertFalse(navBar.exists)
    25. }
    26. /// 测试_界面测试视图_注册按钮_能登录
    27. func test_UITestingBootcampView_signUpButton_shouldSignIn(){
    28. // Given
    29. signUpAndSignIn(shouldTypeOnKeyboard: true)
    30. // When
    31. let navBar = app.navigationBars["Welcome"]
    32. // Then 断言导航栏存在
    33. XCTAssertTrue(navBar.exists)
    34. }
    35. /// 测试_登录到主页_显示警告按钮_能显示警告弹框
    36. func test_SignedInHomeView_showAlertButton_shouldDisplayAlert(){
    37. // Given
    38. signUpAndSignIn(shouldTypeOnKeyboard: true)
    39. // When
    40. tapAlertButton(shouldDismissAlert: false)
    41. // Then
    42. // 查找第一个警告框
    43. let alert = app.alerts.firstMatch
    44. // 警告框是否存在
    45. XCTAssertTrue(alert.exists)
    46. }
    47. /// 测试_登录到主页_显示警告按钮_能显示并关闭警告弹框
    48. func test_SignedInHomeView_showAlertButton_shouldDisplayAndDismissAlert(){
    49. // Given
    50. signUpAndSignIn(shouldTypeOnKeyboard: true)
    51. // When
    52. tapAlertButton(shouldDismissAlert: true)
    53. // Then 断言
    54. // sleep(1)
    55. // 查找第一个警告框,存不存在
    56. let alertExists = app.alerts.firstMatch.waitForExistence(timeout: 5)
    57. XCTAssertFalse(alertExists)
    58. }
    59. /// 测试_登录到主页_导航连接器_能够跳转到
    60. func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestination(){
    61. // Given
    62. signUpAndSignIn(shouldTypeOnKeyboard: true)
    63. // When
    64. tapNavigationLink(shouldDismissDestination: false)
    65. //then 断言文本是否存在
    66. let destinationText = app.staticTexts["Destination"]
    67. XCTAssertTrue(destinationText.exists)
    68. }
    69. /// 测试_登录到主页_导航连接到目标视图_能显示并关闭警告弹框
    70. func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestinationAndGoBack(){
    71. // Given
    72. signUpAndSignIn(shouldTypeOnKeyboard: true)
    73. // When
    74. tapNavigationLink(shouldDismissDestination: true)
    75. //then 断言 Home View 导航栏是否存在
    76. let navBar = app.navigationBars["Welcome"]
    77. // 导航栏是否存在
    78. XCTAssertTrue(navBar.exists)
    79. }
    80. /// 测试_登录到主页_导航连接到目标视图_能显示并关闭警告弹框
    81. // func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestinationAndGoBack2(){
    82. // // Given
    83. //
    84. // // When
    85. // tapNavigationLink(shouldDismissDestination: true)
    86. //
    87. // //then 断言 Home View 导航栏是否存在
    88. // let navBar = app.navigationBars["Welcome"]
    89. // // 导航栏是否存在
    90. // XCTAssertTrue(navBar.exists)
    91. // }
    92. }
    93. // MARK: 也许可能函数
    94. extension UITestingBootcampView_UITests{
    95. /// 提取公共部分代码 注册并登录,键盘输入: trur false
    96. func signUpAndSignIn(shouldTypeOnKeyboard: Bool){
    97. let textfield = app.textFields["SignUpTextField"]
    98. textfield.tap()
    99. if shouldTypeOnKeyboard {
    100. let keyA = app.keys["A"]
    101. keyA.tap()
    102. let keyA1 = app.keys["a"]
    103. keyA1.tap()
    104. keyA1.tap()
    105. let returnButton = app.buttons["Return"]
    106. returnButton.tap()
    107. }
    108. let signUpButton = app.buttons["SignUpButton"]
    109. signUpButton.tap()
    110. }
    111. /// 提取提示框按钮,是否关闭提示框
    112. func tapAlertButton(shouldDismissAlert: Bool){
    113. let showAlertButton = app.buttons["ShowAlertButton"]
    114. showAlertButton.tap()
    115. if shouldDismissAlert{
    116. // 查找第一个警告框 中的 OK 按钮
    117. let alertOKButton = app.alerts.firstMatch.buttons["OK"]
    118. // sleep(1)
    119. // 等待至少 5 秒,让 alertOKButton 存在
    120. let alertPKButtonExists = alertOKButton.waitForExistence(timeout: 5)
    121. // 断言按钮是否存在
    122. XCTAssertTrue(alertPKButtonExists)
    123. alertOKButton.tap()
    124. }
    125. }
    126. /// 提取导航连接器 ,是否关闭目标视图
    127. func tapNavigationLink(shouldDismissDestination: Bool){
    128. // 导航器按钮
    129. let navLinkButton = app.buttons["NavigationLinkToDestination"]
    130. navLinkButton.tap()
    131. if shouldDismissDestination{
    132. // 返回按钮
    133. let backButton = app.navigationBars.buttons["Welcome"]
    134. backButton.tap()
    135. }
    136. }
    137. }

      2.2 点击 test_UITestingBootcampView_signUpButton_shouldNotSignIn 测试方法前 方形运行按钮,得到测试效果,如图:

      2.3 如上测试方法 test_SignedInHomeView_showAlertButton_shouldDisplayAlert 效果图:

      2.4 其他测试方法操作,如上一致。

    3. 从 App 启动类中加载界面测试 View,界面测试时,App 启动类中也需要添加界面测试 View

      3.1 可配启动参数,菜单栏点击 Product -> Scheme -> Edit Scheme... -> Run 选项卡页添加参数,如图:

      3.2 获取配置参数,加载测试界面视图 SwiftfulThinkingAdvancedLearningApp.swift

    1. import SwiftUI
    2. @main
    3. struct SwiftfulThinkingAdvancedLearningApp: App {
    4. let currentUserIsSignedIn: Bool
    5. init() {
    6. // 获取启动参数,判断是否有此字符串: UITestingBootcampView
    7. // let userIsSignedIn:Bool = CommandLine.arguments.contains("-UITest_startSignedIn") ? true : false
    8. let userIsSignedIn:Bool = ProcessInfo.processInfo.arguments.contains("-UITest_startSignedIn") ? true : false
    9. // 获取环境变量配置值
    10. // let value = ProcessInfo.processInfo.environment["-UITest_startSignedIn2"]
    11. // let userIsSignedIn:Bool = value == "true" ? true : false
    12. self.currentUserIsSignedIn = userIsSignedIn
    13. //print("USER IS SIGNED IN: \(userIsSignedIn)")
    14. //print("USER IS SIGNED IN2: \(value ?? "")")
    15. }
    16. var body: some Scene {
    17. WindowGroup {
    18. UITestingBootcampView(currentUserIsSignedIn: self.currentUserIsSignedIn)
    19. }
    20. }
    21. }
  • 相关阅读:
    Ubuntu安装Samba(阿里云服务器、samba端口映射)
    MacOS(M1)交叉编译安卓版本OpenCV(附带FFmpeg)
    数据挖掘助力零售业务增长:从数据分析到策略制定的全过程
    Mac 远程桌面软件
    100天精通Python(爬虫篇)——第44天:requests库大总结
    运动爱好者的专属耳机,轻巧时尚又好用,哈氪无界上手
    Metabase学习教程:视图-3
    openjudge 1.8.5 计算鞍点
    笔试强训第16天
    Selinux
  • 原文地址:https://blog.csdn.net/u011193452/article/details/133889215