UITesting 界面测试

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

import SwiftUI/// 界面测试 ViewModel
class UITestingBootcampViewModel: ObservableObject{let placeholderText: String = "Add name here..."@Published var textFiledText: String = ""@Published var currentUserIsSignedIn: Boolinit(currentUserIsSignedIn: Bool) {self.currentUserIsSignedIn = currentUserIsSignedIn}/// 登录按钮处理,模拟测试func signUpButtonPressed() {guard !textFiledText.isEmpty else { return }currentUserIsSignedIn = true}
}/// 界面测试
struct UITestingBootcampView: View {@StateObject private var viewModel: UITestingBootcampViewModelinit(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 = falsevar 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)}
}

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

  2.1 添加界面测试类

      添加方法与单元测试类添加方法一样,注意的是 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(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: false)// Whenlet navBar = app.navigationBars["Welcome"]// Then 断言导航栏不存在XCTAssertFalse(navBar.exists)}/// 测试_界面测试视图_注册按钮_能登录func test_UITestingBootcampView_signUpButton_shouldSignIn(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: true)// Whenlet navBar = app.navigationBars["Welcome"]// Then 断言导航栏存在XCTAssertTrue(navBar.exists)}/// 测试_登录到主页_显示警告按钮_能显示警告弹框func test_SignedInHomeView_showAlertButton_shouldDisplayAlert(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: true)// WhentapAlertButton(shouldDismissAlert: false)// Then// 查找第一个警告框let alert = app.alerts.firstMatch// 警告框是否存在XCTAssertTrue(alert.exists)}/// 测试_登录到主页_显示警告按钮_能显示并关闭警告弹框func test_SignedInHomeView_showAlertButton_shouldDisplayAndDismissAlert(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: true)// WhentapAlertButton(shouldDismissAlert: true)// Then 断言// sleep(1)// 查找第一个警告框,存不存在let alertExists = app.alerts.firstMatch.waitForExistence(timeout: 5)XCTAssertFalse(alertExists)}/// 测试_登录到主页_导航连接器_能够跳转到func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestination(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: true)// WhentapNavigationLink(shouldDismissDestination: false)//then 断言文本是否存在let destinationText = app.staticTexts["Destination"]XCTAssertTrue(destinationText.exists)}/// 测试_登录到主页_导航连接到目标视图_能显示并关闭警告弹框func test_SignedInHomeView_navigationLinkToDestination_shouldNavigateToDestinationAndGoBack(){// GivensignUpAndSignIn(shouldTypeOnKeyboard: true)// WhentapNavigationLink(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 falsefunc 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()}}
}

  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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/164376.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『吴秋霖赠书活动 | 第三期』《Python asyncio并发编程》

文章目录 1. 写在前面2. 浅谈asyncio3. Python asyncio并发编程 不再受限于!asyncio异步让你的程序在高并发时翱翔自如! 声明:赠书活动是博主与出版社达成合作,只属于粉丝的专属福利 本期书籍:《Python asyncio并发编程…

数字货币和区块链:跨境电商的未来之革命

随着全球数字化浪潮的不断涌现,跨境电商正经历着前所未有的革命。其中,数字货币和区块链技术被认为是这场革命的关键驱动力。 它们不仅改变了支付方式,还提供了更安全、高效的交易体验,同时也为跨境电商开启了新的商业模式和机会…

38 WEB漏洞-反序列化之PHPJAVA全解(下)

目录 Java中的API实现序列化和反序列化演示案例WebGoat_Javaweb靶场反序列化测试2020-网鼎杯-朱雀组-Web-think java真题复现 文章参考: https://www.cnblogs.com/zhengna/p/15737517.html https://blog.csdn.net/MCTSOG/article/details/123819548 ysoserial生成攻…

可以更改字体颜色的便签备忘录工具选择用哪个

日常添加笔记记录是一个非常好的习惯,通过笔记来记录一些重要的内容一方面可以帮助大家回顾过去的相关记录,另一方面如果记录的笔记是有关学习类的,还有助于大家随时查看记录的笔记。 多数时候记录笔记内容大家通常会选择一些比较方便易操作…

SQL数据库管理工具RazorSQL mac中文版特点与功能

RazorSQL mac是一款功能强大的SQL数据库管理工具,它支持多种数据库,包括MySQL、Oracle、Microsoft SQL Server、SQLite、PostgreSQL等。 RazorSQL mac 软件特点和功能 多种数据库支持:RazorSQL支持多种数据库,用户可以通过一个工…

Windows 事件日志监控

Windows 事件日志是记录 Microsoft 系统上发生的所有活动的文件,在 Windows 环境中,将记录系统上托管的系统、安全性和应用程序的事件,事件日志提供包含有关事件的详细信息,包括日期、时间、事件 ID、源、事件类型和发起它的用户。…

UE4 材质实操记录

TexCoord的R通道是从左到右的递增量,G通道是从上到下的递增量,R通道减去0.5,那么左边就是【-0.5~0】区间,所以左边为全黑,Abs取绝对值,就达到一个两边向中间的一个递减的效果,G通道同理&#xf…

01. 汇编LED驱动实验

01. 汇编LED驱动实验 汇编原理分析为什么要学习Cortex—A汇编STM32IO初始化流程IMX6UL初始化流程 汇编基础处理器内部数据传输指令存储器访问指令 编写驱动编译程序烧写bin文件 汇编原理分析 为什么要学习Cortex—A汇编 需要用汇编初始化一些SOC外设使用汇编初始化DDR&#x…

QT_day2

使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为…

python 对图片增加边框,logo贴图,获取图片exif参数,填写图片文本内容

完整代码 # 找到个可以下载免费字体的网站https://font.chi删除我naz.com/mi删除我anfei.html from PIL import Image, ImageDraw, ImageFont import exifreaddef photo_exif(image_path):f open(image_path, rb)tags exifread.process_file(f)# 打印所有照片信息&#xff0…

Mac电脑版交互式原型设计软件 Axure RP 8汉化 for mac

Axure RP 8是一款专业快速原型设计软件,它主要用于定义需求、设计功能和界面等,适用于商业分析师、信息架构师、产品经理、IT咨询师、用户体验设计师、交互设计师和UI设计师等用户。 该软件可以快速、高效地创建原型,并支持多人协作设计和版…

【vue3】组件间通讯

1.上级传给下级 父级组件&#xff1a; <ReqTab ref"crontabRef" hide"openCronfalse" fill"crontabFill" :expression"expression" :method"method" ></ReqTab> 函数中赋值&#xff1a; 子组件&#xff1a; …

Android问题笔记 - NoSuchmethodException: could not find Fragment constructor

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

AFL安全漏洞挖掘

安全之安全(security)博客目录导读 ATF(TF-A)/OPTEE之FUZZ安全漏洞挖掘汇总 目录 一、AFL简介 二、AFL的安装 三、代码示例及种子语料库 四、AFL插桩编译 五、AFL运行及测试 六、AFL结果分析 一、AFL简介 模糊测试&#xff08;Fuzzing&#xff09;技术作为漏洞挖掘最有…

【AI视野·今日Robot 机器人论文速览 第五十六期】Tue, 17 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 17 Oct 2023 Totally 60 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Interactive Task Planning with Language Models Authors Boyi Li, Philipp Wu, Pieter Abbeel, Jitendra Malik交互式机器人…

配置 Pod 以使用 PersistentVolume 作为存储

配置 Pod 以使用 PersistentVolume 作为存储 本文将向你介绍如何配置 Pod 使用 PersistentVolumeClaim 作为存储。 以下是该过程的总结&#xff1a; 你作为集群管理员创建由物理存储支持的 PersistentVolume。你不会将该卷与任何 Pod 关联。你现在以开发人员或者集群用户的角色…

Docker安装GitLab及使用图文教程

作者&#xff1a; 宋发元 GitLab安装及使用教程 官方教程 https://docs.gitlab.com/ee/install/docker.html Docker安装GitLab 宿主机创建容器持久化目录卷 mkdir -p /docker/gitlab/{config,data,logs}拉取GitLab镜像 docker pull gitlab/gitlab-ce:15.3.1-ce.0运行GitLa…

idea中java类属性(字段)链式赋值

很多人看到标题可能会想到 lombok 的 Builder&#xff0c;lombok 在国内用的挺多的&#xff0c;开源的组件中 mybatis-plus 中用到了这个&#xff0c;使用这个有一个问题就是通过对应 get 和 set 方法找不到对应的赋值方法&#xff0c;因为 lombok 使用了 apt 在编译期生成了相…

屏幕录制视频编辑软件 Camtasia 2023 mac中文版软件功能

Camtasia 2023 mac是一款功能强大的屏幕录制和视频编辑软件&#xff0c;可以用于制作教育课程、演示文稿、培训视频等。它具有一系列工具和功能&#xff0c;包括屏幕录制、视频编辑、音频编辑、字幕、特效等&#xff0c;使用户可以轻松地创建高质量的视频内容。 Camtasia2023的…

如何使用 Selenium 实现自动化操作?

本篇咱们来谈谈Selenium自动化脚本是如何工作的&#xff0c;以及如何实现一个简单的自动化示例&#xff1b; 一、关于Selenium 1.1、为什么选择它作为web自动化的测试工具&#xff1f; 选择Selenium作为web自动化测试工具的原因&#xff08;面试也许会问&#xff09;&#xf…