parent
3a576dfa6b
commit
3ff513a94d
10
README.md
10
README.md
|
@ -19,14 +19,16 @@
|
|||
|
||||
---
|
||||
|
||||
**Deepin 社区:** <a href="https://github.com/linuxdeepin/youqu" target="_blank">GitHub</a> | <a href="https://gitee.com/deepin-community/youqu" target="_blank">Gitee</a>
|
||||
**深度社区:<a href="https://github.com/linuxdeepin/youqu" target="_blank">linuxdeepin</a> | <a href="https://gitee.com/deepin-community/youqu" target="_blank">deepin-community</a>**
|
||||
|
||||
**openEuler 社区:** <a href="https://gitee.com/src-openeuler/youqu" target="_blank">Gitee</a>
|
||||
**欧拉社区: <a href="https://gitee.com/src-openeuler/youqu" target="_blank">src-openeuler</a>**
|
||||
|
||||
**官方文档:** <a href="https://youqu.uniontech.com" target="_blank">https://youqu.uniontech.com</a>
|
||||
**官方文档: <a href="https://youqu.uniontech.com" target="_blank">https://youqu.uniontech.com</a>**
|
||||
|
||||
**欢迎加入 [YouQu官方兴趣小组](https://youqu.uniontech.com/SIG.html)**
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
YouQu(有趣)是统信公司(Deepin/UOS)开源的一个 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。🔥
|
||||
|
@ -68,6 +70,8 @@ $ sudo pip3 install youqu
|
|||
$ youqu-startproject my_project
|
||||
```
|
||||
|
||||
注意:所有命令不要以 `root` 用户执行!
|
||||
|
||||
如果 `youqu-startproject` 后面不加参数,默认的项目名称为:`youqu` ;
|
||||
|
||||
![](./docs/assets/install.gif)
|
||||
|
|
16
RELEASE.md
16
RELEASE.md
|
@ -1,5 +1,21 @@
|
|||
# 版本更新记录
|
||||
|
||||
## 2.6.1(dev)
|
||||
|
||||
**Fix 🐛**
|
||||
|
||||
- 修复统计 `commit` 数据中修复方法数量错误的问题;
|
||||
|
||||
- 修改 JSON 报告计算逻辑:
|
||||
|
||||
- 用例总数 = 通过数 + 失败数 (剔除跳过数)
|
||||
|
||||
- 失败数:剔除跳过数
|
||||
|
||||
- 跳过数:跳过用例数
|
||||
|
||||
- 通过率 = 通过数 / 用例总数
|
||||
|
||||
## 2.6.0(2024/05/14)
|
||||
|
||||
近期,`YouQu` 自动化测试框架迎来了一系列令人振奋的更新,这些更新不仅提升了框架的性能和稳定性,也拓展了其功能和适用范围。通过引入 `OCR` 服务集群化部署和模型 `v4`,我们显著提高了文本识别的准确性和效率。新增的链式调用函数接口使操作更加直观和便捷。
|
||||
|
|
|
@ -14,28 +14,6 @@ h2 {
|
|||
|
||||
}
|
||||
|
||||
/* 提示框背景颜色 */
|
||||
:root {
|
||||
--vp-custom-block-tip-bg: var(--vp-c-green-soft);
|
||||
}
|
||||
|
||||
/* 提示框 */
|
||||
.custom-block.tip {
|
||||
border-color: var(--vp-c-green-2);
|
||||
}
|
||||
|
||||
/* 警告框 */
|
||||
.custom-block.warning {
|
||||
/* border-color: #d97706; */
|
||||
border-color: var(--vp-c-yellow-2);
|
||||
}
|
||||
|
||||
/* 危险框 */
|
||||
.custom-block.danger {
|
||||
/* border-color: #f43f5e; */
|
||||
border-color: var(--vp-c-red-2);
|
||||
}
|
||||
|
||||
.medium-zoom-overlay {
|
||||
z-index: 20;
|
||||
}
|
||||
|
|
11
docs/SIG.md
11
docs/SIG.md
|
@ -1,7 +1,12 @@
|
|||
# YouQu 官方兴趣小组(SIG)
|
||||
# YouQu 官方兴趣小组
|
||||
|
||||
------------
|
||||
|
||||
加入 YouQu 官方兴趣小组(SIG)群,与众多 Linux自动化测试专家交流,共同探索 YouQu 框架的无限可能,助力您的技术成长和职业发展!
|
||||
致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。
|
||||
|
||||
相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。
|
||||
|
||||
-----------
|
||||
|
||||
<img src="/wechat.jpg" width = "400" alt="YouQu官方兴趣小组" align=center/>
|
||||
|
||||
<img src="/wechat.jpg" width = "400" alt="YouQu官方兴趣小组" align=center />
|
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
|
@ -128,7 +128,29 @@ if __name__ == "__main__":
|
|||
|
||||
随着 OCR 服务在自动化测试子项目中被广泛使用,单台服务远不能满足业务需求,因此我们需要将 OCR 服务做分布式集群化部署,然后通过负载均衡技术将业务请求分发到 OCR 服务器上。
|
||||
|
||||
### 基于 Nginx 的负载均衡方案为什么不能满足业务需求
|
||||
### 为什么基于 Nginx 的负载均衡方案不能满足业务需求
|
||||
|
||||
1. 每 1 次 OCR 识别业务实际是 2 次 RPC 接口请求,第 1 次是将当前屏幕截图并发送到 PRC 服务器,第 2 次调用识别的接口做识别,采用 Nginx 轮询算法做负载均衡会出现 2 次 RPC 请求被分发到 2 台不同的服务器上,这明显是错误的。
|
||||
2. 基于 Nginx `ip_hash` 的 session 管理负载均衡算法时,Nginx 默认取 IP 的前 3 段做哈希,而我们的测试机都在同一个网段,IP 前 3 段是一样的,因此会导致负载不均衡。
|
||||
1. 每次 `OCR` 识别业务实际是两次 `RPC` 接口请求,第 1 次是将当前屏幕截图并发送到 `PRC` 服务器,第 2 次调用识别的接口做识别,采用 Nginx 轮询算法做负载均衡会出现两次 `RPC` 请求被分发到两台不同的服务器上,这明显是错误的。
|
||||
2. 基于 Nginx `ip_hash` 的 `session` 管理负载均衡算法时,Nginx 默认取 IP 的前 3 段做哈希,而我们的测试机都在同一个网段,IP 前 3 段是一样的,因此会导致负载不均衡。
|
||||
|
||||
### YouQu 的解决方案
|
||||
|
||||
为了解决上面 2 个问题,YouQu 在 `ocr_utils` 模块对 [pdocr-rpc](https://linuxdeepin.github.io/pdocr-rpc/) 功能进行了增强,实现了一个中间件用以在用例跑测过程中对 OCR 服务集群进行负载均衡。
|
||||
|
||||
![](/指南/元素定位/youqu-ocr.png)
|
||||
|
||||
## 链式调用
|
||||
|
||||
YouQu OCR 支持链式调用函数接口,使用更方便更符合语义,原函数接口使用方法不变以保持兼容性。
|
||||
|
||||
```python
|
||||
from src import OCR
|
||||
|
||||
# 新的函数接口ocrx,支持链式调用
|
||||
OCR.ocrx("确定").click()
|
||||
OCR.ocrx("确定").center()
|
||||
OCR.ocrx("确定").right_click()
|
||||
OCR.ocrx("确定").double_click()
|
||||
# 原函数接口ocr,返回坐标
|
||||
OCR.ocr("确定")
|
||||
```
|
||||
|
|
|
@ -33,6 +33,12 @@ export PATH=$PATH:$HOME/.local/lib/pythonX.X/site-packages
|
|||
$ youqu-startproject my_project
|
||||
```
|
||||
|
||||
::: danger 注意
|
||||
|
||||
不要以 `root` 用户执行命令!
|
||||
|
||||
:::
|
||||
|
||||
如果 `youqu-startproject` 后面不加参数,默认的项目名称为:`youqu` ;
|
||||
|
||||
![](/install.gif)
|
||||
|
|
2
env.sh
2
env.sh
|
@ -44,7 +44,7 @@ PYTHON_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.v
|
|||
whitelist="/usr/share/deepin-elf-verify/whitelist"
|
||||
pypi_mirror="https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||
|
||||
echo "${PASSWORD}" | sudo -S su
|
||||
echo "${PASSWORD}" | sudo -S su > /dev/null 2>&1
|
||||
|
||||
if [ ! -f "$HOME/.Xauthority" ]; then
|
||||
touch $HOME/.Xauthority
|
||||
|
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||
|
||||
[project]
|
||||
name = "youqu"
|
||||
version = "2.6.0"
|
||||
version = "2.6.1"
|
||||
authors = [
|
||||
{ name = "mikigo", email = "huangmingqiang@uniontech.com" },
|
||||
]
|
||||
|
|
|
@ -40,16 +40,13 @@ def git_control(parser=None, sub_parser_git=None):
|
|||
from src.git.clone import clone as git_clone
|
||||
check_git_installed()
|
||||
git_clone(**git_kwargs)
|
||||
elif all(
|
||||
[
|
||||
git_kwargs.get(Args.app_name.value),
|
||||
git_kwargs.get(Args.startdate.value),
|
||||
]
|
||||
):
|
||||
from src.git.code_statistics import CodeStatistics
|
||||
|
||||
check_git_installed()
|
||||
CodeStatistics(**git_kwargs).codex()
|
||||
if git_kwargs.get(Args.app_name.value):
|
||||
if git_kwargs.get(Args.startdate.value):
|
||||
from src.git.code_statistics import CodeStatistics
|
||||
|
||||
check_git_installed()
|
||||
CodeStatistics(**git_kwargs).codex()
|
||||
else:
|
||||
print("-s/--startdate 参数未传入")
|
||||
else:
|
||||
print("参数异常")
|
||||
print("-a/--app 参数未传入")
|
||||
|
|
|
@ -11,6 +11,7 @@ from setting import conf
|
|||
from src.depends.colorama import Fore
|
||||
from src.git.commit import Commit
|
||||
from src.rtk._base import transform_app_name
|
||||
from src import logger
|
||||
|
||||
|
||||
class CodeStatistics(Commit):
|
||||
|
@ -61,8 +62,8 @@ class CodeStatistics(Commit):
|
|||
for filepath in git_files:
|
||||
filename = filepath.split("/")[-1]
|
||||
dif_texts = os.popen(f"cd {self.repo_path}/;git show {commit_id} -- {filepath}").read()
|
||||
print(Fore.GREEN, "=" * 100, Fore.RESET)
|
||||
print(filepath, "\n", dif_texts)
|
||||
logger.info(Fore.GREEN + ("=" * 100) + Fore.RESET)
|
||||
logger.info(filepath + "\n" + dif_texts)
|
||||
dif_lines = dif_texts.splitlines()
|
||||
# case
|
||||
if filename.startswith("test_"):
|
||||
|
@ -157,8 +158,8 @@ class CodeStatistics(Commit):
|
|||
f.write(json.dumps(res, ensure_ascii=False, indent=4, default=None))
|
||||
|
||||
with open(result_file, "r", encoding="utf-8") as f:
|
||||
print(f.read())
|
||||
print(f"{Fore.GREEN}数据结果{'详细' if detail else '汇总'}报告:{result_file}{Fore.RESET}")
|
||||
logger.info(f.read())
|
||||
logger.info(f"{Fore.GREEN}数据结果{'详细' if detail else '汇总'}报告:{result_file}{Fore.RESET}")
|
||||
|
||||
def codex(self):
|
||||
results = None
|
||||
|
@ -193,7 +194,7 @@ class CodeStatistics(Commit):
|
|||
|
||||
if results is None:
|
||||
raise ValueError()
|
||||
print(Fore.GREEN, "=" * 100, Fore.RESET)
|
||||
logger.info(Fore.GREEN + ("=" * 100) + Fore.RESET)
|
||||
self.write_result(results)
|
||||
if results_detail:
|
||||
self.write_result(results_detail, detail=True)
|
||||
|
|
|
@ -89,34 +89,34 @@ class OCRUtils:
|
|||
return cls.result
|
||||
|
||||
@classmethod
|
||||
def check_xy(cls):
|
||||
def _check_xy(cls):
|
||||
if cls.x is None and cls.y is None:
|
||||
raise ValueError("ocr_pro 没有识别到")
|
||||
raise ValueError("ocrx 没有识别到")
|
||||
|
||||
@classmethod
|
||||
def click(cls):
|
||||
from src.mouse_key import MouseKey
|
||||
cls.check_xy()
|
||||
cls._check_xy()
|
||||
MouseKey.click(cls.x, cls.y)
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
def right_click(cls):
|
||||
from src.mouse_key import MouseKey
|
||||
cls.check_xy()
|
||||
cls._check_xy()
|
||||
MouseKey.right_click(cls.x, cls.y)
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
def double_click(cls):
|
||||
from src.mouse_key import MouseKey
|
||||
cls.check_xy()
|
||||
cls._check_xy()
|
||||
MouseKey.double_click(cls.x, cls.y)
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
def center(cls):
|
||||
cls.check_xy()
|
||||
cls._check_xy()
|
||||
return cls.x, cls.y
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -85,11 +85,12 @@ def transform_app_name(app_name):
|
|||
|
||||
def collect_result(results):
|
||||
res = Counter([results.get(i).get("result") for i in results])
|
||||
total = sum(res.values())
|
||||
_total = sum(res.values())
|
||||
skiped = res.get("skip", 0)
|
||||
total = _total - skiped
|
||||
passed = res.get("pass", 0)
|
||||
failed = total - skiped - passed
|
||||
pass_rate = f"{round((passed / (total - skiped)) * 100, 2)}%" if passed else "0%"
|
||||
failed = total - passed
|
||||
pass_rate = f"{round((passed / total) * 100, 2)}%" if passed else "0%"
|
||||
return total, failed, passed, skiped, pass_rate
|
||||
|
||||
|
||||
|
@ -125,5 +126,6 @@ def write_json(project_name=None, build_location=None, line=None):
|
|||
with open(json_res_path, "w+", encoding="utf-8") as _f:
|
||||
_f.write(json.dumps(results, indent=2, ensure_ascii=False))
|
||||
sleep(1)
|
||||
from src import logger
|
||||
with open(json_res_path, "r", encoding="utf-8") as _f:
|
||||
print("CICD数据结果:\n", _f.read())
|
||||
logger.info("CICD数据结果:\n", _f.read())
|
||||
|
|
|
@ -187,7 +187,7 @@ echo "${python_virtualenv_path}"
|
|||
pipenv run pip list
|
||||
system_env
|
||||
|
||||
echo 'pipenv run python "$@"' | sudo tee /usr/bin/youqu > /dev/null 2>&1
|
||||
echo 'export PIPENV_VERBOSITY=-1;pipenv run python "$@"' | sudo tee /usr/bin/youqu > /dev/null 2>&1
|
||||
echo "pipenv shell" | sudo tee /usr/bin/youqu-shell > /dev/null 2>&1
|
||||
echo "pipenv --rm" | sudo tee /usr/bin/youqu-rm > /dev/null 2>&1
|
||||
sudo chmod +x /usr/bin/youqu
|
||||
|
|
Loading…
Reference in New Issue