diff --git a/test/scripts/main.py b/test/scripts/main.py new file mode 100644 index 0000000000000000000000000000000000000000..a9ab51d55608e4b1c7e15e4ff414a2d7df296609 --- /dev/null +++ b/test/scripts/main.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import pkg_resources +import pytest +import os +import time + +GetVersion = "V1.0.0" + +def check_library_installation(library_name): + try: + pkg_resources.get_distribution(library_name) + return 0 + except pkg_resources.DistributionNotFound: + print(f"\n\n{library_name} is not installed.\n\n") + print(f"try to use command below:") + print(f"pip install {library_name}") + return 1 + + +if __name__ == '__main__': + if check_library_installation("pytest"): + subprocess.check_call(["pip", "install", "-r", "requirements.txt"]) + if check_library_installation("pytest"): + exit(1) + + start_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + pytest.main() + end_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + report_time = time.strftime('%Y-%m-%d_%H_%M_%S', time.localtime(time.time())) + report_dir = os.path.join(os.getcwd(), "reports") + report_file = os.path.join(report_dir, f"{report_time}report.html") + print(f"Test over, the script version is {GetVersion}," + f" start at {start_time}, end at {end_time} \n" + f"=======>{report_file} is saved. \n" + ) + input("=======>press [Enter] key to Show logs.") + + + # os.system("allure generate temp -o reports") diff --git a/test/scripts/prepare.py b/test/scripts/prepare.py new file mode 100644 index 0000000000000000000000000000000000000000..101f3423376489c9bd8f2bf883d01b0beb6b4d57 --- /dev/null +++ b/test/scripts/prepare.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess + +# 自动安装依赖 +def install_dependencies(requirements_file): + try: + subprocess.check_call(["pip", "install", "-r", requirements_file]) + print(f"install requirements.txt success") + except subprocess.CalledProcessError as e: + print(f"install dependence fail: {str(e)}") + +# # 自动生成依赖文件 +# def generate_requirements_file(output_file): +# try: +# subprocess.check_call(["pip", "freeze"], text=True, stdout=open(output_file, 'w')) +# except subprocess.CalledProcessError as e: +# print(f"生成requirements.txt失败: {str(e)}") + +# 使用方法 +# generate_requirements_file("requirements.txt") +install_dependencies("requirements.txt") \ No newline at end of file diff --git a/test/scripts/pytest.ini b/test/scripts/pytest.ini new file mode 100644 index 0000000000000000000000000000000000000000..13164a741dda015bdb0da75b39e938f8666d84d3 --- /dev/null +++ b/test/scripts/pytest.ini @@ -0,0 +1,21 @@ +[pytest] +# 命令行规则,空格分隔 +# -m "L0 or L1" +# --alluredir ./temp +addopts = -vs --html=./reports/report.html --self-contained-html +# 测试用例路径 +testpaths = ../py +# 模块名的规则 +python_files = test*.py +# 类名的规则 +python_classes = Test* +# 方法名的规格 +python_functions = test* +# pytest执行顺序默认从上到下,需要改变顺序进行order参数控制 + +#用例分类 +markers = + L0:冒烟用例 + L1:基础用例 + L2:扩展用例 + diff --git a/test/scripts/readme.md b/test/scripts/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..5d1eaac0af00507a20200b5b79ca7708e24918d5 --- /dev/null +++ b/test/scripts/readme.md @@ -0,0 +1,53 @@ +# pytest命令行参数 +-s: 显示输出调试信息,包括print打印的信息 +-v: 显示更详细的信息 +-n:支持多线程运行脚本(需要保持用例彼此独立) +--reruns NUM:失败用例重跑次数 +-x:表示只要有一个用例报错,那么测试停止 +-k:模糊匹配字符串进行用例跑测 + +# 目录结构 +``` +scripts +├─reports # 测试报告目录 +├─testModule +| ├─resource # 测试资源文件,存放测试过程中使用到的文件 +| └─tests # 测试用例目录 +| ├─test_case1.py # 测试套件1 +| ├─test_case2.py # 测试套件2 +├─main.py # 测试用例执行入口 +├─pytest.ini # pytest配置文件 +└─requirements.txt # 依赖文件 +``` + +## 注意 +rk设备上不用执行test_jsleakwatcher_auto.py的测试用例 + +## 测试用例执行 +windows环境下执行测试用例: +进入scripts目录,打开cmd窗口 +### 方式一: + + ``` + python main.py + ``` +执行参数在pytest.main中配置 + +### 方式二: +- 执行所有用例 + ``` + pytest ./ + ``` +- 执行指定测试文件 + ``` + pytest ./testModule/test_hichecker.py + ``` +- 执行指定测试用例 + ``` + pytest -k "test_hichecker_jssdk" + ``` + +> **user设备需要将预先准备好的测试hap包推入resource目录,会自动安装和启动** + +## 测试报告 +执行python main.py后,会在reports目录下生成测试报告 diff --git a/test/scripts/reports/assets/style.css b/test/scripts/reports/assets/style.css new file mode 100644 index 0000000000000000000000000000000000000000..cea7af2715e8a092ca5ef6935b37ae43ccddf423 --- /dev/null +++ b/test/scripts/reports/assets/style.css @@ -0,0 +1,319 @@ +body { + font-family: Helvetica, Arial, sans-serif; + font-size: 12px; + /* do not increase min-width as some may use split screens */ + min-width: 800px; + color: #999; +} + +h1 { + font-size: 24px; + color: black; +} + +h2 { + font-size: 16px; + color: black; +} + +p { + color: black; +} + +a { + color: #999; +} + +table { + border-collapse: collapse; +} + +/****************************** + * SUMMARY INFORMATION + ******************************/ +#environment td { + padding: 5px; + border: 1px solid #e6e6e6; + vertical-align: top; +} +#environment tr:nth-child(odd) { + background-color: #f6f6f6; +} +#environment ul { + margin: 0; + padding: 0 20px; +} + +/****************************** + * TEST RESULT COLORS + ******************************/ +span.passed, +.passed .col-result { + color: green; +} + +span.skipped, +span.xfailed, +span.rerun, +.skipped .col-result, +.xfailed .col-result, +.rerun .col-result { + color: orange; +} + +span.error, +span.failed, +span.xpassed, +.error .col-result, +.failed .col-result, +.xpassed .col-result { + color: red; +} + +.col-links__extra { + margin-right: 3px; +} + +/****************************** + * RESULTS TABLE + * + * 1. Table Layout + * 2. Extra + * 3. Sorting items + * + ******************************/ +/*------------------ + * 1. Table Layout + *------------------*/ +#results-table { + border: 1px solid #e6e6e6; + color: #999; + font-size: 12px; + width: 100%; +} +#results-table th, +#results-table td { + padding: 5px; + border: 1px solid #e6e6e6; + text-align: left; +} +#results-table th { + font-weight: bold; +} + +/*------------------ + * 2. Extra + *------------------*/ +.logwrapper { + max-height: 230px; + overflow-y: scroll; + background-color: #e6e6e6; +} +.logwrapper.expanded { + max-height: none; +} +.logwrapper.expanded .logexpander:after { + content: "collapse [-]"; +} +.logwrapper .logexpander { + z-index: 1; + position: sticky; + top: 10px; + width: max-content; + border: 1px solid; + border-radius: 3px; + padding: 5px 7px; + margin: 10px 0 10px calc(100% - 80px); + cursor: pointer; + background-color: #e6e6e6; +} +.logwrapper .logexpander:after { + content: "expand [+]"; +} +.logwrapper .logexpander:hover { + color: #000; + border-color: #000; +} +.logwrapper .log { + min-height: 40px; + position: relative; + top: -50px; + height: calc(100% + 50px); + border: 1px solid #e6e6e6; + color: black; + display: block; + font-family: "Courier New", Courier, monospace; + padding: 5px; + padding-right: 80px; + white-space: pre-wrap; +} + +div.media { + border: 1px solid #e6e6e6; + float: right; + height: 240px; + margin: 0 5px; + overflow: hidden; + width: 320px; +} + +.media-container { + display: grid; + grid-template-columns: 25px auto 25px; + align-items: center; + flex: 1 1; + overflow: hidden; + height: 200px; +} + +.media-container--fullscreen { + grid-template-columns: 0px auto 0px; +} + +.media-container__nav--right, +.media-container__nav--left { + text-align: center; + cursor: pointer; +} + +.media-container__viewport { + cursor: pointer; + text-align: center; + height: inherit; +} +.media-container__viewport img, +.media-container__viewport video { + object-fit: cover; + width: 100%; + max-height: 100%; +} + +.media__name, +.media__counter { + display: flex; + flex-direction: row; + justify-content: space-around; + flex: 0 0 25px; + align-items: center; +} + +.collapsible td:not(.col-links) { + cursor: pointer; +} +.collapsible td:not(.col-links):hover::after { + color: #bbb; + font-style: italic; + cursor: pointer; +} + +.col-result { + width: 130px; +} +.col-result:hover::after { + content: " (hide details)"; +} + +.col-result.collapsed:hover::after { + content: " (show details)"; +} + +#environment-header h2:hover::after { + content: " (hide details)"; + color: #bbb; + font-style: italic; + cursor: pointer; + font-size: 12px; +} + +#environment-header.collapsed h2:hover::after { + content: " (show details)"; + color: #bbb; + font-style: italic; + cursor: pointer; + font-size: 12px; +} + +/*------------------ + * 3. Sorting items + *------------------*/ +.sortable { + cursor: pointer; +} +.sortable.desc:after { + content: " "; + position: relative; + left: 5px; + bottom: -12.5px; + border: 10px solid #4caf50; + border-bottom: 0; + border-left-color: transparent; + border-right-color: transparent; +} +.sortable.asc:after { + content: " "; + position: relative; + left: 5px; + bottom: 12.5px; + border: 10px solid #4caf50; + border-top: 0; + border-left-color: transparent; + border-right-color: transparent; +} + +.hidden, .summary__reload__button.hidden { + display: none; +} + +.summary__data { + flex: 0 0 550px; +} +.summary__reload { + flex: 1 1; + display: flex; + justify-content: center; +} +.summary__reload__button { + flex: 0 0 300px; + display: flex; + color: white; + font-weight: bold; + background-color: #4caf50; + text-align: center; + justify-content: center; + align-items: center; + border-radius: 3px; + cursor: pointer; +} +.summary__reload__button:hover { + background-color: #46a049; +} +.summary__spacer { + flex: 0 0 550px; +} + +.controls { + display: flex; + justify-content: space-between; +} + +.filters, +.collapse { + display: flex; + align-items: center; +} +.filters button, +.collapse button { + color: #999; + border: none; + background: none; + cursor: pointer; + text-decoration: underline; +} +.filters button:hover, +.collapse button:hover { + color: #ccc; +} + +.filter__label { + margin-right: 10px; +} diff --git a/test/scripts/requirements.txt b/test/scripts/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..9cd339113c03f739c851bf71252c8f0812a99fec --- /dev/null +++ b/test/scripts/requirements.txt @@ -0,0 +1,8 @@ +pytest +allure-pytest +pytest-xdist +pytest-ordering +pytest-rerunfailures +pytest-html +pytest-repeat +hypium \ No newline at end of file diff --git a/test/scripts/testModule/test_hichecker.py b/test/scripts/testModule/test_hichecker.py new file mode 100644 index 0000000000000000000000000000000000000000..10ae221978cf507f86e8ed8db4be334700d28e72 --- /dev/null +++ b/test/scripts/testModule/test_hichecker.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import time +import pytest +import re +import os +import subprocess +import colorama + +class TestHicheckerjssdk: + @pytest.mark.L0 + def test_hichecker_installhap(self): + subprocess.check_call("hdc install testModule/resource/hichecker.hap", shell=True) + time.sleep(2) + subprocess.check_call("hdc shell aa start -a EntryAbility -b com.example.myapplication", shell=True) + time.sleep(2) + subprocess.check_call("hdc uninstall com.example.myapplication", shell=True) + time.sleep(2) + + @pytest.mark.L0 + def test_hichecker_hicheckersdk(self): + process = subprocess.Popen("hdc shell \"hilog | grep HICHECKER | grep NotifySlowProcess\"", stdout=subprocess.PIPE, shell=True, text=True) + output = "" + for _ in range(1): + output += process.stdout.readline() + assert "NotifySlowProcess" in output + process.kill() \ No newline at end of file diff --git a/test/scripts/testModule/test_jsleakwatcher_auto.py b/test/scripts/testModule/test_jsleakwatcher_auto.py new file mode 100644 index 0000000000000000000000000000000000000000..77c7d924d86ccc426b4d79bba531e0a989b16048 --- /dev/null +++ b/test/scripts/testModule/test_jsleakwatcher_auto.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import time +import pytest +import re +import os +import subprocess +import colorama + +from hypium import UiDriver +from hypium import BY +from hypium import Point +from hypium.model import UiParam + +driver = UiDriver.connect() + +class TestHicheckerjssdk: + @pytest.mark.L0 + def test_hichecker_leakwatchersdk(self): + subprocess.check_call("hdc install testModule/resource/jsleakwatchr.hap", shell=True) + time.sleep(3) + subprocess.check_call("hdc shell aa start -a EntryAbility -b com.example.myapplication", shell=True) + time.sleep(3) + driver.touch(BY.text("Dump").type("Button"), mode=UiParam.DOUBLE) + time.sleep(3) + command = "ls -l /data/app/el2/100/base/com.example.myapplication/haps/entry/files|grep -e heapsnapshot -e jsleaklist" + output = subprocess.check_output(f"hdc shell \"{command}\"", shell=True, text=True, encoding="utf-8") + assert "heapsnapshot" in output + assert "jsleaklist" in output + subprocess.check_call("hdc uninstall com.example.myapplication", shell=True) \ No newline at end of file diff --git a/test/scripts/testModule/test_jsleakwatcher_semiauto.py b/test/scripts/testModule/test_jsleakwatcher_semiauto.py new file mode 100644 index 0000000000000000000000000000000000000000..839ad682a00c79c53bc994e1c4bcdcf3848aceac --- /dev/null +++ b/test/scripts/testModule/test_jsleakwatcher_semiauto.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Copyright (C) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import time +import pytest +import re +import os +import subprocess +import colorama + +class TestHicheckerjssdk: + @pytest.mark.L0 + def test_hichecker_leakwatchersdk(self): + subprocess.check_call("hdc install testModule/resource/jsleakwatchr.hap", shell=True) + time.sleep(3) + subprocess.check_call("hdc shell aa start -a EntryAbility -b com.example.myapplication", shell=True) + print(colorama.Fore.RED + "*********************************************") + print(colorama.Fore.RED + "*******请点击被打开的hap的dump按钮!!!*****") + print(colorama.Fore.RED + "*********************************************") + time.sleep(15) + command = "ls -l /data/app/el2/100/base/com.example.myapplication/haps/entry/files|grep -e heapsnapshot -e jsleaklist" + output = subprocess.check_output(f"hdc shell \"{command}\"", shell=True, text=True, encoding="utf-8") + assert "heapsnapshot" in output + assert "jsleaklist" in output + subprocess.check_call("hdc uninstall com.example.myapplication", shell=True) \ No newline at end of file