• Home
Name Date Size #Lines LOC

..--

jsunit/12-May-2024-3,2452,485

uitest/12-May-2024-13,98411,079

CODEOWNERSD12-May-2024602 1413

LICENSED12-May-20249.9 KiB177150

OAT.xmlD12-May-20243.8 KiB6112

README_en.mdD12-May-202448.3 KiB1,106862

README_zh.mdD12-May-202451.1 KiB1,230986

bundle.jsonD12-May-20241.3 KiB5756

README_en.md

1# arkXtest
2
3## Introduction
4arkXtest, the automated test framework of OpenHarmony, consists of the JS unit test framework (JsUnit) and UI test framework (UiTest).
5
6JsUnit provides APIs for writing test cases for system or application interfaces, executing unit test cases, and generating test reports.
7
8UiTest provides simple and easy-to-use APIs for locating and operating UI components, helping users to develop automatic test scripts based on UI operations.
9
10## Directory Structure
11
12```
13arkXtest
14  |-----jsunit  Unit test framework
15  |-----uitest UI test framework
16```
17## Constraints
18The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version.
19
20## JsUnit Features
21
22| No.  | Feature    | Description                                                    |
23| ---- | -------- | ------------------------------------------------------------ |
24| 1    | Basic process support| Provides APIs for writing and executing test cases.                                    |
25| 2    | Assertion library  | Provides APIs for checking whether the actual value of a test case is the same as the expected value.                        |
26| 3    | Mock| Provides APIs for mocking functions to return the specified value or perform the specified action.|
27| 4    | Data driving| Provides APIs for reusing a test script with different input data.|
28
29### How to Use
30
31####  Basic Process Support
32
33Test cases use the common syntax in the industry. **describe** defines a test suite, and **it** specifies a test case.
34
35| No.  | API        | Description                                                    |
36| ---- | ---------- | ------------------------------------------------------------ |
37| 1    | describe   | Defines a test suite. This API supports two parameters: test suite name and test suite function.      |
38| 2    | beforeAll  | Presets an action, which is performed only once before all test cases of the test suite start. This API supports only one parameter: preset action function.|
39| 3    | beforeEach | Presets an action, which is performed before each unit test case starts. The number of execution times is the same as the number of test cases defined by **it**. This API supports only one parameter: preset action function.|
40| 4    | afterEach  | Presets a clear action, which is performed after each unit test case ends. The number of execution times is the same as the number of test cases defined by **it**. This API supports only one parameter: clear action function.|
41| 5    | afterAll   | Presets a clear action, which is performed after all test cases of the test suite end. This API supports only one parameter: clear action function.|
42| 6    | it         | Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.|
43| 7    | expect     | Defines a variety of assertion methods, which are used to declare expected Boolean conditions.                            |
44
45The sample code is as follows:
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####  Assertion Library
77
78Available APIs:
79
80
81| No.  | API              | Description                                                    |
82| :--- | :--------------- | ------------------------------------------------------------ |
83| 1    | assertClose      | Checks whether the proximity between the actual value and the expected value (0) is the expected value (1).|
84| 2    | assertContain    | Checks whether the actual value contains the expected value.                      |
85| 3    | assertEqual      | Checks whether the actual value is equal to the expected value.                     |
86| 4    | assertFail       | Throws an error.                                              |
87| 5    | assertFalse      | Check whether the actual value is **false**.                                |
88| 6    | assertTrue       | Checks whether the actual value is **true**.                                 |
89| 7    | assertInstanceOf | Checks whether the actual value is of the type specified by the expected value.                      |
90| 8    | assertLarger     | Checks whether the actual value is greater than the expected value.                        |
91| 9    | assertLess       | Checks whether the actual value is less than the expected value.                        |
92| 10   | assertNull       | Checks whether the actual value is null.                                 |
93| 11   | assertThrowError | Checks whether the error thrown by the actual value is the expected value.             |
94| 12   | assertUndefined  | Checks whether the actual value is **undefined**.                            |
95
96The sample code is as follows:
97
98```javascript
99import { describe, it, expect } from '@ohos/hypium'
100export default async function abilityTest() {
101  describe('assertClose', function () {
102    it('assertBeClose success', 0, function () {
103      let a = 100
104      let b = 0.1
105      expect(a).assertClose(99, b)
106    })
107    it('assertBeClose fail', 0, function () {
108      let a = 100
109      let b = 0.1
110      expect(a).assertClose(1, b)
111    })
112    it('assertBeClose fail', 0, function () {
113      let a = 100
114      let b = 0.1
115      expect(a).assertClose(null, b)
116    })
117    it('assertBeClose fail', 0, function () {
118      expect(null).assertClose(null, 0)
119    })
120  })
121}
122```
123
124
125#### Mock
126
127##### Constraints
128
129JsUnit provides the mock capability since npm [1.0.1](https://repo.harmonyos.com/#/en/application/atomService/@ohos%2Fhypium). You must modify the npm version in **package.info** of the source code project before using the mock capability.
130
131-  **Available APIs**
132
133| No. | API | Description|
134| --- | --- | --- |
135| 1 | mockFunc(obj: object, f: function())| Mocks a function in the object of a class. The parameters **obj** and **f** must be passed in. This API supports asynchronous functions. <br>**NOTE**: This API does not focus on the implementation of the original function. Therefore, it does not matter whether the original function is implemented synchronously or asynchronously.|
136| 2 | when(mockedfunc: function)| Checks whether the input function is mocked and marked. A function declaration is returned.|
137| 3 | afterReturn(x: value)| Sets an expected return value, for example, a string or promise.|
138| 4 | afterReturnNothing() | Sets the expected return value to **undefined**, that is, no value will be returned.|
139| 5 | afterAction(x: action)| Sets the expected return value to be an action executed by a function.|
140| 6 | afterThrow(x: msg)| Sets an exception to throw and the error message.|
141| 7 | clear() | Restores the mocked object after the test case is complete (restores the original features of the object).|
142| 8 | any | Returns the expected value if a parameter of any type (except **undefined** and **null**) is passed in. This API must be called by **ArgumentMatchers.any**.|
143| 9 | anyString | Returns the expected value if a string is passed in. This API must be called by **ArgumentMatchers.anyString**.|
144| 10 | anyBoolean | Returns the expected value if a Boolean value is passed in. This API must be called by **ArgumentMatchers.anyBoolean**.|
145| 11 | anyFunction | Returns the expected value if a function is passed in. This API must be called by **ArgumentMatchers.anyFunction**.|
146| 12 | anyNumber | Returns the expected value if a number is passed in. This API must be called by **ArgumentMatchers.anyNumber**.|
147| 13 | anyObj | Returns the expected value if an object is passed in. This API must be called by **ArgumentMatchers.anyObj**.|
148| 14 | matchRegexs(Regex) | Returns the expected value if a regular expression is passed in. This API must be called by **ArgumentMatchers.matchRegexs(Regex)**.|
149| 15 | verify(methodName, argsArray) | Verifies whether a function and its parameters are processed as expected. This API returns a **VerificationMode**, which is a class that provides the verification mode. This class provides functions such as **times(count)**, **once()**, **atLeast(x)**, **atMost(x)**, and **never()**.|
150| 16 | times(count) | Verifies whether the function was executed the specified number of times.|
151| 17 | once() | Verifies whether the function was executed only once.|
152| 18 | atLeast(count) | Verifies whether the function was executed at least **count** times.|
153| 19 | atMost(count) | Verifies whether the function was executed at most **count** times.|
154| 20 | never | Verifies whether the function has never been executed.|
155| 21 | ignoreMock(obj, method) | Restores the mocked function in the object. This API is valid for mocked functions.|
156| 22 | clearAll() | Clears all data and memory after the test cases are complete.|
157
158-  **Examples**
159
160You can refer to the following examples to import the mock module and write test cases.
161
162- **NOTICE**<br>
163You must import **MockKit** and **when**. You can import other assertion APIs based on the test cases.
164Example: `import {describe, expect, it, MockKit, when} from '@ohos/hypium'`
165
166Example 1: Use **afterReturn**.
167
168```javascript
169import {describe, expect, it, MockKit, when} from '@ohos/hypium';
170
171export default function ActsAbilityTest() {
172    describe('ActsAbilityTest', function () {
173        it('testMockfunc', 0, function () {
174            console.info("it1 begin");
175
176            // 1. Create a MockKit object.
177            let mocker = new MockKit();
178
179            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
180            class ClassName {
181                constructor() {
182                }
183
184                method_1(arg) {
185                    return '888888';
186                }
187
188                method_2(arg) {
189                    return '999999';
190                }
191            }
192
193            let claser = new ClassName();
194
195            // 3. Mock method_1 of the ClassName class.
196            let mockfunc = mocker.mockFunc(claser, claser.method_1);
197            when(mockfunc)('test').afterReturn('1');
198
199            // 4. Assert whether the mocked function is implemented as expected.
200            // The operation is successful if 'test' is passed in.
201            expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
202
203            // The operation fails if 'abc' is passed in.
204            //expect(claser.method_1('abc')).assertEqual('1'); // The operation fails.
205        });
206    });
207}
208```
209- **NOTICE**<br>
210In `when(mockfunc)('test').afterReturn('1');`, `('test')` is the value to pass in the mocked function. Currently, only one parameter is supported. `afterReturn('1')` is the expected return value. The expected value is returned only when `('test')` is passed in.
211
212Example 2: Use **afterReturnNothing**.
213
214```javascript
215import {describe, expect, it, MockKit, when} from '@ohos/hypium';
216
217export default function ActsAbilityTest() {
218    describe('ActsAbilityTest', function () {
219        it('testMockfunc', 0, function () {
220            console.info("it1 begin");
221
222            // 1. Create a MockKit object.
223            let mocker = new MockKit();
224
225            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
226            class ClassName {
227                constructor() {
228                }
229
230                method_1(arg) {
231                    return '888888';
232                }
233
234                method_2(arg) {
235                    return '999999';
236                }
237            }
238
239            let claser = new ClassName();
240
241            // 3. Mock method_1 of the ClassName class.
242            let mockfunc = mocker.mockFunc(claser, claser.method_1);
243
244            // 4. Set the action to be performed when the test case ends. For example, set it to afterReturnNothing(), which returns no value.
245            when(mockfunc)('test').afterReturnNothing();
246
247            // 5. Assert whether the mocked function is implemented as expected. Use the assertion APIs corresponding to Step 4.
248            // The operation is successful if 'test' is passed in.
249            // The mocked claser.method_1 does not return '888888'. Instead, afterReturnNothing() takes effect, that is, no value is returned.
250            expect(claser.method_1('test')).assertUndefined(); // The operation is successful.
251
252            // The operation fails if '123' is passed in.
253            // expect(method_1(123)).assertUndefined();// The operation fails.
254        });
255    });
256}
257```
258
259Example 3: Set the parameter type to **any**, that is, allow any parameter value except **undefine** and **null**.
260
261
262- **NOTICE**<br>
263The **ArgumentMatchers** class, for example, **ArgumentMatchers.any**, must be imported.
264
265```javascript
266import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
267
268export default function ActsAbilityTest() {
269    describe('ActsAbilityTest', function () {
270        it('testMockfunc', 0, function () {
271            console.info("it1 begin");
272
273            // 1. Create a MockKit object.
274            let mocker = new MockKit();
275
276            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
277            class ClassName {
278                constructor() {
279                }
280
281                method_1(arg) {
282                    return '888888';
283                }
284
285                method_2(arg) {
286                    return '999999';
287                }
288            }
289
290            let claser = new ClassName();
291
292            // 3. Mock method_1 of the ClassName class.
293            let mockfunc = mocker.mockFunc(claser, claser.method_1);
294            // Set the parameter matcher and expected return value as required.
295            when(mockfunc)(ArgumentMatchers.any).afterReturn('1');
296
297            // 4. Assert whether the mocked function is implemented as expected.
298            // The operation is successful if a string is passed in.
299            expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
300            // The operation is successful if a number (for example '123') is passed in.
301            expect(claser.method_1(123)).assertEqual('1'); // The operation is successful.
302            // The operation is successful if a Boolean value (for example 'true') is passed in.
303            expect(claser.method_1(true)).assertEqual('1');// The operation is successful.
304
305            // The operation fails if an empty value is passed in.
306            //expect(claser.method_1()).assertEqual('1');// The operation fails.
307        });
308    });
309}
310```
311
312Example 4: Set the parameter type to **anyString**.
313
314```javascript
315import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
316
317export default function ActsAbilityTest() {
318    describe('ActsAbilityTest', function () {
319        it('testMockfunc', 0, function () {
320            console.info("it1 begin");
321
322            // 1. Create a MockKit object.
323            let mocker = new MockKit();
324
325            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
326            class ClassName {
327                constructor() {
328                }
329
330                method_1(arg) {
331                    return '888888';
332                }
333
334                method_2(arg) {
335                    return '999999';
336                }
337            }
338
339            let claser = new ClassName();
340
341            // 3. Mock method_1 of the ClassName class.
342            let mockfunc = mocker.mockFunc(claser, claser.method_1);
343            // Set the following parameters as required.
344            when(mockfunc)(ArgumentMatchers.anyString).afterReturn('1');
345
346            // 4. Assert whether the mocked function is implemented as expected.
347            // The operation is successful if a string is passed in.
348            expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
349            expect(claser.method_1('abc')).assertEqual('1'); // The operation is successful.
350
351            // The operation fails if a number or a Boolean value is passed in.
352            //expect(claser.method_1(123)).assertEqual('1'); // The operation fails.
353            //expect(claser.method_1(true)).assertEqual('1'); // The operation fails.
354        });
355    });
356}
357```
358
359Example 5: Set the parameter type to **matchRegexs (Regex)**.
360```javascript
361import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
362
363export default function ActsAbilityTest() {
364    describe('ActsAbilityTest', function () {
365        it('testMockfunc', 0, function () {
366            console.info("it1 begin");
367
368            // 1. Create a MockKit object.
369            let mocker = new MockKit();
370
371            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
372            class ClassName {
373                constructor() {
374                }
375
376                method_1(arg) {
377                    return '888888';
378                }
379
380                method_2(arg) {
381                    return '999999';
382                }
383            }
384
385            let claser = new ClassName();
386
387            // 3. Mock method_1 of the ClassName class.
388            let mockfunc = mocker.mockFunc(claser, claser.method_1);
389            // Set a regular expression to match, for example, /123456/.
390            when(mockfunc)(ArgumentMatchers.matchRegexs(/123456/)).afterReturn('1');
391
392            // 4. Assert whether the mocked function is implemented as expected.
393            // The operation is successful if a string, for example, '1234567898', is passed in.
394            expect(claser.method_1('1234567898')).assertEqual('1'); // The operation is successful.
395            // The string '1234567898' matches the regular expression /123456/.
396
397            // The operation fails if '1234' is passed in.
398            //expect(claser.method_1('1234').assertEqual('1'); // The operation fails because '1234' does not match the regular expression /123456/.
399        });
400    });
401}
402```
403
404Example 6: Use **verify()**.
405```javascript
406import {describe, expect, it, MockKit, when} from '@ohos/hypium';
407
408export default function ActsAbilityTest() {
409    describe('ActsAbilityTest', function () {
410        it('testMockfunc', 0, function () {
411            console.info("it1 begin");
412
413            // 1. Create a MockKit object.
414            let mocker = new MockKit();
415
416            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
417            class ClassName {
418                constructor() {
419                }
420
421                method_1(...arg) {
422                    return '888888';
423                }
424
425                method_2(...arg) {
426                    return '999999';
427                }
428            }
429
430            let claser = new ClassName();
431
432            // 3. Mock method_1 and method_2 of the ClassName class.
433            mocker.mockFunc(claser, claser.method_1);
434            mocker.mockFunc(claser, claser.method_2);
435
436            // 4. Call the following methods.
437            claser.method_1('abc', 'ppp');
438            claser.method_1('abc');
439            claser.method_1('xyz');
440            claser.method_1();
441            claser.method_1('abc', 'xxx', 'yyy');
442            claser.method_1();
443            claser.method_2('111');
444            claser.method_2('111', '222');
445
446            //5. Verify the mocked functions.
447            mocker.verify('method_1', []).atLeast(3); // The result is "failed".
448            // Verify whether 'method_1' with an empty parameter list was executed at least three times.
449            // The result is "failed" because 'method_1' with an empty parameter list was executed only twice in Step 4.
450            //mocker.verify('method_2',['111']).once(); // The result is "success".
451            //mocker.verify('method_2',['111',,'222']).once(); // The result is "success".
452        });
453    });
454}
455```
456
457Example 7: Use **ignoreMock(obj, method)**.
458```javascript
459import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
460
461export default function ActsAbilityTest() {
462    describe('ActsAbilityTest', function () {
463        it('testMockfunc', 0, function () {
464            console.info("it1 begin");
465
466            // 1. Create a MockKit object.
467            let mocker = new MockKit();
468
469            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
470            class ClassName {
471                constructor() {
472                }
473
474                method_1(...arg) {
475                    return '888888';
476                }
477
478                method_2(...arg) {
479                    return '999999';
480                }
481            }
482
483            let claser = new ClassName();
484
485            // 3. Mock method_1 and method_2 of the ClassName class.
486            let func_1 = mocker.mockFunc(claser, claser.method_1);
487            let func_2 = mocker.mockFunc(claser, claser.method_2);
488
489            // 4. Modify the mocked functions.
490            when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
491            when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
492
493            // 5. Call the following methods.
494            console.log(claser.method_1(123)); // The return value is 4, which is the same as the expected value in Step 4.
495            console.log(claser.method_2(456)); // The return value is 5, which is the same as the expected value in Step 4.
496
497            // 6. Restore method_1 using ignoreMock().
498            mocker.ignoreMock(claser, claser.method_1);
499            // Call claser.method_1 and check the execution result.
500            console.log(claser.method_1(123)); // The return value is 888888, which is the same as that returned by the original function.
501            // Test with assertions.
502            expect(claser.method_1(123)).assertEqual('4'); // The return value is "failed", which meets the expected value of ignoreMock().
503            claser.method_2(456); // The return value is 5, which is the same as the expected value in Step 4 because method_2 is not restored.
504        });
505    });
506}
507```
508
509Example 8: Use **clear()**.
510
511```javascript
512import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
513
514export default function ActsAbilityTest() {
515    describe('ActsAbilityTest', function () {
516        it('testMockfunc', 0, function () {
517            console.info("it1 begin");
518
519            // 1. Create a MockKit object.
520            let mocker = new MockKit();
521
522            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
523            class ClassName {
524                constructor() {
525                }
526
527                method_1(...arg) {
528                    return '888888';
529                }
530
531                method_2(...arg) {
532                    return '999999';
533                }
534            }
535            let claser = new ClassName();
536
537            // 3. Mock method_1 and method_2 of the ClassName class.
538            let func_1 = mocker.mockFunc(claser, claser.method_1);
539            let func_2 = mocker.mockFunc(claser, claser.method_2);
540
541            // 4. Modify the mocked functions.
542            when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
543            when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
544
545            // 5. Call the following methods.
546            //expect(claser.method_1(123)).assertEqual('4'); // The return value is the same as the expected value.
547            //expect(claser.method_2(456)).assertEqual('5'); // The return value is the same as the expected value.
548
549            // 6. Clear the mock operation.
550            mocker.clear(claser);
551            // Call claser.method_1 and check the execution result.
552            expect(claser.method_1(123)).assertEqual('4'); // The return value is "failed", which meets the expectation.
553            expect(claser.method_2(456)).assertEqual('5'); // The return value is "failed", which meets the expectation.
554        });
555    });
556}
557```
558
559
560Example 9: Use **afterThrow(msg)**.
561
562```javascript
563import {describe, expect, it, MockKit, when} from '@ohos/hypium';
564
565export default function ActsAbilityTest() {
566    describe('ActsAbilityTest', function () {
567        it('testMockfunc', 0, function () {
568            console.info("it1 begin");
569
570            // 1. Create a MockKit object.
571            let mocker = new MockKit();
572
573            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
574            class ClassName {
575                constructor() {
576                }
577
578                method_1(arg) {
579                    return '888888';
580                }
581            }
582
583            let claser = new ClassName();
584
585            // 3. Mock method_1 of the ClassName class.
586            let mockfunc = mocker.mockFunc(claser, claser.method_1);
587
588            // 4. Set the action to be performed when the test case ends. For example, set it to afterReturnNothing(), which returns no value.
589            when(mockfunc)('test').afterThrow('error xxx');
590
591            // 5. Execute the mocked function, capture the exception, and use assertEqual() to check whether message meets the expectation.
592            try {
593                claser.method_1('test');
594            } catch (e) {
595                expect(e).assertEqual('error xxx'); // The execution is successful.
596            }
597        });
598    });
599}
600```
601
602Example 10: Mock asynchronous functions.
603
604```javascript
605import {describe, expect, it, MockKit, when} from '@ohos/hypium';
606
607export default function ActsAbilityTest() {
608    describe('ActsAbilityTest', function () {
609        it('testMockfunc', 0, function () {
610            console.info("it1 begin");
611
612            // 1. Create a MockKit object.
613            let mocker = new MockKit();
614
615            // 2. Define the ClassName class, which contains two functions, and then create a claser object.
616            class ClassName {
617                constructor() {
618                }
619
620                async method_1(arg) {
621                    return new Promise((res, rej) => {
622                        // Perform asynchronous operations.
623                        setTimeout(function () {
624                            console.log ('Execute');
625                            res('Pass data');
626                        }, 2000);
627                    });
628                }
629            }
630
631            let claser = new ClassName();
632
633            // 3. Mock method_1 of the ClassName class.
634            let mockfunc = mocker.mockFunc(claser, claser.method_1);
635
636            // 4. Set the action to be performed after the test case ends. For example, set it to afterRetrun(), which returns a custom promise.
637            when(mockfunc)('test').afterReturn(new Promise((res, rej) => {
638                console.log("do something");
639                res('success something');
640            }));
641
642            // 5. Execute the mocked function, that is, execute the promise.
643            claser.method_1('test').then(function (data) {
644                // Code for data processing
645                console.log('result : ' + data);
646            });
647        });
648    });
649}
650```
651
652Example 11: Mock a system function.
653
654```javascript
655export default function ActsAbilityTest() {
656    describe('ActsAbilityTest', function () {
657        it('test_systemApi', 0, function () {
658            // 1. Create a MockKit object.
659            let mocker = new MockKit();
660            // 2. Mock the app.getInfo() function.
661            let mockf = mocker.mockFunc(app, app.getInfo);
662            when(mockf)('test').afterReturn('1');
663            // The operation is successful.
664            expect(app.getInfo('test')).assertEqual('1');
665        });
666    });
667}
668```
669
670
671Example 12: Verify **times(count)**.
672
673```javascript
674import { describe, expect, it, MockKit, when } from '@ohos/hypium'
675
676export default function ActsAbilityTest() {
677    describe('ActsAbilityTest', function () {
678        it('test_verify_times', 0, function () {
679            // 1. Create a MockKit object.
680            let mocker = new MockKit();
681            // 2. Define the class to be mocked.
682            class ClassName {
683                constructor() {
684                }
685
686                method_1(...arg) {
687                    return '888888';
688                }
689            }
690            // 3. Create an object of the class.
691            let claser = new ClassName();
692            // 4. Mock a function, for example, method_1, of the object.
693            let func_1 = mocker.mockFunc(claser, claser.method_1);
694            // 5. Set the expected value to be returned by the mocked function.
695            when(func_1)('123').afterReturn('4');
696
697            // 6. Execute the function several times, with parameters set as follows:
698            claser.method_1('123', 'ppp');
699            claser.method_1('abc');
700            claser.method_1('xyz');
701            claser.method_1();
702            claser.method_1('abc', 'xxx', 'yyy');
703            claser.method_1('abc');
704            claser.method_1();
705            // 7. Check whether method_1 with the parameter of 'abc' was executed twice.
706            mocker.verify('method_1', ['abc']).times(2);
707        });
708    });
709}
710```
711
712
713Example 13: Verify **atLeast(count)**.
714
715```javascript
716import { describe, expect, it, MockKit, when } from '@ohos/hypium'
717
718export default function ActsAbilityTest() {
719    describe('ActsAbilityTest', function () {
720        it('test_verify_atLeast', 0, function () {
721            // 1. Create a MockKit object.
722            let mocker = new MockKit();
723            // 2. Define the class to be mocked.
724            class ClassName {
725                constructor() {
726                }
727
728                method_1(...arg) {
729                    return '888888';
730                }
731            }
732
733            // 3. Create an object of the class.
734            let claser = new ClassName();
735            // 4. Mock a function, for example, method_1, of the object.
736            let func_1 = mocker.mockFunc(claser, claser.method_1);
737            // 5. Set the expected value to be returned by the mocked function.
738            when(func_1)('123').afterReturn('4');
739            // 6. Execute the function several times, with parameters set as follows:
740            claser.method_1('123', 'ppp');
741            claser.method_1('abc');
742            claser.method_1('xyz');
743            claser.method_1();
744            claser.method_1('abc', 'xxx', 'yyy');
745            claser.method_1();
746            // 7. Check whether method_1 with an empty value was executed at least twice.
747            mocker.verify('method_1', []).atLeast(2);
748        });
749    });
750}
751```
752
753#### Data Driving
754
755##### Constraints
756
757JsUnit provides the following data driving capability since [Hypium 1.0.2](https://repo.harmonyos.com/#/en/application/atomService/@ohos%2Fhypium):
758
759- Passes parameters for the specified test suite and test case.
760- Specifies the number of times that the test suite and test case are executed.
761
762The execution times of test cases and the parameters passed in each time are determined by the settings in **data.json**. The file content is as follows:
763
764>**NOTE**<br>The **data.json** file is in the same directory as the **.test.js** or **.test.ets** file.
765
766```json
767{
768	"suites": [{
769		"describe": ["actsAbilityTest"],
770		"stress": 2,
771		"params": {
772			"suiteParams1": "suiteParams001",
773			"suiteParams2": "suiteParams002"
774		},
775		"items": [{
776			"it": "testDataDriverAsync",
777			"stress": 2,
778			"params": [{
779				"name": "tom",
780				"value": 5
781			}, {
782				"name": "jerry",
783				"value": 4
784			}]
785		}, {
786			"it": "testDataDriver",
787			"stress": 3
788		}]
789	}]
790}
791```
792
793Parameter description:
794
795|      | Name| Description                                 | Mandatory|
796| :--- | :--------- | :------------------------------------ | ---- |
797| 1    | "suite"    | Test suite configuration.                        | Yes  |
798| 2    | "items"    | Test case configuration.                      | Yes  |
799| 3    | "describe" | Test suite name.                        | Yes  |
800| 4    | "it"       | Test case name.                      | Yes  |
801| 5    | "params"   | Parameters to be passed to the test suite or test case.| No  |
802| 6    | "stress"   | Number of times that the test suite or test case is executed.    | No  |
803
804The sample code is as follows:
805
806Import the **data.json** file to the **app.js** or **app.ets** file in the **TestAbility** directory, and set parameters before executing the **Hypium.hypiumTest()** method.
807
808```javascript
809import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
810import { Hypium } from '@ohos/hypium'
811import testsuite from '../test/List.test'
812import data from '../test/data.json';
813
814...
815Hypium.setData(data);
816Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
817...
818```
819
820```javascript
821import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium';
822
823export default function abilityTest() {
824    describe('actsAbilityTest', function () {
825        it('testDataDriverAsync', 0, async function (done, data) {
826            console.info('name: ' + data.name);
827            console.info('value: ' + data.value);
828            done();
829        });
830
831        it('testDataDriver', 0, function () {
832            console.info('stress test');
833        });
834    });
835}
836```
837
838### How to Use
839
840JsUnit is released as an npm (hypium) package at the [service component official website](https://repo.harmonyos.com/#/en/application/atomService/@ohos%2Fhypium). You can download Deveco Studio, configure dependencies in the application project, and use JsUnit. For details about how to create a test project and execute test scripts, see the [OpenHarmony Test Framework](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001267284568).
841
842## UiTest Features
843
844| No.  | Feature       | Description                                                    |
845| ---- | ----------- | ------------------------------------------------------------ |
846| 1    | UiDriver    | Provides the UI test entry. It provides APIs for locating a component, checking whether a component exists, and injecting a key.|
847| 2    | By          | Describes the attributes (such as text, ID, and type) of UI components. `UiDriver` locates the component based on the attributes described by `By`.|
848| 3    | UiComponent | Provides the UI component object, which provides APIs for obtaining component attributes, clicking a component, and scrolling to search for a component.|
849| 4    | UiWindow    | Provides the window object, which provides APIs for obtaining window attributes, dragging a window, and adjusting the window size.|
850
851Import the following to the test script:
852
853```typescript
854import {UiDriver,BY,UiComponent,Uiwindow,MatchPattern} from '@ohos.uitest'
855```
856
857> **NOTICE**<br>
858> - All APIs provided by the `By` class are synchronous. You can use `builder` to call the APIs in chain mode to construct component filtering conditions.
859> - All the APIs provided by the `UiDriver` and `UiComponent` classes are asynchronous (in `Promise` mode), and `await` must be used.
860> - All UI test cases must be written in the asynchronous syntax and comply with the asynchronous test case specifications of JsUnit.
861
862
863
864Import the `By`, `UiDriver`, and `UiComponent` classes to the test case file, and then call the APIs to write test cases.
865
866```javascript
867import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium'
868import {BY, UiDriver, UiComponent, MatchPattern} from '@ohos.uitest'
869
870export default async function abilityTest() {
871  describe('uiTestDemo', function() {
872    it('uitest_demo0', 0, async function() {
873      // create UiDriver
874      let driver = await UiDriver.create()
875      // find component by text
876      let button = await driver.findComponent(BY.text('hello').enabled(true))
877      // click component
878      await button.click()
879      // get and assert component text
880      let content = await button.getText()
881      expect(content).assertEquals('clicked!')
882    })
883  })
884}
885```
886
887### Using UiDriver
888
889As the main entry to UiTest, the `UiDriver` class provides APIs for component matching/search, key injection, coordinate clicking/swiping, and screenshot.
890
891| No.  | API                                                          | Description                |
892| ---- | ------------------------------------------------------------ | ------------------------ |
893| 1    | create():Promise<UiDriver>                                   | Creates a **UiDriver** object. This API is a static method.|
894| 2    | findComponent(b:By):Promise<UiComponent>                     | Searches for a component.          |
895| 3    | pressBack():Promise<void>                                    | Presses the BACK button.            |
896| 4    | click(x:number, y:number):Promise<void>                      | Clicks a specific point based on the given coordinates.      |
897| 5    | swipe(x1:number, y1:number, x2:number, y2:number):Promise<void> | Swipes based on the given coordinates.      |
898| 6    | assertComponentExist(b:By):Promise<void>                     | Asserts that the component matching the given attributes exists on the current page.    |
899| 7    | delayMs(t:number):Promise<void>                              | Delays this **UiDriver** object for the specified duration.                  |
900| 8    | screenCap(s:path):Promise<void>                              | Captures the current screen.                  |
901| 9    | findWindow(filter: WindowFilter): Promise<UiWindow>          | Searches for a window.          |
902
903**assertComponentExist()** is an assertion API, which is used to assert that the target component exists on the current page. If the component does not exist, a JS exception will be thrown, causing the test case to fail.
904
905```javascript
906import {BY,UiDriver,UiComponent} from '@ohos.uitest'
907
908export default async function abilityTest() {
909  describe('UiTestDemo', function() {
910    it('Uitest_demo0', 0, async function(done) {
911      try{
912        // create UiDriver
913        let driver = await UiDriver.create()
914        // assert text 'hello' exists on current Ui
915        await assertComponentExist(BY.text('hello'))
916      } finally {
917        done()
918      }
919    })
920  })
921}
922```
923
924For details about the APIs of `UiDriver`, see [@ohos.uitest.d.ts](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts) and [UiDriver](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-uitest.md#uidriver).
925
926### Using By
927
928UiTest provides a wide range of UI component feature description APIs in the `By` class to filter and match components. The APIs provided by `By` exhibit the following features:
929
930- Allow one or more attributes as the match conditions. For example, you can specify both the text and id attributes to find a component.
931- Provide a variety of match patterns (`EQUALS`, `CONTAINS`, `STARTS_WITH`, and `ENDS_WITH`) for component attributes.
932- Support relative positioning for components. APIs such as `isBefore` and `isAfter` can be used to specify the features of adjacent components to assist positioning.
933
934| No.  | API                                | Description                                        |
935| ---- | ---------------------------------- | ------------------------------------------------ |
936| 1    | id(i:number):By                    | Specifies the component ID.                                    |
937| 2    | text(t:string, p?:MatchPattern):By | Specifies the component text. You can specify the match pattern.                  |
938| 3    | type(t:string)):By                 | Specifies the component type.                                  |
939| 4    | enabled(e:bool):By                 | Specifies the component state, which can be enabled or disabled.                              |
940| 5    | clickable(c:bool):By               | Specifies the clickable status of the component.                            |
941| 6    | focused(f:bool):By                 | Specifies the focused status of the component.                              |
942| 7    | scrollable(s:bool):By              | Specifies the scrollable status of the component.                            |
943| 8    | selected(s:bool):By                | Specifies the selected status of the component.                              |
944| 9    | isBefore(b:By):By                  | Specifies the attributes of the component that locates before the target component.|
945| 10   | isAfter(b:By):By                   | Specifies the attributes of the component that locates after the target component.|
946
947The `text` attribute supports match patterns `MatchPattern.EQUALS`, `MatchPattern.CONTAINS`, `MatchPattern.STARTS_WITH`, and `MatchPattern.ENDS_WITH`. The default match pattern is `MatchPattern.EQUALS`.
948
949For details about the APIs of `By`, see [@ohos.uitest.d.ts](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts) and [By](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-uitest.md#by).
950
951#### Absolute Positioning of a Component
952
953Example 1: Search for component `Id_button`.
954
955```javascript
956let button = await driver.findComponent(BY.id(Id_button))
957```
958
959 Example 2: Search for component `Id_button` in the `enabled` state. Use this API when the component cannot be located based on a single attribute.
960
961```javascript
962let button = await driver.findComponent(BY.id(Id_button).enabled(true))
963```
964
965Use `By.id(x).enabled(y)` to specify multiple attributes of the target component.
966
967Example 3: Search for the component whose text contains `hello`. Use this API when the component attribute values cannot be completely determined.
968
969```javascript
970let txt = await driver.findComponent(BY.text("hello", MatchPattern.CONTAINS))
971```
972
973`By.text()` passes the second parameter `MatchPattern.CONTAINS` to specify the matching rule. The default rule is `MatchPattern.EQUALS`, that is, the text attribute of the target component must be equal to the specified value.
974
975####  Relative Positioning of a Component
976
977Example 1: Search for the switch component `ResourceTable.Id_switch` following the text component `Item3_3`.
978
979```javascript
980let switch = await driver.findComponent(BY.id(Id_switch).isAfter(BY.text("Item3_3")))
981```
982
983Use `By.isAfter` to specify the attributes of the feature component located before the target component for relative positioning. Generally, a feature component is a component that has a globally unique feature (for example, a unique ID or a unique text).
984
985Similarly, you can use `By.isBefore` to specify the attributes of the feature component located after the target component to implement relative positioning.
986
987### Using UiComponent
988
989The `UiComponent` class represents a UI component, which can be located by using `UiDriver.findComponent(by)`. It provides APIs for obtaining component attributes, clicking a component, scrolling to search for a component, and text injection.
990
991`UiComponent` provides the following APIs:
992
993| No.  | API                               | Description                                      |
994| ---- | --------------------------------- | ---------------------------------------------- |
995| 1    | click():Promise<void>             | Clicks the component.                                  |
996| 2    | inputText(t:string):Promise<void> | Inputs text into the component. This API is applicable to text box components.          |
997| 3    | scrollSearch(s:By):Promise<bool>  | Scrolls on this component to search for the target component. This API is applicable to the **List** components.|
998| 4    | getText():Promise<string>         | Obtains the component text.                                |
999| 5    | getId():Promise<number>           | Obtains the component ID.                                  |
1000| 6    | getType():Promise<string>         | Obtains the component type.                                |
1001| 7    | isEnabled():Promise<bool>         | Obtains the component state, which can be enabled or disabled.                            |
1002
1003For details about the APIs of `UiComponent`, see [@ohos.uitest.d.ts](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts) and [UiComponent](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-uitest.md#uicomponent).
1004
1005Example 1: Click a component.
1006
1007```javascript
1008let button = await driver.findComponent(BY.id(Id_button))
1009await button.click()
1010```
1011
1012Example 2: After obtaining component attributes, use **assert()** to make assertion.
1013
1014```javascript
1015let component = await driver.findComponent(BY.id(Id_title))
1016expect(component !== null).assertTrue()
1017```
1018
1019Example 3: Scroll on the **List** component to locate the child component with text `Item3_3`.
1020
1021```javascript
1022let list = await driver.findComponent(BY.id(Id_list))
1023let found = await list.scrollSearch(BY.text("Item3_3"))
1024expect(found).assertTrue()
1025```
1026
1027Example 4: Input text in a text box.
1028
1029```javascript
1030let editText = await driver.findComponent(BY.type('InputText'))
1031await editText.inputText("user_name")
1032```
1033### Using UiWindow
1034
1035The `UiWindow` class represents a UI window, which can be located by using `UiDriver.findWindow(by)`. You can use the instance provided by this class to obtain window attributes, drag a window, and adjust the window size.
1036
1037`UiWindow` provides the following APIs:
1038
1039| No.  | API                                                          | Description                                          |
1040| ---- | ------------------------------------------------------------ | -------------------------------------------------- |
1041| 1    | getBundleName(): Promise<string>                             | Obtains the bundle name of the window.                            |
1042| 2    | getTitle(): Promise<string>                                  | Obtains the window title.                                |
1043| 3    | focus(): Promise<bool>                                       | Gives focus to the current window.                            |
1044| 4    | moveTo(x: number, y: number): Promise<bool>;                 | Moves the current window to the specified position. This API is applicable to the windows that can be moved.|
1045| 5    | resize(wide: number, height: number, direction: ResizeDirection): Promise<bool> | Adjusts the window size. This API is applicable to the windows that can be resized.        |
1046| 6    | split(): Promise<bool>                                       | Splits the current window. This API is applicable to the windows that support split-screen mode.  |
1047| 7    | close(): Promise<bool>                                       | Closes the current window.                                    |
1048
1049For details about the APIs of `UiWindow`, see [@ohos.uitest.d.ts](https://gitee.com/openharmony/interface_sdk-js/blob/master/api/@ohos.uitest.d.ts) and [UiWindow](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-uitest.md#uiwindow9).
1050
1051Example 1: Obtain the window attributes.
1052
1053```javascript
1054let window = await driver.findWindow({actived: true})
1055let bundelName = await window.getBundleName()
1056```
1057
1058Example 2: Move the window.
1059
1060```javascript
1061let window = await driver.findWindow({actived: true})
1062await window.moveTo(500,500)
1063```
1064
1065Example 3: Close the window.
1066
1067```javascript
1068let window = await driver.findWindow({actived: true})
1069await window.close()
1070```
1071
1072### How to Use
1073
1074  Download Deveco Studio, create a test project, and call the APIs provided by UiTest to perform related tests. For details about how to create a test project and execute test scripts, see [OpenHarmony Test Framework](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001267284568).
1075  Run the following command to enable UiTest:
1076
1077>```shell
1078> hdc_std shell param set persist.ace.testmode.enabled 1
1079>```
1080### Building UiTest
1081
1082> UiTest is not built with OpenHarmony 3.1 Release and needs to be manually built. For details, see [Pushing UiTest to a Device](https://gitee.com/openharmony/arkXtest/blob/OpenHarmony-3.1-Release/README_en.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).
1083
1084If you want to modify UiTest code and verify the modification, use the following commands.
1085
1086#### Building UiTest
1087
1088```shell
1089./build.sh --product-name rk3568 --build-target uitestkit
1090```
1091#### Sending UiTest
1092
1093```shell
1094hdc_std target mount
1095hdc_std shell mount -o rw,remount /
1096hdc_std file send uitest /system/bin/uitest
1097hdc_std file send libuitest.z.so /system/lib/module/libuitest.z.so
1098hdc_std shell chmod +x /system/bin/uitest
1099```
1100
1101### Version Information
1102
1103| Version | Description                                                  |
1104| :------ | :----------------------------------------------------------- |
1105| 3.2.2.1 | 1. Added the APIs for obtaining and setting the screen orientation and flinging.<br>2. Added the window processing logic for unsupported scenarios. |
1106

README_zh.md

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