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