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.hqwc.cn/news/140145.html

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

相关文章

c++实现最大堆

前言 在写leetcode的时候,看到一道优先队列的题目,复习了一下最大堆,用c实现了一下。以前听网课的时候,根本看不懂实现,现在自己也能实现了。 参考文献 这个我觉得讲得挺好的,图很生动形象 代码 #incl…

百度智能云推出,国内首个大模型全链路生态支持体系

在10月17日举行的百度世界2023上,百度智能云宣布,百度智能云千帆大模型服务平台已服务17000多家客户,覆盖近500个场景。 同时,新的企业和开发者还正在不断地涌入千帆,大模型调用量高速攀升。平台上既有年龄仅14岁的小…

代理模式(初学)

代理模式 一、什么是代理模式 代理模式:为其他对象提供一种代理以控制对这个对象的访问 二、简单例子 这里面的骏骏就起到了代理的身份,而贵贵则是被代理的身份。 三、代码实现 1、用一个接口(GivingGifts)来保存送礼物的动作…

网工记背命令(6)----链路聚合配置

目录 1.配置手工负载分担模式链路聚合 2.配置LACP模式的链路聚合 3.HUAWEI设备与C厂商设备对接 链路聚合(Link Aggregation)是将多条物理链路捆绑在一起成为一条逻辑链路,从而增加链路带 宽的技术。 常用配置命令 1、执行命令 interface …

轻重链剖分+启发式合并专题

Codeforces-741D(Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths) 一棵根为1 的树,每条边上有一个字符(a-v共22种)。 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中…

大数据Flink(九十七):EXPLAIN、USE和SHOW 子句

文章目录 EXPLAIN、USE和SHOW 子句 一、EXPLAIN 子句 二、USE 子句

C++特性——引用与指针详解

文章目录 引用1. 引用的作用1.1 引用可以做函数参数:1.2 引用做函数返回值: 2 常引用3 引用和指针3.1 引用和指针在语法层面和底层的异同3.1 引用和指针的不同 引用 简单来说,引用就是给一个变量起一个别名。例如: int a 1; in…

阿里云云服务器实例使用教学

目录 云服务器免费试用 详细步骤 Xshell 远程连接 云服务器免费试用 阿里云云服务器网址:阿里云免费试用 - 阿里云 详细步骤 访问阿里云免费试用。单击页面右上方的登录/注册按钮,并根据页面提示完成账号登录(已有阿里云账号)…

vue 自定义指令 -- 指令的值

vue 自定义指令 – 指令的值 **创建 工程: H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day05\准备代码\05-自定义指令-指令的值 vue --vers…

k8s-13 存储之secret

Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。 敏感信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活 。 Pod 可以用两种方式使用 secret:作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里 当 kubelet 为 pod 拉…

HugeGraph 部署和Hubble1.0.0的数据导入Bug修复

背景 HugeGraph 安装部署了最新版本1.0.0,发现它的 Web 工具 Hubble 有一个大 Bug。数据导入的时候,配置节点属性映射这个选项时,下拉框只有一个选项,但实际上,元数据配置中的属性有3个,这个 Bug 是怎么产…

从零开始搭建第一个django项目

目录 配置环境创建 Django 项目和 APP项目组成  ‍子目录文件组成应用文件组成 配置 settings.py启动项目 数据表创建models.pyDjango-models的常用字段和常用配置 Django-admin 引入admin后台和管理员外键views.pyurls.pypostman接口测试 QuerySetInstance功能APIView 的概念…