| name | harmonyos-autotest |
| description | Complete HarmonyOS automated testing workflow orchestrator. Converts natural language test requirements to executable Hypium test cases through step parsing, environment checking, project creation, control parsing, operation execution, debugging, and test case writing. Use when user wants to run complete automated test workflow, create HarmonyOS test projects, or mentions HarmonyOSæµè¯, èªåšåæµè¯, run test, execute test. Trigger keywords: harmonyos test, èªåšåæµè¯, run test, test workflow, 宿޿µè¯æµçš, hypium, å建æµè¯å·¥çš. |
HarmonyOS èªåšåæµè¯
åè°å®æŽç HarmonyOS èªåšåæµè¯å·¥äœæµçšïŒå°èªç¶è¯èšæµè¯éæ±èœ¬æ¢äžºå¯æ§è¡ç Hypium æµè¯çšäŸã
æ žå¿ååïŒäž¥æ Œåæ¥è°è¯
ç»å¯¹çŠæ¢å°å€äžªæ¥éª€åå¹¶è°è¯ïŒæ¯æ¬¡åªè°è¯äžäžªæ¥éª€ïŒ
- 已确讀éè¿çæ¥éª€ïŒå¿
é¡»å
šéšæ³šé
- åœåè°è¯çæ¥éª€ïŒåªæäžäžªæªæ³šé
- åç»åŸ
è°è¯æ¥éª€ïŒå¿
é¡»å
šéšæ³šé
- è°è¯æéŽæ³šé setup/teardownïŒè°è¯è¿çšäžå¿
é¡»æ³šéæ setup å teardown åœæ°ïŒåŠåæ¯æ¬¡è°è¯éœäŒåå°æ¡é¢åå
³éåºçšïŒå¯ŒèŽæ æ³è¿ç»è°è¯
- 端å°ç«¯æµè¯åæ¢å€ïŒæææ¥éª€è°è¯å®æåïŒå
åæ¶ setup/teardown çæ³šéïŒååæ¶æææ¥éª€ç泚éïŒç¶åæ§è¡ç«¯å°ç«¯æµè¯
â ïž æçŽ¢æäœè§èïŒå¿
é¡»éµå®ïŒ
æçŽ¢æäœå¿
é¡»äž¥æ Œæç
§äžæ¥æµçšæ§è¡ïŒçŠæ¢çŽæ¥ç¹å»æçŽ¢æé®ïŒ
æçŽ¢æäœçæ£ç¡®æµçš
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Step 1: ç¹å»æçŽ¢èŸå
¥æ¡ â
â - ç®çïŒè§ŠåèŸå
¥æ¡è·åçŠç¹ïŒæŸç€ºé®ç â
â - æ§ä»¶ç±»åïŒSearchFieldãTextInputãTextField â
â - å®äœæ¹åŒïŒBY.type("SearchField") æ BY.key("search_*") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Step 2: èŸå
¥æçŽ¢å
容 â
â - äœ¿çš input_text_on_current_cursor() æ input_text() â
â - çåŸ
èŸå
¥å®æ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Step 3: ç¹å»æçŽ¢æé®ææå蜊æ§è¡æçŽ¢ â
â - ç¹å»æçŽ¢æé®ïŒBY.text("æçŽ¢") â
â - ææå蜊ïŒKeyCode.ENTER â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
éè¯¯ç€ºäŸ â
self.driver.touch(BY.text("æçŽ¢"))
self.driver.input_text("åšé»éž")
æ£ç¡®ç€ºäŸ â
self.driver.touch(BY.type("SearchField"))
time.sleep(3)
self.driver.input_text_on_current_cursor("åšé»éž")
time.sleep(3)
self.driver.press_key(KeyCode.ENTER)
æçŽ¢èŸå
¥æ¡è¯å«èŠç¹
| æ§ä»¶ç±»å | 诎æ | å®äœæ¹åŒ |
|---|
| SearchField | äžçšæçŽ¢èŸå
¥æ¡ | BY.type("SearchField") |
| TextInput | éçšææ¬èŸå
¥æ¡ | BY.type("TextInput") |
| TextField | ææ¬åæ®µ | BY.type("TextField") |
| 垊æç€ºæåçèŸå
¥æ¡ | æŸç€º"请èŸå
¥"ã"æçŽ¢"çæç€º | éè¿åæ å®äœ |
泚æïŒæçŽ¢èŸå
¥æ¡éåžžæ²¡æææŸç"æçŽ¢"ææ¬ïŒéèŠéè¿ç±»åïŒtypeïŒækeyæ¥è¯å«ïŒ
â ïž æ§ä»¶å®äœäŒå
级ïŒå¿
é¡»éµå®ïŒ
äŒå
äœ¿çšæ§ä»¶å®äœåšïŒåæ å®äœæ¯å€éæ¹æ¡ïŒ
æ§ä»¶å®äœçäŒå
级顺åº
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äŒå
级 1: BY.text() - éè¿ææ¬å
容å®äœ â
â éçšäºïŒæé®ãèåé¡¹ãæ çŸçææç¡®æåçæ§ä»¶ â
â 瀺äŸïŒBY.text("ç¡®å®"), BY.text("讟眮") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äŒå
级 2: BY.type() - éè¿æ§ä»¶ç±»åå®äœ â
â éçšäºïŒç¹å®ç±»åçæ§ä»¶ïŒæé®ãèŸå
¥æ¡ãåŒå
³çïŒ â
â 瀺äŸïŒBY.type("Button"), BY.type("Toggle"), BY.type("Slider")â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äŒå
级 3: BY.key() - éè¿æ§ä»¶key屿§å®äœ â
â éçšäºïŒæå¯äžkeyæ è¯çæ§ä»¶ â
â 瀺äŸïŒBY.key("search_input"), BY.key("btn_submit") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äŒå
级 4: BY.id() - éè¿æ§ä»¶idå®äœ â
â éçšäºïŒæå¯äžidçæ§ä»¶ â
â 瀺äŸïŒBY.id("com.example:id/button") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äŒå
级 5: ç»åå®äœåš - å€å±æ§ç»å â
â éçšäºïŒåäžå±æ§æ æ³å¯äžç¡®å®æ¶ â
â 瀺äŸïŒBY.text("ç¡®å®").type("Button") â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â å€éæ¹æ¡: åæ å®äœ touch((x, y)) â
â ä»
åšä»¥äžæ
åµäœ¿çšïŒ â
â - æ§ä»¶æ äžæ æ³æŸå°ä»»äœå¯çšçå®äœå±æ§ â
â - æ§ä»¶æ¯çº¯åŸåœ¢/åŸæ ïŒæ æåãtypeãkeyç屿§ â
â - æ§ä»¶å®äœåšåå€å€±èŽ¥åçæåææ®µ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
䞺ä»ä¹äŒå
äœ¿çšæ§ä»¶å®äœåšïŒ
| äŒå¿ | 诎æ |
|---|
| çš³å®æ§ | æ§ä»¶å±æ§éåžžäžäŒå å±å¹å蟚çååèæ¹å |
| å¯ç»Žæ€æ§ | ä»£ç æŽæè¯»ïŒBY.text("ç¡®å®") æ¯ (658, 483) æŽæçè§£ |
| éåºæ§ | èªåšéåºäžå讟å€å°ºå¯žååžå±åå |
| è°è¯æ§ | 倱莥æ¶éè¯¯ä¿¡æ¯æŽæç¡® |
éè¯¯ç€ºäŸ â
self.driver.touch((658, 483))
self.driver.touch((577, 227))
æ£ç¡®ç€ºäŸ â
self.driver.touch(BY.text("ç¡®å®"))
self.driver.touch(BY.type("Toggle"))
self.driver.touch(BY.key("btn_submit"))
self.driver.touch((658, 483))
æ§ä»¶æ åæèŠç¹
åææ§ä»¶æ æ¶ïŒå¿
é¡»éŠå
è®°åœä»¥äžå±æ§ïŒ
- text: æ§ä»¶æŸç€ºçææ¬å
容
- type: æ§ä»¶ç±»åïŒButton, Toggle, Slider, Text, ImageçïŒ
- key: æ§ä»¶çkey屿§
- id: æ§ä»¶çid屿§
- clickable: æ¯åŠå¯ç¹å»
åªæåœä»¥äžå±æ§éœæ æ³çšäºå®äœæ¶ïŒæè®°åœ centeråæ äœäžºå€éã
å·¥äœæµçš
çšæ·èŸå
¥èªç¶è¯èšæµè¯éæ±
â
âŒ
âââââââââââââââââââââââ
â 1. å建项ç®ç®åœ â å建ç»äžçé¡¹ç®æ ¹ç®åœ
âââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââ
â 2. æ¥éª€è§£æ â è§£ææµè¯æ¥éª€äžº JSONïŒåèreferences/step-parser.md
âââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââ
â 3. ç¯å¢æ£æµ â æ£æµç¯å¢æ¯åŠå°±ç»ªïŒåèreferences/environment.md
âââââââââââââââââââââââ
â (倱莥åç»æ¢)
âŒ
âââââââââââââââââââââââ
â 4. å建æµè¯å·¥çš â å建æµè¯é¡¹ç®ç»æïŒåèreferences/project-template.md
âââââââââââââââââââââââ
â
âŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 5. 埪ç¯: 对æ¯äžªæµè¯æ¥éª€ (鿥è°è¯) â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â â ïž æ¯æ¥å¿
é¡»å
读å对åºåèææ¡£ïŒ â â
â â â â
â â a. æ§ä»¶è§£æ: â â
â â â 读å references/control-parser.md â â
â â ⡠读å references/debug.md (ä¿®æ£çç¥) â â
â â â¢ å¯Œåºæ§ä»¶æ ïŒ**äŒå
æ¥æŸæ§ä»¶çtext/type/key屿§** â â
â â ⣠**ä»
åšæ å¯çšå±æ§æ¶**æäœ¿çšåæ äœäžºå€é â â
â â â€ è¥æ§ä»¶æ å®å
šæ æ³å®äœ â æªåŸ + AIåæ â â
â â â â
â â b. çŒå代ç : â â
â â â 读å references/testcase-writer.md â â
â â ⡠读å references/operation.md (APIçšæ³) â â
â â ⢠ç»åæäœæ¹åŒçŒåæµè¯ä»£ç â â
â â â â
â â c. æ§è¡è°è¯: è¿è¡æµè¯å·¥çšïŒéªè¯åœåæ¥éª€æ¯åŠæå â â
â â d. 人䞺确讀: çåŸ
çšæ·ç¡®è®€æ¥éª€æ§è¡æ£ç¡® â â
â â e. 泚é代ç : å°å·²ç¡®è®€çæ¥éª€ä»£ç æ³šéæ â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
âŒ
âââââââââââââââââââââââ
â 6. 端å°ç«¯æµè¯ â å»ææ³šéïŒæ§è¡å®æŽæµè¯
âââââââââââââââââââââââ
â
âŒ
èŸåºæµè¯æ¥å
å¯çšèæ¬
| èæ¬ | çšæ³ | 诎æ |
|---|
scripts/create_project.py | python create_project.py <app> <feature> | å建æµè¯é¡¹ç® |
scripts/check_environment.py | python check_environment.py | æ£æµç¯å¢ç¶æ |
scripts/dump_controls.py | python dump_controls.py [output_dir] | å¯Œåºæ§ä»¶æ |
scripts/run_test.py | python run_test.py [test_name] | è¿è¡æµè¯çšäŸ |
è¯Šç»æå
æ§è¡æ¥éª€
1. å建项ç®ç®åœ
åšåœåå·¥äœç®åœäžå建 projects æ ¹ç®åœå项ç®ïŒ
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
PROJECT_NAME="{app_name}_{test_feature}_${TIMESTAMP}"
PROJECT_ROOT="./projects/${PROJECT_NAME}"
mkdir -p "${PROJECT_ROOT}"/{config,testcases,aw,resource/images,output/{controls,screenshots,reports,logs,temp}}
export HARMONYOS_PROJECT_ROOT="$(cd ${PROJECT_ROOT} && pwd)"
2. æ¥éª€è§£æ
â ïž å¿
é¡»å
读å references/step-parser.md
å°èªç¶è¯èšæµè¯æ¥éª€è§£æäžºç»æåJSONã
3. ç¯å¢æ£æµ
â ïž å¿
é¡»å
读å references/environment.md
æ£æµ HDCãHypiumã讟å€è¿æ¥ç¶æã
4. å建æµè¯å·¥çš
â ïž å¿
é¡»å
读å references/project-template.md
åºäºæš¡æ¿å建æµè¯é¡¹ç®ã
5. 鿥è°è¯
â ïž æ¯æ¥è°è¯åå¿
é¡»å
读å对åºåèææ¡£ïŒ
- æ§ä»¶è§£æ: 读å
references/control-parser.md å references/debug.md
- çŒå代ç : 读å
references/testcase-writer.md å references/operation.md
- æ§ä»¶æ æ æ³å®äœæ¶: äœ¿çšæªåŸ+AIåæ (è§
references/debug.md çç¥3)
对æ¯äžªæµè¯æ¥éª€æ§è¡è°è¯åŸªç¯ïŒ
cd {PROJECT_ROOT}
xdevice run -l Example -ta agent_mode:bin;screenshot:true
6. 端å°ç«¯æµè¯
hdc shell aa force-stop {package_name}
xdevice run -l Example -ta agent_mode:bin
æµè¯ä»£ç 瀺äŸ
è°è¯æéŽçç¶æïŒsetup/teardown 已泚éïŒ
from devicetest.core.test_case import TestCase, Step
from hypium import *
import time
class Example(TestCase):
def __init__(self, controllers):
self.TAG = self.__class__.__name__
TestCase.__init__(self, self.TAG, controllers)
self.driver = UiDriver(self.device1)
def process(self):
Step('2.ç¹å»æé®')
self.driver.touch(BY.text("æé®"))
time.sleep(3)
端å°ç«¯æµè¯åçç¶æïŒæææ³šé已忶ïŒ
from devicetest.core.test_case import TestCase, Step
from hypium import *
import time
class Example(TestCase):
def __init__(self, controllers):
self.TAG = self.__class__.__name__
TestCase.__init__(self, self.TAG, controllers)
self.driver = UiDriver(self.device1)
def setup(self):
Step('1.åå°æ¡é¢')
self.driver.swipe_to_home()
time.sleep(3)
def process(self):
Step('2.å¯åšåºçš')
self.driver.start_app(package_name="com.example.app")
time.sleep(3)
Step('3.ç¹å»æé®')
self.driver.touch(BY.text("æé®"))
time.sleep(3)
def teardown(self):
Step('4.æž
çç¯å¢')
self.driver.stop_app("com.example.app")
åžžè§åºçšå
å
| åºçš | å
å |
|---|
| 讟眮 | com.huawei.hmos.settings |
| 仿¥å€Žæ¡ | com.ss.android.article.news |
| 埮信 | com.tencent.mm |
| çŸå¢ | com.sankuai.hmeituan |
| 滎滎åºè¡ | com.sdu.didi.hmos.psnger |
èŸåºç»æ
{
"success": true,
"test_name": "æµè¯åç§°",
"project_path": "{PROJECT_ROOT}",
"testcase_path": "{PROJECT_ROOT}/testcases/Example.py",
"execution_summary": {
"total_steps": 5,
"passed": 5,
"failed": 0
},
"report_path": "{PROJECT_ROOT}/output/reports/test_report.md"
}
䜿çšç€ºäŸ
ç€ºäŸ 1: 宿޿µè¯æµçšïŒéæ¥è°è¯ïŒ
çšæ·èŸå
¥:
æµè¯è®Ÿçœ®æŸç€ºå亮床åèœïŒ
1. å¯åšè®Ÿçœ®
2. ç¹å»æçŽ¢æ¡
3. èŸå
¥"æŸç€ºå亮床"
4. ç¹å»æçŽ¢ç»æ
5. è®Ÿçœ®æ·±è²æš¡åŒ
Agent æ§è¡:
1. å建项ç®ç®åœ
2. è§£ææµè¯æ¥éª€äžº JSON
3. æ£æµç¯å¢
4. å建æµè¯å·¥çš
=== åŒå§éæ¥è°è¯ ===
--- æ¥éª€ 1: å¯åšè®Ÿçœ®åºçš ---
[çŽæ¥æ§è¡] driver.start_app(package_name="com.huawei.hmos.settings")
[debug] æ§è¡æµè¯... æå
请确讀: åºçšæ¯åŠæ£ç¡®å¯åšïŒ(ok/倱莥)
> ok
[æ³šéæ¥éª€ 1 代ç ]
--- æ¥éª€ 2: ç¹å»æçŽ¢æ¡ ---
[control-parser] 富åºè®Ÿçœ®é¡µæ§ä»¶æ
[testcase-writer] çŒåç¹å»æçŽ¢æ¡ä»£ç
[debug] æ§è¡æµè¯... æå
请确讀: æçŽ¢æ¡æ¯åŠè¢«ç¹å»ïŒ(ok/倱莥)
> ok
[æ³šéæ¥éª€ 2 代ç ]
... (ç»§ç»æ¥éª€ 3-5)
=== æææ¥éª€è°è¯å®æ ===
=== 端å°ç«¯æµè¯ ===
[区å¶å
³éåºçš] hdc shell aa force-stop com.huawei.hmos.settings
[å»ææææ³šé]
[æ§è¡å®æŽæµè¯]
[çææµè¯æ¥å]
ç€ºäŸ 2: è°è¯å€±èޥ鿰å°è¯
--- æ¥éª€ 3: èŸå
¥æçŽ¢è¯ ---
[control-parser] å¯Œåºæ§ä»¶æ
[testcase-writer] çŒåèŸå
¥ä»£ç
[debug] æ§è¡æµè¯... 倱莥: æ§ä»¶æªæŸå°
[debug] åæ: å®äœåš BY.key('search_input') æªæŸå°
[debug] å°è¯å€çšå®äœåš: BY.type('SearchField')
[testcase-writer] æŽæ°ä»£ç
[debug] éæ°æ§è¡... æå
请确讀: æ¯åŠæ£ç¡®èŸå
¥äºæçŽ¢è¯ïŒ(ok/倱莥)
é
眮
é»è®€é
眮:
defaults:
device_sn: auto
timeout: 30000
retry: 2
output_dir: ./output
apps:
settings: com.huawei.hmos.settings
toutiao: com.ss.android.article.news
wechat: com.tencent.mm
meituan: com.sankuai.hmeituan
泚æäºé¡¹
- 鿥è°è¯: æ¯æ¥éœéèŠäººäžºç¡®è®€åæèœç»§ç»
- æ³šéæºå¶: å·²ç¡®è®€çæ¥éª€äŒè¢«æ³šéïŒç¡®ä¿äžæ¬¡åªæ§è¡æ°æ¥éª€
- è°è¯æéŽæ³šé setup/teardown: è°è¯è¿çšäžå¿
é¡»æ³šéæ setup å teardown åœæ°ïŒåŠåæ¯æ¬¡è°è¯éœäŒåå°æ¡é¢åå
³éåºçšïŒæ æ³è¿ç»è°è¯
- 端å°ç«¯æµè¯åæ¢å€: æææ¥éª€è°è¯å®æåïŒå
åæ¶ setup/teardown çæ³šéïŒååæ¶æææ¥éª€ç泚é
- æ§è¡è°è¯åå¿
é¡»è¿å
¥é¡¹ç®ç®åœ: æ¯æ¬¡è¿è¡
xdevice åïŒå¿
é¡»å
cd {PROJECT_ROOT}
- 端å°ç«¯æµè¯åå¿
é¡»å
³éåºçš: 䜿çš
hdc shell aa force-stop {package_name} 区å¶å
³éåºçš
- å¯åšåºçšäŒå: å¯åšåºçšæ¥éª€çŽæ¥äœ¿çš
driver.start_app()ïŒäžéèŠå¯Œåºæ§ä»¶æ
- â ïž æ§ä»¶å®äœäŒå
级: äŒå
䜿çš
BY.text(), BY.type(), BY.key() çæ§ä»¶å®äœåšïŒåæ touch((x,y)) æ¯å€éæ¹æ¡ïŒä»
åšæ§ä»¶æ å¯çšå±æ§æ¶äœ¿çš
- â ïž æçŽ¢æäœå¿
é¡»äžæ¥èµ°: 1.å
ç¹å»æçŽ¢èŸå
¥æ¡ â 2.èŸå
¥å
容 â 3.ç¹å»æçŽ¢æé®æå蜊ãçŠæ¢çŽæ¥ç¹å»æçŽ¢æé®ïŒ
- æçŽ¢èŸå
¥æ¡è¯å«: éè¿
BY.type("SearchField/TextInput") æ BY.key() å®äœïŒäžèŠçš BY.text("æçŽ¢")
- æ¯æäžè±ææ··åèŸå
¥
- èªåšå€çæ§ä»¶å®äœå€±èŽ¥
- æ²æ·è°è¯è§åäŸåç»äœ¿çš