1# OpenHarmony自动化测试框架使用介绍 2 3## 简介 4 OpenHarmony自动化测试框架代码部件仓arkXtest,包含单元测试框架(JsUnit)和Ui测试框架(UiTest)。 5 6 单元测试框架(JsUnit)提供单元测试用例执行能力,提供用例编写基础接口,生成对应报告,用于测试系统或应用接口。 7 8 Ui测试框架(UiTest)通过简洁易用的API提供查找和操作界面控件能力,支持用户开发基于界面操作的自动化测试脚本。 9 10## 目录 11 12``` 13arkXtest 14 |-----jsunit 单元测试框架 15 |-----uitest Ui测试框架 16``` 17## 约束限制 18本模块首批接口从API version 8开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 19 20## 单元测试框架功能特性 21 22| No. | 特性 | 功能说明 | 23| ---- | -------- | ---------------------------------- | 24| 1 | 基础流程 | 支持编写及执行基础用例 | 25| 2 | 断言库 | 判断用例实际期望值与预期值是否相符 | 26 27### 使用说明 28 29#### 基础流程 30 31测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。 32 33| No. | API | 功能说明 | 34| ---- | ---------- | ------------------------------------------------------------ | 35| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数 | 36| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数 | 37| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数 | 38| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数 | 39| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数 | 40| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数 | 41| 7 | expect | 支持bool类型判断等多种断言方法 | 42 43示例代码: 44 45```javascript 46import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'hypium/index' 47import demo from '@ohos.bundle' 48 49export default async function abilityTest() { 50 describe('ActsAbilityTest', function () { 51 it('String_assertContain_success', 0, function () { 52 let a = 'abc' 53 let b = 'b' 54 expect(a).assertContain(b) 55 expect(a).assertEqual(a) 56 }) 57 it('getBundleInfo_0100', 0, async function () { 58 const NAME1 = "com.example.MyApplicationStage" 59 await demo.getBundleInfo(NAME1, 60 demo.BundleFlag.GET_BUNDLE_WITH_ABILITIES | demo.BundleFlag.GET_BUNDLE_WITH_REQUESTED_PERMISSION) 61 .then((value) => { 62 console.info(value.appId) 63 }) 64 .catch((err) => { 65 console.info(err.code) 66 }) 67 }) 68 }) 69} 70``` 71 72 73 74#### 断言库 75 76断言功能列表: 77 78 79| No. | API | 功能说明 | 80| :--- | :--------------- | ------------------------------------------------------------ | 81| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1) | 82| 2 | assertContain | 检验actualvalue中是否包含expectvalue | 83| 3 | assertEqual | 检验actualvalue是否等于expectvalue[0] | 84| 4 | assertFail | 抛出一个错误 | 85| 5 | assertFalse | 检验actualvalue是否是false | 86| 6 | assertTrue | 检验actualvalue是否是true | 87| 7 | assertInstanceOf | 检验actualvalue是否是expectvalue类型 | 88| 8 | assertLarger | 检验actualvalue是否大于expectvalue | 89| 9 | assertLess | 检验actualvalue是否小于expectvalue | 90| 10 | assertNull | 检验actualvalue是否是null | 91| 11 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue | 92| 12 | assertUndefined | 检验actualvalue是否是undefined | 93 94示例代码: 95 96```javascript 97import { describe, it, expect } from 'hypium/index' 98export default async function abilityTest() { 99 describe('assertClose', function () { 100 it('assertBeClose success', 0, function () { 101 let a = 100 102 let b = 0.1 103 expect(a).assertClose(99, b) 104 }) 105 it('assertBeClose fail', 0, function () { 106 let a = 100 107 let b = 0.1 108 expect(a).assertClose(1, b) 109 }) 110 it('assertBeClose fail', 0, function () { 111 let a = 100 112 let b = 0.1 113 expect(a).assertClose(null, b) 114 }) 115 it('assertBeClose fail', 0, function () { 116 expect(null).assertClose(null, 0) 117 }) 118 }) 119} 120``` 121### 使用方式 122 123 单元测试框架以npm包(hypium)形式发布至官网([https://www.npmjs.com/](https://www.npmjs.com/)),集成至sdk,开发者可以下载Deveco Studio使用,测试工程创建及测试脚本执行使用指南请参见[IDE指导文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001263160453)。 124 125## Ui测试框架功能特性 126 127| No. | 特性 | 功能说明 | 128| ---- | ----------- | ------------------------------------------------------------ | 129| 1 | UiDriver | Ui测试的入口,提供查找控件,检查控件存在性以及注入按键能力 | 130| 2 | By | 用于描述目标控件特征(文本、id、类型等),`UiDriver`根据`By`描述的控件特征信息来查找控件 | 131| 3 | UiComponent | UiDriver查找返回的控件对象,提供查询控件属性,滑动查找等触控和检视能力 | 132 133**使用者在测试脚本通过如下方式引入使用:** 134 135```typescript 136import {UiDriver,BY,UiComponent,MatchPattern} from '@ohos.uitest' 137``` 138 139> 注意事项 140> 1. `By`类提供的接口全部是同步接口,使用者可以使用`builder`模式链式调用其接口构造控件筛选条件。 141> 2. `UiDrivier`和`UiComponent`类提供的接口全部是异步接口(`Promise`形式),**需使用`await`语法**。 142> 3. Ui测试用例均需使用**异步**语法编写用例,需遵循单元测试框架异步用例编写规范。 143 144 145 146在测试用例文件中import `By/UiDriver/UiComponent`类,然后调用API接口编写测试用例。 147 148```javascript 149import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'hypium/index' 150import {BY, UiDriver, UiComponent, MatchPattern} from '@ohos.uitest' 151 152export default async function abilityTest() { 153 describe('uiTestDemo', function() { 154 it('uitest_demo0', 0, async function() { 155 // create UiDriver 156 let driver = await UiDriver.create() 157 // find component by text 158 let button = await driver.findComponent(BY.text('hello').enabled(true)) 159 // click component 160 await button.click() 161 // get and assert component text 162 let content = await button.getText() 163 expect(content).assertEquals('clicked!') 164 }) 165 }) 166} 167``` 168 169### UiDriver使用说明 170 171`UiDriver`类作为UiTest测试框架的总入口,提供查找控件,注入按键,单击坐标,滑动控件,手势操作,截图等能力。 172 173| No. | API | 功能描述 | 174| ---- | ------------------------------------------------------------ | ---------------------- | 175| 1 | create():Promise<UiDriver> | 静态方法,构造UiDriver | 176| 2 | findComponent(b:By):Promise<UiComponent> | 查找匹配控件 | 177| 3 | pressBack():Promise<void> | 单击BACK键 | 178| 4 | click(x:number, y:number):Promise<void> | 基于坐标点的单击 | 179| 5 | swipe(x1:number, y1:number, x2:number, y2:number):Promise<void> | 基于坐标点的滑动 | 180| 6 | assertComponentExist(b:By):Promise<void> | 断言匹配的控件存在 | 181| 7 | delayMs(t:number):Promise<void> | 延时 | 182| 8 | screenCap(s:path):Promise<void> | 截屏 | 183 184其中assertComponentExist接口是断言API,用于断言当前界面存在目标控件;如果控件不存在,该API将抛出JS异常,使当前测试用例失败。 185 186```javascript 187import {BY,UiDriver,UiComponent} from '@ohos.uitest' 188 189export default async function abilityTest() { 190 describe('UiTestDemo', function() { 191 it('Uitest_demo0', 0, async function(done) { 192 try{ 193 // create UiDriver 194 let driver = await UiDriver.create() 195 // assert text 'hello' exists on current Ui 196 await assertComponentExist(BY.text('hello')) 197 } finally { 198 done() 199 } 200 }) 201 }) 202} 203``` 204 205### By使用说明 206 207Ui测试框架通过`By`类提供了丰富的控件特征描述API,用来匹配查找要操作或检视的目标控件。`By`提供的API能力具有以下特点: 208 209- 支持匹配单属性和匹配多属性组合,例如同时指定目标控件text和id。 210- 控件属性支持多种匹配模式(等于,包含,`STARTS_WITH`,`ENDS_WITH`)。 211- 支持相对定位控件,可通过`isBefore`和`isAfter`等API限定邻近控件特征进行辅助定位。 212 213| No. | API | 功能描述 | 214| ---- | ---------------------------------- | ---------------------------------------------- | 215| 1 | id(i:number):By | 指定控件id | 216| 2 | text(t:string, p?:MatchPattern):By | 指定控件文本,可指定匹配模式 | 217| 3 | type(t:string)):By | 指定控件类型 | 218| 4 | enabled(e:bool):By | 指定控件使能状态 | 219| 5 | clickable(c:bool):By | 指定控件可单击状态 | 220| 6 | focused(f:bool):By | 指定控件获焦状态 | 221| 7 | scrollable(s:bool):By | 指定控件可滑动状态 | 222| 8 | selected(s:bool):By | 指定控件选中状态 | 223| 9 | isBefore(b:By):By | **相对定位**,限定目标控件位于指定特征控件之前 | 224| 10 | isAfter(b:By):By | **相对定位**,限定目标控件位于指定特征控件之后 | 225 226其中,`text`属性支持{`MatchPattern.EQUALS`,`MatchPattern.CONTAINS`,`MatchPattern.STARTS_WITH`,`MatchPattern.ENDS_WITH`}四种匹配模式,缺省使用`MatchPattern.EQUALS`模式。 227 228#### 控件绝对定位 229 230**示例代码1**:查找id是`Id_button`的控件。 231 232```javascript 233let button = await driver.findComponent(BY.id(Id_button)) 234``` 235 236 **示例代码2**:查找id是`Id_button`并且状态是`enabled`的控件,适用于无法通过单一属性定位的场景。 237 238```javascript 239let button = await driver.findComponent(BY.id(Id_button).enabled(true)) 240``` 241 242通过`By.id(x).enabled(y)`来指定目标控件的多个属性。 243 244**示例代码3**:查找文本中包含`hello`的控件,适用于不能完全确定控件属性取值的场景。 245 246```javascript 247let txt = await driver.findComponent(BY.text("hello", MatchPattern.CONTAINS)) 248``` 249 250通过向`By.text()`方法传入第二个参数`MatchPattern.CONTAINS`来指定文本匹配规则;默认规则是`MatchPattern.EQUALS`,即目标控件text属性必须严格等于给定值。 251 252#### 控件相对定位 253 254**示例代码1**:查找位于文本控件`Item3_3`后面的,id是`ResourceTable.Id_switch`的Switch控件。 255 256```javascript 257let switch = await driver.findComponent(BY.id(Id_switch).isAfter(BY.text("Item3_3"))) 258``` 259 260通过`By.isAfter`方法,指定位于目标控件前面的特征控件属性,通过该特征控件进行相对定位。一般地,特征控件是某个具有全局唯一特征的控件(例如具有唯一的id或者唯一的text)。 261 262 263类似的,可以使用`By.isBefore`控件指定位于目标控件后面的特征控件属性,实现相对定位。 264 265### UiComponent使用说明 266 267`UiComponent`类代表了Ui界面上的一个控件,一般是通过`UiDriver.findComponent(by)`方法查找到的。通过该类的实例,用户可以获取控件属性,单击控件,滑动查找,注入文本等操作。 268 269`UiComponent`包含的常用API: 270 271| No. | API | 功能描述 | 272| ---- | --------------------------------- | -------------------------------------------- | 273| 1 | click():Promise<void> | 单击该控件 | 274| 2 | inputText(t:string):Promise<void> | 向控件中输入文本(适用于文本框控件) | 275| 3 | scrollSearch(s:By):Promise<bool> | 在该控件上滑动查找目标控件(适用于List等控件) | 276| 4 | getText():Promise<string> | 获取控件text | 277| 5 | getId():Promise<number> | 获取控件id | 278| 6 | getType():Promise<string> | 获取控件类型 | 279| 7 | isEnabled():Promise<bool> | 获取控件使能状态 | 280 281`UiComponent`完整的API列表请参考其API文档。 282 283**示例代码1**:单击控件。 284 285```javascript 286let button = await driver.findComponent(BY.id(Id_button)) 287await button.click() 288``` 289 290**示例代码2**:通过get接口获取控件属性后,可以使用单元测试框架提供的assert*接口做断言检查。 291 292```javascript 293let component = await driver.findComponent(BY.id(Id_title)) 294expect(component !== null).assertTrue() 295``` 296 297**示例代码3**:在List控件中滑动查找text是`Item3_3`的子控件。 298 299```javascript 300let list = await driver.findComponent(BY.id(Id_list)) 301let found = await list.scrollSearch(BY.text("Item3_3")) 302expect(found).assertTrue() 303``` 304 305**示例代码4**:向输入框控件中输入文本。 306 307```javascript 308let editText = await driver.findComponent(BY.type('InputText')) 309await editText.inputText("user_name") 310``` 311### 使用方式 312 313 开发者可以下载Deveco Studio创建测试工程后,在其中调用框架提供接口进行相关测试操作,测试工程创建及测试脚本执行使用指南请参见[IDE指导文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001263160453)。 314 315### 推送Ui测试框架至设备 316 317> Ui测试框架3.1Release版本暂不随版本编译,使用时需自行编译后推送至OpenHarmony设备。后续随版本编译后,直接使用版本即可。 318 319#### 下载代码 320 321在工程test目录下执行如下命令下载测试框架仓代码。 322 323```shell 324git clone https://gitee.com/openharmony/arkXtest.git -b OpenHarmony-3.1-Release 325``` 326#### 编译脚本修改 327 328修改build仓中subsystem_config.json文件,增加如下字段。 329 330```shell 331"arkXtest": { 332 "path": "test/arkXtest", 333 "name": "arkXtest" 334 }, 335``` 336修改productdefine_common仓中 rk3568.json文件,增加如下字段。 337```shell 338"arkXtest:arkXtest":{}, 339``` 340#### 构建方式 341 342```shell 343./build.sh --product-name rk3568 --build-target uitestkit 344``` 345#### 推送方式 346 347```shell 348hdc_std target mount 349hdc_std shell mount -o rw,remount / 350hdc_std file send uitest /system/bin/uitest 351hdc_std file send libuitest.z.so /system/lib/module/libuitest.z.so 352hdc_std shell chmod +x /system/bin/uitest 353``` 354