• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 自动化测试框架使用介绍
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| 3    | Mock能力 | 支持函数级mock能力,对定义的函数进行mock后修改函数的行为,使其返回指定的值或者执行某种动作。 |
27| 4    | 数据驱动 | 提供数据驱动能力,支持复用同一个测试脚本,使用不同输入数据驱动执行。 |
28
29### 使用说明
30
31####  基础流程
32
33测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。
34
35| No.  | API        | 功能说明                                                     |
36| ---- | ---------- | ------------------------------------------------------------ |
37| 1    | describe   | 定义一个测试套,支持两个参数:测试套名称和测试套函数。       |
38| 2    | beforeAll  | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数。 |
39| 3    | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数。 |
40| 4    | afterEach  | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数。 |
41| 5    | afterAll   | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数。 |
42| 6    | it         | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数。 |
43| 7    | expect     | 支持bool类型判断等多种断言方法。                             |
44
45示例代码:
46
47```javascript
48import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
49import demo from '@ohos.bundle'
50
51export default async function abilityTest() {
52  describe('ActsAbilityTest', function () {
53    it('String_assertContain_success', 0, function () {
54      let a = 'abc'
55      let b = 'b'
56      expect(a).assertContain(b)
57      expect(a).assertEqual(a)
58    })
59    it('getBundleInfo_0100', 0, async function () {
60      const NAME1 = "com.example.MyApplicationStage"
61      await demo.getBundleInfo(NAME1,
62        demo.BundleFlag.GET_BUNDLE_WITH_ABILITIES | demo.BundleFlag.GET_BUNDLE_WITH_REQUESTED_PERMISSION)
63        .then((value) => {
64          console.info(value.appId)
65        })
66        .catch((err) => {
67          console.info(err.code)
68        })
69    })
70  })
71}
72```
73
74
75
76####  断言库
77
78断言功能列表:
79
80
81| No.  | API                | 功能说明                                                     |
82| :--- | :------------------| ------------------------------------------------------------ |
83| 1    | assertClose        | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1)。 |
84| 2    | assertContain      | 检验actualvalue中是否包含expectvalue。                       |
85| 3    | assertEqual        | 检验actualvalue是否等于expectvalue[0]。                      |
86| 4    | assertFail         | 抛出一个错误。                                               |
87| 5    | assertFalse        | 检验actualvalue是否是false。                                 |
88| 6    | assertTrue         | 检验actualvalue是否是true。                                  |
89| 7    | assertInstanceOf   | 检验actualvalue是否是expectvalue类型。                       |
90| 8    | assertLarger       | 检验actualvalue是否大于expectvalue。                         |
91| 9    | assertLess         | 检验actualvalue是否小于expectvalue。                         |
92| 10   | assertNull         | 检验actualvalue是否是null。                                  |
93| 11   | assertThrowError   | 检验actualvalue抛出Error内容是否是expectValue。              |
94| 12   | assertUndefined    | 检验actualvalue是否是undefined。                             |
95| 13   | assertNaN          | 检验actualvalue是否是一个NAN                                 |
96| 14   | assertNegUnlimited | 检验actualvalue是否等于Number.NEGATIVE_INFINITY             |
97| 15   | assertPosUnlimited | 检验actualvalue是否等于Number.POSITIVE_INFINITY             |
98| 16   | assertDeepEquals   | 检验actualvalue和expectvalue是否完全相等               |
99| 17   | assertPromiseIsPending | 判断promise是否处于Pending状态。                         |
100| 18   | assertPromiseIsRejected | 判断promise是否处于Rejected状态。                       |
101| 19   | assertPromiseIsRejectedWith | 判断promise是否处于Rejected状态,并且比较执行的结果值。|
102| 20   | assertPromiseIsRejectedWithError | 判断promise是否处于Rejected状态并有异常,同时比较异常的类型和message值。                   |
103| 21   | assertPromiseIsResolved | 判断promise是否处于Resolved状态。                       |
104| 22   | assertPromiseIsResolvedWith | 判断promise是否处于Resolved状态,并且比较执行的结果值。|
105| 23   | not                | 断言取反,支持上面所有的断言功能                                 |
106
107示例代码:
108
109```javascript
110import { describe, it, expect } from '@ohos/hypium'
111export default async function abilityTest() {
112  describe('assertClose', function () {
113    it('assertBeClose success', 0, function () {
114      let a = 100
115      let b = 0.1
116      expect(a).assertClose(99, b)
117    })
118    it('assertBeClose fail', 0, function () {
119      let a = 100
120      let b = 0.1
121      expect(a).assertClose(1, b)
122    })
123    it('assertBeClose fail', 0, function () {
124      let a = 100
125      let b = 0.1
126      expect(a).assertClose(null, b)
127    })
128    it('assertBeClose fail', 0, function () {
129      expect(null).assertClose(null, 0)
130    })
131    it('assertNaN success',0, function () {
132      expect(Number.NaN).assertNaN(); // true
133    })
134    it('assertNegUnlimited success',0, function () {
135      expect(Number.NEGATIVE_INFINITY).assertNegUnlimited(); // true
136    })
137    it('assertPosUnlimited success',0, function () {
138      expect(Number.POSITIVE_INFINITY).assertPosUnlimited(); // true
139    })
140    it('not_number_true',0, function () {
141      expect(1).not().assertLargerOrEqual(2)
142    })
143    it('not_number_true_1',0, function () {
144      expect(3).not().assertLessOrEqual(2);
145    })
146    it('not_NaN_true',0, function () {
147      expect(3).not().assertNaN();
148    })
149    it('not_contain_true',0, function () {
150      let a = "abc";
151      let b= "cdf"
152      expect(a).not().assertContain(b);
153    })
154    it('not_large_true',0, function () {
155      expect(3).not().assertLarger(4);
156    })
157    it('not_less_true',0, function () {
158      expect(3).not().assertLess(2);
159    })
160    it('not_undefined_true',0, function () {
161      expect(3).not().assertUndefined();
162    })
163    it('deepEquals_null_true',0, function () {
164      // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
165      expect(null).assertDeepEquals(null)
166    })
167    it('deepEquals_array_not_have_true',0, function () {
168      // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
169      const  a= []
170      const  b= []
171      expect(a).assertDeepEquals(b)
172    })
173    it('deepEquals_map_equal_length_success',0, function () {
174      // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
175      const a =  new Map();
176      const b =  new Map();
177      a.set(1,100);
178      a.set(2,200);
179      b.set(1, 100);
180      b.set(2, 200);
181      expect(a).assertDeepEquals(b)
182    })
183    it("deepEquals_obj_success_1", 0, function () {
184      const a = {x:1};
185      const b = {x:1};
186      expect(a).assertDeepEquals(b);
187    })
188    it("deepEquals_regExp_success_0", 0, function () {
189      const a = new RegExp("/test/");
190      const b = new RegExp("/test/");
191      expect(a).assertDeepEquals(b)
192    })
193    it('test_isPending_pass_1', 0, function () {
194      let p = new Promise(function () {
195      });
196      expect(p).assertPromiseIsPending();
197    });
198    it('test_isRejected_pass_1', 0, function () {
199      let p = Promise.reject({
200        bad: 'no'
201      });
202      expect(p).assertPromiseIsRejected();
203    });
204    it('test_isRejectedWith_pass_1', 0, function () {
205      let p = Promise.reject({
206        res: 'reject value'
207      });
208      expect(p).assertPromiseIsRejectedWith({
209        res: 'reject value'
210      });
211    });
212    it('test_isRejectedWithError_pass_1', 0, function () {
213      let p1 = Promise.reject(new TypeError('number'));
214      expect(p1).assertPromiseIsRejectedWithError(TypeError);
215    });
216    it('test_isResolved_pass_1', 0, function () {
217      let p = Promise.resolve({
218        res: 'result value'
219      });
220      expect(p).assertPromiseIsResolved();
221    });
222    it('test_isResolvedTo_pass_1', 0, function () {
223      let p = Promise.resolve({
224        res: 'result value'
225      });
226      expect(p).assertPromiseIsResolvedWith({
227        res: 'result value'
228      });
229    });
230    it('test_isPending_failed_1', 0, function () {
231      let p = Promise.reject({
232        bad: 'no1'
233      });
234      expect(p).assertPromiseIsPending();
235    });
236    it('test_isRejectedWithError_failed_1', 0, function () {
237      let p = Promise.reject(new TypeError('number'));
238      expect(p).assertPromiseIsRejectedWithError(TypeError, 'number one');
239    });
240  })
241}
242```
243
244
245#### Mock能力
246
247##### 约束限制
248
249单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium)开始支持,需修改源码工程中package.info中配置依赖npm包版本号后使用。
250
251-  **接口列表:**
252
253| No. | API | 功能说明 |
254| --- | --- | --- |
255| 1 | mockFunc(obj: object, f:function()) | mock某个类的对象obj的函数f,那么需要传两个参数:obj和f,支持使用异步函数(说明:对mock而言原函数实现是同步或异步没太多区别,因为mock并不关注原函数的实现)。 |
256| 2 | when(mockedfunc:function) | 对传入后方法做检查,检查是否被mock并标记过,返回的是一个方法声明。 |
257| 3 | afterReturn(x:value) | 设定预期返回一个自定义的值value,比如某个字符串或者一个promise。 |
258| 4 | afterReturnNothing() | 设定预期没有返回值,即 undefined。 |
259| 5 | afterAction(x:action) | 设定预期返回一个函数执行的操作。 |
260| 6 | afterThrow(x:msg) | 设定预期抛出异常,并指定异常msg。 |
261| 7 | clear() | 用例执行完毕后,进行数据mocker对象的还原处理(还原之后对象恢复被mock之前的功能)。 |
262| 8 | any | 设定用户传任何类型参数(undefined和null除外),执行的结果都是预期的值,使用ArgumentMatchers.any方式调用。 |
263| 9 | anyString | 设定用户传任何字符串参数,执行的结果都是预期的值,使用ArgumentMatchers.anyString方式调用。 |
264| 10 | anyBoolean | 设定用户传任何boolean类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyBoolean方式调用。 |
265| 11 | anyFunction | 设定用户传任何function类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyFunction方式调用。 |
266| 12 | anyNumber | 设定用户传任何数字类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyNumber方式调用。 |
267| 13 | anyObj | 设定用户传任何对象类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyObj方式调用。 |
268| 14 | matchRegexs(Regex) | 设定用户传任何正则表达式类型参数Regex,执行的结果都是预期的值,使用ArgumentMatchers.matchRegexs(Regex)方式调用。 |
269| 15 | verify(methodName, argsArray) | 验证methodName(函数名字符串)所对应的函数和其参数列表argsArray的执行行为是否符合预期,返回一个VerificationMode:一个提供验证模式的类,它有times(count)、once()、atLeast(x)、atMost(x)、never()等函数可供选择。 |
270| 16 | times(count) | 验证行为调用过count次。 |
271| 17 | once() | 验证行为调用过一次。 |
272| 18 | atLeast(count) | 验证行为至少调用过count次。 |
273| 19 | atMost(count) | 验证行为至多调用过count次。 |
274| 20 | never | 验证行为从未发生过。 |
275| 21 | ignoreMock(obj, method) | 使用ignoreMock可以还原obj对象中被mock后的函数,对被mock后的函数有效。 |
276| 22 | clearAll() | 用例执行完毕后,进行数据和内存清理。 |
277
278-  **使用示例:**
279
280用户可以通过以下方式进行引入mock模块进行测试用例编写:
281
282- **须知:**
283使用时候必须引入的mock能力模块: MockKit,when
284根据自己用例需要引入断言能力api
285例如:`import { describe, expect, it, MockKit, when} from '@ohos/hypium'`
286
287**示例1:afterReturn 的使用**
288
289```javascript
290import {describe, expect, it, MockKit, when} from '@ohos/hypium';
291
292export default function ActsAbilityTest() {
293    describe('ActsAbilityTest', function () {
294        it('testMockfunc', 0, function () {
295            console.info("it1 begin");
296
297            //1.创建一个mock能力的对象MockKit
298            let mocker = new MockKit();
299
300            //2.定类ClassName,里面两个函数,然后创建一个对象claser
301            class ClassName {
302                constructor() {
303                }
304
305                method_1(arg) {
306                    return '888888';
307                }
308
309                method_2(arg) {
310                    return '999999';
311                }
312            }
313
314            let claser = new ClassName();
315
316            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
317            let mockfunc = mocker.mockFunc(claser, claser.method_1);
318            when(mockfunc)('test').afterReturn('1');
319
320            //4.对mock后的函数进行断言,看是否符合预期
321            //执行成功案例,参数为'test'
322            expect(claser.method_1('test')).assertEqual('1'); //执行通过
323
324            //执行失败案例,参数为 'abc'
325            //expect(claser.method_1('abc')).assertEqual('1');//执行失败
326        });
327    });
328}
329```
330- **须知:**
331`when(mockfunc)('test').afterReturn('1');`
332这句代码中的`('test')`是mock后的函数需要传递的匹配参数,目前支持一个参数
333`afterReturn('1')`是用户需要预期返回的结果。
334有且只有在参数是`('test')`的时候,执行的结果才是用户自定义的预期结果。
335
336**示例2: afterReturnNothing 的使用**
337
338```javascript
339import {describe, expect, it, MockKit, when} from '@ohos/hypium';
340
341export default function ActsAbilityTest() {
342    describe('ActsAbilityTest', function () {
343        it('testMockfunc', 0, function () {
344            console.info("it1 begin");
345
346            //1.创建一个mock能力的对象MockKit
347            let mocker = new MockKit();
348
349            //2.定类ClassName,里面两个函数,然后创建一个对象claser
350            class ClassName {
351                constructor() {
352                }
353
354                method_1(arg) {
355                    return '888888';
356                }
357
358                method_2(arg) {
359                    return '999999';
360                }
361            }
362
363            let claser = new ClassName();
364
365            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
366            let mockfunc = mocker.mockFunc(claser, claser.method_1);
367
368            //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterReturnNothing();即不返回任何值
369            when(mockfunc)('test').afterReturnNothing();
370
371            //5.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
372            //执行成功案例,参数为'test',这时候执行原对象claser.method_1的方法,会发生变化
373            // 这时候执行的claser.method_1不会再返回'888888',而是设定的afterReturnNothing()生效//不返回任何值;
374            expect(claser.method_1('test')).assertUndefined(); //执行通过
375
376            // 执行失败案例,参数传为 123
377            // expect(method_1(123)).assertUndefined();//执行失败
378        });
379    });
380}
381```
382
383**示例3: 设定参数类型为any ,即接受任何参数(undefine和null除外)的使用**
384
385
386- **须知:**
387需要引入ArgumentMatchers类,即参数匹配器,例如:ArgumentMatchers.any
388
389```javascript
390import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
391
392export default function ActsAbilityTest() {
393    describe('ActsAbilityTest', function () {
394        it('testMockfunc', 0, function () {
395            console.info("it1 begin");
396
397            //1.创建一个mock能力的对象MockKit
398            let mocker = new MockKit();
399
400            //2.定类ClassName,里面两个函数,然后创建一个对象claser
401            class ClassName {
402                constructor() {
403                }
404
405                method_1(arg) {
406                    return '888888';
407                }
408
409                method_2(arg) {
410                    return '999999';
411                }
412            }
413
414            let claser = new ClassName();
415
416            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
417            let mockfunc = mocker.mockFunc(claser, claser.method_1);
418            //根据自己需求进行选择参数匹配器和预期方法,
419            when(mockfunc)(ArgumentMatchers.any).afterReturn('1');
420
421            //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
422            //执行成功的案例1,传参为字符串类型
423            expect(claser.method_1('test')).assertEqual('1'); //用例执行通过。
424            //执行成功的案例2,传参为数字类型123
425            expect(claser.method_1(123)).assertEqual('1');//用例执行通过。
426            //执行成功的案例3,传参为boolean类型true
427            expect(claser.method_1(true)).assertEqual('1');//用例执行通过。
428
429            //执行失败的案例,传参为数字类型空
430            //expect(claser.method_1()).assertEqual('1');//用例执行失败。
431        });
432    });
433}
434```
435
436**示例4: 设定参数类型为anyString,anyBoolean等的使用**
437
438```javascript
439import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
440
441export default function ActsAbilityTest() {
442    describe('ActsAbilityTest', function () {
443        it('testMockfunc', 0, function () {
444            console.info("it1 begin");
445
446            //1.创建一个mock能力的对象MockKit
447            let mocker = new MockKit();
448
449            //2.定类ClassName,里面两个函数,然后创建一个对象claser
450            class ClassName {
451                constructor() {
452                }
453
454                method_1(arg) {
455                    return '888888';
456                }
457
458                method_2(arg) {
459                    return '999999';
460                }
461            }
462
463            let claser = new ClassName();
464
465            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
466            let mockfunc = mocker.mockFunc(claser, claser.method_1);
467            //根据自己需求进行选择
468            when(mockfunc)(ArgumentMatchers.anyString).afterReturn('1');
469
470            //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
471            //执行成功的案例,传参为字符串类型
472            expect(claser.method_1('test')).assertEqual('1'); //用例执行通过。
473            expect(claser.method_1('abc')).assertEqual('1'); //用例执行通过。
474
475            //执行失败的案例,传参为数字类型
476            //expect(claser.method_1(123)).assertEqual('1');//用例执行失败。
477            //expect(claser.method_1(true)).assertEqual('1');//用例执行失败。
478        });
479    });
480}
481```
482
483**示例5: 设定参数类型为matchRegexs(Regex)等 的使用**
484```javascript
485import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
486
487export default function ActsAbilityTest() {
488    describe('ActsAbilityTest', function () {
489        it('testMockfunc', 0, function () {
490            console.info("it1 begin");
491
492            //1.创建一个mock能力的对象MockKit
493            let mocker = new MockKit();
494
495            //2.定类ClassName,里面两个函数,然后创建一个对象claser
496            class ClassName {
497                constructor() {
498                }
499
500                method_1(arg) {
501                    return '888888';
502                }
503
504                method_2(arg) {
505                    return '999999';
506                }
507            }
508
509            let claser = new ClassName();
510
511            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
512            let mockfunc = mocker.mockFunc(claser, claser.method_1);
513            //根据自己需求进行选择,这里假设匹配正则,且正则为/123456/
514            when(mockfunc)(ArgumentMatchers.matchRegexs(/123456/)).afterReturn('1');
515
516            //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
517            //执行成功的案例,传参为字符串 比如 '1234567898'
518            expect(claser.method_1('1234567898')).assertEqual('1'); //用例执行通过。
519            //因为字符串 '1234567898'可以和正则/123456/匹配上
520
521            //执行失败的案例,传参为字符串'1234'
522            //expect(claser.method_1('1234')).assertEqual('1');//用例执行失败。反之
523        });
524    });
525}
526```
527
528**示例6: 验证功能 Verify函数的使用**
529```javascript
530import {describe, expect, it, MockKit, when} from '@ohos/hypium';
531
532export default function ActsAbilityTest() {
533    describe('ActsAbilityTest', function () {
534        it('testMockfunc', 0, function () {
535            console.info("it1 begin");
536
537            //1.创建一个mock能力的对象MockKit
538            let mocker = new MockKit();
539
540            //2.定类ClassName,里面两个函数,然后创建一个对象claser
541            class ClassName {
542                constructor() {
543                }
544
545                method_1(...arg) {
546                    return '888888';
547                }
548
549                method_2(...arg) {
550                    return '999999';
551                }
552            }
553
554            let claser = new ClassName();
555
556            //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
557            mocker.mockFunc(claser, claser.method_1);
558            mocker.mockFunc(claser, claser.method_2);
559
560            //4.方法调用如下
561            claser.method_1('abc', 'ppp');
562            claser.method_1('abc');
563            claser.method_1('xyz');
564            claser.method_1();
565            claser.method_1('abc', 'xxx', 'yyy');
566            claser.method_1();
567            claser.method_2('111');
568            claser.method_2('111', '222');
569
570            //5.现在对mock后的两个函数进行验证,验证调用情况
571            mocker.verify('method_1', []).atLeast(3); //结果为failed
572            //解释:验证函数'method_1',参数列表为空:[] 的函数,至少执行过3次,
573            //执行结果为failed,因为'method_1'且无参数 在4中只执行过2次
574            //mocker.verify('method_2',['111']).once();//执行success,原因同上
575            //mocker.verify('method_2',['111',,'222']).once();//执行success,原因同上
576        });
577    });
578}
579```
580
581**示例7:  ignoreMock(obj, method) 忽略函数的使用**
582```javascript
583import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
584
585export default function ActsAbilityTest() {
586    describe('ActsAbilityTest', function () {
587        it('testMockfunc', 0, function () {
588            console.info("it1 begin");
589
590            //1.创建一个mock能力的对象MockKit
591            let mocker = new MockKit();
592
593            //2.定类ClassName,里面两个函数,然后创建一个对象claser
594            class ClassName {
595                constructor() {
596                }
597
598                method_1(...arg) {
599                    return '888888';
600                }
601
602                method_2(...arg) {
603                    return '999999';
604                }
605            }
606
607            let claser = new ClassName();
608
609            //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
610            let func_1 = mocker.mockFunc(claser, claser.method_1);
611            let func_2 = mocker.mockFunc(claser, claser.method_2);
612
613            //4.对mock后的函数的行为进行修改
614            when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
615            when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
616
617            //5.方法调用如下
618            console.log(claser.method_1(123)); //执行结果是4,符合步骤4中的预期
619            console.log(claser.method_2(456)); //执行结果是5,符合步骤4中的预期
620
621            //6.现在对mock后的两个函数的其中一个函数method_1进行忽略处理(原理是就是还原)
622            mocker.ignoreMock(claser, claser.method_1);
623            //然后再去调用 claser.method_1函数,看执行结果
624            console.log(claser.method_1(123)); //执行结果是888888,发现这时结果跟步骤4中的预期不一样了,执行了claser.method_1没被mock之前的结果
625            //用断言测试
626            expect(claser.method_1(123)).assertEqual('4'); //结果为failed 符合ignoreMock预期
627            claser.method_2(456); //执行结果是5,因为method_2没有执行ignore忽略,所有也符合步骤4中的预期
628        });
629    });
630}
631```
632
633**示例8:  clear()函数的使用**
634
635```javascript
636import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
637
638export default function ActsAbilityTest() {
639    describe('ActsAbilityTest', function () {
640        it('testMockfunc', 0, function () {
641            console.info("it1 begin");
642
643            //1.创建一个mock能力的对象MockKit
644            let mocker = new MockKit();
645
646            //2.定类ClassName,里面两个函数,然后创建一个对象claser
647            class ClassName {
648                constructor() {
649                }
650
651                method_1(...arg) {
652                    return '888888';
653                }
654
655                method_2(...arg) {
656                    return '999999';
657                }
658            }
659            let claser = new ClassName();
660
661            //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
662            let func_1 = mocker.mockFunc(claser, claser.method_1);
663            let func_2 = mocker.mockFunc(claser, claser.method_2);
664
665            //4.对mock后的函数的行为进行修改
666            when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
667            when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
668
669            //5.方法调用如下
670            //expect(claser.method_1(123)).assertEqual('4');//ok 符合预期
671            //expect(claser.method_2(456)).assertEqual('5');//ok 符合预期
672
673            //6.清除mock操作(原理是就是还原)
674            mocker.clear(claser);
675            //然后再去调用 claser.method_1函数,看执行结果
676            expect(claser.method_1(123)).assertEqual('4');//failed 符合预期
677            expect(claser.method_2(456)).assertEqual('5');//failed 符合预期
678        });
679    });
680}
681```
682
683
684**示例9:  afterThrow(msg) 函数的使用**
685
686```javascript
687import {describe, expect, it, MockKit, when} from '@ohos/hypium';
688
689export default function ActsAbilityTest() {
690    describe('ActsAbilityTest', function () {
691        it('testMockfunc', 0, function () {
692            console.info("it1 begin");
693
694            //1.创建一个mock能力的对象MockKit
695            let mocker = new MockKit();
696
697            //2.定类ClassName,里面两个函数,然后创建一个对象claser
698            class ClassName {
699                constructor() {
700                }
701
702                method_1(arg) {
703                    return '888888';
704                }
705            }
706
707            let claser = new ClassName();
708
709            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
710            let mockfunc = mocker.mockFunc(claser, claser.method_1);
711
712            //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterReturnNothing();即不返回任何值
713            when(mockfunc)('test').afterThrow('error xxx');
714
715            //5.执行mock后的函数,捕捉异常并使用assertEqual对比msg否符合预期
716            try {
717                claser.method_1('test');
718            } catch (e) {
719                expect(e).assertEqual('error xxx');//执行通过
720            }
721        });
722    });
723}
724```
725
726**示例10:  mock异步 函数的使用**
727
728```javascript
729import {describe, expect, it, MockKit, when} from '@ohos/hypium';
730
731export default function ActsAbilityTest() {
732    describe('ActsAbilityTest', function () {
733        it('testMockfunc', 0, function () {
734            console.info("it1 begin");
735
736            //1.创建一个mock能力的对象MockKit
737            let mocker = new MockKit();
738
739            //2.定类ClassName,里面两个函数,然后创建一个对象claser
740            class ClassName {
741                constructor() {
742                }
743
744                async method_1(arg) {
745                    return new Promise((res, rej) => {
746                        //做一些异步操作
747                        setTimeout(function () {
748                            console.log('执行');
749                            res('数据传递');
750                        }, 2000);
751                    });
752                }
753            }
754
755            let claser = new ClassName();
756
757            //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
758            let mockfunc = mocker.mockFunc(claser, claser.method_1);
759
760            //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterRetrun; 可以自定义返回一个promise
761            when(mockfunc)('test').afterReturn(new Promise((res, rej) => {
762                console.log("do something");
763                res('success something');
764            }));
765
766            //5.执行mock后的函数,即对定义的promise进行后续执行
767            claser.method_1('test').then(function (data) {
768                //数据处理代码...
769                console.log('result : ' + data);
770            });
771        });
772    });
773}
774```
775
776**示例11:mock 系统函数的使用**
777
778```javascript
779export default function ActsAbilityTest() {
780    describe('ActsAbilityTest', function () {
781        it('test_systemApi', 0, function () {
782            //1.创建MockKit对象
783            let mocker = new MockKit();
784            //2.mock app.getInfo函数
785            let mockf = mocker.mockFunc(app, app.getInfo);
786            when(mockf)('test').afterReturn('1');
787            //执行成功案例
788            expect(app.getInfo('test')).assertEqual('1');
789        });
790    });
791}
792```
793
794
795**示例12:verify times函数的使用(验证函数调用次数)**
796
797```javascript
798import { describe, expect, it, MockKit, when } from '@ohos/hypium'
799
800export default function ActsAbilityTest() {
801    describe('ActsAbilityTest', function () {
802        it('test_verify_times', 0, function () {
803            //1.创建MockKit对象
804            let mocker = new MockKit();
805            //2.定义需要被mock的类
806            class ClassName {
807                constructor() {
808                }
809
810                method_1(...arg) {
811                    return '888888';
812                }
813            }
814            //3.创建类对象
815            let claser = new ClassName();
816            //4.mock 类ClassName对象的某个方法,比如method_1
817            let func_1 = mocker.mockFunc(claser, claser.method_1);
818            //5.期望被mock后的函数能够返回自己假设的结果
819            when(func_1)('123').afterReturn('4');
820
821            //6.随机执行几次函数,参数如下
822            claser.method_1('123', 'ppp');
823            claser.method_1('abc');
824            claser.method_1('xyz');
825            claser.method_1();
826            claser.method_1('abc', 'xxx', 'yyy');
827            claser.method_1('abc');
828            claser.method_1();
829            //7.验证函数method_1且参数为'abc'时,执行过的次数是否为2
830            mocker.verify('method_1', ['abc']).times(2);
831        });
832    });
833}
834```
835
836
837**示例13:  verify atLeast 函数的使用 (验证函数调用次数)**
838
839```javascript
840import { describe, expect, it, MockKit, when } from '@ohos/hypium'
841
842export default function ActsAbilityTest() {
843    describe('ActsAbilityTest', function () {
844        it('test_verify_atLeast', 0, function () {
845            //1.创建MockKit对象
846            let mocker = new MockKit();
847            //2.定义需要被mock的类
848            class ClassName {
849                constructor() {
850                }
851
852                method_1(...arg) {
853                    return '888888';
854                }
855            }
856
857            //3.创建类对象
858            let claser = new ClassName();
859            //4.mock  类ClassName对象的某个方法,比如method_1
860            let func_1 = mocker.mockFunc(claser, claser.method_1);
861            //5.期望被mock后的函数能够返回自己假设的结果
862            when(func_1)('123').afterReturn('4');
863            //6.随机执行几次函数,参数如下
864            claser.method_1('123', 'ppp');
865            claser.method_1('abc');
866            claser.method_1('xyz');
867            claser.method_1();
868            claser.method_1('abc', 'xxx', 'yyy');
869            claser.method_1();
870            //7.验证函数method_1且参数为空时,是否至少执行过2次
871            mocker.verify('method_1', []).atLeast(2);
872        });
873    });
874}
875```
876
877#### 数据驱动
878
879##### 约束限制
880
881单元测试框架数据驱动能力从[hypium 1.0.2版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium)开始支持。
882
883- 数据参数传递 : 为指定测试套、测试用例传递测试输入数据参数。
884- 压力测试 : 为指定测试套、测试用例设置执行次数。
885
886数据驱动可以根据配置参数来驱动测试用例的执行次数和每一次传入的参数,使用时依赖data.json配置文件,文件内容如下:
887
888>说明 : data.json与测试用例*.test.js|ets文件同目录
889
890```json
891{
892	"suites": [{
893		"describe": ["actsAbilityTest"],
894		"stress": 2,
895		"params": {
896			"suiteParams1": "suiteParams001",
897			"suiteParams2": "suiteParams002"
898		},
899		"items": [{
900			"it": "testDataDriverAsync",
901			"stress": 2,
902			"params": [{
903				"name": "tom",
904				"value": 5
905			}, {
906				"name": "jerry",
907				"value": 4
908			}]
909		}, {
910			"it": "testDataDriver",
911			"stress": 3
912		}]
913	}]
914}
915```
916
917配置参数说明:
918
919|      | 配置项名称 | 功能                                  | 必填 |
920| :--- | :--------- | :------------------------------------ | ---- |
921| 1    | "suite"    | 测试套配置 。                         | 是   |
922| 2    | "items"    | 测试用例配置 。                       | 是   |
923| 3    | "describe" | 测试套名称 。                         | 是   |
924| 4    | "it"       | 测试用例名称 。                       | 是   |
925| 5    | "params"   | 测试套 / 测试用例 可传入使用的参数 。 | 否   |
926| 6    | "stress"   | 测试套 / 测试用例 指定执行次数 。     | 否   |
927
928示例代码:
929
930在TestAbility目录下app.js|ets文件中导入data.json,并在Hypium.hypiumTest() 方法执行前,设置参数数据
931
932```javascript
933import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
934import { Hypium } from '@ohos/hypium'
935import testsuite from '../test/List.test'
936import data from '../test/data.json';
937
938...
939Hypium.setData(data);
940Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
941...
942```
943
944```javascript
945import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium';
946
947export default function abilityTest() {
948    describe('actsAbilityTest', function () {
949        it('testDataDriverAsync', 0, async function (done, data) {
950            console.info('name: ' + data.name);
951            console.info('value: ' + data.value);
952            done();
953        });
954
955        it('testDataDriver', 0, function () {
956            console.info('stress test');
957        });
958    });
959}
960```
961
962### 使用方式
963
964单元测试框架以npm包(hypium)形式发布至[服务组件官网](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium),开发者可以下载Deveco Studio后,在应用工程中配置依赖后使用框架能力,测试工程创建及测试脚本执行使用指南请参见[IDE指导文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001267284568)965
966## Ui测试框架功能特性
967
968| No.  | 特性        | 功能说明                                                     |
969| ---- | ----------- | ------------------------------------------------------------ |
970| 1    | UiDriver    | Ui测试的入口,提供查找控件,检查控件存在性以及注入按键能力。 |
971| 2    | By          | 用于描述目标控件特征(文本、id、类型等),`UiDriver`根据`By`描述的控件特征信息来查找控件。 |
972| 3    | UiComponent | UiDriver查找返回的控件对象,提供查询控件属性,滑动查找等触控和检视能力。 |
973| 4    | UiWindow    | UiDriver查找返回的窗口对象,提供获取窗口属性、操作窗口的能力。 |
974
975**使用者在测试脚本通过如下方式引入使用:**
976
977```typescript
978import {UiDriver,BY,UiComponent,Uiwindow,MatchPattern} from '@ohos.uitest'
979```
980
981> 须知
982> 1. `By`类提供的接口全部是同步接口,使用者可以使用`builder`模式链式调用其接口构造控件筛选条件。
983> 2. `UiDriver`和`UiComponent`类提供的接口全部是异步接口(`Promise`形式),**需使用`await`语法**。
984> 3. Ui测试用例均需使用**异步**语法编写用例,需遵循单元测试框架异步用例编写规范。
985
986
987
988在测试用例文件中import `By/UiDriver/UiComponent`类,然后调用API接口编写测试用例。
989
990```javascript
991import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium'
992import {BY, UiDriver, UiComponent, MatchPattern} from '@ohos.uitest'
993
994export default async function abilityTest() {
995  describe('uiTestDemo', function() {
996    it('uitest_demo0', 0, async function() {
997      // create UiDriver
998      let driver = await UiDriver.create()
999      // find component by text
1000      let button = await driver.findComponent(BY.text('hello').enabled(true))
1001      // click component
1002      await button.click()
1003      // get and assert component text
1004      let content = await button.getText()
1005      expect(content).assertEquals('clicked!')
1006    })
1007  })
1008}
1009```
1010
1011### UiDriver使用说明
1012
1013`UiDriver`类作为UiTest测试框架的总入口,提供查找控件,注入按键,单击坐标,滑动控件,手势操作,截图等能力。
1014
1015| No.  | API                                                          | 功能描述                 |
1016| ---- | ------------------------------------------------------------ | ------------------------ |
1017| 1    | create():Promise<UiDriver>                                   | 静态方法,构造UiDriver。 |
1018| 2    | findComponent(b:By):Promise<UiComponent>                     | 查找匹配控件。           |
1019| 3    | pressBack():Promise<void>                                    | 单击BACK键。             |
1020| 4    | click(x:number, y:number):Promise<void>                      | 基于坐标点的单击。       |
1021| 5    | swipe(x1:number, y1:number, x2:number, y2:number):Promise<void> | 基于坐标点的滑动。       |
1022| 6    | assertComponentExist(b:By):Promise<void>                     | 断言匹配的控件存在。     |
1023| 7    | delayMs(t:number):Promise<void>                              | 延时。                   |
1024| 8    | screenCap(s:path):Promise<void>                              | 截屏。                   |
1025| 9    | findWindow(filter: WindowFilter): Promise<UiWindow>          | 查找匹配窗口。           |
1026
1027其中assertComponentExist接口是断言API,用于断言当前界面存在目标控件;如果控件不存在,该API将抛出JS异常,使当前测试用例失败。
1028
1029```javascript
1030import {BY,UiDriver,UiComponent} from '@ohos.uitest'
1031
1032export default async function abilityTest() {
1033  describe('UiTestDemo', function() {
1034    it('Uitest_demo0', 0, async function(done) {
1035      try{
1036        // create UiDriver
1037        let driver = await UiDriver.create()
1038        // assert text 'hello' exists on current Ui
1039        await assertComponentExist(BY.text('hello'))
1040      } finally {
1041        done()
1042      }
1043    })
1044  })
1045}
1046```
1047
1048`UiDriver`完整的API列表请参考[API文档](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts)及[示例文档说明](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-uitest.md#uidriver)1049
1050### By使用说明
1051
1052Ui测试框架通过`By`类提供了丰富的控件特征描述API,用来匹配查找要操作或检视的目标控件。`By`提供的API能力具有以下特点:
1053
1054- 支持匹配单属性和匹配多属性组合,例如同时指定目标控件text和id。
1055- 控件属性支持多种匹配模式(等于,包含,`STARTS_WITH`,`ENDS_WITH`)。
1056- 支持相对定位控件,可通过`isBefore`和`isAfter`等API限定邻近控件特征进行辅助定位。
1057
1058| No.  | API                                | 功能描述                                         |
1059| ---- | ---------------------------------- | ------------------------------------------------ |
1060| 1    | id(i:number):By                    | 指定控件id。                                     |
1061| 2    | text(t:string, p?:MatchPattern):By | 指定控件文本,可指定匹配模式。                   |
1062| 3    | type(t:string)):By                 | 指定控件类型。                                   |
1063| 4    | enabled(e:bool):By                 | 指定控件使能状态。                               |
1064| 5    | clickable(c:bool):By               | 指定控件可单击状态。                             |
1065| 6    | focused(f:bool):By                 | 指定控件获焦状态。                               |
1066| 7    | scrollable(s:bool):By              | 指定控件可滑动状态。                             |
1067| 8    | selected(s:bool):By                | 指定控件选中状态。                               |
1068| 9    | isBefore(b:By):By                  | **相对定位**,限定目标控件位于指定特征控件之前。 |
1069| 10   | isAfter(b:By):By                   | **相对定位**,限定目标控件位于指定特征控件之后。 |
1070
1071其中,`text`属性支持{`MatchPattern.EQUALS`,`MatchPattern.CONTAINS`,`MatchPattern.STARTS_WITH`,`MatchPattern.ENDS_WITH`}四种匹配模式,缺省使用`MatchPattern.EQUALS`模式。
1072
1073`By`完整的API列表请参考[API文档](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts)及[示例文档说明](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-uitest.md#by)1074
1075#### 控件绝对定位
1076
1077**示例代码1**:查找id是`Id_button`的控件。
1078
1079```javascript
1080let button = await driver.findComponent(BY.id(Id_button))
1081```
1082
1083 **示例代码2**:查找id是`Id_button`并且状态是`enabled`的控件,适用于无法通过单一属性定位的场景。
1084
1085```javascript
1086let button = await driver.findComponent(BY.id(Id_button).enabled(true))
1087```
1088
1089通过`By.id(x).enabled(y)`来指定目标控件的多个属性。
1090
1091**示例代码3**:查找文本中包含`hello`的控件,适用于不能完全确定控件属性取值的场景。
1092
1093```javascript
1094let txt = await driver.findComponent(BY.text("hello", MatchPattern.CONTAINS))
1095```
1096
1097通过向`By.text()`方法传入第二个参数`MatchPattern.CONTAINS`来指定文本匹配规则;默认规则是`MatchPattern.EQUALS`,即目标控件text属性必须严格等于给定值。
1098
1099####  控件相对定位
1100
1101**示例代码1**:查找位于文本控件`Item3_3`后面的,id是`ResourceTable.Id_switch`的Switch控件。
1102
1103```javascript
1104let switch = await driver.findComponent(BY.id(Id_switch).isAfter(BY.text("Item3_3")))
1105```
1106
1107通过`By.isAfter`方法,指定位于目标控件前面的特征控件属性,通过该特征控件进行相对定位。一般地,特征控件是某个具有全局唯一特征的控件(例如具有唯一的id或者唯一的text)。
1108
1109类似的,可以使用`By.isBefore`控件指定位于目标控件后面的特征控件属性,实现相对定位。
1110
1111### UiComponent使用说明
1112
1113`UiComponent`类代表了Ui界面上的一个控件,一般是通过`UiDriver.findComponent(by)`方法查找到的。通过该类的实例,用户可以获取控件属性,单击控件,滑动查找,注入文本等操作。
1114
1115`UiComponent`包含的常用API:
1116
1117| No.  | API                               | 功能描述                                       |
1118| ---- | --------------------------------- | ---------------------------------------------- |
1119| 1    | click():Promise<void>             | 单击该控件。                                   |
1120| 2    | inputText(t:string):Promise<void> | 向控件中输入文本(适用于文本框控件)。           |
1121| 3    | scrollSearch(s:By):Promise<bool>  | 在该控件上滑动查找目标控件(适用于List等控件)。 |
1122| 4    | getText():Promise<string>         | 获取控件text。                                 |
1123| 5    | getId():Promise<number>           | 获取控件id。                                   |
1124| 6    | getType():Promise<string>         | 获取控件类型。                                 |
1125| 7    | isEnabled():Promise<bool>         | 获取控件使能状态。                             |
1126
1127`UiComponent`完整的API列表请参考[API文档](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts)及[示例文档说明](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-uitest.md#uicomponent)1128
1129**示例代码1**:单击控件。
1130
1131```javascript
1132let button = await driver.findComponent(BY.id(Id_button))
1133await button.click()
1134```
1135
1136**示例代码2**:通过get接口获取控件属性后,可以使用单元测试框架提供的assert*接口做断言检查。
1137
1138```javascript
1139let component = await driver.findComponent(BY.id(Id_title))
1140expect(component !== null).assertTrue()
1141```
1142
1143**示例代码3**:在List控件中滑动查找text是`Item3_3`的子控件。
1144
1145```javascript
1146let list = await driver.findComponent(BY.id(Id_list))
1147let found = await list.scrollSearch(BY.text("Item3_3"))
1148expect(found).assertTrue()
1149```
1150
1151**示例代码4**:向输入框控件中输入文本。
1152
1153```javascript
1154let editText = await driver.findComponent(BY.type('InputText'))
1155await editText.inputText("user_name")
1156```
1157### UiWindow使用说明
1158
1159`UiWindow`类代表了Ui界面上的一个窗口,一般是通过`UiDriver.findWindow(by)`方法查找到的。通过该类的实例,用户可以获取窗口属性,并进行窗口拖动、调整窗口大小等操作。
1160
1161`UiWindow`包含的常用API:
1162
1163| No.  | API                                                          | 功能描述                                           |
1164| ---- | ------------------------------------------------------------ | -------------------------------------------------- |
1165| 1    | getBundleName(): Promise<string>                             | 获取窗口所属应用包名。                             |
1166| 2    | getTitle(): Promise<string>                                  | 获取窗口标题信息。                                 |
1167| 3    | focus(): Promise<bool>                                       | 使得当前窗口获取焦点。                             |
1168| 4    | moveTo(x: number, y: number): Promise<bool>;                 | 将当前窗口移动到指定位置(适用于支持移动的窗口)。 |
1169| 5    | resize(wide: number, height: number, direction: ResizeDirection): Promise<bool> | 调整窗口大小(适用于支持调整大小的窗口)。         |
1170| 6    | split(): Promise<bool>                                       | 将窗口模式切换为分屏模式(适用于支持分屏的窗口)。   |
1171| 7    | close(): Promise<bool>                                       | 关闭当前窗口。                                     |
1172
1173`UiWindow`完整的API列表请参考[API文档](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts)及[示例文档说明](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-uitest.md#uiwindow9)1174
1175**示例代码1**:获取窗口属性。
1176
1177```javascript
1178let window = await driver.findWindow({actived: true})
1179let bundelName = await window.getBundleName()
1180```
1181
1182**示例代码2**:移动窗口。
1183
1184```javascript
1185let window = await driver.findWindow({actived: true})
1186await window.moveTo(500,500)
1187```
1188
1189**示例代码3**:关闭窗口。
1190
1191```javascript
1192let window = await driver.findWindow({actived: true})
1193await window.close()
1194```
1195
1196### 使用方式
1197
1198  开发者可以下载Deveco Studio创建测试工程后,在其中调用框架提供接口进行相关测试操作,测试工程创建及测试脚本执行使用指南请参见[IDE指导文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001267284568)1199  UI测试框架使能需要执行如下命令。
1200
1201>```shell
1202> hdc_std shell param set persist.ace.testmode.enabled 1
1203>```
1204### UI测试框架自构建方式
1205
1206> Ui测试框架在OpenHarmony-3.1-Release版本中未随版本编译,需手动处理,请参考[3.1-Release版本使用指导](https://gitee.com/openharmony/arkXtest/blob/OpenHarmony-3.1-Release/README_zh.md#%E6%8E%A8%E9%80%81ui%E6%B5%8B%E8%AF%95%E6%A1%86%E6%9E%B6%E8%87%B3%E8%AE%BE%E5%A4%87)1207
1208开发者如需自行编译Ui测试框架代码验证子修改内容,构建命令和推送位置请参考本章节内容。
1209
1210#### 构建命令
1211
1212```shell
1213./build.sh --product-name rk3568 --build-target uitestkit
1214```
1215#### 推送位置
1216
1217```shell
1218hdc_std target mount
1219hdc_std shell mount -o rw,remount /
1220hdc_std file send uitest /system/bin/uitest
1221hdc_std file send libuitest.z.so /system/lib/module/libuitest.z.so
1222hdc_std shell chmod +x /system/bin/uitest
1223```
1224
1225### 版本信息
1226
1227| 版本号  | 功能说明                                                     |
1228| :------ | :----------------------------------------------------------- |
1229| 3.2.2.1 | 1、增加抛滑、获取/设置屏幕方向接口<br />2、窗口处理逻辑增加不支持场景处理逻辑 |
1230