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,basic types are supported. |
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 it('assertInstanceOf_success', 0, function () {
121 let a = 'strTest'
122 expect(a).assertInstanceOf('String')
123 })
124 })
125}
126```
127
128
129#### Mock
130
131##### Constraints
132
133JsUnit 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.
134
135- **Available APIs**
136
137| No. | API | Description|
138| --- | --- | --- |
139| 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.|
140| 2 | when(mockedfunc: function)| Checks whether the input function is mocked and marked. A function declaration is returned.|
141| 3 | afterReturn(x: value)| Sets an expected return value, for example, a string or promise.|
142| 4 | afterReturnNothing() | Sets the expected return value to **undefined**, that is, no value will be returned.|
143| 5 | afterAction(x: action)| Sets the expected return value to be an action executed by a function.|
144| 6 | afterThrow(x: msg)| Sets an exception to throw and the error message.|
145| 7 | clear() | Restores the mocked object after the test case is complete (restores the original features of the object).|
146| 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**.|
147| 9 | anyString | Returns the expected value if a string is passed in. This API must be called by **ArgumentMatchers.anyString**.|
148| 10 | anyBoolean | Returns the expected value if a Boolean value is passed in. This API must be called by **ArgumentMatchers.anyBoolean**.|
149| 11 | anyFunction | Returns the expected value if a function is passed in. This API must be called by **ArgumentMatchers.anyFunction**.|
150| 12 | anyNumber | Returns the expected value if a number is passed in. This API must be called by **ArgumentMatchers.anyNumber**.|
151| 13 | anyObj | Returns the expected value if an object is passed in. This API must be called by **ArgumentMatchers.anyObj**.|
152| 14 | matchRegexs(Regex) | Returns the expected value if a regular expression is passed in. This API must be called by **ArgumentMatchers.matchRegexs(Regex)**.|
153| 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()**.|
154| 16 | times(count) | Verifies whether the function was executed the specified number of times.|
155| 17 | once() | Verifies whether the function was executed only once.|
156| 18 | atLeast(count) | Verifies whether the function was executed at least **count** times.|
157| 19 | atMost(count) | Verifies whether the function was executed at most **count** times.|
158| 20 | never | Verifies whether the function has never been executed.|
159| 21 | ignoreMock(obj, method) | Restores the mocked function in the object. This API is valid for mocked functions.|
160| 22 | clearAll() | Clears all data and memory after the test cases are complete.|
161
162- **Examples**
163
164You can refer to the following examples to import the mock module and write test cases.
165
166- **NOTICE**<br>
167You must import **MockKit** and **when**. You can import other assertion APIs based on the test cases.
168Example: `import {describe, expect, it, MockKit, when} from '@ohos/hypium'`
169
170Example 1: Use **afterReturn**.
171
172```javascript
173import {describe, expect, it, MockKit, when} from '@ohos/hypium';
174
175export default function ActsAbilityTest() {
176 describe('ActsAbilityTest', function () {
177 it('testMockfunc', 0, function () {
178 console.info("it1 begin");
179
180 // 1. Create a MockKit object.
181 let mocker = new MockKit();
182
183 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
184 class ClassName {
185 constructor() {
186 }
187
188 method_1(arg) {
189 return '888888';
190 }
191
192 method_2(arg) {
193 return '999999';
194 }
195 }
196
197 let claser = new ClassName();
198
199 // 3. Mock method_1 of the ClassName class.
200 let mockfunc = mocker.mockFunc(claser, claser.method_1);
201 when(mockfunc)('test').afterReturn('1');
202
203 // 4. Assert whether the mocked function is implemented as expected.
204 // The operation is successful if 'test' is passed in.
205 expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
206
207 // The operation fails if 'abc' is passed in.
208 //expect(claser.method_1('abc')).assertEqual('1'); // The operation fails.
209 });
210 });
211}
212```
213- **NOTICE**<br>
214In `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.
215
216Example 2: Use **afterReturnNothing**.
217
218```javascript
219import {describe, expect, it, MockKit, when} from '@ohos/hypium';
220
221export default function ActsAbilityTest() {
222 describe('ActsAbilityTest', function () {
223 it('testMockfunc', 0, function () {
224 console.info("it1 begin");
225
226 // 1. Create a MockKit object.
227 let mocker = new MockKit();
228
229 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
230 class ClassName {
231 constructor() {
232 }
233
234 method_1(arg) {
235 return '888888';
236 }
237
238 method_2(arg) {
239 return '999999';
240 }
241 }
242
243 let claser = new ClassName();
244
245 // 3. Mock method_1 of the ClassName class.
246 let mockfunc = mocker.mockFunc(claser, claser.method_1);
247
248 // 4. Set the action to be performed when the test case ends. For example, set it to afterReturnNothing(), which returns no value.
249 when(mockfunc)('test').afterReturnNothing();
250
251 // 5. Assert whether the mocked function is implemented as expected. Use the assertion APIs corresponding to Step 4.
252 // The operation is successful if 'test' is passed in.
253 // The mocked claser.method_1 does not return '888888'. Instead, afterReturnNothing() takes effect, that is, no value is returned.
254 expect(claser.method_1('test')).assertUndefined(); // The operation is successful.
255
256 // The operation fails if '123' is passed in.
257 // expect(method_1(123)).assertUndefined();// The operation fails.
258 });
259 });
260}
261```
262
263Example 3: Set the parameter type to **any**, that is, allow any parameter value except **undefine** and **null**.
264
265
266- **NOTICE**<br>
267The **ArgumentMatchers** class, for example, **ArgumentMatchers.any**, must be imported.
268
269```javascript
270import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
271
272export default function ActsAbilityTest() {
273 describe('ActsAbilityTest', function () {
274 it('testMockfunc', 0, function () {
275 console.info("it1 begin");
276
277 // 1. Create a MockKit object.
278 let mocker = new MockKit();
279
280 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
281 class ClassName {
282 constructor() {
283 }
284
285 method_1(arg) {
286 return '888888';
287 }
288
289 method_2(arg) {
290 return '999999';
291 }
292 }
293
294 let claser = new ClassName();
295
296 // 3. Mock method_1 of the ClassName class.
297 let mockfunc = mocker.mockFunc(claser, claser.method_1);
298 // Set the parameter matcher and expected return value as required.
299 when(mockfunc)(ArgumentMatchers.any).afterReturn('1');
300
301 // 4. Assert whether the mocked function is implemented as expected.
302 // The operation is successful if a string is passed in.
303 expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
304 // The operation is successful if a number (for example '123') is passed in.
305 expect(claser.method_1(123)).assertEqual('1'); // The operation is successful.
306 // The operation is successful if a Boolean value (for example 'true') is passed in.
307 expect(claser.method_1(true)).assertEqual('1');// The operation is successful.
308
309 // The operation fails if an empty value is passed in.
310 //expect(claser.method_1()).assertEqual('1');// The operation fails.
311 });
312 });
313}
314```
315
316Example 4: Set the parameter type to **anyString**.
317
318```javascript
319import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
320
321export default function ActsAbilityTest() {
322 describe('ActsAbilityTest', function () {
323 it('testMockfunc', 0, function () {
324 console.info("it1 begin");
325
326 // 1. Create a MockKit object.
327 let mocker = new MockKit();
328
329 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
330 class ClassName {
331 constructor() {
332 }
333
334 method_1(arg) {
335 return '888888';
336 }
337
338 method_2(arg) {
339 return '999999';
340 }
341 }
342
343 let claser = new ClassName();
344
345 // 3. Mock method_1 of the ClassName class.
346 let mockfunc = mocker.mockFunc(claser, claser.method_1);
347 // Set the following parameters as required.
348 when(mockfunc)(ArgumentMatchers.anyString).afterReturn('1');
349
350 // 4. Assert whether the mocked function is implemented as expected.
351 // The operation is successful if a string is passed in.
352 expect(claser.method_1('test')).assertEqual('1'); // The operation is successful.
353 expect(claser.method_1('abc')).assertEqual('1'); // The operation is successful.
354
355 // The operation fails if a number or a Boolean value is passed in.
356 //expect(claser.method_1(123)).assertEqual('1'); // The operation fails.
357 //expect(claser.method_1(true)).assertEqual('1'); // The operation fails.
358 });
359 });
360}
361```
362
363Example 5: Set the parameter type to **matchRegexs (Regex)**.
364```javascript
365import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
366
367export default function ActsAbilityTest() {
368 describe('ActsAbilityTest', function () {
369 it('testMockfunc', 0, function () {
370 console.info("it1 begin");
371
372 // 1. Create a MockKit object.
373 let mocker = new MockKit();
374
375 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
376 class ClassName {
377 constructor() {
378 }
379
380 method_1(arg) {
381 return '888888';
382 }
383
384 method_2(arg) {
385 return '999999';
386 }
387 }
388
389 let claser = new ClassName();
390
391 // 3. Mock method_1 of the ClassName class.
392 let mockfunc = mocker.mockFunc(claser, claser.method_1);
393 // Set a regular expression to match, for example, /123456/.
394 when(mockfunc)(ArgumentMatchers.matchRegexs(/123456/)).afterReturn('1');
395
396 // 4. Assert whether the mocked function is implemented as expected.
397 // The operation is successful if a string, for example, '1234567898', is passed in.
398 expect(claser.method_1('1234567898')).assertEqual('1'); // The operation is successful.
399 // The string '1234567898' matches the regular expression /123456/.
400
401 // The operation fails if '1234' is passed in.
402 //expect(claser.method_1('1234').assertEqual('1'); // The operation fails because '1234' does not match the regular expression /123456/.
403 });
404 });
405}
406```
407
408Example 6: Use **verify()**.
409```javascript
410import {describe, expect, it, MockKit, when} from '@ohos/hypium';
411
412export default function ActsAbilityTest() {
413 describe('ActsAbilityTest', function () {
414 it('testMockfunc', 0, function () {
415 console.info("it1 begin");
416
417 // 1. Create a MockKit object.
418 let mocker = new MockKit();
419
420 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
421 class ClassName {
422 constructor() {
423 }
424
425 method_1(...arg) {
426 return '888888';
427 }
428
429 method_2(...arg) {
430 return '999999';
431 }
432 }
433
434 let claser = new ClassName();
435
436 // 3. Mock method_1 and method_2 of the ClassName class.
437 mocker.mockFunc(claser, claser.method_1);
438 mocker.mockFunc(claser, claser.method_2);
439
440 // 4. Call the following methods.
441 claser.method_1('abc', 'ppp');
442 claser.method_1('abc');
443 claser.method_1('xyz');
444 claser.method_1();
445 claser.method_1('abc', 'xxx', 'yyy');
446 claser.method_1();
447 claser.method_2('111');
448 claser.method_2('111', '222');
449
450 //5. Verify the mocked functions.
451 mocker.verify('method_1', []).atLeast(3); // The result is "failed".
452 // Verify whether 'method_1' with an empty parameter list was executed at least three times.
453 // The result is "failed" because 'method_1' with an empty parameter list was executed only twice in Step 4.
454 //mocker.verify('method_2',['111']).once(); // The result is "success".
455 //mocker.verify('method_2',['111',,'222']).once(); // The result is "success".
456 });
457 });
458}
459```
460
461Example 7: Use **ignoreMock(obj, method)**.
462```javascript
463import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
464
465export default function ActsAbilityTest() {
466 describe('ActsAbilityTest', function () {
467 it('testMockfunc', 0, function () {
468 console.info("it1 begin");
469
470 // 1. Create a MockKit object.
471 let mocker = new MockKit();
472
473 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
474 class ClassName {
475 constructor() {
476 }
477
478 method_1(...arg) {
479 return '888888';
480 }
481
482 method_2(...arg) {
483 return '999999';
484 }
485 }
486
487 let claser = new ClassName();
488
489 // 3. Mock method_1 and method_2 of the ClassName class.
490 let func_1 = mocker.mockFunc(claser, claser.method_1);
491 let func_2 = mocker.mockFunc(claser, claser.method_2);
492
493 // 4. Modify the mocked functions.
494 when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
495 when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
496
497 // 5. Call the following methods.
498 console.log(claser.method_1(123)); // The return value is 4, which is the same as the expected value in Step 4.
499 console.log(claser.method_2(456)); // The return value is 5, which is the same as the expected value in Step 4.
500
501 // 6. Restore method_1 using ignoreMock().
502 mocker.ignoreMock(claser, claser.method_1);
503 // Call claser.method_1 and check the execution result.
504 console.log(claser.method_1(123)); // The return value is 888888, which is the same as that returned by the original function.
505 // Test with assertions.
506 expect(claser.method_1(123)).assertEqual('4'); // The return value is "failed", which meets the expected value of ignoreMock().
507 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.
508 });
509 });
510}
511```
512
513Example 8: Use **clear()**.
514
515```javascript
516import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
517
518export default function ActsAbilityTest() {
519 describe('ActsAbilityTest', function () {
520 it('testMockfunc', 0, function () {
521 console.info("it1 begin");
522
523 // 1. Create a MockKit object.
524 let mocker = new MockKit();
525
526 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
527 class ClassName {
528 constructor() {
529 }
530
531 method_1(...arg) {
532 return '888888';
533 }
534
535 method_2(...arg) {
536 return '999999';
537 }
538 }
539 let claser = new ClassName();
540
541 // 3. Mock method_1 and method_2 of the ClassName class.
542 let func_1 = mocker.mockFunc(claser, claser.method_1);
543 let func_2 = mocker.mockFunc(claser, claser.method_2);
544
545 // 4. Modify the mocked functions.
546 when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
547 when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
548
549 // 5. Call the following methods.
550 //expect(claser.method_1(123)).assertEqual('4'); // The return value is the same as the expected value.
551 //expect(claser.method_2(456)).assertEqual('5'); // The return value is the same as the expected value.
552
553 // 6. Clear the mock operation.
554 mocker.clear(claser);
555 // Call claser.method_1 and check the execution result.
556 expect(claser.method_1(123)).assertEqual('4'); // The return value is "failed", which meets the expectation.
557 expect(claser.method_2(456)).assertEqual('5'); // The return value is "failed", which meets the expectation.
558 });
559 });
560}
561```
562
563
564Example 9: Use **afterThrow(msg)**.
565
566```javascript
567import {describe, expect, it, MockKit, when} from '@ohos/hypium';
568
569export default function ActsAbilityTest() {
570 describe('ActsAbilityTest', function () {
571 it('testMockfunc', 0, function () {
572 console.info("it1 begin");
573
574 // 1. Create a MockKit object.
575 let mocker = new MockKit();
576
577 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
578 class ClassName {
579 constructor() {
580 }
581
582 method_1(arg) {
583 return '888888';
584 }
585 }
586
587 let claser = new ClassName();
588
589 // 3. Mock method_1 of the ClassName class.
590 let mockfunc = mocker.mockFunc(claser, claser.method_1);
591
592 // 4. Set the action to be performed when the test case ends. For example, set it to afterReturnNothing(), which returns no value.
593 when(mockfunc)('test').afterThrow('error xxx');
594
595 // 5. Execute the mocked function, capture the exception, and use assertEqual() to check whether message meets the expectation.
596 try {
597 claser.method_1('test');
598 } catch (e) {
599 expect(e).assertEqual('error xxx'); // The execution is successful.
600 }
601 });
602 });
603}
604```
605
606Example 10: Mock asynchronous functions.
607
608```javascript
609import {describe, expect, it, MockKit, when} from '@ohos/hypium';
610
611export default function ActsAbilityTest() {
612 describe('ActsAbilityTest', function () {
613 it('testMockfunc', 0, function () {
614 console.info("it1 begin");
615
616 // 1. Create a MockKit object.
617 let mocker = new MockKit();
618
619 // 2. Define the ClassName class, which contains two functions, and then create a claser object.
620 class ClassName {
621 constructor() {
622 }
623
624 async method_1(arg) {
625 return new Promise((res, rej) => {
626 // Perform asynchronous operations.
627 setTimeout(function () {
628 console.log ('Execute');
629 res('Pass data');
630 }, 2000);
631 });
632 }
633 }
634
635 let claser = new ClassName();
636
637 // 3. Mock method_1 of the ClassName class.
638 let mockfunc = mocker.mockFunc(claser, claser.method_1);
639
640 // 4. Set the action to be performed after the test case ends. For example, set it to afterRetrun(), which returns a custom promise.
641 when(mockfunc)('test').afterReturn(new Promise((res, rej) => {
642 console.log("do something");
643 res('success something');
644 }));
645
646 // 5. Execute the mocked function, that is, execute the promise.
647 claser.method_1('test').then(function (data) {
648 // Code for data processing
649 console.log('result : ' + data);
650 });
651 });
652 });
653}
654```
655
656Example 11: Mock a system function.
657
658```javascript
659export default function ActsAbilityTest() {
660 describe('ActsAbilityTest', function () {
661 it('test_systemApi', 0, function () {
662 // 1. Create a MockKit object.
663 let mocker = new MockKit();
664 // 2. Mock the app.getInfo() function.
665 let mockf = mocker.mockFunc(app, app.getInfo);
666 when(mockf)('test').afterReturn('1');
667 // The operation is successful.
668 expect(app.getInfo('test')).assertEqual('1');
669 });
670 });
671}
672```
673
674
675Example 12: Verify **times(count)**.
676
677```javascript
678import { describe, expect, it, MockKit, when } from '@ohos/hypium'
679
680export default function ActsAbilityTest() {
681 describe('ActsAbilityTest', function () {
682 it('test_verify_times', 0, function () {
683 // 1. Create a MockKit object.
684 let mocker = new MockKit();
685 // 2. Define the class to be mocked.
686 class ClassName {
687 constructor() {
688 }
689
690 method_1(...arg) {
691 return '888888';
692 }
693 }
694 // 3. Create an object of the class.
695 let claser = new ClassName();
696 // 4. Mock a function, for example, method_1, of the object.
697 let func_1 = mocker.mockFunc(claser, claser.method_1);
698 // 5. Set the expected value to be returned by the mocked function.
699 when(func_1)('123').afterReturn('4');
700
701 // 6. Execute the function several times, with parameters set as follows:
702 claser.method_1('123', 'ppp');
703 claser.method_1('abc');
704 claser.method_1('xyz');
705 claser.method_1();
706 claser.method_1('abc', 'xxx', 'yyy');
707 claser.method_1('abc');
708 claser.method_1();
709 // 7. Check whether method_1 with the parameter of 'abc' was executed twice.
710 mocker.verify('method_1', ['abc']).times(2);
711 });
712 });
713}
714```
715
716
717Example 13: Verify **atLeast(count)**.
718
719```javascript
720import { describe, expect, it, MockKit, when } from '@ohos/hypium'
721
722export default function ActsAbilityTest() {
723 describe('ActsAbilityTest', function () {
724 it('test_verify_atLeast', 0, function () {
725 // 1. Create a MockKit object.
726 let mocker = new MockKit();
727 // 2. Define the class to be mocked.
728 class ClassName {
729 constructor() {
730 }
731
732 method_1(...arg) {
733 return '888888';
734 }
735 }
736
737 // 3. Create an object of the class.
738 let claser = new ClassName();
739 // 4. Mock a function, for example, method_1, of the object.
740 let func_1 = mocker.mockFunc(claser, claser.method_1);
741 // 5. Set the expected value to be returned by the mocked function.
742 when(func_1)('123').afterReturn('4');
743 // 6. Execute the function several times, with parameters set as follows:
744 claser.method_1('123', 'ppp');
745 claser.method_1('abc');
746 claser.method_1('xyz');
747 claser.method_1();
748 claser.method_1('abc', 'xxx', 'yyy');
749 claser.method_1();
750 // 7. Check whether method_1 with an empty value was executed at least twice.
751 mocker.verify('method_1', []).atLeast(2);
752 });
753 });
754}
755```
756
757#### Data Driving
758
759##### Constraints
760
761JsUnit provides the following data driving capability since [Hypium 1.0.2](https://repo.harmonyos.com/#/en/application/atomService/@ohos%2Fhypium):
762
763- Passes parameters for the specified test suite and test case.
764- Specifies the number of times that the test suite and test case are executed.
765
766The 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:
767
768>**NOTE**<br>The **data.json** file is in the same directory as the **.test.js** or **.test.ets** file.
769
770```json
771{
772 "suites": [{
773 "describe": ["actsAbilityTest"],
774 "stress": 2,
775 "params": {
776 "suiteParams1": "suiteParams001",
777 "suiteParams2": "suiteParams002"
778 },
779 "items": [{
780 "it": "testDataDriverAsync",
781 "stress": 2,
782 "params": [{
783 "name": "tom",
784 "value": 5
785 }, {
786 "name": "jerry",
787 "value": 4
788 }]
789 }, {
790 "it": "testDataDriver",
791 "stress": 3
792 }]
793 }]
794}
795```
796
797Parameter description:
798
799| | Name| Description | Mandatory|
800| :--- | :--------- | :------------------------------------ | ---- |
801| 1 | "suite" | Test suite configuration. | Yes |
802| 2 | "items" | Test case configuration. | Yes |
803| 3 | "describe" | Test suite name. | Yes |
804| 4 | "it" | Test case name. | Yes |
805| 5 | "params" | Parameters to be passed to the test suite or test case.| No |
806| 6 | "stress" | Number of times that the test suite or test case is executed. | No |
807
808The sample code is as follows:
809
810Import 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.
811
812```javascript
813import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
814import { Hypium } from '@ohos/hypium'
815import testsuite from '../test/List.test'
816import data from '../test/data.json';
817
818...
819Hypium.setData(data);
820Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
821...
822```
823
824```javascript
825import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium';
826
827export default function abilityTest() {
828 describe('actsAbilityTest', function () {
829 it('testDataDriverAsync', 0, async function (done, data) {
830 console.info('name: ' + data.name);
831 console.info('value: ' + data.value);
832 done();
833 });
834
835 it('testDataDriver', 0, function () {
836 console.info('stress test');
837 });
838 });
839}
840```
841
842### How to Use
843
844JsUnit 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).
845
846## UiTest Features
847
848| No. | Feature | Description |
849| ---- | ----------- | ------------------------------------------------------------ |
850| 1 | UiDriver | Provides the UI test entry. It provides APIs for locating a component, checking whether a component exists, and injecting a key.|
851| 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`.|
852| 3 | UiComponent | Provides the UI component object, which provides APIs for obtaining component attributes, clicking a component, and scrolling to search for a component.|
853| 4 | UiWindow | Provides the window object, which provides APIs for obtaining window attributes, dragging a window, and adjusting the window size.|
854
855Import the following to the test script:
856
857```typescript
858import {UiDriver,BY,UiComponent,Uiwindow,MatchPattern} from '@ohos.uitest'
859```
860
861> **NOTICE**<br>
862> - 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.
863> - All the APIs provided by the `UiDriver` and `UiComponent` classes are asynchronous (in `Promise` mode), and `await` must be used.
864> - All UI test cases must be written in the asynchronous syntax and comply with the asynchronous test case specifications of JsUnit.
865
866
867
868Import the `By`, `UiDriver`, and `UiComponent` classes to the test case file, and then call the APIs to write test cases.
869
870```javascript
871import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium'
872import {BY, UiDriver, UiComponent, MatchPattern} from '@ohos.uitest'
873
874export default async function abilityTest() {
875 describe('uiTestDemo', function() {
876 it('uitest_demo0', 0, async function() {
877 // create UiDriver
878 let driver = await UiDriver.create()
879 // find component by text
880 let button = await driver.findComponent(BY.text('hello').enabled(true))
881 // click component
882 await button.click()
883 // get and assert component text
884 let content = await button.getText()
885 expect(content).assertEquals('clicked!')
886 })
887 })
888}
889```
890
891### Using UiDriver
892
893As the main entry to UiTest, the `UiDriver` class provides APIs for component matching/search, key injection, coordinate clicking/swiping, and screenshot.
894
895| No. | API | Description |
896| ---- | ------------------------------------------------------------ | ------------------------ |
897| 1 | create():Promise<UiDriver> | Creates a **UiDriver** object. This API is a static method.|
898| 2 | findComponent(b:By):Promise<UiComponent> | Searches for a component. |
899| 3 | pressBack():Promise<void> | Presses the BACK button. |
900| 4 | click(x:number, y:number):Promise<void> | Clicks a specific point based on the given coordinates. |
901| 5 | swipe(x1:number, y1:number, x2:number, y2:number):Promise<void> | Swipes based on the given coordinates. |
902| 6 | assertComponentExist(b:By):Promise<void> | Asserts that the component matching the given attributes exists on the current page. |
903| 7 | delayMs(t:number):Promise<void> | Delays this **UiDriver** object for the specified duration. |
904| 8 | screenCap(s:path):Promise<void> | Captures the current screen. |
905| 9 | findWindow(filter: WindowFilter): Promise<UiWindow> | Searches for a window. |
906
907**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.
908
909```javascript
910import {BY,UiDriver,UiComponent} from '@ohos.uitest'
911
912export default async function abilityTest() {
913 describe('UiTestDemo', function() {
914 it('Uitest_demo0', 0, async function(done) {
915 try{
916 // create UiDriver
917 let driver = await UiDriver.create()
918 // assert text 'hello' exists on current Ui
919 await assertComponentExist(BY.text('hello'))
920 } finally {
921 done()
922 }
923 })
924 })
925}
926```
927
928For 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).
929
930### Using By
931
932UiTest 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:
933
934- Allow one or more attributes as the match conditions. For example, you can specify both the text and id attributes to find a component.
935- Provide a variety of match patterns (`EQUALS`, `CONTAINS`, `STARTS_WITH`, and `ENDS_WITH`) for component attributes.
936- Support relative positioning for components. APIs such as `isBefore` and `isAfter` can be used to specify the features of adjacent components to assist positioning.
937
938| No. | API | Description |
939| ---- | ---------------------------------- | ------------------------------------------------ |
940| 1 | id(i:number):By | Specifies the component ID. |
941| 2 | text(t:string, p?:MatchPattern):By | Specifies the component text. You can specify the match pattern. |
942| 3 | type(t:string)):By | Specifies the component type. |
943| 4 | enabled(e:bool):By | Specifies the component state, which can be enabled or disabled. |
944| 5 | clickable(c:bool):By | Specifies the clickable status of the component. |
945| 6 | focused(f:bool):By | Specifies the focused status of the component. |
946| 7 | scrollable(s:bool):By | Specifies the scrollable status of the component. |
947| 8 | selected(s:bool):By | Specifies the selected status of the component. |
948| 9 | isBefore(b:By):By | Specifies the attributes of the component that locates before the target component.|
949| 10 | isAfter(b:By):By | Specifies the attributes of the component that locates after the target component.|
950
951The `text` attribute supports match patterns `MatchPattern.EQUALS`, `MatchPattern.CONTAINS`, `MatchPattern.STARTS_WITH`, and `MatchPattern.ENDS_WITH`. The default match pattern is `MatchPattern.EQUALS`.
952
953For 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).
954
955#### Absolute Positioning of a Component
956
957Example 1: Search for component `Id_button`.
958
959```javascript
960let button = await driver.findComponent(BY.id(Id_button))
961```
962
963 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.
964
965```javascript
966let button = await driver.findComponent(BY.id(Id_button).enabled(true))
967```
968
969Use `By.id(x).enabled(y)` to specify multiple attributes of the target component.
970
971Example 3: Search for the component whose text contains `hello`. Use this API when the component attribute values cannot be completely determined.
972
973```javascript
974let txt = await driver.findComponent(BY.text("hello", MatchPattern.CONTAINS))
975```
976
977`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.
978
979#### Relative Positioning of a Component
980
981Example 1: Search for the switch component `ResourceTable.Id_switch` following the text component `Item3_3`.
982
983```javascript
984let switch = await driver.findComponent(BY.id(Id_switch).isAfter(BY.text("Item3_3")))
985```
986
987Use `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).
988
989Similarly, you can use `By.isBefore` to specify the attributes of the feature component located after the target component to implement relative positioning.
990
991### Using UiComponent
992
993The `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.
994
995`UiComponent` provides the following APIs:
996
997| No. | API | Description |
998| ---- | --------------------------------- | ---------------------------------------------- |
999| 1 | click():Promise<void> | Clicks the component. |
1000| 2 | inputText(t:string):Promise<void> | Inputs text into the component. This API is applicable to text box components. |
1001| 3 | scrollSearch(s:By):Promise<bool> | Scrolls on this component to search for the target component. This API is applicable to the **List** components.|
1002| 4 | getText():Promise<string> | Obtains the component text. |
1003| 5 | getId():Promise<number> | Obtains the component ID. |
1004| 6 | getType():Promise<string> | Obtains the component type. |
1005| 7 | isEnabled():Promise<bool> | Obtains the component state, which can be enabled or disabled. |
1006
1007For 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).
1008
1009Example 1: Click a component.
1010
1011```javascript
1012let button = await driver.findComponent(BY.id(Id_button))
1013await button.click()
1014```
1015
1016Example 2: After obtaining component attributes, use **assert()** to make assertion.
1017
1018```javascript
1019let component = await driver.findComponent(BY.id(Id_title))
1020expect(component !== null).assertTrue()
1021```
1022
1023Example 3: Scroll on the **List** component to locate the child component with text `Item3_3`.
1024
1025```javascript
1026let list = await driver.findComponent(BY.id(Id_list))
1027let found = await list.scrollSearch(BY.text("Item3_3"))
1028expect(found).assertTrue()
1029```
1030
1031Example 4: Input text in a text box.
1032
1033```javascript
1034let editText = await driver.findComponent(BY.type('InputText'))
1035await editText.inputText("user_name")
1036```
1037### Using UiWindow
1038
1039The `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.
1040
1041`UiWindow` provides the following APIs:
1042
1043| No. | API | Description |
1044| ---- | ------------------------------------------------------------ | -------------------------------------------------- |
1045| 1 | getBundleName(): Promise<string> | Obtains the bundle name of the window. |
1046| 2 | getTitle(): Promise<string> | Obtains the window title. |
1047| 3 | focus(): Promise<bool> | Gives focus to the current window. |
1048| 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.|
1049| 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. |
1050| 6 | split(): Promise<bool> | Splits the current window. This API is applicable to the windows that support split-screen mode. |
1051| 7 | close(): Promise<bool> | Closes the current window. |
1052
1053For 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).
1054
1055Example 1: Obtain the window attributes.
1056
1057```javascript
1058let window = await driver.findWindow({actived: true})
1059let bundelName = await window.getBundleName()
1060```
1061
1062Example 2: Move the window.
1063
1064```javascript
1065let window = await driver.findWindow({actived: true})
1066await window.moveTo(500,500)
1067```
1068
1069Example 3: Close the window.
1070
1071```javascript
1072let window = await driver.findWindow({actived: true})
1073await window.close()
1074```
1075
1076### How to Use
1077
1078 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).
1079 Run the following command to enable UiTest:
1080
1081>```shell
1082> hdc_std shell param set persist.ace.testmode.enabled 1
1083>```
1084### Building UiTest
1085
1086> UiTest is not built with OpenHarmony 3.1 Release and needs to be manually built.
1087
1088If you want to modify UiTest code and verify the modification, use the following commands.
1089
1090#### Building UiTest
1091
1092```shell
1093./build.sh --product-name rk3568 --build-target uitestkit
1094```
1095#### Sending UiTest
1096
1097```shell
1098hdc_std target mount
1099hdc_std shell mount -o rw,remount /
1100hdc_std file send uitest /system/bin/uitest
1101hdc_std file send libuitest.z.so /system/lib/module/libuitest.z.so
1102hdc_std shell chmod +x /system/bin/uitest
1103```
1104
1105### Version Information
1106
1107| Version | Description |
1108| :------ | :----------------------------------------------------------- |
1109| 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. |
1110
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| 5 | 专项能力 | 支持测试套与用例筛选、随机执行、压力测试、超时设置、遇错即停模式等。 |
29
30### 使用说明
31
32#### 基础流程
33
34测试用例采用业内通用语法,describe代表一个测试套, it代表一条用例。
35
36| No. | API | 功能说明 |
37| ---- | ---------- | ------------------------------------------------------------ |
38| 1 | describe | 定义一个测试套,支持两个参数:测试套名称和测试套函数。 |
39| 2 | beforeAll | 在测试套内定义一个预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数。 |
40| 3 | beforeEach | 在测试套内定义一个单元预置条件,在每条测试用例开始前执行,执行次数与it定义的测试用例数一致,支持一个参数:预置动作函数。 |
41| 4 | afterEach | 在测试套内定义一个单元清理条件,在每条测试用例结束后执行,执行次数与it定义的测试用例数一致,支持一个参数:清理动作函数。 |
42| 5 | afterAll | 在测试套内定义一个清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数。 |
43| 6 | it | 定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数。 |
44| 7 | expect | 支持bool类型判断等多种断言方法。 |
45
46示例代码:
47
48```javascript
49import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
50import demo from '@ohos.bundle'
51
52export default async function abilityTest() {
53 describe('ActsAbilityTest', function () {
54 it('String_assertContain_success', 0, function () {
55 let a = 'abc'
56 let b = 'b'
57 expect(a).assertContain(b)
58 expect(a).assertEqual(a)
59 })
60 it('getBundleInfo_0100', 0, async function () {
61 const NAME1 = "com.example.MyApplicationStage"
62 await demo.getBundleInfo(NAME1,
63 demo.BundleFlag.GET_BUNDLE_WITH_ABILITIES | demo.BundleFlag.GET_BUNDLE_WITH_REQUESTED_PERMISSION)
64 .then((value) => {
65 console.info(value.appId)
66 })
67 .catch((err) => {
68 console.info(err.code)
69 })
70 })
71 })
72}
73```
74
75同时,@since1.0.6 测试套describe支持嵌套定义 。
76
77约束限制:describe仅支持两层嵌套定义,且内层的describe-“innerDescribe”不支持“数据驱动”、“专项能力”特性。
78
79示例代码:
80
81```javascript
82export default async function nestedDescribeTest() {
83 describe('outerDescribe', function () {
84 describe('innerDescribe', function () {
85 it('innerIt', 0, function () {
86 let a = 'abc'
87 expect(a).assertEqual(a)
88 })
89 })
90 it('outerIt', 0, function () {
91 let a = 'abc'
92 expect(a).assertEqual(a)
93 })
94 })
95}
96```
97
98#### 断言库
99
100断言功能列表:
101
102
103| No. | API | 功能说明 |
104| :--- | :------------------| ------------------------------------------------------------ |
105| 1 | assertClose | 检验actualvalue和expectvalue(0)的接近程度是否是expectValue(1)。 |
106| 2 | assertContain | 检验actualvalue中是否包含expectvalue。 |
107| 3 | assertEqual | 检验actualvalue是否等于expectvalue[0]。 |
108| 4 | assertFail | 抛出一个错误。 |
109| 5 | assertFalse | 检验actualvalue是否是false。 |
110| 6 | assertTrue | 检验actualvalue是否是true。 |
111| 7 | assertInstanceOf | 检验actualvalue是否是expectvalue类型,支持基础类型。 |
112| 8 | assertLarger | 检验actualvalue是否大于expectvalue。 |
113| 9 | assertLess | 检验actualvalue是否小于expectvalue。 |
114| 10 | assertNull | 检验actualvalue是否是null。 |
115| 11 | assertThrowError | 检验actualvalue抛出Error内容是否是expectValue。 |
116| 12 | assertUndefined | 检验actualvalue是否是undefined。 |
117| 13 | assertNaN | @since1.0.4 检验actualvalue是否是一个NAN |
118| 14 | assertNegUnlimited | @since1.0.4 检验actualvalue是否等于Number.NEGATIVE_INFINITY |
119| 15 | assertPosUnlimited | @since1.0.4 检验actualvalue是否等于Number.POSITIVE_INFINITY |
120| 16 | assertDeepEquals | @since1.0.4 检验actualvalue和expectvalue是否完全相等 |
121| 17 | assertPromiseIsPending | @since1.0.4 判断promise是否处于Pending状态。 |
122| 18 | assertPromiseIsRejected | @since1.0.4 判断promise是否处于Rejected状态。 |
123| 19 | assertPromiseIsRejectedWith | @since1.0.4 判断promise是否处于Rejected状态,并且比较执行的结果值。 |
124| 20 | assertPromiseIsRejectedWithError | @since1.0.4 判断promise是否处于Rejected状态并有异常,同时比较异常的类型和message值。 |
125| 21 | assertPromiseIsResolved | @since1.0.4 判断promise是否处于Resolved状态。 |
126| 22 | assertPromiseIsResolvedWith | @since1.0.4 判断promise是否处于Resolved状态,并且比较执行的结果值。 |
127| 23 | not | @since1.0.4 断言取反,支持上面所有的断言功能 |
128
129示例代码:
130
131```javascript
132import { describe, it, expect } from '@ohos/hypium'
133export default async function abilityTest() {
134 describe('assertTest', function () {
135 it('assertClose_success', 0, function () {
136 let a = 100
137 let b = 0.1
138 expect(a).assertClose(99, b)
139 })
140 it('assertClose_fail', 0, function () {
141 let a = 100
142 let b = 0.1
143 expect(a).assertClose(1, b)
144 })
145 it('assertClose_null_fail_001', 0, function () {
146 let a = 100
147 let b = 0.1
148 expect(a).assertClose(null, b)
149 })
150 it('assertClose_null_fail_002', 0, function () {
151 expect(null).assertClose(null, 0)
152 })
153 it('assertEqual', 0, function () {
154 let a = 1;
155 let b = 1;
156 expect(a).assertEqual(b)
157 })
158 it('assertFail', 0, function () {
159 expect().assertFail();
160 })
161 it('assertFalse', 0, function () {
162 let a = false;
163 expect(a).assertFalse();
164 })
165 it('assertTrue', 0, function () {
166 let a = true;
167 expect(a).assertTrue();
168 })
169 it('assertInstanceOf_success', 0, function () {
170 let a = 'strTest'
171 expect(a).assertInstanceOf('String')
172 })
173 it('assertLarger', 0, function () {
174 let a = 1;
175 let b = 2;
176 expect(b).assertLarger(a);
177 })
178 it('assertLess', 0, function () {
179 let a = 1;
180 let b = 2;
181 expect(a).assertLess(b);
182 })
183 it('assertNull', 0, function () {
184 let a = null;
185 expect(a).assertNull()
186 })
187 it('assertThrowError', 0, function () {
188 function testError() {
189 throw new Error('error message')
190 }
191 expect(testError).assertThrowError('error message')
192 })
193 it('assertUndefined', 0, function () {
194 let a = undefined;
195 expect(a).assertUndefined();
196 })
197 it('assertNaN', 0, function () {
198 let a = 'str'
199 expect(a).assertNaN()
200 })
201 it('assertInstanceOf_success', 0, function () {
202 let a = 'strTest'
203 expect(a).assertInstanceOf('String')
204 })
205 it('assertNaN_success',0, function () {
206 expect(Number.NaN).assertNaN(); // true
207 })
208 it('assertNegUnlimited_success',0, function () {
209 expect(Number.NEGATIVE_INFINITY).assertNegUnlimited(); // true
210 })
211 it('assertPosUnlimited_success',0, function () {
212 expect(Number.POSITIVE_INFINITY).assertPosUnlimited(); // true
213 })
214 it('not_number_true',0, function () {
215 expect(1).not().assertLargerOrEqual(2)
216 })
217 it('not_number_true_1',0, function () {
218 expect(3).not().assertLessOrEqual(2);
219 })
220 it('not_NaN_true',0, function () {
221 expect(3).not().assertNaN();
222 })
223 it('not_contain_true',0, function () {
224 let a = "abc";
225 let b= "cdf"
226 expect(a).not().assertContain(b);
227 })
228 it('not_large_true',0, function () {
229 expect(3).not().assertLarger(4);
230 })
231 it('not_less_true',0, function () {
232 expect(3).not().assertLess(2);
233 })
234 it('not_undefined_true',0, function () {
235 expect(3).not().assertUndefined();
236 })
237 it('deepEquals_null_true',0, function () {
238 // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
239 expect(null).assertDeepEquals(null)
240 })
241 it('deepEquals_array_not_have_true',0, function () {
242 // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
243 const a= []
244 const b= []
245 expect(a).assertDeepEquals(b)
246 })
247 it('deepEquals_map_equal_length_success',0, function () {
248 // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
249 const a = new Map();
250 const b = new Map();
251 a.set(1,100);
252 a.set(2,200);
253 b.set(1, 100);
254 b.set(2, 200);
255 expect(a).assertDeepEquals(b)
256 })
257 it("deepEquals_obj_success_1", 0, function () {
258 const a = {x:1};
259 const b = {x:1};
260 expect(a).assertDeepEquals(b);
261 })
262 it("deepEquals_regExp_success_0", 0, function () {
263 const a = new RegExp("/test/");
264 const b = new RegExp("/test/");
265 expect(a).assertDeepEquals(b)
266 })
267 it('test_isPending_pass_1', 0, function () {
268 let p = new Promise(function () {
269 });
270 expect(p).assertPromiseIsPending();
271 });
272 it('test_isRejected_pass_1', 0, function () {
273 let p = Promise.reject({
274 bad: 'no'
275 });
276 expect(p).assertPromiseIsRejected();
277 });
278 it('test_isRejectedWith_pass_1', 0, function () {
279 let p = Promise.reject({
280 res: 'reject value'
281 });
282 expect(p).assertPromiseIsRejectedWith({
283 res: 'reject value'
284 });
285 });
286 it('test_isRejectedWithError_pass_1', 0, function () {
287 let p1 = Promise.reject(new TypeError('number'));
288 expect(p1).assertPromiseIsRejectedWithError(TypeError);
289 });
290 it('test_isResolved_pass_1', 0, function () {
291 let p = Promise.resolve({
292 res: 'result value'
293 });
294 expect(p).assertPromiseIsResolved();
295 });
296 it('test_isResolvedTo_pass_1', 0, function () {
297 let p = Promise.resolve({
298 res: 'result value'
299 });
300 expect(p).assertPromiseIsResolvedWith({
301 res: 'result value'
302 });
303 });
304 it('test_isPending_failed_1', 0, function () {
305 let p = Promise.reject({
306 bad: 'no1'
307 });
308 expect(p).assertPromiseIsPending();
309 });
310 it('test_isRejectedWithError_failed_1', 0, function () {
311 let p = Promise.reject(new TypeError('number'));
312 expect(p).assertPromiseIsRejectedWithError(TypeError, 'number one');
313 });
314 })
315}
316```
317
318
319#### Mock能力
320
321##### 约束限制
322
323单元测试框架Mock能力从npm包[1.0.1版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium)开始支持,需修改源码工程中package.info中配置依赖npm包版本号后使用。
324
325- **接口列表:**
326
327| No. | API | 功能说明 |
328| --- | --- | --- |
329| 1 | mockFunc(obj: object, f:function()) | mock某个类的对象obj的函数f,那么需要传两个参数:obj和f,支持使用异步函数(说明:对mock而言原函数实现是同步或异步没太多区别,因为mock并不关注原函数的实现)。 |
330| 2 | when(mockedfunc:function) | 对传入后方法做检查,检查是否被mock并标记过,返回的是一个方法声明。 |
331| 3 | afterReturn(x:value) | 设定预期返回一个自定义的值value,比如某个字符串或者一个promise。 |
332| 4 | afterReturnNothing() | 设定预期没有返回值,即 undefined。 |
333| 5 | afterAction(x:action) | 设定预期返回一个函数执行的操作。 |
334| 6 | afterThrow(x:msg) | 设定预期抛出异常,并指定异常msg。 |
335| 7 | clear() | 用例执行完毕后,进行数据mocker对象的还原处理(还原之后对象恢复被mock之前的功能)。 |
336| 8 | any | 设定用户传任何类型参数(undefined和null除外),执行的结果都是预期的值,使用ArgumentMatchers.any方式调用。 |
337| 9 | anyString | 设定用户传任何字符串参数,执行的结果都是预期的值,使用ArgumentMatchers.anyString方式调用。 |
338| 10 | anyBoolean | 设定用户传任何boolean类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyBoolean方式调用。 |
339| 11 | anyFunction | 设定用户传任何function类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyFunction方式调用。 |
340| 12 | anyNumber | 设定用户传任何数字类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyNumber方式调用。 |
341| 13 | anyObj | 设定用户传任何对象类型参数,执行的结果都是预期的值,使用ArgumentMatchers.anyObj方式调用。 |
342| 14 | matchRegexs(Regex) | 设定用户传任何正则表达式类型参数Regex,执行的结果都是预期的值,使用ArgumentMatchers.matchRegexs(Regex)方式调用。 |
343| 15 | verify(methodName, argsArray) | 验证methodName(函数名字符串)所对应的函数和其参数列表argsArray的执行行为是否符合预期,返回一个VerificationMode:一个提供验证模式的类,它有times(count)、once()、atLeast(x)、atMost(x)、never()等函数可供选择。 |
344| 16 | times(count) | 验证行为调用过count次。 |
345| 17 | once() | 验证行为调用过一次。 |
346| 18 | atLeast(count) | 验证行为至少调用过count次。 |
347| 19 | atMost(count) | 验证行为至多调用过count次。 |
348| 20 | never | 验证行为从未发生过。 |
349| 21 | ignoreMock(obj, method) | 使用ignoreMock可以还原obj对象中被mock后的函数,对被mock后的函数有效。 |
350| 22 | clearAll() | 用例执行完毕后,进行数据和内存清理。 |
351
352- **使用示例:**
353
354用户可以通过以下方式进行引入mock模块进行测试用例编写:
355
356- **须知:**
357使用时候必须引入的mock能力模块: MockKit,when
358根据自己用例需要引入断言能力api
359例如:`import { describe, expect, it, MockKit, when} from '@ohos/hypium'`
360
361**示例1:afterReturn 的使用**
362
363```javascript
364import {describe, expect, it, MockKit, when} from '@ohos/hypium';
365
366export default function ActsAbilityTest() {
367 describe('ActsAbilityTest', function () {
368 it('testMockfunc', 0, function () {
369 console.info("it1 begin");
370
371 //1.创建一个mock能力的对象MockKit
372 let mocker = new MockKit();
373
374 //2.定类ClassName,里面两个函数,然后创建一个对象claser
375 class ClassName {
376 constructor() {
377 }
378
379 method_1(arg) {
380 return '888888';
381 }
382
383 method_2(arg) {
384 return '999999';
385 }
386 }
387
388 let claser = new ClassName();
389
390 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
391 let mockfunc = mocker.mockFunc(claser, claser.method_1);
392 when(mockfunc)('test').afterReturn('1');
393
394 //4.对mock后的函数进行断言,看是否符合预期
395 //执行成功案例,参数为'test'
396 expect(claser.method_1('test')).assertEqual('1'); //执行通过
397
398 //执行失败案例,参数为 'abc'
399 //expect(claser.method_1('abc')).assertEqual('1');//执行失败
400 });
401 });
402}
403```
404- **须知:**
405`when(mockfunc)('test').afterReturn('1');`
406这句代码中的`('test')`是mock后的函数需要传递的匹配参数,目前支持一个参数
407`afterReturn('1')`是用户需要预期返回的结果。
408有且只有在参数是`('test')`的时候,执行的结果才是用户自定义的预期结果。
409
410**示例2: afterReturnNothing 的使用**
411
412```javascript
413import {describe, expect, it, MockKit, when} from '@ohos/hypium';
414
415export default function ActsAbilityTest() {
416 describe('ActsAbilityTest', function () {
417 it('testMockfunc', 0, function () {
418 console.info("it1 begin");
419
420 //1.创建一个mock能力的对象MockKit
421 let mocker = new MockKit();
422
423 //2.定类ClassName,里面两个函数,然后创建一个对象claser
424 class ClassName {
425 constructor() {
426 }
427
428 method_1(arg) {
429 return '888888';
430 }
431
432 method_2(arg) {
433 return '999999';
434 }
435 }
436
437 let claser = new ClassName();
438
439 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
440 let mockfunc = mocker.mockFunc(claser, claser.method_1);
441
442 //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterReturnNothing();即不返回任何值
443 when(mockfunc)('test').afterReturnNothing();
444
445 //5.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
446 //执行成功案例,参数为'test',这时候执行原对象claser.method_1的方法,会发生变化
447 // 这时候执行的claser.method_1不会再返回'888888',而是设定的afterReturnNothing()生效//不返回任何值;
448 expect(claser.method_1('test')).assertUndefined(); //执行通过
449
450 // 执行失败案例,参数传为 123
451 // expect(method_1(123)).assertUndefined();//执行失败
452 });
453 });
454}
455```
456
457**示例3: 设定参数类型为any ,即接受任何参数(undefine和null除外)的使用**
458
459
460- **须知:**
461需要引入ArgumentMatchers类,即参数匹配器,例如:ArgumentMatchers.any
462
463```javascript
464import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
465
466export default function ActsAbilityTest() {
467 describe('ActsAbilityTest', function () {
468 it('testMockfunc', 0, function () {
469 console.info("it1 begin");
470
471 //1.创建一个mock能力的对象MockKit
472 let mocker = new MockKit();
473
474 //2.定类ClassName,里面两个函数,然后创建一个对象claser
475 class ClassName {
476 constructor() {
477 }
478
479 method_1(arg) {
480 return '888888';
481 }
482
483 method_2(arg) {
484 return '999999';
485 }
486 }
487
488 let claser = new ClassName();
489
490 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
491 let mockfunc = mocker.mockFunc(claser, claser.method_1);
492 //根据自己需求进行选择参数匹配器和预期方法,
493 when(mockfunc)(ArgumentMatchers.any).afterReturn('1');
494
495 //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
496 //执行成功的案例1,传参为字符串类型
497 expect(claser.method_1('test')).assertEqual('1'); //用例执行通过。
498 //执行成功的案例2,传参为数字类型123
499 expect(claser.method_1(123)).assertEqual('1');//用例执行通过。
500 //执行成功的案例3,传参为boolean类型true
501 expect(claser.method_1(true)).assertEqual('1');//用例执行通过。
502
503 //执行失败的案例,传参为数字类型空
504 //expect(claser.method_1()).assertEqual('1');//用例执行失败。
505 });
506 });
507}
508```
509
510**示例4: 设定参数类型ArgumentMatchers的使用**
511
512```javascript
513import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
514
515export default function ActsAbilityTest() {
516 describe('ActsAbilityTest', function () {
517 it('testMockfunc', 0, function () {
518 console.info("it1 begin");
519
520 //1.创建一个mock能力的对象MockKit
521 let mocker = new MockKit();
522
523 //2.定类ClassName,里面两个函数,然后创建一个对象claser
524 class ClassName {
525 constructor() {
526 }
527
528 method_1(arg) {
529 return '888888';
530 }
531
532 method_2(arg) {
533 return '999999';
534 }
535 }
536
537 let claser = new ClassName();
538
539 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
540 let mockfunc = mocker.mockFunc(claser, claser.method_1);
541 //根据自己需求进行选择
542 when(mockfunc)(ArgumentMatchers.anyString).afterReturn('0');
543
544 //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
545 //执行成功的案例,传参为字符串类型
546 expect(claser.method_1('test')).assertEqual('0'); //用例执行通过。
547 expect(claser.method_1('abc')).assertEqual('0'); //用例执行通过。
548
549 when(mockfunc)(ArgumentMatchers.anyNumber).afterReturn('1');
550 expect(claser.method_1(1)).assertEqual('1')
551
552 when(mockfunc)(ArgumentMatchers.anyBoolean).afterReturn('2');
553 expect(claser.method_1(true)).assertEqual('2')
554
555 when(mockfunc)(ArgumentMatchers.anyFunction).afterReturn('3');
556 function testFn() {
557 return 2;
558 }
559 expect(claser.method_1(testFn)).assertEqual('3')
560
561 when(mockfunc)(ArgumentMatchers.anyObj).afterReturn('4');
562 expect(claser.method_1(new String('test'))).assertEqual('4')
563
564 //执行失败的案例,传参为数字类型
565 //expect(claser.method_1(123)).assertEqual('1');//用例执行失败。
566 //expect(claser.method_1(true)).assertEqual('1');//用例执行失败。
567 });
568 });
569}
570```
571
572**示例5: 设定参数类型为matchRegexs(Regex)等 的使用**
573```javascript
574import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
575
576export default function ActsAbilityTest() {
577 describe('ActsAbilityTest', function () {
578 it('testMockfunc', 0, function () {
579 console.info("it1 begin");
580
581 //1.创建一个mock能力的对象MockKit
582 let mocker = new MockKit();
583
584 //2.定类ClassName,里面两个函数,然后创建一个对象claser
585 class ClassName {
586 constructor() {
587 }
588
589 method_1(arg) {
590 return '888888';
591 }
592
593 method_2(arg) {
594 return '999999';
595 }
596 }
597
598 let claser = new ClassName();
599
600 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
601 let mockfunc = mocker.mockFunc(claser, claser.method_1);
602 //根据自己需求进行选择,这里假设匹配正则,且正则为/123456/
603 when(mockfunc)(ArgumentMatchers.matchRegexs(/123456/)).afterReturn('1');
604
605 //4.对mock后的函数进行断言,看是否符合预期,注意选择跟第4步中对应的断言方法
606 //执行成功的案例,传参为字符串 比如 '1234567898'
607 expect(claser.method_1('1234567898')).assertEqual('1'); //用例执行通过。
608 //因为字符串 '1234567898'可以和正则/123456/匹配上
609
610 //执行失败的案例,传参为字符串'1234'
611 //expect(claser.method_1('1234')).assertEqual('1');//用例执行失败。反之
612 });
613 });
614}
615```
616
617**示例6: 验证功能 Verify函数的使用**
618```javascript
619import {describe, expect, it, MockKit, when} from '@ohos/hypium';
620
621export default function ActsAbilityTest() {
622 describe('ActsAbilityTest', function () {
623 it('testMockfunc', 0, function () {
624 console.info("it1 begin");
625
626 //1.创建一个mock能力的对象MockKit
627 let mocker = new MockKit();
628
629 //2.定类ClassName,里面两个函数,然后创建一个对象claser
630 class ClassName {
631 constructor() {
632 }
633
634 method_1(...arg) {
635 return '888888';
636 }
637
638 method_2(...arg) {
639 return '999999';
640 }
641 }
642
643 let claser = new ClassName();
644
645 //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
646 mocker.mockFunc(claser, claser.method_1);
647 mocker.mockFunc(claser, claser.method_2);
648
649 //4.方法调用如下
650 claser.method_1('abc', 'ppp');
651 claser.method_1('abc');
652 claser.method_1('xyz');
653 claser.method_1();
654 claser.method_1('abc', 'xxx', 'yyy');
655 claser.method_1();
656 claser.method_2('111');
657 claser.method_2('111', '222');
658
659 //5.现在对mock后的两个函数进行验证,验证调用情况
660 mocker.verify('method_1', []).atLeast(3); //结果为failed
661 //解释:验证函数'method_1',参数列表为空:[] 的函数,至少执行过3次,
662 //执行结果为failed,因为'method_1'且无参数 在4中只执行过2次
663 //mocker.verify('method_2',['111']).once();//执行success,原因同上
664 //mocker.verify('method_2',['111',,'222']).once();//执行success,原因同上
665 });
666 });
667}
668```
669
670**示例7: ignoreMock(obj, method) 忽略函数的使用**
671```javascript
672import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
673
674export default function ActsAbilityTest() {
675 describe('ActsAbilityTest', function () {
676 it('testMockfunc', 0, function () {
677 console.info("it1 begin");
678
679 //1.创建一个mock能力的对象MockKit
680 let mocker = new MockKit();
681
682 //2.定类ClassName,里面两个函数,然后创建一个对象claser
683 class ClassName {
684 constructor() {
685 }
686
687 method_1(...arg) {
688 return '888888';
689 }
690
691 method_2(...arg) {
692 return '999999';
693 }
694 }
695
696 let claser = new ClassName();
697
698 //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
699 let func_1 = mocker.mockFunc(claser, claser.method_1);
700 let func_2 = mocker.mockFunc(claser, claser.method_2);
701
702 //4.对mock后的函数的行为进行修改
703 when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
704 when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
705
706 //5.方法调用如下
707 console.log(claser.method_1(123)); //执行结果是4,符合步骤4中的预期
708 console.log(claser.method_2(456)); //执行结果是5,符合步骤4中的预期
709
710 //6.现在对mock后的两个函数的其中一个函数method_1进行忽略处理(原理是就是还原)
711 mocker.ignoreMock(claser, claser.method_1);
712 //然后再去调用 claser.method_1函数,看执行结果
713 console.log(claser.method_1(123)); //执行结果是888888,发现这时结果跟步骤4中的预期不一样了,执行了claser.method_1没被mock之前的结果
714 //用断言测试
715 expect(claser.method_1(123)).assertEqual('4'); //结果为failed 符合ignoreMock预期
716 claser.method_2(456); //执行结果是5,因为method_2没有执行ignore忽略,所有也符合步骤4中的预期
717 });
718 });
719}
720```
721
722**示例8: clear()函数的使用**
723
724```javascript
725import {describe, expect, it, MockKit, when, ArgumentMatchers} from '@ohos/hypium';
726
727export default function ActsAbilityTest() {
728 describe('ActsAbilityTest', function () {
729 it('testMockfunc', 0, function () {
730 console.info("it1 begin");
731
732 //1.创建一个mock能力的对象MockKit
733 let mocker = new MockKit();
734
735 //2.定类ClassName,里面两个函数,然后创建一个对象claser
736 class ClassName {
737 constructor() {
738 }
739
740 method_1(...arg) {
741 return '888888';
742 }
743
744 method_2(...arg) {
745 return '999999';
746 }
747 }
748 let claser = new ClassName();
749
750 //3.进行mock操作,比如需要对ClassName类的method_1和method_2两个函数进行mock
751 let func_1 = mocker.mockFunc(claser, claser.method_1);
752 let func_2 = mocker.mockFunc(claser, claser.method_2);
753
754 //4.对mock后的函数的行为进行修改
755 when(func_1)(ArgumentMatchers.anyNumber).afterReturn('4');
756 when(func_2)(ArgumentMatchers.anyNumber).afterReturn('5');
757
758 //5.方法调用如下
759 //expect(claser.method_1(123)).assertEqual('4');//ok 符合预期
760 //expect(claser.method_2(456)).assertEqual('5');//ok 符合预期
761
762 //6.清除mock操作(原理是就是还原)
763 mocker.clear(claser);
764 //然后再去调用 claser.method_1函数,看执行结果
765 expect(claser.method_1(123)).assertEqual('4');//failed 符合预期
766 expect(claser.method_2(456)).assertEqual('5');//failed 符合预期
767 });
768 });
769}
770```
771
772
773**示例9: afterThrow(msg) 函数的使用**
774
775```javascript
776import {describe, expect, it, MockKit, when} from '@ohos/hypium';
777
778export default function ActsAbilityTest() {
779 describe('ActsAbilityTest', function () {
780 it('testMockfunc', 0, function () {
781 console.info("it1 begin");
782
783 //1.创建一个mock能力的对象MockKit
784 let mocker = new MockKit();
785
786 //2.定类ClassName,里面两个函数,然后创建一个对象claser
787 class ClassName {
788 constructor() {
789 }
790
791 method_1(arg) {
792 return '888888';
793 }
794 }
795
796 let claser = new ClassName();
797
798 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
799 let mockfunc = mocker.mockFunc(claser, claser.method_1);
800
801 //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterReturnNothing();即不返回任何值
802 when(mockfunc)('test').afterThrow('error xxx');
803
804 //5.执行mock后的函数,捕捉异常并使用assertEqual对比msg否符合预期
805 try {
806 claser.method_1('test');
807 } catch (e) {
808 expect(e).assertEqual('error xxx');//执行通过
809 }
810 });
811 });
812}
813```
814
815**示例10: mock异步 函数的使用**
816
817```javascript
818import {describe, expect, it, MockKit, when} from '@ohos/hypium';
819
820export default function ActsAbilityTest() {
821 describe('ActsAbilityTest', function () {
822 it('testMockfunc', 0, function () {
823 console.info("it1 begin");
824
825 //1.创建一个mock能力的对象MockKit
826 let mocker = new MockKit();
827
828 //2.定类ClassName,里面两个函数,然后创建一个对象claser
829 class ClassName {
830 constructor() {
831 }
832
833 async method_1(arg) {
834 return new Promise((res, rej) => {
835 //做一些异步操作
836 setTimeout(function () {
837 console.log('执行');
838 res('数据传递');
839 }, 2000);
840 });
841 }
842 }
843
844 let claser = new ClassName();
845
846 //3.进行mock操作,比如需要对ClassName类的method_1函数进行mock
847 let mockfunc = mocker.mockFunc(claser, claser.method_1);
848
849 //4.根据自己需求进行选择 执行完毕后的动作,比如这里选择afterRetrun; 可以自定义返回一个promise
850 when(mockfunc)('test').afterReturn(new Promise((res, rej) => {
851 console.log("do something");
852 res('success something');
853 }));
854
855 //5.执行mock后的函数,即对定义的promise进行后续执行
856 claser.method_1('test').then(function (data) {
857 //数据处理代码...
858 console.log('result : ' + data);
859 });
860 });
861 });
862}
863```
864
865**示例11:mock 系统函数的使用**
866
867```javascript
868export default function ActsAbilityTest() {
869 describe('ActsAbilityTest', function () {
870 it('test_systemApi', 0, function () {
871 //1.创建MockKit对象
872 let mocker = new MockKit();
873 //2.mock app.getInfo函数
874 let mockf = mocker.mockFunc(app, app.getInfo);
875 when(mockf)('test').afterReturn('1');
876 //执行成功案例
877 expect(app.getInfo('test')).assertEqual('1');
878 });
879 });
880}
881```
882
883
884**示例12:verify times函数的使用(验证函数调用次数)**
885
886```javascript
887import { describe, expect, it, MockKit, when } from '@ohos/hypium'
888
889export default function ActsAbilityTest() {
890 describe('ActsAbilityTest', function () {
891 it('test_verify_times', 0, function () {
892 //1.创建MockKit对象
893 let mocker = new MockKit();
894 //2.定义需要被mock的类
895 class ClassName {
896 constructor() {
897 }
898
899 method_1(...arg) {
900 return '888888';
901 }
902 }
903 //3.创建类对象
904 let claser = new ClassName();
905 //4.mock 类ClassName对象的某个方法,比如method_1
906 let func_1 = mocker.mockFunc(claser, claser.method_1);
907 //5.期望被mock后的函数能够返回自己假设的结果
908 when(func_1)('123').afterReturn('4');
909
910 //6.随机执行几次函数,参数如下
911 claser.method_1('123', 'ppp');
912 claser.method_1('abc');
913 claser.method_1('xyz');
914 claser.method_1();
915 claser.method_1('abc', 'xxx', 'yyy');
916 claser.method_1('abc');
917 claser.method_1();
918 //7.验证函数method_1且参数为'abc'时,执行过的次数是否为2
919 mocker.verify('method_1', ['abc']).times(2);
920 });
921 });
922}
923```
924
925
926**示例13: verify atLeast 函数的使用 (验证函数调用次数)**
927
928```javascript
929import { describe, expect, it, MockKit, when } from '@ohos/hypium'
930
931export default function ActsAbilityTest() {
932 describe('ActsAbilityTest', function () {
933 it('test_verify_atLeast', 0, function () {
934 //1.创建MockKit对象
935 let mocker = new MockKit();
936 //2.定义需要被mock的类
937 class ClassName {
938 constructor() {
939 }
940
941 method_1(...arg) {
942 return '888888';
943 }
944 }
945
946 //3.创建类对象
947 let claser = new ClassName();
948 //4.mock 类ClassName对象的某个方法,比如method_1
949 let func_1 = mocker.mockFunc(claser, claser.method_1);
950 //5.期望被mock后的函数能够返回自己假设的结果
951 when(func_1)('123').afterReturn('4');
952 //6.随机执行几次函数,参数如下
953 claser.method_1('123', 'ppp');
954 claser.method_1('abc');
955 claser.method_1('xyz');
956 claser.method_1();
957 claser.method_1('abc', 'xxx', 'yyy');
958 claser.method_1();
959 //7.验证函数method_1且参数为空时,是否至少执行过2次
960 mocker.verify('method_1', []).atLeast(2);
961 });
962 });
963}
964```
965
966#### 数据驱动
967
968##### 约束限制
969
970单元测试框架数据驱动能力从[hypium 1.0.2版本](https://repo.harmonyos.com/#/cn/application/atomService/@ohos%2Fhypium)开始支持。
971
972- 数据参数传递 : 为指定测试套、测试用例传递测试输入数据参数。
973- 压力测试 : 为指定测试套、测试用例设置执行次数。
974
975数据驱动可以根据配置参数来驱动测试用例的执行次数和每一次传入的参数,使用时依赖data.json配置文件,文件内容如下:
976
977>说明 : data.json与测试用例*.test.js|ets文件同目录
978
979```json
980{
981 "suites": [{
982 "describe": ["actsAbilityTest"],
983 "stress": 2,
984 "params": {
985 "suiteParams1": "suiteParams001",
986 "suiteParams2": "suiteParams002"
987 },
988 "items": [{
989 "it": "testDataDriverAsync",
990 "stress": 2,
991 "params": [{
992 "name": "tom",
993 "value": 5
994 }, {
995 "name": "jerry",
996 "value": 4
997 }]
998 }, {
999 "it": "testDataDriver",
1000 "stress": 3
1001 }]
1002 }]
1003}
1004```
1005
1006配置参数说明:
1007
1008| | 配置项名称 | 功能 | 必填 |
1009| :--- | :--------- | :------------------------------------ | ---- |
1010| 1 | "suite" | 测试套配置 。 | 是 |
1011| 2 | "items" | 测试用例配置 。 | 是 |
1012| 3 | "describe" | 测试套名称 。 | 是 |
1013| 4 | "it" | 测试用例名称 。 | 是 |
1014| 5 | "params" | 测试套 / 测试用例 可传入使用的参数 。 | 否 |
1015| 6 | "stress" | 测试套 / 测试用例 指定执行次数 。 | 否 |
1016
1017示例代码:
1018
1019在TestAbility目录下app.js|ets文件中导入data.json,并在Hypium.hypiumTest() 方法执行前,设置参数数据
1020
1021```javascript
1022import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
1023import { Hypium } from '@ohos/hypium'
1024import testsuite from '../test/List.test'
1025import data from '../test/data.json';
1026
1027...
1028Hypium.setData(data);
1029Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
1030...
1031```
1032
1033```javascript
1034import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium';
1035
1036export default function abilityTest() {
1037 describe('actsAbilityTest', function () {
1038 it('testDataDriverAsync', 0, async function (done, data) {
1039 console.info('name: ' + data.name);
1040 console.info('value: ' + data.value);
1041 done();
1042 });
1043
1044 it('testDataDriver', 0, function () {
1045 console.info('stress test');
1046 });
1047 });
1048}
1049```
1050#### 专项能力
1051
1052该项能力需通过在cmd窗口中输入aa test命令执行触发,并通过设置执行参数触发不同功能。另外,测试应用模型与编译方式不同,对应的aa test命令也不同,具体可参考[自动化测试框架使用指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/application-test/arkxtest-guidelines.md#cmd%E6%89%A7%E8%A1%8C)
1053
1054- **筛选能力**
1055
1056 1、按测试用例属性筛选
1057
1058 可以利用hypium提供的Level、Size、TestType 对象,对测试用例进行标记,以区分测试用例的级别、粒度、测试类型,各字段含义及代码如下:
1059
1060 | Key | 含义说明 | Value取值范围 |
1061 | -------- | ------------ | ------------------------------------------------------------ |
1062 | level | 用例级别 | "0","1","2","3","4", 例如:-s level 1 |
1063 | size | 用例粒度 | "small","medium","large", 例如:-s size small |
1064 | testType | 用例测试类型 | "function","performance","power","reliability","security","global","compatibility","user","standard","safety","resilience", 例如:-s testType function |
1065
1066 示例代码:
1067
1068 ```javascript
1069 import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium';
1070
1071 export default function attributeTest() {
1072 describe('attributeTest', function () {
1073 it("testAttributeIt", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () {
1074 console.info('Hello Test');
1075 })
1076 })
1077 }
1078 ```
1079
1080 示例命令:
1081
1082 ```shell
1083 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s testType function -s size small -s level 0
1084 ```
1085
1086 该命令作用是筛选测试应用中同时满足,用例测试类型是“function”、用例粒度是“small”、用例级别是“0”的三个条件用例执行。
1087
1088 2、按测试套/测试用例名称筛选
1089
1090 hypium可以通过指定测试套与测试用例名称,来指定特定用例的执行,测试套与用例名称用“#”号连接,多个用“,”英文逗号分隔
1091
1092 | Key | 含义说明 | Value取值范围 |
1093 | -------- | ----------------------- | ------------------------------------------------------------ |
1094 | class | 指定要执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s class attributeTest#testAttributeIt |
1095 | notClass | 指定不执行的测试套&用例 | ${describeName}#${itName},${describeName} , 例如:-s notClass attributeTest#testAttribut |
1096
1097 示例代码:
1098
1099 ```javascript
1100 import { describe, it, expect, TestType, Size, Level } from '@ohos/hypium';
1101
1102 export default function attributeTest() {
1103 describe('describeTest_000', function () {
1104 it("testIt_00", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () {
1105 console.info('Hello Test');
1106 })
1107
1108 it("testIt_01", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () {
1109 console.info('Hello Test');
1110 })
1111 })
1112
1113 describe('describeTest_001', function () {
1114 it("testIt_02", TestType.FUNCTION | Size.SMALLTEST | Level.LEVEL0, function () {
1115 console.info('Hello Test');
1116 })
1117 })
1118 }
1119 ```
1120
1121 示例命令1:
1122
1123 ```shell
1124 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s class describeTest_000#testIt_00,describeTest_001
1125 ```
1126
1127 该命令作用是执行“describeTest_001”测试套中所用用例,以及“describeTest_000”测试套中的“testIt_00”用例。
1128
1129 示例命令2:
1130
1131 ```shell
1132 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s notClass describeTest_000#testIt_01
1133 ```
1134
1135 该命令作用是不执行“describeTest_000”测试套中的“testIt_01”用例。
1136
1137- **随机执行**
1138
1139 使测试套与测试用例随机执行,用于稳定性测试。
1140
1141 | Key | 含义说明 | Value取值范围 |
1142 | ------ | ------------------------------------ | ---------------------------------------------- |
1143 | random | @since1.0.3 测试套、测试用例随机执行 | true, 不传参默认为false, 例如:-s random true |
1144
1145 示例命令:
1146
1147 ```shell
1148 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s dryRun true
1149 ```
1150
1151- **压力测试**
1152
1153 指定要执行用例的执行次数,用于压力测试。
1154
1155 | Key | 含义说明 | Value取值范围 |
1156 | ------ | ------------------------------------ | ------------------------------ |
1157 | stress | @since1.0.5 指定要执行用例的执行次数 | 正整数, 例如: -s stress 1000 |
1158
1159 示例命令:
1160
1161 ```shell
1162 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s stress 1000
1163 ```
1164
1165- **用例超时时间设置**
1166
1167 指定测试用例执行的超时时间,用例实际耗时如果大于超时时间,用例会抛出"timeout"异常,用例结果会显示“excute timeout XXX”
1168
1169 | Key | 含义说明 | Value取值范围 |
1170 | ------- | -------------------------- | ---------------------------------------------------- |
1171 | timeout | 指定测试用例执行的超时时间 | 正整数(单位ms),默认为 5000,例如: -s timeout 15000 |
1172
1173 示例命令:
1174
1175 ```shell
1176 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s timeout 15000
1177 ```
1178
1179- **遇错即停模式**
1180
1181 | Key | 含义说明 | Value取值范围 |
1182 | ------------ | ------------------------------------------------------------ | ---------------------------------------------------- |
1183 | breakOnError | @since1.0.6 遇错即停模式,当执行用例断言失败或者发生错误时,退出测试执行流程 | true, 不传参默认为false, 例如:-s breakOnError true |
1184
1185 示例命令:
1186
1187 ```shell
1188 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s breakOnError true
1189 ```
1190
1191- **测试套中用例信息输出**
1192
1193 输出测试应用中待执行的测试用例信息
1194
1195 | Key | 含义说明 | Value取值范围 |
1196 | ------ | ---------------------------- | ---------------------------------------------- |
1197 | dryRun | 显示待执行的测试用例信息全集 | true, 不传参默认为false, 例如:-s dryRun true |
1198
1199 示例命令:
1200
1201 ```shell
1202 hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner -s dryRun true
1203 ```
1204
1205### 使用方式
1206
1207单元测试框架以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-0000001263160453)。
1208
1209## Ui测试框架功能特性
1210
1211| No. | 特性 | 功能说明 |
1212| ---- |-----------|-------------------------------------------------|
1213| 1 | Driver | Ui测试的入口,提供查找控件,检查控件存在性以及注入按键能力。 |
1214| 2 | On | 用于描述目标控件特征(文本、id、类型等),`Driver`根据`On`描述的控件特征信息来查找控件。 |
1215| 3 | Component | Driver查找返回的控件对象,提供查询控件属性,滑动查找等触控和检视能力。 |
1216| 4 | UiWindow | Driver查找返回的窗口对象,提供获取窗口属性、操作窗口的能力。 |
1217
1218**使用者在测试脚本通过如下方式引入使用:**
1219
1220```typescript
1221import {Driver,ON,Component,Uiwindow,MatchPattern} from '@ohos.UiTest'
1222```
1223
1224> 须知
1225> 1. `On`类提供的接口全部是同步接口,使用者可以使用`builder`模式链式调用其接口构造控件筛选条件。
1226> 2. `Driver`和`Component`类提供的接口全部是异步接口(`Promise`形式),**需使用`await`语法**。
1227> 3. Ui测试用例均需使用**异步**语法编写用例,需遵循单元测试框架异步用例编写规范。
1228
1229
1230
1231在测试用例文件中import `On/Driver/Component`类,然后调用API接口编写测试用例。
1232
1233```javascript
1234import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from '@ohos/hypium'
1235import {ON, Driver, Component, MatchPattern} from '@ohos.UiTest'
1236
1237export default async function abilityTest() {
1238 describe('uiTestDemo', function() {
1239 it('uitest_demo0', 0, async function() {
1240 // create Driver
1241 let driver = Driver.create()
1242 // find component by text
1243 let button = await driver.findComponent(ON.text('hello').enabled(true))
1244 // click component
1245 await button.click()
1246 // get and assert component text
1247 let content = await button.getText()
1248 expect(content).assertEqual('clicked!')
1249 })
1250 })
1251}
1252```
1253
1254### Driver使用说明
1255
1256`Driver`类作为UiTest测试框架的总入口,提供查找控件,注入按键,单击坐标,滑动控件,手势操作,截图等能力。
1257
1258| No. | API | 功能描述 |
1259| ---- |-----------------------------------------------------------------| ---------------------- |
1260| 1 | create():Promise<Driver> | 静态方法,构造Driver。 |
1261| 2 | findComponent(on:On):Promise<Component> | 查找匹配控件。 |
1262| 3 | pressBack():Promise<void> | 单击BACK键。 |
1263| 4 | click(x:number, y:number):Promise<void> | 基于坐标点的单击。 |
1264| 5 | swipe(x1:number, y1:number, x2:number, y2:number):Promise<void> | 基于坐标点的滑动。 |
1265| 6 | assertComponentExist(on:On):Promise<void> | 断言匹配的控件存在。 |
1266| 7 | delayMs(t:number):Promise<void> | 延时。 |
1267| 8 | screenCap(s:path):Promise<void> | 截屏。 |
1268| 9 | findWindow(filter: WindowFilter): Promise<UiWindow> | 查找匹配窗口。 |
1269
1270其中assertComponentExist接口是断言API,用于断言当前界面存在目标控件;如果控件不存在,该API将抛出JS异常,使当前测试用例失败。
1271
1272```javascript
1273import {ON,Driver,Component} from '@ohos.UiTest'
1274
1275export default async function abilityTest() {
1276 describe('UiTestDemo', function() {
1277 it('Uitest_demo0', 0, async function(done) {
1278 try{
1279 // create Driver
1280 let driver = Driver.create()
1281 // assert text 'hello' exists on current Ui
1282 await assertComponentExist(ON.text('hello'))
1283 } finally {
1284 done()
1285 }
1286 })
1287 })
1288}
1289```
1290
1291`Driver`完整的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#driver9)。
1292
1293### On使用说明
1294
1295Ui测试框架通过`On`类提供了丰富的控件特征描述API,用来匹配查找要操作或检视的目标控件。`On`提供的API能力具有以下特点:
1296
1297- 支持匹配单属性和匹配多属性组合,例如同时指定目标控件text和id。
1298- 控件属性支持多种匹配模式(等于,包含,`STARTS_WITH`,`ENDS_WITH`)。
1299- 支持相对定位控件,可通过`isBefore`和`isAfter`等API限定邻近控件特征进行辅助定位。
1300
1301| No. | API | 功能描述 |
1302|-----|------------------------------------|----------------------------|
1303| 1 | id(i:string):On | 指定控件id。 |
1304| 2 | text(t:string, p?:MatchPattern):On | 指定控件文本,可指定匹配模式。 |
1305| 3 | type(t:string):On | 指定控件类型。 |
1306| 4 | enabled(e:bool):On | 指定控件使能状态。 |
1307| 5 | clickable(c:bool):On | 指定控件可单击状态。 |
1308| 6 | longClickable(l:bool):On | 指定控件可长按状态。 |
1309| 7 | focused(f:bool):On | 指定控件获焦状态。 |
1310| 8 | scrollable(s:bool):On | 指定控件可滑动状态。 |
1311| 9 | selected(s:bool):On | 指定控件选中状态。 |
1312| 10 | checked(c:bool):On | 指定控件选择状态。 |
1313| 11 | checkable(c:bool):On | 指定控件可选择状态。 |
1314| 12 | isBefore(b:On):On | **相对定位**,限定目标控件位于指定特征控件之前。 |
1315| 13 | isAfter(b:On):On | **相对定位**,限定目标控件位于指定特征控件之后。 |
1316
1317其中,`text`属性支持{`MatchPattern.EQUALS`,`MatchPattern.CONTAINS`,`MatchPattern.STARTS_WITH`,`MatchPattern.ENDS_WITH`}四种匹配模式,缺省使用`MatchPattern.EQUALS`模式。
1318
1319`On`完整的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#on9)。
1320
1321#### 控件绝对定位
1322
1323**示例代码1**:查找id是`Id_button`的控件。
1324
1325```javascript
1326let button = await driver.findComponent(ON.id('Id_button'))
1327```
1328
1329 **示例代码2**:查找id是`Id_button`并且状态是`enabled`的控件,适用于无法通过单一属性定位的场景。
1330
1331```javascript
1332let button = await driver.findComponent(ON.id('Id_button').enabled(true))
1333```
1334
1335通过`On.id(x).enabled(y)`来指定目标控件的多个属性。
1336
1337**示例代码3**:查找文本中包含`hello`的控件,适用于不能完全确定控件属性取值的场景。
1338
1339```javascript
1340let txt = await driver.findComponent(ON.text('hello', MatchPattern.CONTAINS))
1341```
1342
1343通过向`On.text()`方法传入第二个参数`MatchPattern.CONTAINS`来指定文本匹配规则;默认规则是`MatchPattern.EQUALS`,即目标控件text属性必须严格等于给定值。
1344
1345#### 控件相对定位
1346
1347**示例代码1**:查找位于文本控件`Item3_3`后面的,id是`Id_switch`的Switch控件。
1348
1349```javascript
1350let switch = await driver.findComponent(ON.id('Id_switch').isAfter(ON.text('Item3_3')))
1351```
1352
1353通过`On.isAfter`方法,指定位于目标控件前面的特征控件属性,通过该特征控件进行相对定位。一般地,特征控件是某个具有全局唯一特征的控件(例如具有唯一的id或者唯一的text)。
1354
1355类似的,可以使用`On.isBefore`控件指定位于目标控件后面的特征控件属性,实现相对定位。
1356
1357### Component使用说明
1358
1359`Component`类代表了Ui界面上的一个控件,一般是通过`Driver.findComponent(on)`方法查找到的。通过该类的实例,用户可以获取控件属性,单击控件,滑动查找,注入文本等操作。
1360
1361`Component`包含的常用API:
1362
1363| No. | API | 功能描述 |
1364|-----|------------------------------------|----------------------------|
1365| 1 | click():Promise<void> | 单击该控件。 |
1366| 2 | inputText(t:string):Promise<void> | 向控件中输入文本(适用于文本框控件)。 |
1367| 3 | scrollSearch(s:On):Promise<Component> | 在该控件上滑动查找目标控件(适用于List等控件)。 |
1368| 4 | scrollToTop(s:number):Promise<void> | 滑动到该控件顶部(适用于List等控件)。 |
1369| 5 | scrollTobottom(s:number):Promise<void> | 滑动到该控件底部(适用于List等控件)。 |
1370| 6 | getText():Promise<string> | 获取控件text。 |
1371| 7 | getId():Promise<number> | 获取控件id。 |
1372| 8 | getType():Promise<string> | 获取控件类型。 |
1373| 9 | isEnabled():Promise<bool> | 获取控件使能状态。 |
1374
1375`Component`完整的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#component9)。
1376
1377**示例代码1**:单击控件。
1378
1379```javascript
1380let button = await driver.findComponent(ON.id('Id_button'))
1381await button.click()
1382```
1383
1384**示例代码2**:通过get接口获取控件属性后,可以使用单元测试框架提供的assert*接口做断言检查。
1385
1386```javascript
1387let component = await driver.findComponent(ON.id('Id_title'))
1388expect(component !== null).assertTrue()
1389```
1390
1391**示例代码3**:在List控件中滑动查找text是`Item3_3`的子控件。
1392
1393```javascript
1394let list = await driver.findComponent(ON.id('Id_list'))
1395let found = await list.scrollSearch(ON.text('Item3_3'))
1396expect(found).assertTrue()
1397```
1398
1399**示例代码4**:向输入框控件中输入文本。
1400
1401```javascript
1402let editText = await driver.findComponent(ON.type('InputText'))
1403await editText.inputText('user_name')
1404```
1405### UiWindow使用说明
1406
1407`UiWindow`类代表了Ui界面上的一个窗口,一般是通过`Driver.findWindow(WindowFilter)`方法查找到的。通过该类的实例,用户可以获取窗口属性,并进行窗口拖动、调整窗口大小等操作。
1408
1409`UiWindow`包含的常用API:
1410
1411| No. | API | 功能描述 |
1412| ---- | ------------------------------------------------------------ | -------------------------------------------------- |
1413| 1 | getBundleName(): Promise<string> | 获取窗口所属应用包名。 |
1414| 2 | getTitle(): Promise<string> | 获取窗口标题信息。 |
1415| 3 | focus(): Promise<bool> | 使得当前窗口获取焦点。 |
1416| 4 | moveTo(x: number, y: number): Promise<bool> | 将当前窗口移动到指定位置(适用于支持移动的窗口)。 |
1417| 5 | resize(wide: number, height: number, direction: ResizeDirection): Promise<bool> | 调整窗口大小(适用于支持调整大小的窗口)。 |
1418| 6 | split(): Promise<bool> | 将窗口模式切换为分屏模式(适用于支持分屏的窗口)。 |
1419| 7 | close(): Promise<bool> | 关闭当前窗口。 |
1420
1421`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)。
1422
1423**示例代码1**:获取窗口属性。
1424
1425```javascript
1426let window = await driver.findWindow({actived: true})
1427let bundelName = await window.getBundleName()
1428```
1429
1430**示例代码2**:移动窗口。
1431
1432```javascript
1433let window = await driver.findWindow({actived: true})
1434await window.moveTo(500,500)
1435```
1436
1437**示例代码3**:关闭窗口。
1438
1439```javascript
1440let window = await driver.findWindow({actived: true})
1441await window.close()
1442```
1443
1444### 使用方式
1445
1446 开发者可以下载Deveco Studio创建测试工程后,在其中调用框架提供接口进行相关测试操作,测试工程创建及测试脚本执行使用指南请参见[IDE指导文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-openharmony-test-framework-0000001267284568)。
1447 UI测试框架使能需要执行如下命令。
1448
1449>```shell
1450> hdc shell param set persist.ace.testmode.enabled 1
1451>```
1452### UI测试框架自构建方式
1453
1454> Ui测试框架在OpenHarmony-3.1-Release版本中未随版本编译,需手动处理,请参考[3.1-Release版本使用指导](https://gitee.com/openharmony/testfwk_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)。
1455
1456开发者如需自行编译Ui测试框架代码验证子修改内容,构建命令和推送位置请参考本章节内容。
1457
1458#### 构建命令
1459
1460```shell
1461./build.sh --product-name rk3568 --build-target uitestkit
1462```
1463#### 推送位置
1464
1465```shell
1466hdc target mount
1467hdc shell mount -o rw,remount /
1468hdc file send uitest /system/bin/uitest
1469hdc file send libuitest.z.so /system/lib/module/libuitest.z.so
1470hdc shell chmod +x /system/bin/uitest
1471```
1472
1473### 命令行使用说明
1474
1475 开发者可以输入如下命令来实现对应功能。
1476
14771、打印使用帮助
1478
1479```shell
1480hdc shell uitest help
1481```
1482
14832、截屏
1484
1485```
1486hdc shell uitest screenCap
1487// 默认存储路径:/data/local/tmp,文件名:时间戳 + .png。
1488hdc shell uitest screenCap -p /data/local/1.png
1489// 指定存储路径和文件名。
1490```
1491
14923、获取设备当前Ui控件树信息
1493
1494```shell
1495hdc shell uitest dumpLayout
1496// 默认存储路径:/data/local/tmp,文件名:时间戳 + .json。
1497hdc shell uitest screenCap -p /data/local/1.json
1498// 指定存储路径和文件名。
1499```
1500
15014、录制Ui操作
1502
1503```shell
1504hdc shell uitest uiRecord record
1505// 将当前执行的Ui操作记录到/data/local/tmp/layout/record.csv
1506hdc shell uitest uiRecord read
1507// 将记录的Ui操作打印出来
1508```
1509
1510### 版本信息
1511
1512| 版本号 | 功能说明 |
1513| :------ | :----------------------------------------------------------- |
1514| 3.2.2.1 | 1、增加抛滑、获取/设置屏幕方向接口<br />2、窗口处理逻辑增加不支持场景处理逻辑 |
1515| 3.2.3.0 | 1、滑动控件进行滑动查找、滑动到尾部/顶部功能优化 |
1516| 3.2.4.0 | 1、接口调用异常时会抛出错误码 |
1517| 3.2.5.0 | 1、通信机制变更 |
1518| 3.2.6.0 | 1、增加模拟鼠标操作能力接口<br />2、增加指定应用的窗口下查找目标控件接口 |
1519| 4.0.1.1 | 1、支持在daemon运行时执行uitest dumpLayout |
1520| 4.0.1.2 | 1、模拟鼠标动作、键鼠协同功能优化 |
1521| 4.0.1.3 | 1、示例代码更新<br />2、滑动控件进行滑动查找、滑动到尾部/顶部功能优化 |
1522| 4.0.1.4 | 1、可选参数传入undefined时,当作默认值处理 |
1523| 4.0.2.0 | 1、支持监听toast和dialog控件出现,使用callback的形式返回结果。 |
1524| 4.0.3.0 | 1、增加加载运行.abc文件机制。 |
1525| 4.0.4.0 | 1、支持abc_loader框架获取UI操作录制数据,屏幕数据,控件树等,并以callback的形式返回结果<br />2、修改录制数据结构 |