2023年7月14日发(作者:)
iOS⾃动化测试(XCTest,UITests)前⾔如何创建⾃动化测试创建好的⾃动化测试在哪⾥?如何使⽤⾃动化测试⽣命周期(运⾏流程)具体使⽤介绍初始化 App获取元素根据类型取元素根据 label 取元素根据下标取元素根据 identifier 取元素对元素的操作点击双击长按滑动捏合旋转实际⽤例具体点击 UITableView 某⼀⾏直接打开其他 App系统桌⾯ App(springboard)申请系统权限, 点击系统权限弹框(例如通知权限)Home键系统⾳量按键Siri设备转⽅向项⽬地址前⾔最近正在学习 iOS ⾃动化测试(系统⾃带的 XCTest), 就总结⼀下⾃动化测试⼀些知识.内容可能有点啰嗦, 如想直接看代码, 可直接跳到最后⼀栏, 去下载项⽬如何创建⾃动化测试这⾥分两种创建情况1. 刚新建项⽬创建项⽬时, 勾上 Include UI Tests 即可iOS ⾃动化测试(XCTest, UITests)2. 已有了项⽬,却没有⾃动化测试其实就是添加 target我们点击 '+' 号,在这⾥插⼊图⽚描述选择 UI Testing Bundle在这⾥插⼊图⽚描述创建好的⾃动化测试在哪⾥?创建好之后, 是在该⽬录下(看图), 默认名称是 项⽬名 + UITests看到这⾥, 写过 app extension 的⽼哥应该都明⽩了, 其实这个⾃动化测试就是⼀个 app extension 来的, 我们可以随意删除和创建, 甚⾄创建多个都是没问题的在这⾥插⼊图⽚描述如何使⽤⾃动化测试这⾥⼀般有两种使⽤法1. 在 Show the Test Navigator 中使⽤如图, 放⿏标到, 放在函数上, 例如 testExample()这时我们就能看到右边有个播放的⼩箭头, 点击这个⼩箭头, 我们就开始运⾏这个 testExample() 函数了如果运⾏⼤写 T(XQUITestDemoUITests), 就是运⾏这个测试模块中所有函数的意思运⾏⾃动化测试, 和运⾏项⽬⼀样的, 可以先选择设备, 就是选择真机或者某个模拟器刚创建时, 只有 testLaunchPerformance() 和 testExample() 两个函数其他函数是我后⾯写的在这⾥插⼊图⽚描述2. 在 UITest 模块的 .swift ⽂件⾥⾯选择运⾏上⾯的 testExample() 这些函数, 其实就是关联这个⽂件⾥⾯的函数我们点开 UITest 模块的 .swift ⽂件(如下图), 就⼀切明了了在这⾥插⼊图⽚描述代码⾏数那⾥的四边形, 点击效果和上⾯说的⼀样, 就是运⾏⾃动化测试点击 class 旁边的运⾏, 是运⾏整个类⾥⾯所有函数的(和上⾯说的运⾏整个测试模块⼀样)注意! 能单独执⾏的函数⼀定要 test 开头(就是旁边有四边形的函数)就⽐如 testA() 这个就是可以的. methodA() 旁边就没有四边形.⽣命周期(运⾏流程)周期如下1. setUp()2. ⾃定义执⾏的函数3. tearDown()这⾥有个点, 要注意⼀下, ⽐如你当前测试模块⾥⾯有 testA(), testB() 两个函数.然后你直接点击运⾏整个测试模块, 他执⾏的顺序是.1. setUp()2. testA()3. tearDown()然后再执⾏1. setUp()2. testB()3. tearDown()就是你会看到APP启动和关闭了两次.具体使⽤介绍初始化 App// 初始化 XCUIApplicationlet app = XCUIApplication()// 启动app
()// 默认不填 bundleIdentifier, 就会初始化当前项⽬APP// 如果是想搞其他APP, 可传⼊ bundleIdentifier 初始化, 就可获得其实例let sefariApp = (bundleIdentifier: "safari")注意, 以下⽂章出现 app 的代码, 都是指代 let app = XCUIApplication() 这个获取元素这⾥我就举例⼏种常⽤的就⾏, 其他的, ⼤家可⾃⾏研究根据类型取元素可直接查看系统 XCUIElementTypeQueryProvider在这⾥插⼊图⽚描述⽐如这样就能取得该 app 下⾯所有的 s但取到 XCUIElementQuery, 还不能直接⽤这个时候我们取到具体某个元素才⾏为了⽐较好明⽩, 这⾥我举⼀个例⼦, UI是这样在这⾥插⼊图⽚描述以下是 print(escription) 输出的数据这⾥再啰嗦⼀下, debugDescription 属性对于获取元素层级来说挺舒服的, 我们要记得常⽤ debugDescription →Application, 0x2819e7720, pid: 4843, label: 'XQUITestDemo' Window (Main), 0x2819e78e0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e79c0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e7aa0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e7b80, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e7c60, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e7d40, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e7e20, {{0.0, 0.0}, {375.0, 667.0}} NavigationBar, 0x2819e7f00, {{0.0, 20.0}, {375.0, 44.0}}, identifier: '我的' StaticText, 0x2819e8000, {{170.0, 32.0}, {35.0, 20.5}}, label: '我的' Other, 0x2819e80e0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e81c0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e82a0, {{0.0, 64.0}, {375.0, 603.0}} Button, 0x280c8eae0, {{30.0, 214.0}, {60.0, 60.0}}, identifier: 'touchMe', label: '点我' StaticText, 0x2819e8460, {{41.5, 233.0}, {37.0, 22.0}}, label: '点我' TabBar, 0x2819e8540, {{0.0, 618.0}, {375.0, 49.0}} Button, 0x2819e8620, {{2.0, 619.0}, {184.0, 48.0}}, label: '⾸页' Button, 0x2819e1b20, {{190.0, 619.0}, {183.0, 48.0}}, label: '我的', Selected Other, 0x2819e1a40, {{0.0, 0.0}, {375.0, 667.0}}, Disabled Other, 0x2819e0b60, {{0.0, 0.0}, {375.0, 667.0}}, identifier: 'SVProgressHUD' Window, 0x2819e1ce0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e1f80, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2819e2060, {{0.0, 0.0}, {375.0, 667.0}}注意, Other 对应的是 UIView我们现在要点击 tabbar ⾸页这个按钮, 跳转到⾸页那么该怎么做呢? 很简单, 代码就两句// 取元素let homePageBtn = s["⾸页"]// 点击元素()这⾥我解析⼀下第⼀句取元素s 取到的是以下数据TabBar, 0x2835c3800, {{0.0, 618.0}, {375.0, 49.0}} Button, 0x2835c38e0, {{2.0, 619.0}, {184.0, 48.0}}, label: '⾸页' Button, 0x2835c39c0, {{190.0, 619.0}, {183.0, 48.0}}, label: '我的', Selected然后 s 取到的是Button, 0x2835c38e0, {{2.0, 619.0}, {184.0, 48.0}}, label: '⾸页'Button, 0x2835c39c0, {{190.0, 619.0}, {183.0, 48.0}}, label: '我的', Selected这个时候, 我们根据类型取元素, 就已经取到最后了想取⾸页按钮的话, 有⼏种⽅法, 请继续往下看根据 label 取元素根据 label 来获取 s["⾸页"]当然, 按照当前这个UI, 最简单就是 s["⾸页"]但是为了能够更准确的取到某个元素, 最好不要吝啬⼀点代码根据下标取元素因为打印的数据, ⾥⾯的元素是有序的. 那么我们也可以通过下标来获取元素// 传⼊具体的下标, 取出按钮t(boundBy: 0)// 当然, 也有类似数组⼀样取法, 取第⼀个atch根据 identifier 取元素不过你要提前在项⽬的代码, 或者 xib 中设置好 identifier 才⾏// 这⾥取的不是 tabbar 的 ⾸页按钮, 是那个黄⾊按钮t(matching: .button, identifier: "touchMe")在代码中设置accessibilityIdentifier 就是设置⾃动化测试时的 identifierlet btn = UIButton() = (x: 30, y: 150, width: 60, height: 60)le("点我", for: .normal)oundColor = ibilityIdentifier = "touchMe"xib 或者 storyboard 中设置在这⾥插⼊图⽚描述对元素的操作以下 button 就代表是⼀个按钮元素( XCUIElement类 )点击()双击Tap()长按// 长按三秒(forDuration: 3)滑动// 上扫p()// 下扫own()// 左扫eft()// 右扫ight()捏合(withScale: 1.5, velocity: 1)旋转(0.5, withVelocity: 1)实际⽤例这⾥举例⼀些我学习的时候, 搜了挺久, 都没搜到的实际⽤例吧这些⽤例我都放在了 项⽬ ⾥⾯,有兴趣的,可直接去下载 项⽬ 运⾏⼀下具体点击 UITableView 某⼀⾏⽰例 UI 如下在这⾥插⼊图⽚描述打印 escription 数据如下 →Application, 0x2838da060, pid: 1007, label: 'XQUITestDemo' Window (Main), 0x2838db560, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838db640, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838db720, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838db800, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838db8e0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838db9c0, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838dbaa0, {{0.0, 0.0}, {375.0, 667.0}} NavigationBar, 0x2838dbb80, {{0.0, 20.0}, {375.0, 44.0}}, identifier: 'TableView' Button, 0x2838dbc60, {{0.0, 20.0}, {62.0, 44.0}}, label: '⾸页' StaticText, 0x2838dbd40, {{147.0, 32.0}, {81.0, 20.5}}, label: 'TableView' Other, 0x2838dbe20, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838dbf00, {{0.0, 0.0}, {375.0, 667.0}} Other, 0x2838de760, {{0.0, 64.0}, {375.0, 603.0}} Table, 0x2838debc0, {{0.0, 64.0}, {375.0, 611.0}} Cell, 0x2838dea00, {{0.0, 64.0}, {375.0, 43.5}} Image, 0x2838d0000, {{15.0, 73.5}, {24.0, 24.0}} StaticText, 0x2838d00e0, {{54.0, 64.0}, {306.0, 43.5}}, label: '测试: 0' Other, 0x2838d01c0, {{54.0, 107.0}, {321.0, 0.5}} Button, 0x2838d02a0, {{281.0, 69.0}, {74.0, 34.0}}, label: '我是按钮' StaticText, 0x2838d0380, {{281.0, 75.0}, {74.0, 22.0}}, label: '我是按钮' Cell, 0x2838d0460, {{0.0, 107.5}, {375.0, 43.5}} Image, 0x2838d0540, {{15.0, 117.0}, {24.0, 24.0}} StaticText, 0x2838d0620, {{54.0, 107.5}, {306.0, 43.5}}, label: '测试: 1' Other, 0x2838d0700, {{54.0, 150.5}, {321.0, 0.5}} Button, 0x2838d07e0, {{281.0, 112.5}, {74.0, 34.0}}, label: '我是按钮' StaticText, 0x2838d08c0, {{281.0, 118.5}, {74.0, 22.0}}, label: '我是按钮' ...后⾯ cell 就省略了, 都是⼀样的数据格式 TabBar, 0x2838f0fc0, {{0.0, 618.0}, {375.0, 49.0}} Button, 0x2838f10a0, {{2.0, 619.0}, {184.0, 48.0}}, label: '⾸页', Selected Button, 0x2838f1180, {{190.0, 619.0}, {183.0, 48.0}}, label: '我的'其实逻辑挺简单, 就是找出 cell, 然后并且点击⽽已其实最关键的字段是 ==isHittable==, 请看以下代码, 虽然有点长. 不过请耐⼼看完class XQUITestDemoUITests: XCTestCase { /// 测试 tableView func testTableView() { // 初始化, 并打开APP let app = XCUIApplication() () // 读取 tableView 元素 let tables = atch // 获取下标 30 的 cell let cell = t(boundBy: 30) // 调⽤封装的⽅法, 滚动到该 cell if _scrollToElement(element: cell) { // 已经找到 cell, 点击 cell () } }}/// 对于 tableview 的封装extension XCUIElement { /// 滚动到某个元素 /// 默认向下滚动 /// 这⾥可以再封装⼀下的,⽐如可以向上滚动, 可以⽆限循环上下滚动等等... /// - Parameter element: UI元素 /// - Parameter isAutoStop: true 滚动到最后⼀个, ⾃动停下来 /// /// 返回 true 表⽰找到了传⼊的元素 /// func xq_scrollToElement(element: XCUIElement, isAutoStop: Bool = true) -> Bool { // 判断是否是, tableView if tType != .table { return false } // ⼀直滚动到某个元素可被点击为⽌ while !able {
// 滚动到最后就停下来 if isAutoStop { // 获取最后⼀个元素 let lastElement = t(boundBy: - 1) // 滚动到最后了, 那么就停下来 if able { return false } }
p() } return true }}直接打开其他 App这⾥举例打开 Safari.// 传⼊ bundle id, 初始化某个 applet safariApp = (bundleIdentifier: "safari")()当然, 我们打开 Safari 之后, 也能取到 safari 上⾯的元素, 并且能操作系统桌⾯ App(springboard)如果我们想去获取当前状态栏上⾯的信息. ⽐如电量, 是否正常充电, 信号强度这些的其实可以通过初始化桌⾯APP,来获取的// 注意, 这⾥不⽤ launch() 了
let springboard = (bundleIdentifier: "board")// 第⼀次获取桌⾯元素信息, 有时候会特别慢...所以这⾥并不是卡死了, 请耐⼼等待// 不知道其中缘由,感觉有点⽞学// 反正我测的时候⼀般要等待 3 ~ 20 秒print(escription)当然,我们可以调⽤ Home 键, 回到桌⾯, 然后根据获取的信息, 去点击桌⾯APP,这样也可以⾏得通这个 springboard 可以搞很多骚操作, 具体可看我项⽬, ⾥⾯有⼀些实际⽤例申请系统权限, 点击系统权限弹框(例如通知权限)代码如下class XQUITestDemoUITests: XCTestCase { /// 测试系统按钮⾃动点击, 通知权限 func testSystemAlertNotification() { // 初始化, 并打开APP let app = XCUIApplication() ()
// 点击 app ⾥⾯的 cell, 去申请通知权限 let view = t(boundBy: 9) ()
// 调⽤封装好的⽅法, 点击下标 1 的系统 Alert 按钮 // 下标 1, 就是右边同意按钮 _tapSystemAlert(index: 1)
// 等待⼀会 let _ = (for: .notRunning, timeout: 3) }}
extension XCTestCase { /// 点击系统弹框 /// - Parameter index: 按钮的下标. /// 下标是从左边开始算起, 0为起始下标. 就⽐如通知权限, 要同意的话, 就传⼊ 1 func xq_tapSystemAlert(index: Int) { let springboard = (bundleIdentifier: "board") _tapAlert(index: index) }
}extension XCUIApplication {
/// /// 注意, actionSheet 的弹框是没办法调⽤这个点击的. /// 因为 actionSheet 是⽤两个 ScrollView 组成...并且系统不认为他是⼀个 ///
/// 点击弹框 /// - Parameter index: 按钮的下标. /// 下标是从左边开始算起, 0为起始下标. func xq_tapAlert(index: Int) { let alerts = if > 0 { let _ = (for: .notRunning, timeout: 1) t(boundBy: index).tap() let _ = (for: .notRunning, timeout: 1) } }
}Home键当前没有发现能双击 Home 键的⽅法, 有知道的⽼哥, 请留⾔告诉我// 单击 Home 键(.home)系统⾳量按键// 调节⾳量, +(.volumeUp)// 调节⾳量, -(.volumeDown)Siri突然唤醒 Siri, 会说话很⼤声, 在公司玩耍的话, 建议先调⼩声
发布者:admin,转转请注明出处:http://www.yc00.com/news/1689265036a226449.html
评论列表(0条)