鸿蒙5.0开辟【自动化测试框架使用指导(基于ArkTS和Shell下令)】测试框架 [复制链接]
发表于 2025-9-23 04:54:51 | 显示全部楼层 |阅读模式
概述

自动化测试框架arkxtest,作为工具集的紧张构成部门,支持JS/TS语言的单位测试框架(JsUnit)及UI测试框架(UiTest)。
JsUnit提供单位测试用例执行本事,提供用例编写基础接口,天生对应陈诉,用于测试体系或应用接口。
UiTest通过轻便易用的API提供查找和操作界面控件本事,支持用户开辟基于界面操作的自动化测试脚本。
本指南先容了测试框架的紧张功能、实现原理、环境准备,以及测试脚本编写和执行方法。同时,以shell下令方式,对外提供了获取截屏、控件树、录制用户操作、便捷注入UI模仿操作等本事,助力开辟者更机动方便测试和验证。
实现原理

测试框架分为单位测试框架和UI测试框架。
单位测试框架是测试框架的基础底座,提供了最根本的用例识别、调度、执行及结果汇总的本事。
UI测试框架紧张对外提供了UiTest API供开辟职员在对应测试场景调用,而其脚本的运行基础还是单位测试框架。
单位测试框架

图1.单位测试框架紧张功能

图2.脚本基础流程运行图

UI测试框架

图3.UI测试框架紧张功能

基于ArkTS编写和执行测试

搭建环境

DevEco Studio可参考其官网先容举行[下载],并举行干系的设置动作。
新建和编写测试脚本

新建测试脚本
在DevEco Studio中新建应用开辟工程,此中ohosTest和test目次均为测试脚本所在的目次,API10及以上版本支持创建Instrument Test和Local Test。

  • Instrument Test:测试用例存放在ohosTest测试目次下,须要运行在设备或模仿器上,支持单位测试和UI测试。
  • Local Test:测试用例存放在test测试目次下,不须要运行在设备或模仿器上,支持单位测试。
  • Instrument Test和Local Test创建的具体操作。
编写单位测试脚本
本章节紧张形貌单位测试框架支持本事,以及本事的使用方法。
在单位测试框架,测试脚本须要包罗如下根本元素:
1、依靠导包,以便使用依靠的测试接口。
2、测试代码编写,紧张编写测试代码的干系逻辑,如接口调用等。
3、断言接口调用,设置测试代码中的查抄点,如无查抄点,则不可以为一个完备的测试脚本。
如下示例代码实现的场景是:启动测试页面,查抄设备当前体现的页面是否为预期页面。
  1. import { describe, it, expect } from '@ohos/hypium';
  2. import { abilityDelegatorRegistry } from '@kit.TestKit';
  3. import { UIAbility, Want } from '@kit.AbilityKit';
  4. const delegator = abilityDelegatorRegistry.getAbilityDelegator()
  5. const bundleName = abilityDelegatorRegistry.getArguments().bundleName;
  6. function sleep(time: number) {
  7.   return new Promise<void>((resolve: Function) => setTimeout(resolve, time));
  8. }
  9. export default function abilityTest() {
  10.   describe('ActsAbilityTest', () =>{
  11.     it('testUiExample',0, async (done: Function) => {
  12.       console.info("uitest: TestUiExample begin");
  13.       //start tested ability
  14.       const want: Want = {
  15.         bundleName: bundleName,
  16.         abilityName: 'EntryAbility'
  17.       }
  18.       await delegator.startAbility(want);
  19.       await sleep(1000);
  20.       //check top display ability
  21.       const ability: UIAbility = await delegator.getCurrentTopAbility();
  22.       console.info("get top ability");
  23.       expect(ability.context.abilityInfo.name).assertEqual('EntryAbility');
  24.       done();
  25.     })
  26.   })
  27. }
复制代码
编写UI测试脚本
本章节紧张先容UI测试框架支持本事,以及对应本事API的使用方法。
UI测试基于单位测试,UI测试脚本在单位测试脚本上增长了对UiTest接口。
如下的示例代码是在上面的单位测试脚本基础上增量编写,实现的场景是:在启动的应用页面上举行点击操作,然后检测当前页面厘革是否为预期厘革。
1.编写Index.ets页面代码, 作为被测示例demo。
  1. @Entry
  2. @Component
  3. struct Index {
  4.    @State message: string = 'Hello World'
  5.    build() {
  6.      Row() {
  7.        Column() {
  8.          Text(this.message)
  9.            .fontSize(50)
  10.            .fontWeight(FontWeight.Bold)
  11.          Text("Next")
  12.            .fontSize(50)
  13.            .margin({top:20})
  14.            .fontWeight(FontWeight.Bold)
  15.          Text("after click")
  16.            .fontSize(50)
  17.            .margin({top:20})
  18.            .fontWeight(FontWeight.Bold)
  19.        }
  20.        .width('100%')
  21.      }
  22.      .height('100%')
  23.    }
  24. }
复制代码
2.在ohosTest > ets > test文件夹下.test.ets文件中编写具体测试代码。
  1. import { describe, it, expect } from '@ohos/hypium';
  2. // 导入测试依赖kit
  3. import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit';
  4. import { UIAbility, Want } from '@kit.AbilityKit';
  5. const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
  6. const bundleName = abilityDelegatorRegistry.getArguments().bundleName;
  7. function sleep(time: number) {
  8.    return new Promise<void>((resolve: Function) => setTimeout(resolve, time));
  9. }
  10. export default function abilityTest() {
  11.    describe('ActsAbilityTest', () => {
  12.       it('testUiExample',0, async (done: Function) => {
  13.          console.info("uitest: TestUiExample begin");
  14.          //start tested ability
  15.          const want: Want = {
  16.             bundleName: bundleName,
  17.             abilityName: 'EntryAbility'
  18.          }
  19.          await delegator.startAbility(want);
  20.          await sleep(1000);
  21.          //check top display ability
  22.          const ability = await delegator.getCurrentTopAbility();
  23.          console.info("get top ability");
  24.          expect(ability.context.abilityInfo.name).assertEqual('EntryAbility');
  25.          //ui test code
  26.          //init driver
  27.          const driver = Driver.create();
  28.          await driver.delayMs(1000);
  29.          //find button on text 'Next'
  30.          const button = await driver.findComponent(ON.text('Next'));
  31.          //click button
  32.          await button.click();
  33.          await driver.delayMs(1000);
  34.          //check text
  35.          await driver.assertComponentExist(ON.text('after click'));
  36.          await driver.pressBack();
  37.          done();
  38.       })
  39.    })
  40. }
复制代码
执行测试脚本

在DevEco Studio执行
脚本执行须要毗连硬件设备。通过点击按钮执行,当前支持以下执行方式:
1、测试包级别执行,即执行测试包内的全部用例。
2、测试套级别执行,即执行describe方法中定义的全部测试用例。
3、测试方法级别执行,即执行指定it方法也就是单条测试用例。

查看测试结果
测试执行完毕后可直接在DevEco Studio中查看测试结果,如下图示例所示:

查看测试用例覆盖率
执行完测试用例后可以查看测试用例覆盖率
在CMD执行
脚本执行须要毗连硬件设备,将应用测试包安装到测试设备上,在cmd窗口中执行aa下令,完成对用例测试。
说明
使用cmd的方式,须要设置好hdc干系的环境变量。
aa test下令执行设置参数
执行参数全写执行参数缩写执行参数寄义执行参数示例–bundleName-b应用Bundle名称- b com.test.example–packageName-p应用模块名,实用于FA模子应用- p com.test.example.entry–moduleName-m应用模块名,实用于STAGE模子应用-m entryNA-s特定参数,以<key, value>键值对方式传入- s unittest /ets/testrunner/OpenHarmonyTestRunner框架当前支持多种用例执行方式,通过上表中的-s参数后的设置键值对参数传入触发,如下表所示。
设置参数名设置参数寄义设置参数取值设置参数示例unittest用例执行所使用OpenHarmonyTestRunner对象OpenHarmonyTestRunner或用户自定义runner名称- s unittest OpenHarmonyTestRunnerclass指定要执行的测试套或测试用例{describeName}#{itName},{describeName}-s class attributeTest#testAttributeItnotClass指定不须要执行的测试套或测试用例{describeName}#{itName},{describeName}-s notClass attributeTest#testAttributeItitName指定要执行的测试用例{itName}-s itName testAttributeIttimeout测试用例执行的超时时间正整数(单位ms),如不设置默以为 5000-s timeout 15000breakOnError遇错即停模式,当执行用例断言失败或者发生错误时,退出测试执行流程true/false(默认值)-s breakOnError truerandom测试用例随机序次执行true/false(默认值)-s random truetestType指定要执行用例的用例范例function,performance,power,reliability, security,global,compatibility,user,standard,safety,resilience’-s testType functionlevel指定要执行用例的用例级别0,1,2,3,4-s level 0size指定要执行用例的用例规模small,medium,large-s size smallstress指定要执行用例的执行次数正整数-s stress 1000在cmd窗口执行test下令
说明
参数设置和下令均是基于Stage模子。
示例代码1:执行全部测试用例。
  1. hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
复制代码
示例代码2:执行指定的describe测试套用例,指定多个需用逗号隔开。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s class s1,s2
复制代码
示例代码3:执行指定测试套中指定的用例,指定多个需用逗号隔开。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s class testStop#stop_1,testStop1#stop_0
复制代码
示例代码4:执行指定除设置以外的全部的用例,设置不执行多个测试套需用逗号隔开。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s notClass testStop
复制代码
示例代码5:执行指定it名称的全部用例,指定多个需用逗号隔开。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s itName stop_0
复制代码
示例代码6:用例执行超时时长设置。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s timeout 15000
复制代码
示例代码7:用例以breakOnError模式执行用例。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s breakOnError true
复制代码
示例代码8:执行测试范例匹配的测试用例。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s testType function
复制代码
示例代码9:执行测试级别匹配的测试用例。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s level 0
复制代码
示例代码10:执行测试规模匹配的测试用例。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s size small
复制代码
示例代码11:执行测试用例指定次数。
  1.   hdc shell aa test -b xxx -m xxx -s unittest OpenHarmonyTestRunner
  2. -s stress 1000
复制代码
查看测试结果

  • cmd模式执行过程,会打印如下干系日记信息。
  1. OHOS_REPORT_STATUS: class=testStop
  2. OHOS_REPORT_STATUS: current=1
  3. OHOS_REPORT_STATUS: id=JS
  4. OHOS_REPORT_STATUS: numtests=447
  5. OHOS_REPORT_STATUS: stream=
  6. OHOS_REPORT_STATUS: test=stop_0
  7. OHOS_REPORT_STATUS_CODE: 1
  8. OHOS_REPORT_STATUS: class=testStop
  9. OHOS_REPORT_STATUS: current=1
  10. OHOS_REPORT_STATUS: id=JS
  11. OHOS_REPORT_STATUS: numtests=447
  12. OHOS_REPORT_STATUS: stream=
  13. OHOS_REPORT_STATUS: test=stop_0
  14. OHOS_REPORT_STATUS_CODE: 0
  15. OHOS_REPORT_STATUS: consuming=4
复制代码
日记输出字段日记输出字段寄义OHOS_REPORT_SUM当前测试套用例总数。OHOS_REPORT_STATUS: class当前执行用例测试套名称。OHOS_REPORT_STATUS: id用例执行语言,默认JS。OHOS_REPORT_STATUS: numtests测试包中测试用例总数 。OHOS_REPORT_STATUS: stream当前用例发生错误时,记载错误信息。OHOS_REPORT_STATUS: test当前用例执行的it name。OHOS_REPORT_STATUS_CODE当前用例执行结果状态。0表示通过,1表示错误,2表示失败。OHOS_REPORT_STATUS: consuming当前用例执行斲丧的时长(ms)。

  • cmd执行完成后,会打印如下干系日记信息。
  1. OHOS_REPORT_RESULT: stream=Tests run: 447, Failure: 0, Error: 1, Pass: 201, Ignore: 245
  2. OHOS_REPORT_CODE: 0
  3. OHOS_REPORT_RESULT: breakOnError model, Stopping whole test suite if one specific test case failed or error
  4. OHOS_REPORT_STATUS: taskconsuming=16029
复制代码
日记输出字段日记输出字段寄义run当前测试包用例总数。Failure当前测试失败用例个数。Error当前执行用例发生错误用例个数。Pass当前执行用例通过用例个数 。Ignore当前未执行用例个数。taskconsuming执行当前测试用例总耗时(ms)。说明
当处于breakOnError模式,用例发生错误时,注意查看Ignore以及克制说明。
基于shell下令测试

在开辟过程中,若须要快速举行截屏、 录屏、注入UI模仿操作、获取控件树等操作,可以使用shell下令,更方便完成相应测试。
说明
使用cmd的方式,须要设置好hdc干系的环境变量。
下令列表
下令设置参数形貌helphelp体现uitest工具可以或许支持的下令信息。screenCap[-p]截屏。非必填。指定存储路径和文件名, 只支持存放在/data/local/tmp/下。默认存储路径:/data/local/tmp,文件名:时间戳 + .png。dumpLayout[-p] <-i-a>uiRecorduiRecord <recordread>uiInput<helpclick–version–version获取当前工具版本信息。start-daemonstart-daemon拉起uitest测试进程。截图使用示例
  1. # 存储路径:/data/local/tmp,文件名:时间戳 + .png。
  2. hdc shell uitest screenCap
  3. # 指定存储路径和文件名,存放在/data/local/tmp/下。
  4. hdc shell uitest screenCap -p /data/local/tmp/1.png
复制代码
获取控件树使用示例
  1. hdc shell uitest dumpLayout -p /data/local/tmp/1.json
复制代码
用户录制操作

说明
录制过程中,需等候当前操作的识别结果在下令行输出后,再举行下一步操作。
  1. # 将当前界面操作记录到/data/local/tmp/record.csv,结束录制操作使用Ctrl+C结束录制。
  2. hdc shell uitest uiRecord record
  3. # 读取并打印录制数据。
  4. hdc shell uitest uiRecord read
复制代码
以下举例为:record数据中包罗的字段及字段寄义,仅供参考
  1. {
  2.     "ABILITY": "com.ohos.launcher.MainAbility", // 前台应用界面
  3.     "BUNDLE": "com.ohos.launcher", // 操作应用
  4.     "CENTER_X": "", // 预留字段,暂未使用
  5.     "CENTER_Y": "", // 预留字段,暂未使用
  6.     "EVENT_TYPE": "pointer", //  
  7.     "LENGTH": "0", // 总体步长
  8.     "OP_TYPE": "click", //事件类型,当前支持点击、双击、长按、拖拽、滑动、抛滑动作录制
  9.     "VELO": "0.000000", // 离手速度
  10.     "direction.X": "0.000000",// 总体移动X方向
  11.     "direction.Y": "0.000000", // 总体移动Y方向
  12.     "duration": 33885000.0, // 手势操作持续时间
  13.     "fingerList": [{
  14.         "LENGTH": "0", // 总体步长
  15.         "MAX_VEL": "40000", // 最大速度
  16.         "VELO": "0.000000", // 离手速度
  17.         "W1_BOUNDS": "{"bottom":361,"left":37,"right":118,"top":280}", // 起点控件bounds
  18.         "W1_HIER": "ROOT,3,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0", // 起点控件hierarchy
  19.         "W1_ID": "", // 起点控件id
  20.         "W1_Text": "", // 起点控件text
  21.         "W1_Type": "Image", // 起点控件类型
  22.         "W2_BOUNDS": "{"bottom":361,"left":37,"right":118,"top":280}", // 终点控件bounds
  23.         "W2_HIER": "ROOT,3,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0", // 终点控件hierarchy
  24.         "W2_ID": "", // 终点控件id
  25.         "W2_Text": "", // 终点控件text
  26.         "W2_Type": "Image", // 终点控件类型
  27.         "X2_POSI": "47", // 终点X
  28.         "X_POSI": "47", // 起点X
  29.         "Y2_POSI": "301", // 终点Y
  30.         "Y_POSI": "301", // 起点Y
  31.         "direction.X": "0.000000", // x方向移动量
  32.         "direction.Y": "0.000000" // Y方向移动量
  33.     }],
  34.     "fingerNumber": "1" //手指数量
  35. }"direction.Y": "0.000000" // Y方向移动量    }],    "fingerNumber": "1" //手指数量}
复制代码
注入UI模仿操作

下令必填形貌help是uiInput下令干系资助信息。click是模仿单击操作。doubleClick是模仿双击操作。longClick是模仿长按操作。fling是模仿快滑操作。swipe是模仿慢滑操作。drag是模仿拖拽操作。dircFling是模仿指定方向滑动操作。inputText是模仿输入框输入文本操作。keyEvent是模仿实体按键变乱(如:键盘,电源键,返回上一级,返回桌面等),以及组合按键操作。uiInput click/doubleClick/longClick使用示例
设置参数必填形貌point_x是点击x坐标点。point_y是点击y坐标点。
  1. # 执行单击事件。
  2. hdc shell uitest uiInput click 100 100
  3. # 执行双击事件。
  4. hdc shell uitest uiInput doubleClick 100 100
  5. # 执行长按事件。
  6. hdc shell uitest uiInput longClick 100 100
复制代码
uiInput fling使用示例
设置参数必填形貌from_x是滑动出发点x坐标。from_y是滑动出发点y坐标。to_x是滑动尽头x坐标。to_y是滑动尽头y坐标。swipeVelocityPps_否滑动速度,单位: (px/s),取值范围:200-40000。默认值: 600。stepLength_否滑动步长。默认值: 滑动距离/50。为实现更好的模仿结果,保举参数缺省/使用默认值。
  1. # 执行快滑操作,stepLength_缺省。
  2. hdc shell uitest uiInput fling 10 10 200 200 500
复制代码
uiInput swipe/drag使用示例
设置参数必填形貌from_x是滑动出发点x坐标。from_y是滑动出发点y坐标。to_x是滑动尽头x坐标。to_y是滑动尽头y坐标。swipeVelocityPps_否滑动速度,单位: (px/s),取值范围:200-40000。默认值: 600。
  1. # 执行慢滑操作。
  2. hdc shell uitest uiInput swipe 10 10 200 200 500
  3. # 执行拖拽操作。
  4. hdc shell uitest uiInput drag 10 10 100 100 500
复制代码
uiInput dircFling使用示例
设置参数必填形貌direction否滑动方向,取值范围:[0,1,2,3],默认值为0。0代表向左滑动,1代表向右滑动,2代表向上滑动,3代表向下滑动。swipeVelocityPps_否滑动速度,单位: (px/s),取值范围:200-40000。默认值: 600。stepLength否滑动步长。默认值: 滑动距离/50。为更好的模仿结果,保举参数缺省/使用默认值。
  1. # 执行左滑操作
  2. hdc shell uitest uiInput dircFling 0 500
  3. # 执行向右滑动操作
  4. hdc shell uitest uiInput dircFling 1 600
  5. # 执行向上滑动操作。
  6. hdc shell uitest uiInput dircFling 2
  7. # 执行向下滑动操作。
  8. hdc shell uitest uiInput dircFling 3
复制代码
uiInput inputText使用示例
设置参数必填形貌point_x是输入框x坐标点。point_y是输入框y坐标点。text是输入文本内容。
  1. # 执行输入框输入操作。
  2. hdc shell uitest uiInput inputText 100 100 hello
复制代码
uiInput keyEvent使用示例
设置参数必填形貌keyID1是实体按键对应ID,取值范围:KeyCode/Back/Home/Power。当取Back/Home/Power时,不支持输入组合键。keyID2否实体按键对应ID。keyID3否实体按键对应ID。说明
最多支持传入是三个键值。
  1. # 执行执行返回主页操作。
  2. hdc shell uitest uiInput keyEvent Home
  3. # 执行返回主页操作。
  4. hdc shell uitest uiInput keyEvent Back
  5. # 执行组合键粘贴操作。
  6. hdc shell uitest uiInput keyEvent 2072 2038
复制代码
获取版本信息
  1. hdc shell uitest --version
复制代码
拉起uitest测试进程
  1. hdc shell uitest start-daemon
复制代码
说明
设备需调成开辟者模式。
仅元本事aa test拉起的测试hap才能调用Uitest的本事。
测试hap的[APL等级级别]需为system_basic、normal。
常见题目

单位测试用例常见题目

1、用例中增长的打印日记在用例结果之后才打印
题目形貌
用例中增长的日记打印信息,没有在用例执行过程中出现,而是在用例执行竣事之后才出现。
大概缘故原由
此类环境只会存在于用例中有调用异步接口的环境,原则上用例中全部的日记信息均在用例执行竣事之前打印。
办理方法
当被调用的异步接口多于一个时,发起将接口调用封装成Promise方式调用。
2、执行用例时报error:fail to start ability
题目形貌
执行测试用例时间,用例执行失败,控制台返回错误:fail to start ability。
大概缘故原由
测试包打包过程中出现题目,未将测试框架依靠文件打包在测试包中。
办理方法
查抄测试包中是否包罗OpenHarmonyTestRunner.abc文件,如没有则重新编译打包后再次执行测试。
3、执行用例时报用例超时错误
题目形貌
用例执行竣事,控制台提示execute time XXms错误,即用例执行超时。
大概缘故原由
1.用例执行异步接口,但执行过程中没有执行到done函数,导致用例执行一直没有竣事,直到超时竣事。
2.用例调用函数耗时过长,超过用例执行设置的超时时间。
3.用例调用函数克制言失败,抛出失败非常,导致用例执行一直没有竣事,直到超时竣事。
办理方法
1.查抄用例代码逻辑,确保纵然断言失败场景承认走到done函数,保证用例执行竣事。
2.可在IDE中Run/Debug Configurations中修改用例执行超时设置参数,克制用例执行超时。
3.查抄用例代码逻辑,断言结果,确保断言Pass。
UI测试用例常见题目

1、失败日记有“Get windows failed/GetRootByWindow failed”错误信息
题目形貌
UI测试用例执行失败,查看hilog日记发现日记中有“Get windows failed/GetRootByWindow failed”错误信息。
大概缘故原由
体系ArkUI开关未开启,导致被测试界面控件树信息未天生。
办理方法
执行如下下令,并重启设备再次执行用例。
  1. hdc shell param set persist.ace.testmode.enabled 1
复制代码
2、失败日记有“uitest-api dose not allow calling concurrently”错误信息
题目形貌
UI测试用例执行失败,查看hilog日记发现日记中有“uitest-api dose not allow calling concurrently”错误信息。
大概缘故原由
1.用例中UI测试框架提供异步接口没有增长await语法糖调用。
2.多进程执行UI测试用例,导致拉起多个UITest进程,框架不支持多进程调用。
办理方法
1.查抄用例实现,异步接口增长await语法糖调用。
2.克制多进程执行UI测试用例。
3、失败日记有“does not exist on current UI! Check if the UI has changed after you got the widget object”错误信息
题目形貌
UI测试用例执行失败,查看hilog日记发现日记中有“does not exist on current UI! Check if the UI has changed after you got the widget object”错误信息。
大概缘故原由
在用例中代码查找到目的控件后,设备界面发生了厘革,导致查找到的控件丢失,无法举行下一步的模仿操作。
办理方法
重新执行UI测试用例。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表