1# 开发自测试执行框架 2OpenHarmony为开发者提供了一套全面的开发自测试框架OHA-developer_test,开发者可根据测试需求开发相关测试用例,开发阶段提前发现缺陷,大幅提高代码质量。 3 4本文从基础环境构建,用例开发,编译以及执行等方面介绍OpenHarmony开发自测试执行框架如何运行和使用。 5## 基础环境构建 6开发自测试框架依赖于python运行环境,python版本为3.8.X,在使用测试框架之前可参阅以下方式进行配置。 7 - [环境配置](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/device-test/developer_test.md) 8 - [源码获取](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/sourcecode-acquire.md) 9 10开发自测试框架依赖于测试调度框架testfwk_xdevice,在使用时两个框架放在同级目录 11 12## 开发自测试框架目录简介 13以下是开发自测试框架的目录层级架构,在使用开发自测试框架过程中可在相应目录查找对应组件。 14``` 15test # 测试子系统 16├── developer_test # 开发者自测试框架 17│ ├── aw # 测试框架的静态库 18│ ├── config # 测试框架配置 19│ │ │ ... 20│ │ └── user_config.xml # 用户使用配置 21│ ├── examples # 测试用例示例 22│ ├── src # 测试框架源码 23│ ├── third_party # 测试框架依赖第三方组件适配 24│ ├── reports # 测试结果报告 25│ ├── BUILD.gn # 测试框架编译入口 26│ ├── start.bat # 开发者测试入口(Windows) 27│ └── start.sh # 开发者测试入口(Linux) 28└── xdevice # 测试框架依赖组件 29``` 30## 功能特性 31 32### 测试用例 33 34#### 测试用例目录规划 35使用测试框架过程中,可根据以下层级关系规划测试用例目录。 36 37``` 38subsystem # 子系统 39├── partA # 部件A 40│ ├── moduleA # 模块A 41│ │ ├── include 42│ │ ├── src # 业务代码 43│ │ └── test # 测试目录 44│ │ ├── unittest # 单元测试 45│ │ │ ├── common # 公共用例 46│ │ │ │ ├── BUILD.gn # 测试用例编译配置 47│ │ │ │ └── testA_test.cpp # 单元测试用例源码 48│ │ │ ├── phone # 手机形态用例 49│ │ │ ├── ivi # 车机形态用例 50│ │ │ └── liteos-a # ipcamera使用liteos内核的用例 51│ │ ├── moduletest # 模块测试 52│ │ ... 53│ │ 54│ ├── moduleB # 模块B 55│ ├── test 56│ │ └── resource # 依赖资源 57│ │ ├── moduleA # 模块A 58│ │ │ ├── ohos_test.xml # 资源配置文件 59│ │ ... └── 1.txt # 资源 60│ │ 61│ ├── bundle.json # 编译入口配置 62│ ... 63│ 64... 65``` 66> **注意:** 测试用例根据不同设备形态差异分为通用用例和非通用用例,建议将通用用例存放在common目录下,非通用用例存放在相应设备形态目录下。 67 68#### 测试用例编写 69本测试框架支持多种类型测试,针对不同测试类型提供了不同的用例编写模板以供参考。 70 71**TDD测试(C++)** 72 73- 用例源文件命名规范 74 75 测试用例源文件名称和测试套内容保持一致,文件命名采用全小写+下划线方式命名,以test结尾,具体格式为:[功能]_[子功能]_test,子功能支持向下细分。 76 77单线程示例: 78 ``` 79 calculator_sub_test.cpp 80 ``` 81 82- 用例示例 83 ``` 84 /* 85 * Copyright (c) 2021 XXXX Device Co., Ltd. 86 * Licensed under the Apache License, Version 2.0 (the "License"); 87 * you may not use this file except in compliance with the License. 88 * You may obtain a copy of the License at 89 * 90 * http://www.apache.org/licenses/LICENSE-2.0 91 * 92 * Unless required by applicable law or agreed to in writing, software 93 * distributed under the License is distributed on an "AS IS" BASIS, 94 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 95 * See the License for the specific language governing permissions and 96 * limitations under the License. 97 */ 98 99 #include "calculator.h" 100 #include <gtest/gtest.h> 101 102 using namespace testing::ext; 103 104 class CalculatorSubTest : public testing::Test { 105 public: 106 static void SetUpTestCase(void); 107 static void TearDownTestCase(void); 108 void SetUp(); 109 void TearDown(); 110 }; 111 112 void CalculatorSubTest::SetUpTestCase(void) 113 { 114 // input testsuit setup step,setup invoked before all testcases 115 } 116 117 void CalculatorSubTest::TearDownTestCase(void) 118 { 119 // input testsuit teardown step,teardown invoked after all testcases 120 } 121 122 void CalculatorSubTest::SetUp(void) 123 { 124 // input testcase setup step,setup invoked before each testcases 125 } 126 127 void CalculatorSubTest::TearDown(void) 128 { 129 // input testcase teardown step,teardown invoked after each testcases 130 } 131 132 /** 133 * @tc.name: integer_sub_001 134 * @tc.desc: Verify the sub function. 135 * @tc.type: FUNC 136 * @tc.require: issueNumber 137 */ 138 HWTEST_F(CalculatorSubTest, integer_sub_001, TestSize.Level1) 139 { 140 // step 1:调用函数获取结果 141 int actual = Sub(4,0); 142 143 // Step 2:使用断言比较预期与实际结果 144 EXPECT_EQ(4, actual); 145 } 146 ``` 147 详细内容介绍: 148 1. 添加测试用例文件头注释信息 149 ``` 150 /* 151 * Copyright (c) 2021 XXXX Device Co., Ltd. 152 * Licensed under the Apache License, Version 2.0 (the "License"); 153 * you may not use this file except in compliance with the License. 154 * You may obtain a copy of the License at 155 * 156 * http://www.apache.org/licenses/LICENSE-2.0 157 * 158 * Unless required by applicable law or agreed to in writing, software 159 * distributed under the License is distributed on an "AS IS" BASIS, 160 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 161 * See the License for the specific language governing permissions and 162 * limitations under the License. 163 */ 164 ``` 165 2. 引用测试框架头文件和命名空间 166 ``` 167 #include <gtest/gtest.h> 168 169 using namespace testing::ext; 170 ``` 171 3. 添加被测试类的头文件 172 ``` 173 #include "calculator.h" 174 ``` 175 4. 定义测试套(测试类) 176 ``` 177 class CalculatorSubTest : public testing::Test { 178 public: 179 static void SetUpTestCase(void); 180 static void TearDownTestCase(void); 181 void SetUp(); 182 void TearDown(); 183 }; 184 185 void CalculatorSubTest::SetUpTestCase(void) 186 { 187 // input testsuit setup step,setup invoked before all testcases 188 } 189 190 void CalculatorSubTest::TearDownTestCase(void) 191 { 192 // input testsuit teardown step,teardown invoked after all testcases 193 } 194 195 void CalculatorSubTest::SetUp(void) 196 { 197 // input testcase setup step,setup invoked before each testcases 198 } 199 200 void CalculatorSubTest::TearDown(void) 201 { 202 // input testcase teardown step,teardown invoked after each testcases 203 } 204 ``` 205 > **注意:** 在定义测试套时,测试套名称应与编译目标保持一致,采用大驼峰风格。 206 207 5. 测试用例实现,包含用例注释和逻辑实现 208 ``` 209 /** 210 * @tc.name: integer_sub_001 211 * @tc.desc: Verify the sub function. 212 * @tc.type: FUNC 213 * @tc.require: issueNumber 214 */ 215 HWTEST_F(CalculatorSubTest, integer_sub_001, TestSize.Level1) 216 { 217 //step 1:调用函数获取结果 218 int actual = Sub(4,0); 219 220 //Step 2:使用断言比较预期与实际结果 221 EXPECT_EQ(4, actual); 222 } 223 ``` 224 > **注意:** @tc.require: 格式必须以AR/SR或issue开头: 如:issueI56WJ7 225 226多线程示例: 227 ``` 228 base_object_test.cpp 229 ``` 230 231- 多线程用例示例 232 ``` 233 // 测试用例文件头注释信息及用例注释同单线程用例示例。 234 235 #include "base_object.h" 236 #include <gtest/gtest.h> 237 #include <gtest/hwext/gtest-multithread.h> 238 #include <unistd.h> 239 240 using namespace testing::ext; 241 using namespace testing::mt; 242 243 namespace OHOS { 244 namespace AAFwk { 245 class AAFwkBaseObjectTest : public testing::Test {......} 246 247 // Step 1:待测函数,返回阶乘结果 248 int factorial(int n) 249 { 250 int result = 1; 251 for (int i = 1; i <= n; i++) { 252 result *= i; 253 } 254 printf("Factorial Function Result : %d! = %d\n", n, result); 255 return result; 256 } 257 258 // Step 2:使用断言比较预期与实际结果 259 void factorial_test() 260 { 261 int ret = factorial(3); // 调用函数获取结果 262 std::thread::id this_id = std::this_thread::get_id(); 263 std::ostringstream oss; 264 oss << this_id; 265 std::string this_id_str = oss.str(); 266 long int thread_id = atol(this_id_str.c_str()); 267 printf("running thread...: %ld\n", thread_id); // 输出当前线程的id 268 EXPECT_EQ(ret, 6); 269 } 270 271 HWTEST_F(AAFwkBaseObjectTest, Factorial_test_001, TestSize.Level1) 272 { 273 SET_THREAD_NUM(4); 274 printf("Factorial_test_001 BEGIN\n"); 275 GTEST_RUN_TASK(factorial_test); 276 printf("Factorial_test_001 END\n"); 277 } 278 279 HWMTEST_F(AAFwkBaseObjectTest, Factorial_test_002, TestSize.Level1, 6) 280 { 281 printf("Factorial_test_002 BEGIN\n"); 282 factorial_test(); 283 printf("Factorial_test_002 END\n"); 284 } 285 286 } // namespace AAFwk 287 } // namespace OHOS 288 289 ``` 290 详细内容介绍: 291 1. 添加测试用例文件头注释信息 292 293 > **注意:** 与单线程用例标准一致。 294 295 2. 引用测试框架头文件和命名空间 296 ``` 297 #include <gtest/gtest.h> 298 #include <gtest/hwext/gtest-multithread.h> 299 #include <unistd.h> 300 using namespace testing::ext; 301 using namespace testing::mt; 302 ``` 303 3. 添加被测试类的头文件 304 ``` 305 #include "base_object.h" 306 ``` 307 4. 定义测试套(测试类) 308 ``` 309 class AAFwkBaseObjectTest : public testing::Test {......} 310 311 ``` 312 > **注意:** 与单线程用例标准一致。 313 314 5. 测试用例实现,包含用例注释和逻辑实现 315 316 ``` 317 // Step 1:待测函数,返回阶乘结果 318 int factorial(int n) 319 { 320 int result = 1; 321 for (int i = 1; i <= n; i++) { 322 result *= i; 323 } 324 printf("Factorial Function Result : %d! = %d\n", n, result); 325 return result; 326 } 327 328 // Step 2:使用断言比较预期与实际结果 329 void factorial_test() 330 { 331 int ret = factorial(3); // 调用函数获取结果 332 std::thread::id this_id = std::this_thread::get_id(); 333 std::ostringstream oss; 334 oss << this_id; 335 std::string this_id_str = oss.str(); 336 long int thread_id = atol(this_id_str.c_str()); 337 printf("running thread...: %ld\n", thread_id); // 输出当前线程的id 338 EXPECT_EQ(ret, 6); 339 } 340 341 // GTEST_RUN_TASK(TestFunction)多线程启动函数,参数为自定义函数。 342 // 未调用SET_THREAD_NUM()时,默认线程数10个。 343 HWTEST_F(AAFwkBaseObjectTest, Factorial_test_001, TestSize.Level1) 344 { 345 SET_THREAD_NUM(4); // 设置线程数量,同一测试套中可动态设置线程数。 346 printf("Factorial_test_001 BEGIN\n"); 347 GTEST_RUN_TASK(factorial_test); // 启动factorial_test任务的多线程执行 348 printf("Factorial_test_001 END\n"); 349 } 350 351 // HWMTEST_F(TEST_SUITE, TEST_TC, TEST_LEVEL, THREAD_NUM) 352 // THREAD_NUM可设置用例执行的线程数量。 353 // HWMTEST_F会创建指定数量的线程并执行被测函数。 354 HWMTEST_F(AAFwkBaseObjectTest, Factorial_test_002, TestSize.Level1, 6) 355 { 356 printf("Factorial_test_002 BEGIN\n"); 357 factorial_test(); 358 printf("Factorial_test_002 END\n"); 359 } 360 // 新增多线程接口MTEST_ADD_TASK(THREAD_ID,ThreadTestFunc),注册多线程,但不在该用例中执行,之后统一执行,适合多个用例组合场景下的多线程测试。 361 // THREAD_ID从0开始定义区别不同的线程,也可以使用随机THREAD_ID,即传入RANDOM_THREAD_ID,此场景下THREAD_ID是不会重复的。 362 // 新增多线程接口MTEST_POST_RUN(),统一执行之前注册的多线程用例。 363 ``` 364 > **注意:** 用例注释与单线程用例标准一致。 365 366 在编写用例时,我们提供了四种用例模板供您选择。 367 368 | 类型 | 描述 | 369 | ------------| ------------| 370 | HWTEST(A,B,C)| 用例执行不依赖Setup&Teardown时,可选取| 371 | HWTEST_F(A,B,C)| 用例执行(不含参数)依赖于Setup&Teardown时,可选取| 372 | HWMTEST_F(A,B,C,D)| 多线程用例执行依赖于Setup&Teardown时,可选取| 373 | HWTEST_P(A,B,C)| 用例执行(含参数)依赖于Set&Teardown时,可选取| 374 375 其中,参数A,B,C,D的含义如下: 376 - 参数A为测试套名。 377 - 参数B为测试用例名,其命名必须遵循[功能点]_[编号]的格式,编号为3位数字,从001开始。 378 - 参数C为测试用例等级,具体分为门禁level0 以及非门禁level1-level4共五个等级,其中非门禁level1-level4等级的具体选取规则为:测试用例功能越重要,level等级越低。 379 - 参数D为多线程用例执行的线程数量设置。 380 381 **注意:** 382 - 测试用例的预期结果必须有对应的断言。 383 - 测试用例必须填写用例等级。 384 - 测试体建议按照模板分步实现。 385 - 用例描述信息按照标准格式@tc.xxx value书写,注释信息必须包含用例名称,用例描述,用例类型,需求编号四项。其中用例测试类型@tc.type参数的选取,可参考下表。 386 - 如使用HWMTEST_F编写多线程执行用例,必须填线程数量。 387 | 测试类型名称|类型编码| 388 | ------------|------------| 389 |功能测试 |FUNC| 390 |性能测试 |PERF| 391 |可靠性测试 |RELI| 392 |安全测试 |SECU| 393 |模糊测试 |FUZZ| 394 395 396**TDD测试(JS)** 397 398 399- 用例源文件命名规范 400 401 测试用例原文件名称采用大驼峰风格,以TEST结尾,具体格式为:[功能][子功能]TEST,子功能支持向下细分。 402示例: 403 ``` 404 AppInfoTest.js 405 ``` 406 407- 用例示例 408 ``` 409 /* 410 * Copyright (C) 2021 XXXX Device Co., Ltd. 411 * Licensed under the Apache License, Version 2.0 (the "License"); 412 * you may not use this file except in compliance with the License. 413 * You may obtain a copy of the License at 414 * 415 * http://www.apache.org/licenses/LICENSE-2.0 416 * 417 * Unless required by applicable law or agreed to in writing, software 418 * distributed under the License is distributed on an "AS IS" BASIS, 419 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 420 * See the License for the specific language governing permissions and 421 * limitations under the License. 422 */ 423 import app from '@system.app' 424 425 import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' 426 427 describe("AppInfoTest", function () { 428 beforeAll(function() { 429 // input testsuit setup step,setup invoked before all testcases 430 console.info('beforeAll caled') 431 }) 432 433 afterAll(function() { 434 // input testsuit teardown step,teardown invoked after all testcases 435 console.info('afterAll caled') 436 }) 437 438 beforeEach(function() { 439 // input testcase setup step,setup invoked before each testcases 440 console.info('beforeEach caled') 441 }) 442 443 afterEach(function() { 444 // input testcase teardown step,teardown invoked after each testcases 445 console.info('afterEach caled') 446 }) 447 448 /* 449 * @tc.name:appInfoTest001 450 * @tc.desc:verify app info is not null 451 * @tc.type: FUNC 452 * @tc.require: issueNumber 453 */ 454 it("appInfoTest001", 0, function () { 455 //step 1:调用函数获取结果 456 var info = app.getInfo() 457 458 //Step 2:使用断言比较预期与实际结果 459 expect(info != null).assertEqual(true) 460 }) 461 }) 462 ``` 463 详细内容介绍: 464 1. 添加测试用例文件头注释信息 465 ``` 466 /* 467 * Copyright (C) 2021 XXXX Device Co., Ltd. 468 * Licensed under the Apache License, Version 2.0 (the "License"); 469 * you may not use this file except in compliance with the License. 470 * You may obtain a copy of the License at 471 * 472 * http://www.apache.org/licenses/LICENSE-2.0 473 * 474 * Unless required by applicable law or agreed to in writing, software 475 * distributed under the License is distributed on an "AS IS" BASIS, 476 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 477 * See the License for the specific language governing permissions and 478 * limitations under the License. 479 */ 480 ``` 481 2. 导入被测api和jsunit测试库 482 ``` 483 import app from '@system.app' 484 485 import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' 486 ``` 487 3. 定义测试套(测试类) 488 ``` 489 describe("AppInfoTest", function () { 490 beforeAll(function() { 491 // input testsuit setup step,setup invoked before all testcases 492 console.info('beforeAll caled') 493 }) 494 495 afterAll(function() { 496 // input testsuit teardown step,teardown invoked after all testcases 497 console.info('afterAll caled') 498 }) 499 500 beforeEach(function() { 501 // input testcase setup step,setup invoked before each testcases 502 console.info('beforeEach caled') 503 }) 504 505 afterEach(function() { 506 // input testcase teardown step,teardown invoked after each testcases 507 console.info('afterEach caled') 508 }) 509 ``` 510 4. 测试用例实现 511 ``` 512 /* 513 * @tc.name:appInfoTest001 514 * @tc.desc:verify app info is not null 515 * @tc.type: FUNC 516 * @tc.require: issueNumber 517 */ 518 it("appInfoTest001", 0, function () { 519 //step 1:调用函数获取结果 520 var info = app.getInfo() 521 522 //Step 2:使用断言比较预期与实际结果 523 expect(info != null).assertEqual(true) 524 }) 525 ``` 526 > **注意:** @tc.require: 格式必须以AR/SR或issue开头: 如:issueI56WJ7 527 528**Fuzz测试** 529 530[Fuzz用例编写规范](https://gitee.com/openharmony/testfwk_developer_test/blob/master/libs/fuzzlib/README_zh.md) 531 532 533**Benchmark测试** 534 535[Benchmark用例编写规范](https://gitee.com/openharmony/testfwk_developer_test/blob/master/libs/benchmark/README_zh.md) 536 537 538#### 测试用例编译文件编写 539根据测试用例目录规划,当执行某一用例时,测试框架会根据编译文件逐层查找,最终找到所需用例进行编译。下面通过不同示例来讲解gn文件如何编写。 540 541**TDD测试** 542 543针对不同语言,下面提供不同的编译模板以供参考。 544 545- **C++用例编译配置示例** 546 547 ``` 548 # Copyright (c) 2021 XXXX Device Co., Ltd. 549 550 import("//build/test.gni") 551 552 module_output_path = "developer_test/calculator" 553 554 config("module_private_config") { 555 visibility = [ ":*" ] 556 557 include_dirs = [ "../../../include" ] 558 } 559 560 ohos_unittest("CalculatorSubTest") { 561 module_out_path = module_output_path 562 563 sources = [ 564 "../../../include/calculator.h", 565 "../../../src/calculator.cpp", 566 ] 567 568 sources += [ "calculator_sub_test.cpp" ] 569 570 configs = [ ":module_private_config" ] 571 572 deps = [ "//third_party/googletest:gtest_main" ] 573 } 574 575 group("unittest") { 576 testonly = true 577 deps = [":CalculatorSubTest"] 578 } 579 ``` 580 详细内容如下: 581 582 1. 添加文件头注释信息 583 ``` 584 # Copyright (c) 2021 XXXX Device Co., Ltd. 585 ``` 586 2. 导入编译模板文件 587 ``` 588 import("//build/test.gni") 589 ``` 590 3. 指定文件输出路径 591 ``` 592 module_output_path = "developer_test/calculator" 593 ``` 594 > **说明:** 此处输出路径为部件/模块名。 595 596 4. 配置依赖包含目录 597 598 ``` 599 config("module_private_config") { 600 visibility = [ ":*" ] 601 602 include_dirs = [ "../../../include" ] 603 } 604 ``` 605 > **说明:** 一般在此处对相关配置进行设置,在测试用例编译脚本中可直接引用。 606 607 5. 指定测试用例编译目标输出的文件名称 608 609 ``` 610 ohos_unittest("CalculatorSubTest") { 611 } 612 ``` 613 6. 编写具体的测试用例编译脚本(添加需要参与编译的源文件、配置和依赖) 614 ``` 615 ohos_unittest("CalculatorSubTest") { 616 module_out_path = module_output_path 617 sources = [ 618 "../../../include/calculator.h", 619 "../../../src/calculator.cpp", 620 "../../../test/calculator_sub_test.cpp" 621 ] 622 sources += [ "calculator_sub_test.cpp" ] 623 configs = [ ":module_private_config" ] 624 deps = [ "//third_party/googletest:gtest_main" ] 625 } 626 ``` 627 628 > **说明:根据测试类型的不同,在具体编写过程中可选择不同的测试类型:** 629 > - ohos_unittest:单元测试 630 > - ohos_js_unittest: FA模型js用例单元测试 631 > - ohos_js_stage_unittest: stage模型ets用例单元测试 632 > - ohos_moduletest:模块测试 633 > - ohos_systemtest:系统测试 634 > - ohos_performancetest:性能测试 635 > - ohos_securitytest:安全测试 636 > - ohos_reliabilitytest:可靠性测试 637 > - ohos_distributedtest:分布式测试 638 639 7. 对目标测试用例文件进行条件分组 640 641 ``` 642 group("unittest") { 643 testonly = true 644 deps = [":CalculatorSubTest"] 645 } 646 ``` 647 > **说明:** 进行条件分组的目的在于执行用例时可以选择性的执行某一种特定类型的用例。 648 649- ** FA模型JavaScript用例编译配置示例** 650 651 ``` 652 # Copyright (C) 2021 XXXX Device Co., Ltd. 653 654 import("//build/test.gni") 655 656 module_output_path = "developer_test/app_info" 657 658 ohos_js_unittest("GetAppInfoJsTest") { 659 module_out_path = module_output_path 660 661 hap_profile = "./config.json" 662 certificate_profile = "//test/developer_test/signature/openharmony_sx.p7b" 663 } 664 665 group("unittest") { 666 testonly = true 667 deps = [ ":GetAppInfoJsTest" ] 668 } 669 ``` 670 671 详细内容如下: 672 673 1. 添加文件头注释信息 674 675 ``` 676 # Copyright (C) 2021 XXXX Device Co., Ltd. 677 ``` 678 2. 导入编译模板文件 679 680 ``` 681 import("//build/test.gni") 682 ``` 683 3. 指定文件输出路径 684 685 ``` 686 module_output_path = "developer_test/app_info" 687 ``` 688 > **说明:** 此处输出路径为部件/模块名。 689 690 4. 指定测试用例编译目标输出的文件名称 691 692 ``` 693 ohos_js_unittest("GetAppInfoJsTest") { 694 } 695 ``` 696 > **说明:** 697 >- 使用模板ohos_js_unittest定义js测试套,注意与C++用例区分。 698 >- js测试套编译输出文件为hap类型,hap名为此处定义的测试套名,测试套名称必须以JsTest结尾。 699 700 5. 指定hap包配置文件config.json和签名文件,两个配置为必选项 701 702 ``` 703 ohos_js_unittest("GetAppInfoJsTest") { 704 module_out_path = module_output_path 705 706 hap_profile = "./config.json" 707 certificate_profile = "//test/developer_test/signature/openharmony_sx.p7b" 708 } 709 ``` 710 config.json为hap编译所需配置文件,需要开发者根据被测sdk版本配置“target”项,其余项可默认,具体如下所示: 711 712 ``` 713 { 714 "app": { 715 "bundleName": "com.example.myapplication", 716 "vendor": "example", 717 "version": { 718 "code": 1, 719 "name": "1.0" 720 }, 721 "apiVersion": { 722 "compatible": 4, 723 "target": 5 // 根据被测sdk版本进行修改,此例为sdk5 724 } 725 }, 726 "deviceConfig": {}, 727 "module": { 728 "package": "com.example.myapplication", 729 "name": ".MyApplication", 730 "deviceType": [ 731 "phone" 732 ], 733 "distro": { 734 "deliveryWithInstall": true, 735 "moduleName": "entry", 736 "moduleType": "entry" 737 }, 738 "abilities": [ 739 { 740 "skills": [ 741 { 742 "entities": [ 743 "entity.system.home" 744 ], 745 "actions": [ 746 "action.system.home" 747 ] 748 } 749 ], 750 "name": "com.example.myapplication.MainAbility", 751 "icon": "$media:icon", 752 "description": "$string:mainability_description", 753 "label": "MyApplication", 754 "type": "page", 755 "launchType": "standard" 756 } 757 ], 758 "js": [ 759 { 760 "pages": [ 761 "pages/index/index" 762 ], 763 "name": "default", 764 "window": { 765 "designWidth": 720, 766 "autoDesignWidth": false 767 } 768 } 769 ] 770 } 771 } 772 ``` 773 6. 对目标测试用例文件进行条件分组 774 ``` 775 group("unittest") { 776 testonly = true 777 deps = [ ":GetAppInfoJsTest" ] 778 } 779 ``` 780 > **说明:** 进行条件分组的目的在于执行用例时可以选择性的执行某一种特定类型的用例。 781 782- ** stage模型ets用例编译配置示例** 783 784 ``` 785 # Copyright (C) 2022 XXXX Device Co., Ltd. 786 787 import("//build/test.gni") 788 789 want_output_path = "developer_test/stage_test" 790 791 ohos_js_stage_unittest("ActsBundleMgrStageEtsTest") { 792 hap_profile = "entry/src/main/module.json" 793 deps = [ 794 ":actbmsstageetstest_js_assets", 795 ":actbmsstageetstest_resources", 796 ] 797 ets2abc = true 798 certificate_profile = "signature/openharmony_sx.p7b" 799 hap_name = "ActsBundleMgrStageEtsTest" 800 subsystem_name = "developer_test" 801 part_name = "stage_test" // 部件名称 802 module_out_path = want_output_path // 必须定义输出路径 803 } 804 ohos_app_scope("actbmsstageetstest_app_profile") { 805 app_profile = "AppScope/app.json" 806 sources = [ "AppScope/resources" ] 807 } 808 ohos_js_assets("actbmsstageetstest_js_assets") { 809 source_dir = "entry/src/main/ets" 810 } 811 ohos_resources("actbmsstageetstest_resources") { 812 sources = [ "entry/src/main/resources" ] 813 deps = [ ":actbmsstageetstest_app_profile" ] 814 hap_profile = "entry/src/main/module.json" 815 } 816 group("unittest") { 817 testonly = true 818 deps = [] 819 deps += [ ":ActsBundleMgrStageEtsTest" ] 820 } 821 ``` 822 > **说明:** 进行条件分组的目的在于执行用例时可以选择性的执行某一种特定类型的用例。 823 824**编译入口配置文件bundle.json** 825 826当完成用例编译配置文件编写后,需要进一步编写部件编译配置文件,以关联到具体的测试用例。 827``` 828"build": { 829 "sub_component": [ 830 "//test/testfwk/developer_test/examples/app_info:app_info", 831 "//test/testfwk/developer_test/examples/detector:detector", 832 "//test/testfwk/developer_test/examples/calculator:calculator" 833 ], 834 "inner_list": [ 835 { 836 "header": { 837 "header_base": "////test/testfwk/developer_test/examples/detector/include", 838 "header_files": [ 839 "detector.h" 840 ] 841 }, 842 "name": "//test/testfwk/developer_test/examples/detector:detector" 843 } 844 ], 845 "test": [ //配置模块calculator下的test 846 "//test/testfwk/developer_test/examples/app_info/test:unittest", 847 "//test/testfwk/developer_test/examples/calculator/test:unittest", 848 "//test/testfwk/developer_test/examples/calculator/test:fuzztest" 849 } 850``` 851> **说明:** test_list中配置的是对应模块的测试用例。 852 853#### 测试用例资源配置 854测试依赖资源主要包括测试用例在执行过程中需要的图片文件,视频文件、第三方库等对外的文件资源,目前只支持静态资源的配置。 855 856依赖资源文件配置步骤如下: 8571. 在部件的test目录下创建resource目录,在resource目录下创建对应的模块,在模块目录中存放该模块所需要的资源文件 858 8592. 在resource目录下对应的模块目录中创建一个ohos_test.xml文件,文件内容格式如下: 860 ``` 861 <?xml version="1.0" encoding="UTF-8"?> 862 <configuration ver="2.0"> 863 <target name="CalculatorSubTest"> 864 <preparer> 865 <option name="push" value="test.jpg -> /data/test/resource" src="res"/> 866 <option name="push" value="libc++.z.so -> /data/test/resource" src="out"/> 867 </preparer> 868 </target> 869 </configuration> 870 ``` 871 >**说明:**若某些push上去的二进制文件需要增量生成数据字典,则新增一行: 872 ``` 873 <option name="shell" value="hilog -d /设备中的二进制文件路径"/> 874 // 例如 875 <option name="shell" value="hilog -d /data/test/resource/test.z.so"/> 876 ``` 8773. 在测试用例的编译配置文件中定义resource_config_file进行指引,用来指定对应的资源文件ohos_test.xml 878 ``` 879 ohos_unittest("CalculatorSubTest") { 880 resource_config_file = "//system/subsystem/partA/test/resource/calculator/ohos_test.xml" 881 } 882 ``` 883 >**说明:** 884 >- target_name: 测试套的名称,定义在测试目录的BUILD.gn中。preparer: 表示该测试套执行前执行的动作。 885 >- src="res": 表示测试资源位于test目录下的resource目录下,src="out":表示位于out/release/$(部件)目录下。 886 887### 测试用例执行 888在执行测试用例之前,针对用例使用设备的不同,需要对相应配置进行修改,修改完成即可执行测试用例。 889 890#### user_config.xml配置 891``` 892<user_config> 893 <build> 894 <!-- 是否编译demo用例, 默认为false,如果需要编译demo可修改为true --> 895 <example>false</example> 896 <!-- 是否编译版本, 默认为false --> 897 <version>false</version> 898 <!-- 是否编译测试用例, 默认为true,若已完成编译,再执行用例之前可修改为false,防止重新编译 --> 899 <testcase>true</testcase> 900 <!-- 在编译测试用例的情况下,选择编译target_cpu是64位的还是32位的,默认为空(32bit)可以选择: arm64 --> 901 <parameter> 902 <target_cpu></target_cpu> 903 </parameter> 904 </build> 905 <environment> 906 <!-- 配置远程映射机器的IP及端口,以支持HDC连接的设备 --> 907 <device type="usb-hdc"> 908 <ip></ip> 909 <port></port> 910 <sn></sn> 911 </device> 912 <!-- 配置设备的串口信息,以支持串口连接的设备 --> 913 <device type="com" label="ipcamera"> 914 <serial> 915 <com></com> 916 <type>cmd</type> 917 <baud_rate>115200</baud_rate> 918 <data_bits>8</data_bits> 919 <stop_bits>1</stop_bits> 920 <timeout>1</timeout> 921 </serial> 922 </device> 923 </environment> 924 <!-- 配置测试用例路径,若测试用例未编译,即<testcase>标签属性为true时,此处默认不填写;若编译已完成,需在此处指定测试用例的实际路径 --> 925 <test_cases> 926 <dir></dir> 927 </test_cases> 928 <!-- 配置覆盖率编译路径 --> 929 <coverage> 930 <outpath></outpath> 931 </coverage> 932 <!-- NFS挂载信息配置,被测设备仅支持串口连接时配置,指定NFS的映射路径,host_dir为PC侧的NFS目录,board_dir为板侧创建的目录 --> 933 <NFS> 934 <host_dir></host_dir> 935 <mnt_cmd></mnt_cmd> 936 <board_dir></board_dir> 937 </NFS> 938</user_config> 939 940``` 941 942>**说明:** 在执行测试用例之前,若使用HDC连接设备,用例仅需配置设备IP和端口号即可,其余信息均默认不修改。 943 944#### Windows环境执行 945##### 测试用例编译 946 947由于Windows环境下无法实现用例编译,因此执行用例前需要在Linux环境下进行用例编译,用例编译命令: 948``` 949./build.sh --product-name {product_name} --build-target make_test 950``` 951>说明: 952> - product-name:指定编译产品名称。 953> - build-target:指定所需编译用例,make_test表示指定全部用例,实际开发中可指定特定用例。 954 955编译完成后,测试用例将自动保存在out/ohos-arm-release/packages/phone/tests目录下。 956 957##### 搭建执行环境 9581. 在Windows环境创建测试框架目录Test,并在此目录下创建testcase目录 959 9602. 从Linux环境拷贝测试框架developer_test和xdevice到创建的Test目录下,拷贝编译好的测试用例到testcase目录下 961 962 >**说明:** 将测试框架及测试用例从Linux环境移植到Windows环境,以便后续执行。 963 9643. 修改user_config.xml 965 ``` 966 <build> 967 <!-- 由于测试用例已编译完成,此标签属性需改为false --> 968 <testcase>false</testcase> 969 </build> 970 <test_cases> 971 <!-- 由于已将测试用例拷贝到Windows环境下,测试用例输出路径发生改变,需要修改为拷贝后所存放的路径 --> 972 <dir>D:\Test\testcase\tests</dir> 973 </test_cases> 974 ``` 975 >**说明:** `<testcase>`标签表示是否需要编译用例;`<dir>`标签表示测试用例查找路径。 976 977##### 执行用例 9781. 启动测试框架 979 ``` 980 start.bat 981 ``` 9822. 选择产品形态 983 984 进入测试框架,系统会自动提示您选择产品形态,请根据实际的开发板进行选择。 985 986 如需手动添加,请在config/framework_config.xml的\<productform\>标签内增加产品项。 987 9883. 执行测试用例 989 990 当选择完产品形态,可参考如下指令执行TDD测试用例。 991 ``` 992 run -t UT 993 run -t UT -tp PartName 994 run -t UT -tp PartName -tm TestModuleName 995 run -t UT -tp ability_base -ts base_object_test 996 run -t UT -tp PartName -tm TestModuleName -ts CalculatorSubTest 997 run -t UT -ts base_object_test 998 run -t UT -ts base_object_test -tc AAFwkBaseObjectTest.BaseObject_test_001 999 run -t UT -ts CalculatorSubTest -tc CalculatorSubTest.interger_sub_00l 1000 run -t UT -cov coverage 1001 run -t UT -ra random 1002 run -t UT -tp PartName -pd partdeps 1003 run -t UT -ts base_object_test --repeat 5 1004 run -hl 1005 run -rh 3 1006 run --retry 1007 ``` 1008 1009 1010 执行命令参数说明: 1011 ``` 1012 -t [TESTTYPE]: 指定测试用例类型,有UT,MST,ST,PERF,FUZZ,BENCHMARK,另外还有ACTS,HATS等。(必选参数) 1013 -tp [TESTPART]: 指定部件,可独立使用。 1014 -tm [TESTMODULE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 1015 -ts [TESTSUITE]: 指定测试套,可独立使用。 1016 -tc [TESTCASE]: 指定测试用例,同时需要注明测试套内class名称,不可独立使用,需结合-ts指定上级测试套使用。 1017 -cov [COVERAGE]: 覆盖率执行参数。 1018 -h : 帮助命令 1019 -ra [random]: c++用例乱序执行参数 1020 -pd [partdeps]: 二级依赖部件执行参数 1021 --repeat : 支持设置用例执行次数。 1022 -hl [HISTORYLIST]: 显示最近10条测试用例,超过10条,只显示最近10条。 1023 -rh [RUNHISTORY]: 执行历史记录的第几条记录运行 1024 --retry:检查上次运行结果,如果有失败用例则重复测试 1025 ``` 1026 1027 1028#### Linux环境执行 1029##### 远程端口映射 1030为了在Linux远程服务器以及Linux虚拟机两种环境下执行测试用例,需要对端口进行远程映射,以实现与设备的数据通路连接。具体操作如下: 10311. HDC Server指令: 1032 ``` 1033 hdc kill 1034 hdc -m -s 0.0.0.0:8710 1035 ``` 1036 >**说明:** IP和端口号为默认值。 1037 10382. HDC Client指令: 1039 ``` 1040 hdc -s xx.xx.xx.xx:8710 list targets 1041 ``` 1042 >**说明:** 此处IP填写设备侧IP地址。 1043 1044##### 执行用例 10451. 启动测试框架 1046 ``` 1047 ./start.sh 1048 ``` 10492. 选择产品形态 1050 1051 进入测试框架,系统会自动提示您选择产品形态,请根据实际的开发板进行选择。 1052 1053 若需要自测试框架编译测试用例,且没有找到需要的产品形态需手动添加,请在config/framework_config.xml的\<productform\>标签内增加产品项。 1054 1055 ``` 1056 <framework_config> 1057 <productform> 1058 <option name="ipcamera_hispark_aries" /> 1059 <option name="ipcamera_hispark_taurus" /> 1060 <option name="wifiiot_hispark_pegasus" /> 1061 <option name="" /> 1062 </productform> 1063 </framework_config> 1064 1065 ``` 1066 10673. 执行测试用例 1068 1069 1)TDD命令 1070 1071 测试框架在执行用例时会根据指令找到所需用例,自动实现用例编译,执行过程,完成自动化测试。 1072 ``` 1073 run -t UT 1074 run -t UT -tp PartName 1075 run -t UT -tp PartName -tm TestModuleName 1076 run -t UT -tp ability_base -ts base_object_test 1077 run -t UT -tp PartName -tm TestModuleName -ts CalculatorSubTest 1078 run -t UT -ts base_object_test 1079 run -t UT -ts base_object_test -tc AAFwkBaseObjectTest.BaseObject_test_001 1080 run -t UT -ts CalculatorSubTest -tc CalculatorSubTest.interger_sub_00l 1081 run -t -cov coverage 1082 run -t UT -ra random 1083 run -t UT -tp PartName -pd partdeps 1084 run -t UT -ts base_object_test --repeat 5 1085 run -hl 1086 run -rh 3 1087 run --retry 1088 ``` 1089 执行命令参数说明: 1090 ``` 1091 -t [TESTTYPE]: 指定测试用例类型,有UT,MST,ST,PERF,FUZZ,BENCHMARK等。(必选参数) 1092 -tp [TESTPART]: 指定部件,可独立使用。 1093 -tm [TESTMODULE]: 指定模块,不可独立使用,需结合-tp指定上级部件使用。 1094 -ts [TESTSUITE]: 指定测试套,可独立使用。 1095 -tc [TESTCASE]: 指定测试用例,同时需要注明测试套内class名称,不可独立使用,需结合-ts指定上级测试套使用。 1096 -cov [COVERAGE]: 覆盖率执行参数。 1097 -h : 帮助命令 1098 -ra [random]: c++用例乱序执行参数 1099 -pd [partdeps]: 二级依赖部件执行参数 1100 --repeat : 支持设置用例执行次数。 1101 -hl [HISTORYLIST]: 显示最近10条测试用例,超过10条,只显示最近10条。 1102 -rh [RUNHISTORY]: 执行历史记录的第几条记录运行 1103 --retry:检查上次运行结果,如果有失败用例则重复测试 1104 ``` 1105 1106 在linux下可以使用help命令查看有哪些产品形态、测试类型、支持的子系统、部件 1107 ``` 1108 查看帮助命令:help 1109 查看show命令:help show 1110 查看支持的设备形态: show productlist 1111 查看支持的测试类型: show typelist 1112 查看支持的测试子系统: show subsystemlist 1113 查看支持的测试部件: show partlist 1114 ``` 1115 2)ACTS/HATS命令 1116 1117 当选择完产品形态,可以参考如下执行ACTS或HATS测试用例 1118 ``` 1119 run -t ACTS 1120 run -t HATS 1121 run -t ACTS -ss arkui 1122 run -t ACTS -ss arkui, modulemanager 1123 run -t ACTS -ss arkui -ts ActsAceEtsTest 1124 run -t HATS -ss telephony -ts HatsHdfV1RilServiceTest 1125 run -t ACTS -ss arkui -tp ActsPartName 1126 run -t ACTS -ss arkui -ts ActsAceEtsTest,ActsAceEtsResultTest 1127 run -t HATS -ss powermgr -ts HatsPowermgrBatteryTest,HatsPowermgrThermalTest 1128 run -t ACTS -ss arkui -ts ActsAceEtsTest -ta class:alphabetIndexerTest#alphabetIndexerTest001 1129 run -t ACTS -ss arkui -ts ActsAceEtsTest -ta class:alphabetIndexerTest#alphabetIndexerTest001 --repeat 2 1130 run -hl 1131 run -rh 1 1132 run --retry 1133 ``` 1134 执行命令参数说明,ACTS和HATS命令参数一致,与TDD有所不同: 1135 ``` 1136 -t [TESTTYPE]: 指定测试用例类型,有ACTS,HATS等。(必选参数) 1137 -ss [SUBSYSTEM]: 指定子系统,可单独使用,且可以执行多个子系统,用逗号隔开。 1138 -tp [TESTPART]: 指定部件,可独立使用。 1139 -ts [TESTSUITE]: 指定测试套,可独立使用,且可以执行多个测试套,用逗号隔开。 1140 -ta [TESTARGS]: 指定测试类测试方法,需结合-ts指定上级测试套使用。 1141 --repeat : 支持设置用例执行次数。 1142 -hl [HISTORYLIST]: 显示最近10条测试用例,超过10条,只显示最近10条。 1143 -rh [RUNHISTORY]: 执行历史记录的第几条记录运行 1144 --retry:检查上次运行结果,如果有失败用例则重复测试 1145 ``` 1146 1147### 测试报告日志 1148当执行完测试指令,控制台会自动生成测试结果,若需要详细测试报告您可在相应的数据文档中进行查找。 1149 1150#### 测试结果 1151测试结果输出根路径如下: 1152``` 1153test/developer_test/reports/xxxx_xx_xx_xx_xx_xx 1154``` 1155>**说明:** 测试报告文件目录将自动生成。 1156 1157该目录中包含以下几类结果: 1158| 类型 | 描述| 1159| ------------ | ------------ | 1160| result/ |测试用例格式化结果| 1161| log/plan_log_xxxx_xx_xx_xx_xx_xx.log | 测试用例日志 | 1162| summary_report.html | 测试报告汇总 | 1163| details_report.html | 测试报告详情 | 1164 1165#### 测试框架日志 1166``` 1167reports/platform_log_xxxx_xx_xx_xx_xx_xx.log 1168``` 1169 1170### 覆盖率用户指导 11711. (可选执行)为了屏蔽非核心代码产生的冗余分支数据,可以在源码编译之前进入/test/testfwk/developer_test/localCoverage/restore_comment目录下执行: 1172 1173 python3 build_before_generate.py 1174 1175 选择对应的部件,执行命令例如: 1176 1177 run -tp partname 1178 run -tp partname1 partname2 11792. 编译版本之前首先修改编译选项,涉及到自己子系统的build.gn文件cflags或者cflags_cc及ldflags选项都需要加--coverage字段: 1180 1181 ldflags = [ "--coverage" ] 1182 C: cflags = [ "--coverage" ] 1183 C++: cflags_cc = [ "--coverage" ] 1184 1185**推荐:** 也可以参考窗口子系统的方式(推荐这种方式),参考链接:https://gitee.com/openharmony/window_window_manager/pulls/1274/files 11863. 执行覆盖率需要安装以下依赖包: 1187 1188 1)安装lcov, 安装命令:sudo apt install lcov 1189 2)安装dos2unix, 安装命令:apt install dos2unix. 1190 3)安装lxml, 安装命令: pip install lxml 1191 4)安装selectolax, 安装命令: pip install selectolax 1192 5)安装CppHeaderParser, 安装命令 pip install CppHeaderParser 1193 11944. 远程映射设备,修改usr_config.xml中的ip号,设备映射方式查看上面介绍的远程端口映射, 1195 1196``` 1197 <!-- 配置远程映射机器的IP(设备挂载的pc的ip) --> 1198 <device type="usb-hdc"> 1199 <ip></ip> 1200 <port></port> 1201 <sn></sn> 1202 </device> 1203``` 12045. 执行 1205 1206 ./start.sh 1207 1208 命令例如下: 1209 run -t UT -tp 部件名 -cov coverage 1210 run -t UT -ss 子系统名 -cov coverage 1211 run -t UT -ss 子系统名 -tp 部件名 -cov coverage 1212 run -t UT MST ST -tp 部件名 -cov coverage 1213 1214> **注意:** 必须添加 -cov coverage 参数 1215 12166. 覆盖率报告路径 1217 1218 代码覆盖率报告:/test/testfwk/developer_test/localCoverage/codeCoverage/results/coverage/reports/cxx/html 1219 1220 接口覆盖率报告:/test/testfwk/developer_test/localCoverage/interfaceCoverage/results/coverage/interface_kits/html 1221### 涉及仓 1222 1223[test\_xdevice](https://gitee.com/openharmony/testfwk_xdevice) 1224 1225## 发布版本说明 1226 1227| 发布版本号 | 发布功能说明 | 1228| ---------- | ------------------------------------------------------------ | 1229| 3.2.1.0 | 1、增加框架对接执行ACTS测试用例能力<br />2、增加ACTS多种颗粒度执行能力,如子系统、部件等 | 1230| 3.2.2.0 | 1、增加测试任务统计能力,最多统计10个任务<br />2、增加按照指定测试任务ID执行测试任务能力<br />3、增加复测上次任务失败用例能力 | 1231| 3.2.3.0 | 1、增加覆盖率执行<br /> | 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250