fix: 1、修复了远程交互式控制执行的Bug;2、优化了文档内容;

Description:

Log:
This commit is contained in:
mikigo 2024-04-19 17:47:04 +08:00
parent 8de8793c9d
commit 3fa8aa911a
48 changed files with 157 additions and 2642 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ site
public
node_modules/
docs/.vitepress/cache/
pnpm-lock.yaml

View File

@ -10,7 +10,7 @@
## 向 YouQu 提交 Issues
Issues 提交地址https://github.com/linuxdeepin/deepin-autotest-framework/issues
Issues 提交地址https://github.com/linuxdeepin/youqu/issues
## 向 YouQu 仓库提交代码

View File

@ -1,5 +1,5 @@
<p align="center">
<a href="https://linuxdeepin.github.io/deepin-autotest-framework/">
<a href="https://linuxdeepin.github.io/youqu/">
<img src="./docs/assets/logo.png" width="520" alt="YouQu">
</a>
</p>
@ -8,9 +8,9 @@
</p>
[![GitHub issues](https://img.shields.io/github/issues/linuxdeepin/deepin-autotest-framework?color=%23F79431)](https://github.com/linuxdeepin/deepin-autotest-framework/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/linuxdeepin/deepin-autotest-framework?color=%23F79431)](https://github.com/linuxdeepin/deepin-autotest-framework/pulls)
[![GitHub Discussions](https://img.shields.io/github/discussions/linuxdeepin/deepin-autotest-framework?color=%23F79431)](https://github.com/linuxdeepin/deepin-autotest-framework/discussions)
[![GitHub issues](https://img.shields.io/github/issues/linuxdeepin/youqu?color=%23F79431)](https://github.com/linuxdeepin/youqu/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/linuxdeepin/youqu?color=%23F79431)](https://github.com/linuxdeepin/youqu/pulls)
[![GitHub Discussions](https://img.shields.io/github/discussions/linuxdeepin/youqu?color=%23F79431)](https://github.com/linuxdeepin/youqu/discussions)
[![PyPI](https://img.shields.io/pypi/v/youqu?style=flat&logo=github&link=https%3A%2F%2Fpypi.org%2Fproject%2Fyouqu%2F&color=%23F79431)](https://pypi.org/project/youqu/)
![PyPI - License](https://img.shields.io/pypi/l/youqu?color=%23F79431)
@ -22,16 +22,16 @@
[![Downloads](https://static.pepy.tech/badge/youqu/month)](https://pepy.tech/project/youqu)
[![Downloads](https://static.pepy.tech/badge/youqu)](https://pepy.tech/project/youqu)
[![Hits](https://hits.sh/github.com/linuxdeepin/deepin-autotest-framework.svg?style=flat&label=Github_Hits&color=blue)](https://github.com/linuxdeepin/deepin-autotest-framework)
[![Hits](https://hits.sh/linuxdeepin.github.io/deepin-autotest-framework.svg?style=flat&label=GitHub_Pages_Hits&color=blue)](https://linuxdeepin.github.io/deepin-autotest-framework)
[![Hits](https://hits.sh/deepin-community.gitee.io/deepin-autotest-framework.svg?style=flat&label=Gitee_Pages_Hits&color=blue)](https://deepin-community.gitee.io/deepin-autotest-framework/)
[![Hits](https://hits.sh/github.com/linuxdeepin/youqu.svg?style=flat&label=Github_Hits&color=blue)](https://github.com/linuxdeepin/youqu)
[![Hits](https://hits.sh/linuxdeepin.github.io/youqu.svg?style=flat&label=GitHub_Pages_Hits&color=blue)](https://linuxdeepin.github.io/youqu)
[![Hits](https://hits.sh/deepin-community.gitee.io/youqu.svg?style=flat&label=Gitee_Pages_Hits&color=blue)](https://deepin-community.gitee.io/youqu/)
[![Hits](https://hits.sh/pypi.org/project/youqu.svg?style=flat&label=PyPI_Hits&color=blue)](https://pypi.org/project/youqu/)
---
<a href="https://github.com/linuxdeepin/deepin-autotest-framework" target="_blank">GitHub</a> / <a href="https://gitee.com/deepin-community/deepin-autotest-framework" target="_blank">Gitee</a>
<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://linuxdeepin.github.io/deepin-autotest-framework" target="_blank">在线文档</a>
<a href="https://linuxdeepin.github.io/youqu" target="_blank">在线文档</a>
---
@ -216,7 +216,7 @@ $ youqu manage.py run --app apps/autotest_deepin_music --keywords "xxx" --tags "
</div>
更多参数请查看【[命令行参数](https://linuxdeepin.github.io/deepin-autotest-framework/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#21)】
更多参数请查看【[命令行参数](https://linuxdeepin.github.io/youqu/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#21)】
#### 2.2. 配置文件
@ -224,7 +224,7 @@ $ youqu manage.py run --app apps/autotest_deepin_music --keywords "xxx" --tags "
在配置文件 `setting/globalconfig.ini` 里面支持配置对执行的一些参数进行配置,配置完成之后,直接在命令行执行 `manage.py` 就好了。
详细配置项请查看【[配置项](https://linuxdeepin.github.io/deepin-autotest-framework/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#22)】
详细配置项请查看【[配置项](https://linuxdeepin.github.io/youqu/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#22)】
### 3. 远程执行
@ -365,23 +365,23 @@ $ youqu manage.py remote -a ... --parallel no
## 贡献者
[贡献文档](https://github.com/linuxdeepin/deepin-autotest-framework/blob/master/CONTRIBUTING.md)
[贡献文档](https://github.com/linuxdeepin/youqu/blob/master/CONTRIBUTING.md)
--8<-- "docs/contributors.html"
## 开源许可证
有趣 在 [GPL-2.0-only](https://github.com/linuxdeepin/deepin-autotest-framework/blob/master/LICENSE) 下发布。
有趣 在 [GPL-2.0-only](https://github.com/linuxdeepin/youqu/blob/master/LICENSE) 下发布。
------------
[__Github Star History__]()
[![Stargazers over time](https://starchart.cc/linuxdeepin/deepin-autotest-framework.svg)](https://starchart.cc/linuxdeepin/deepin-autotest-framework)
[![Stargazers over time](https://starchart.cc/linuxdeepin/youqu.svg)](https://starchart.cc/linuxdeepin/youqu)
[__Gitee Info__]()
[![deepin-community/deepin-autotest-framework](https://gitee.com/deepin-community/deepin-autotest-framework/widgets/widget_card.svg?colors=4183c4,ffffff,ffffff,e3e9ed,666666,9b9b9b)](https://gitee.com/deepin-community/deepin-autotest-framework)
[![deepin-community/youqu](https://gitee.com/deepin-community/youqu/widgets/widget_card.svg?colors=4183c4,ffffff,ffffff,e3e9ed,666666,9b9b9b)](https://gitee.com/deepin-community/youqu)

View File

@ -30,26 +30,26 @@
**New**
- `startapp` 初始化应用新增 2 条示例用例和一个方法;[issues #46](https://github.com/linuxdeepin/deepin-autotest-framework/issues/46) by [@mikigo](https://github.com/mikigo)
- 新增子命令 `youqu manage.py git` 可用于拉取 `git` 仓库代码到 `apps` 目录下,支持统计分析仓库新增修复的用例或方法数量;[issues #40](https://github.com/linuxdeepin/deepin-autotest-framework/issues/40) by [@mikigo](https://github.com/mikigo)
- 更新[贡献者名单](https://linuxdeepin.github.io/deepin-autotest-framework/#_4)
- `startapp` 初始化应用新增 2 条示例用例和一个方法;[issues #46](https://github.com/linuxdeepin/youqu/issues/46) by [@mikigo](https://github.com/mikigo)
- 新增子命令 `youqu manage.py git` 可用于拉取 `git` 仓库代码到 `apps` 目录下,支持统计分析仓库新增修复的用例或方法数量;[issues #40](https://github.com/linuxdeepin/youqu/issues/40) by [@mikigo](https://github.com/mikigo)
- 更新[贡献者名单](https://linuxdeepin.github.io/youqu/#_4)
**Fix**
- 修复 `env.sh` 中 Python 虚拟环境的解释器版本没有动态获取系统中的 Python 版本的问题;[PR #51](https://github.com/linuxdeepin/deepin-autotest-framework/pull/51) by [@saifeiLee](https://github.com/saifeiLee)
- 修复 `wayland` 环境下 `XAUTHORITY` 环境变量缺失问题;[PR #55](https://github.com/linuxdeepin/deepin-autotest-framework/pull/55) by [@DarkLii](https://github.com/DarkLii)
- `assert_ocr_exist` 新增 `any` 匹配模式,即任意一个匹配成功则通过;[PR #55](https://github.com/linuxdeepin/deepin-autotest-framework/pull/55) by [@DarkLii](https://github.com/DarkLii)
- 修复 `env.sh` 中 Python 虚拟环境的解释器版本没有动态获取系统中的 Python 版本的问题;[PR #51](https://github.com/linuxdeepin/youqu/pull/51) by [@saifeiLee](https://github.com/saifeiLee)
- 修复 `wayland` 环境下 `XAUTHORITY` 环境变量缺失问题;[PR #55](https://github.com/linuxdeepin/youqu/pull/55) by [@DarkLii](https://github.com/DarkLii)
- `assert_ocr_exist` 新增 `any` 匹配模式,即任意一个匹配成功则通过;[PR #55](https://github.com/linuxdeepin/youqu/pull/55) by [@DarkLii](https://github.com/DarkLii)
## 2.5.02024/03/04
**New**
- `startapp` 初始化工程新增 `.gitignore` 文件;[issues #43](https://github.com/linuxdeepin/deepin-autotest-framework/issues/43) by [@mikigo](https://github.com/mikigo)
- `startapp` 初始化工程新增 `.gitignore` 文件;[issues #43](https://github.com/linuxdeepin/youqu/issues/43) by [@mikigo](https://github.com/mikigo)
**Fix**
- 修复 `startapp` 初始化工程中的错误;[@mikigo](https://github.com/mikigo)
- 修复 `skip` 用例在收集阶段报错;[issues #44](https://github.com/linuxdeepin/deepin-autotest-framework/issues/44) by [@mikigo](https://github.com/mikigo)
- 修复 `skip` 用例在收集阶段报错;[issues #44](https://github.com/linuxdeepin/youqu/issues/44) by [@mikigo](https://github.com/mikigo)
## 2.4.62024/02/26
@ -57,8 +57,8 @@
- 计算收集用例数量剔除 `skip``skipif` 的用例数量;[@mikigo](https://github.com/mikigo)
- 报告新增显示当前目录;[@mikigo](https://github.com/mikigo)
- 启用 `Ruff` 代码检查;[issues #38](https://github.com/linuxdeepin/deepin-autotest-framework/issues/38) by [@mikigo](https://github.com/mikigo)
- 新增定制依赖功能支持应用库定义 `deb` 形式 `Python` 包;[issues #37](https://github.com/linuxdeepin/deepin-autotest-framework/issues/37) by [@mikigo](https://github.com/mikigo)
- 启用 `Ruff` 代码检查;[issues #38](https://github.com/linuxdeepin/youqu/issues/38) by [@mikigo](https://github.com/mikigo)
- 新增定制依赖功能支持应用库定义 `deb` 形式 `Python` 包;[issues #37](https://github.com/linuxdeepin/youqu/issues/37) by [@mikigo](https://github.com/mikigo)
**Fix**
@ -100,25 +100,25 @@
**New**
- `UOS 1070` `Wayland` 下窗管团队提供了新的接口(`GetAllWindowStatesList`)用于获取桌面所有窗口的信息,`YouQu` 进行开发适配并兼容新老接口,至此基于 `UI` 的元素定位方案在 `Wayland` 下表现和 `X11` 下表现一致,堪称完美;[issues #21](https://github.com/linuxdeepin/deepin-autotest-framework/issues/21)
- `UOS 1070` `Wayland` 下窗管团队提供了新的接口(`GetAllWindowStatesList`)用于获取桌面所有窗口的信息,`YouQu` 进行开发适配并兼容新老接口,至此基于 `UI` 的元素定位方案在 `Wayland` 下表现和 `X11` 下表现一致,堪称完美;[issues #21](https://github.com/linuxdeepin/youqu/issues/21)
本次功能更新离不开多个部门领导和同事们的协助,这里特别感谢:**[@佳斌](https://github.com/king123666)** **[@孙翠](https://gitlabbj.uniontech.com/ut003620)** **[@泽铭](https://github.com/Jimijun)** **[@任斌](https://github.com/rb-union)**
- 新增贡献者名单及贡献规则文档;[issues #23](https://github.com/linuxdeepin/deepin-autotest-framework/issues/23)
- 新增贡献者名单及贡献规则文档;[issues #23](https://github.com/linuxdeepin/youqu/issues/23)
**Fix**
- 修复 `Wayland``sniff` 命令报错 `~/.Xauthorty` 文件不存在;[issues #22](https://github.com/linuxdeepin/deepin-autotest-framework/issues/22)
- 修复远程执行数据回填过程中报 `HTTPError`[issues #24](https://github.com/linuxdeepin/deepin-autotest-framework/issues/24)
- 修复偶现测试报告生成阶段报错;[issues #25](https://github.com/linuxdeepin/deepin-autotest-framework/issues/25)
- 修复 `globalconfig.ini` 配置文件中 `IMAGE_RATE` 配置项不生效;[issues #26](https://github.com/linuxdeepin/deepin-autotest-framework/issues/26)
- 修复 `Wayland``sniff` 命令报错 `~/.Xauthorty` 文件不存在;[issues #22](https://github.com/linuxdeepin/youqu/issues/22)
- 修复远程执行数据回填过程中报 `HTTPError`[issues #24](https://github.com/linuxdeepin/youqu/issues/24)
- 修复偶现测试报告生成阶段报错;[issues #25](https://github.com/linuxdeepin/youqu/issues/25)
- 修复 `globalconfig.ini` 配置文件中 `IMAGE_RATE` 配置项不生效;[issues #26](https://github.com/linuxdeepin/youqu/issues/26)
## 2.3.72023/12/15
**New**
- `src/__init__.py` 里面的导入全部设置别名,以便后续各组件重命名之后仍能保持接口一致性和兼容性;[@mikigo](https://github.com/mikigo)
- 将 `Wayland` 下输入的方法区分中英文,中文按现有 `input_message` 处理,英文数字字符等使用 `press_key` 处理; [issues #17](https://github.com/linuxdeepin/deepin-autotest-framework/issues/17)
- 将 `Wayland` 下输入的方法区分中英文,中文按现有 `input_message` 处理,英文数字字符等使用 `press_key` 处理; [issues #17](https://github.com/linuxdeepin/youqu/issues/17)
- 有些镜像没有 `$HOME/.Xauthority` 文件(咱也不知道为啥),`YouQu` 执行会报错,我们只能创建一个空的同名文件,以确保程序能正常运行,但 `Xlib.xauth` 获取不到有效信息会有一些 `warning` 日志,看着烦人我都能接受,不能接受的是经常会导致大家在分析用例失败原因的时候将矛头指向它,然后每次我就需要解释这个 `warning` 提示不是问题,因此在底层将这部分日志输出屏蔽掉;[@mikigo](https://github.com/mikigo)
**Fix**
@ -130,7 +130,7 @@
**New**
- 标签化管理支持判断系统版本跳过用例,用 `/etc/os-version` 里面的 `MinorVersion` 字段作为判断依据,在 `setting/skipif.py` 插件中实现了此功能,后续在 `CSV` 文件中可以使用此方法进行条件跳过;[issues #16](https://github.com/linuxdeepin/deepin-autotest-framework/issues/16)
- 标签化管理支持判断系统版本跳过用例,用 `/etc/os-version` 里面的 `MinorVersion` 字段作为判断依据,在 `setting/skipif.py` 插件中实现了此功能,后续在 `CSV` 文件中可以使用此方法进行条件跳过;[issues #16](https://github.com/linuxdeepin/youqu/issues/16)
```python hl_lines="59-68"
--8<-- "setting/skipif.py:59:68"
@ -138,10 +138,10 @@
**Fix**
- 修复 `Wayland` 下系统监视器使用 `WaylandWindowInfo.window_info()`,获取的窗口名称为空;[issues #18](https://github.com/linuxdeepin/deepin-autotest-framework/issues/20)
- 解除 `env.sh` 中某个 `deb` 包安装失败后替换源 `retry` 机制,因为用固定的源替换之后,容易出现某些包安装失败,而不容易关注到首次包安装失败的问题,给定位环境安装失败带来困难;[issues #19](https://github.com/linuxdeepin/deepin-autotest-framework/issues/19)
- 修复 `Wayland` 下系统监视器使用 `WaylandWindowInfo.window_info()`,获取的窗口名称为空;[issues #18](https://github.com/linuxdeepin/youqu/issues/20)
- 解除 `env.sh` 中某个 `deb` 包安装失败后替换源 `retry` 机制,因为用固定的源替换之后,容易出现某些包安装失败,而不容易关注到首次包安装失败的问题,给定位环境安装失败带来困难;[issues #19](https://github.com/linuxdeepin/youqu/issues/19)
- 修复 `env.sh` 里面报错 `ERROR: unknown command "cache" - maybe you meant "check"`[@mikigo](https://github.com/mikigo)
- 修复用例收集数量为 `0` 时,报错 `ci_result.json` 文件找不到;[issues #20](https://github.com/linuxdeepin/deepin-autotest-framework/issues/20)
- 修复用例收集数量为 `0` 时,报错 `ci_result.json` 文件找不到;[issues #20](https://github.com/linuxdeepin/youqu/issues/20)
## 2.3.52023/12/04
@ -292,7 +292,7 @@ fix
new
- 将有趣的文档系统迁移到 **[@linuxdeepin](https://github.com/linuxdeepin/deepin-autotest-framework)** ,剥离文档中的图片资源,采用 `CDN` 网络加速方式加载;[@mikigo](https://github.com/mikigo)
- 将有趣的文档系统迁移到 **[@linuxdeepin](https://github.com/linuxdeepin/youqu)** ,剥离文档中的图片资源,采用 `CDN` 网络加速方式加载;[@mikigo](https://github.com/mikigo)
- 尝试合入一个有趣的功能;
@ -409,7 +409,7 @@ youqu manage.py run
**4、新的文档地址**
过去咱们 `YouQu` 的在线文档是部署在公司内网的,现在开源到 github 了,外部开发者肯定访问不到内网的文档,因此需要将文档部署到公网【[公网文档](https://linuxdeepin.github.io/deepin-autotest-framework/)】;
过去咱们 `YouQu` 的在线文档是部署在公司内网的,现在开源到 github 了,外部开发者肯定访问不到内网的文档,因此需要将文档部署到公网【[公网文档](https://linuxdeepin.github.io/youqu/)】;
公网文档使用的是 github pages白嫖怪一顿狂喜~~),但可能会出现文档速度慢的问题(代理下就好了),不过没关系,咱们【[内网文档](http://youqu.uniontech.com/)】仍然保留,文档内容一样,访问速度更快。

View File

@ -1,3 +1,4 @@
import {defineConfig} from 'vitepress'
import {withMermaid} from "vitepress-plugin-mermaid";
import timeline from "vitepress-markdown-timeline";
@ -23,29 +24,74 @@ export default withMermaid(
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
siteTitle: "官方中文文档",
siteTitle: "",
nav: [
{text: '指南', link: '/快速开始'},
{text: '框架设计', link: '/AT基础框架设计方案'},
{text: '指南', link: '/指南/简介/快速开始'},
{text: '框架设计', link: '/框架设计/AT基础框架设计方案'},
{text: 'FAQ', link: '/FAQ'},
{text: '更新日志', link: '/RELEASE'},
{
text: '插件', items: [
{text: "funnylog", link: "https://linuxdeepin.github.io/funnylog/"},
{text: "letmego", link: "https://linuxdeepin.github.io/letmego/"},
{text: "pdocr-rpc", link: "https://linuxdeepin.github.io/pdocr-rpc/"},
{text: "image-center", link: "https://linuxdeepin.github.io/image-center/"},
]
},
],
sidebar: {
"/快速开始/": [
"/指南/": [
{
text: "快速开始",
text: "简介",
items: [
{text: "YouQu是什么", link: "/快速开始"},
{text: "YouQu是什么", link: "/指南/简介/YouQu是什么"},
{text: "快速开始", link: "/指南/简介/快速开始"},
]
},
{
text: "框架功能介绍",
text: "环境",
collapsed: false,
items: [
{text: "环境部署", link: "/框架功能介绍/环境部署"},
{text: "全局配置", link: "/框架功能介绍/全局配置"},
{text: "环境部署", link: "/指南/环境/环境部署"},
{text: "全局配置", link: "/指南/环境/全局配置"},
]
},
{
text: "元素定位",
collapsed: false,
items: [
{text: "图像识别", link: "/指南/元素定位/图像识别"},
{text: "属性定位", link: "/指南/元素定位/属性定位"},
{text: "OCR识别", link: "/指南/元素定位/OCR识别"},
{text: "相对坐标定位", link: "/指南/元素定位/相对坐标定位"},
]
},
{
text: "框架必备",
collapsed: false,
items: [
{text: "执行管理器", link: "/指南/框架必备/执行管理器"},
{text: "测试报告", link: "/指南/框架必备/测试报告"},
{text: "键鼠操作", link: "/指南/框架必备/键鼠操作"},
]
},
{
text: "特色功能",
collapsed: false,
items: [
{text: "标签化管理", link: "/指南/特色功能/标签化管理"},
{text: "全自动日志", link: "/指南/特色功能/全自动日志"},
{text: "失败录屏", link: "/指南/特色功能/失败录屏"},
{text: "标签自动同步", link: "/指南/特色功能/标签自动同步"},
{text: "Wayland适配", link: "/指南/特色功能/Wayland适配"},
{text: "重启类场景", link: "/指南/特色功能/重启类场景"},
{text: "数据回填", link: "/指南/特色功能/数据回填"},
]
},
],
"框架设计": [
"/框架设计/": [
{text: "AT应用库设计方案", link: "/框架设计/自动化测试架构设计v1.0"},
{text: "AT基础框架设计方案", link: "/框架设计/AT基础框架设计方案"},
{text: "AT应用库设计方案", link: "/框架设计/AT应用库设计方案"},
]

View File

@ -1,535 +0,0 @@
# AT 开发规范
```shell
# ================================================
# Author : mikigo
# ================================================
```
AT 开发规范是根据自动化测试运行多年以来,遇到问题解决问题而形成的一些解决方案,或者说经验总结;
这些经验符合我们现阶段 AT 所应用的场景需要,也是我们经过长期思考,不断试错不断修正,并在自动化测试项目实践中检验过可行的。
以此,希望能帮助参与到自动化的相关人员减少试错成本,更好、更快的编写用例及维护用例。
## 1. 版本及依赖
基础框架会根据自身的功能开发进行版本迭代发布,==基础框架不与某个应用版本绑定==
但是,==应用库会依赖于基础框架的版本==。因此,我们建议在 ==应用库== 目录下保存一个文本文件用于记录所依赖的基础框架版本,类似于开发应用的 `debian/control` 文件的功能,为了保持统一,这个文件就命名为 `control`,放在应用库根目录下。
## 2. 命名规范
- ==用例 ID==
每个应用自己维护一套 ID可以是你自定义的 ID 值,也可以是用某些特有的 ID比如 PMS 用例ID
一个用例类里面有多个用例时,在用例名称后面加序号。
```python title="多用例函数命名"
class TestFileManager(BaseCase):
"""文管用例"""
def test_xxx_015_1(self):
pass
def test_xxx_015_2(self):
pass
```
- ==方法函数命名==
???+ note "方法函数命名关键词列表"
| 名称 | 单词 |
| :----------------- | :----------------------------- |
| 左键点击 | click |
| 右键点击 | right_click |
| 双击 | double_click |
| 移动 | move_to |
| 拖动 | drag |
| 新建 | new |
| 拖动到 | drag_to |
| 从哪里拖动到哪里 | drag_something_from_xxx_to_xxx |
| 获取 | get |
| 获取某个元素的坐标 | get_location |
| 非特殊文件 | file |
| word文件 | doc |
| text文件 | text |
| 文件夹 | dir |
- ==常量关键词命名==
???+ note "常量关键词列表"
| 名称 | 单词 |
| :----------------------------- | :--------- |
| 应用名称 | `APP_NAME` |
| 应用描述 | `DESC` |
| 本应用以外的其他应用,比如帮助 | `HELP` |
- ==方法层文件名==
???+ note "方法层文件名称列表"
| 名称 | 单词 |
| ---------------------------- | :----------------------------------------------------------- |
| 方法包名 | widget |
| 方法文件名<br />(文管举例) | `dfm_widget.py`<br />`title_widget.py`<br />`right_view_widget.py`<br />`left_view_widget.py`<br />`pop_widget.py`<br />`base_widget.py`<br />`dfm_assert.py` |
- ==断言语句名称==
???+ note "断言语句命名规范"
断言语句都是以 assert 开头
| 断言 | 语句 |
| :------------------------- | :----------------------------------------------------------- |
| 判断文件是否存在 | assert_file_exists<br />assert_file_not_exists |
| 判断桌面目录下文件是否存在 | assert_file_exists_in_desktop<br />assert_file_not_exists_in_desktop |
| 判断图片存在 | assert_image_exists<br />assert_image_not_exists |
| 判断影院中是否存在图片 | assert_image_exists_in_movie<br />assert_image_not_exists_in_movie |
| 判断元素是否存在 | assert_element_exist<br />assert_element_not_exist |
| 判断是否相等 | assert_equal<br />assert_not_equal |
| 判断是否为真 | assert_true<br />assert_false |
## 3. Fixture 规范
为统一编码风格方便后续用例代码维护,现做以下规范说明:
- 不建议使用 `Xunit` 的写法,统一采用 `Pytest` `fixture` 的写法。
- 应用内 `fixture` 谨慎使用 `autouse=True` ,非必要的情况下非常不建议使用这个参数。
- 调用 `fixture` 不能使用 `@pytest.mark.usefixture()`,使用直接在用例里面传入函数对象。
- 建议在一个 `conftest.py` 里面去写 `fixture`,一个应用也尽量维护一个 `conftest.py `文件。
- `fixture` 也需要写功能说明,函数名称要有具体含义。
## 4. 方法编写&调用规范
### 4.1. 方法编写
- ==写方法的时候注意方法归属;==
比如文件管理器的界面区域划分为:`TitleWidget` 、`RightViewWidget`、`LeftViewWidget` 、`PopWidget`,方法是在哪个区域操作的,就写在哪个类里面。
举例:
```python hl_lines="3"
from apps.autotest_dde_file_manager.widget import BaseWidget
class TitleWidget(BaseWidget):
"""标题栏方法类"""
def click_xxx_in_title_by_ui(self):
"""点击标题栏xxx"""
# self.dog.find_element_by_attr("xxxx").click()
self.click(*self.ui.btn_center("xxx"))
```
- ==动作开头,注意是动词;==
```asciiarmor
click
double_click
right_click
get
make
```
- ==元素对象名称;==
界面元素直接与元素名称相同,没有名称的就取一个好听易懂的名字。
- ==加上类的关键词;==
避免方法重名,同时可以标记区域。
- ==标定操作方法类型;==
```asciiarmor
by_ui
by_attr
by_mk
by_img
```
- ==正确使用方法类型;==
```python title="方法类型使用逻辑"
if 没有用到实例对象:
if 没有用到类对象:
写静态方法,函数前加 @staticmethod
else
写类方法,函数前加 @classmethod
else:
直接写实例方法
```
举例:
```python hl_lines="2-3 6-7 10-11"
class TitleWidget:
def click_xxx_by_ui(self):
pass
@staticmethod
def click_xxx_by_ui():
pass
@classmethod
def click_xxx_by_ui(cls):
pass
```
- 函数名称尽量不出现数字,需要表示数量的用单词表示。
- ==函数功能注释;==
- 没有参数,没有返回,直接写函数功能说明;
```python
"""点击某个元素"""
```
- 有参数,没有返回,需要写各参数说明;
```python
"""点击某个元素
arg1:xxx
arg2:xxx
"""
```
- 有参数,有返回,需要写返回值说明;
```python
"""点击某个元素
arg1:xxx
arg1:xxx
return: xxx
"""
```
`Pycharm` 的注释模板也可以,只要体现了参数的类型和返回就行了。
- 暂不要求写类型注解。
### 4.2. 方法调用
在用例中调用方法,通过该应用唯一的出口进行调用,比如文件管理器的统一出口类:
```python hl_lines="1"
class DfmWidget(TitleWidget, RightViewWidget, LeftViewWidget, PopWidget):
pass
```
在用例里面只需要导入这一个类即可;
```python hl_lines="1 9"
from apps.autotest_dde_file_manager.widget import DfmWidget
from apps.autotest_dde_file_manager.case.base_case import BaseCase
class TestDdeFileManager(BaseCase):
"""文件管理器用例"""
def test_xxx_001(self):
"""xxx"""
dfm = DfmWidget()
dfm.click_xxx_by_attr()
```
==尽量不要在用例中单独去调用 TitleWidget 、RightViewWidget、LeftViewWidget 、PopWidget 这些类==,否则后期用例会变得不好维护;
## 5. 用例编写规范
### 5.1. 基于类写用例
所有用例都应该基于类去写:
```python hl_lines="1"
class TestMusic(BaseCase):
"""音乐用例"""
def test_music_679537(self):
"""音乐启动"""
```
注意以下几点:
- ==类名不要随便取==,同一个应用应该使用同一个类名,用例类名称必须以 Test 开头,遵循大驼峰命名规范;
- ==用例类继承 BaseCase==,一个应用只有一个 `BaseCase`
- ==一个 py 文件里面只有一个类==,我们称为一个测试类;
- ==一个类里面可以有多个用例函数==,这取决这条用例有多少个测试点:
```python title="test_music_679537.py" hl_lines="4 7 10"
class TestMusic(BaseCase):
"""音乐用例"""
def test_music_679537_1(self):
"""任务栏启动音乐"""
def test_music_679537_2(self):
"""启动器启动音乐"""
def test_music_679537_3(self):
"""桌面启动音乐"""
```
### 5.2. 用例函数规范
- 用例函数以 test 开头,遵循蛇形命名规范,中间为用例的模块名称,后面加用例 ID最后加测试点序号
```shell
test_{module}_{case_id}[_{index}]
```
比如:`test_music_679537_1``index` 从 1 开始。
- ==函数功能说明里面写用例标题,直接复制 PMS 上用例标题即可,注意用三对双引号==
- ==复制 PMS 用例步骤==
直接将 `PMS` 上用例步骤和预期复制进来,然后进行批量注释( ++ctrl+"/"++ ),在注释的基础上去写用例脚本会更加方便全面,也比你自己写注释更节约时间:
举例:
???+ note "PMS用例"
![](https://pic.imgdb.cn/item/64f054c8661c6c8e54ff4c71.png)
直接选中用例内容,复制下来,然后粘贴到自动化用例脚本中:
```python title="test_music_679537.py" hl_lines="7-12"
class TestMusic(BaseCase):
"""音乐用例"""
def test_music_679537(self):
"""演唱者-平铺视图下进入演唱者详情页""" <-- 从PMS上复制的用例标题
# 1
# 点击右上角的【平铺视图】按钮
# 切换为平铺视图
# 2
# 双击任意演唱者封面
# 进入演唱者详情页面
```
上例中井号(#)注释部分就是直接从 `PMS` 上复制过来的,在此基础上写用例:
```python title="test_music_679537.py"
class TestMusic(BaseCase):
"""音乐用例"""
def test_music_679537(self):
"""演唱者-平铺视图下进入演唱者详情页"""
music = DeepinMusicWidget()
music.click_singer_btn_in_music_by_ui()
# 1
# 点击右上角的【平铺视图】按钮
music.click_icon_mode_in_music_by_ui()
# 切换为平铺视图
# 2
# 双击任意演唱者封面
music.double_click_first_singer_in_singer_icon_view_by_ui()
# 进入演唱者详情页面
self.assert_xxx
```
你看,非常清楚每一步在做什么,重点是省去了写注释的时间,真的炒鸡方便。
### 5.3. 数据驱动
- 如果用例操作步骤是相同的,只是一些参数变化,尽量使用数据驱动来实现用例;
- 如果你需要使用外部文件 ==存放数据驱动的数据,尽量不要因此引入依赖==,可以使用一些标准库能读取的文件格式,比如 `json、ini、CSV、xml、txt` 等文件格式;不建议使用 `Yaml、Excel、MySQL` 等数据格式;
- ==读取数据时也尽量使用标准库去做==,如使用 `pandas` 处理 `CSV` 就属于大材小用了,正常的数据驱动还没到需要大数据分析来处理的地步;
- 数据驱动的 ==外部文件存放在widget/ddt/== 目录下;
- ==数据驱动的写法:==
```python hl_lines="1"
@pytest.mark.parametrize("value", data)
def test_smb_049(self, value):
...
```
以上这种参数化的写法本身没什么问题;
但是,这里必须要补充一个没有用的小知识:
- ==使用 ids 参数;==
==加 ids 参数之前:==
如果参数化数据里面的字符会原封不动的输出到 `item.name` 里面,显示非常不优雅,而且可能会引入一些意想不到的问题,可以感受一下:
参数:
```python
data = [
"一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三",
"qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyui",
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678",
]
```
终端日志打印出来,现象是这样色儿的:
```shell
test_smb_049.py::TestFileManager::test_smb_049[一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三]
test_smb_049.py::TestFileManager::test_smb_049[qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertyui]
test_smb_049.py::TestFileManager::test_smb_049[12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678]
```
说实话,看着心里堵得慌,如果这里面包含一些**特殊字符**或者是**超长**,可能还会有一些很奇妙的事情发生。
==加 ids 参数之后:==
```python hl_lines="1"
@pytest.mark.parametrize("value", data, ids=[1, 2, 3])
def test_smb_049(self, value):
...
```
再来感受一下:
```shell
test_smb_049.py::TestFileManager::test_smb_049[1]
test_smb_049.py::TestFileManager::test_smb_049[2]
test_smb_049.py::TestFileManager::test_smb_049[3]
```
明显好多了,所以尽量使用 ids 这个参数。
- 不建议使用 `fixture` 的数据驱动方式,框架虽然支持,但可读性比较差;
如果你不知道这句话在说啥,那你可以忽略,我也不打算详细说这种实现方式,操作比较骚。
### 5.4. 断言资源
- ==用例断言的图片资源==,直接放在 ==用例模块的同级目录下的 assert_res 目录== 下,图片名称以 ==用例的模块名称 + 用例 ID 命名==
- 图像识别断言,不要截取一张很大的图,图片资源包含的元素太多了,非常容易受到需求影响,建议是进行局部的断言;
### 5.5. 元素定位
- 用于 ==用例操作步骤中进行元素定位的图片资源==,放到 ==widget/pic_res 目录== 下,图片名称命名为该元素的名称;
- 用于元素定位的图片截取时尽量精确到这个具体的按钮,图片也不要太大;
- 基于 UI 定位的操作较快,合理加入等待时间能提高用例的稳定性。
### 5.6. 用例资源
- 用例执行过程中需要使用到的一些资源,==存放在 widget/case_res 目录== 下,前提是这些资源不超过 ==10M==
- 如果是一些比较大的资源,建议放到统一的 ftp 服务器,需要执行用例的时候再下载下来;
- ==确保一个资源在一次用例执行中只需要下载一次==,如果每次使用的时候都去下载,这样可能会耗费大量的网络资源,而因为先判断本地是否存在此资源,如果不存在再去下载;
- 测试用例执行过程中,你可能需要将资源拷贝到对应的测试目录下;
比如将 mp3 文件拷贝到 `~/Music` 目录下,但是我们更建议你使用发送快捷链接的方式替代拷贝的操作,因为在拷贝大文件时是很消耗系统资源的,而创建链接则不会;
```python
class DeepinMusicWidget:
@classmethod
def recovery_many_movies_in_movie_by_cmd(cls):
"""恢复多个视频文件至视频目录中"""
work_path = f"/home/{Config.USERNAME}/Videos/auto"
code_path = f"{Config.CASE_RES_PATH}/auto"
cls.run_cmd(f"rm -rf {work_path};mkdir {work_path}")
sleep(1)
flag = False
if not exists(code_path):
cls.run_cmd(f"mkdir -p {code_path}")
flag = True
logger.info(f"ln -s {code_path}/* {work_path}/")
cls.run_cmd(
f"cd {code_path}/;"
f"{cls.wget_file('auto.zip') if flag else ''}"
f"ln -s {code_path}/* {work_path}/ > /dev/null 2>&1"
)
```
资源下载过程中注意 ==超时== 的问题;
如果你的测试资源很大,要特别注意这问题,如果你使用强制等待下载结束( `os.system` ),可能会造成用例执行时长变得不可接受;
在持续集成环境执行时网络下载速度很慢,所以超时机制是很有必要的;`run_cmd` 方法有一个默认超时的时间,你可以根据资源大小对超时时间进行调整;
## 6. 标签化管理规范
### 6.1. 对应关系
写完自动化用例之后,请在 `CSV` 文件中标记用例的 ID、等级等标签。
为了提醒标记,执行用例时在首行会输出 `ERROR` 日志: `CSV 文件里面没有对应的 ID`
==如果 CSV 文件里面没有对应 ID后续在批量执行的时候这些用例是不会执行的。==
### 6.2. 名称一致
==CSV 文件的文件名==、==用例 py 文件中间的名称==、==用例函数中间的名称==,这三个名称一致。
举例:
```python title="test_music_679537.py" hl_lines="3"
class TestMusic:
def test_music_679537():
"""用例标题"""
```
那么 `CSV` 文件的名称为 ==music.csv==。
框架底层代码实现是将 ==CSV 文件的名称== 与 ==用例脚本名称== 进行对应(建立映射);
## 7. 子应用Tag管理规范
- 应用库 tag 根据应用交付节点生成,每次打 tag 之前,相关测试人员需要进行用例调试;
- 调试用例是指的在全架构上调试通过;
- ==tag 号怎么打?==
根据持续集成的要求生成,其中应用版本号需要与项目经理确认本次即将集成的应用版本号是多少;
tag 的 commit 信息格式:
```ini title="# commit msg"
version:5.6.5
```
其中 `5.6.5` 写应用的集成版本号。
## 8. 其他规范
- 不写 `if __name__ == '__main__':`,不写多余的代码;
- 统一文件注释头。
```python title="xxx.py"
#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
"""
:Author:email@uniontech.com
:Date :${DATE} ${TIME}
"""
```
- 日志打印要在方法最前面,否则代码报错没有日志输出,不好定位问题;
- hook 函数只能写到根目录下的 `conftest.py` 里面;
- `apps` 目录下的 `conftest.py` 原则上不会写 `fixture`
- 固定目录或元素控件的操作,将操作方法写死,类似文件的操作可以将文件名留参数;
- 路径拼接规范:
- 系统中固定目录,路径拼接时使用波浪符号,比如:`~/Desktop/`,下层使用 `os.path.expanduser()`,它可以自动识别波浪符号;
- 项目下路径使用配置文件中的路径,比如:`Config.BASE_PATH`,因为项目是可以在任意路径运行的,需要动态拼接路径。

View File

@ -1,144 +0,0 @@
# AT 用例筛选指北
```shell
# ================================================
# Author : mikigo
# ================================================
```
AT 用例筛选标准,是挑选合适的文本用例进行自动化用例转化的一些通用标准。
过去我们在自动化测试实践过程中,写了不少自动化用例,随着需求的迭代,自动化用例会自然腐化,因而需要在迭代的过程中对自动化用例进行维护,在维护自动化用例的过程中我们发现,有些用例维护起来太难了,调试用例耗费大量时间,成本很高。
因此,我们总结一些自动化用例选型的标准,以优化后续自动化用例结构,期待我们能编写出高效、稳定、易于维护的自动化用例。
# 一、不适合做自动化的用例
自动化测试可以分为常规自动化测试和专项自动化测试,常规自动化测试一般只针对一些常规的功能测试,其他非常规功能的用例,应该采用专项的自动化测试方案;
以下是不适合做自动化用例的情况:
## 1. 稳定性、压测用例
稳定性测试、压测用例应该是属于性能相关的测试场景,如:反复多次点击按钮,检验其功能稳定性。因为这些用例断言的预期可能不是很明确,更有甚者不需要断言,用例时长比较长,而且不可控,因此不适合做常规自动化测试。
目前我们有性能自动化的专项方案,以及一些稳定性测试的专项方案,可以考虑将此类用例放到专项自动化里面去做。
## 2. 涉及多个用户操作
常见与文管的用例中,多用户操作的用例一般都会涉及到在系统中进行多个用户间的切换,自动化脚本一般是运行在一个用户空间下的,所以还无法实现多用户间的切换。
此类不建议采用自动化执行。
## 3. 与开关机、注销、重启交互
此类场景多为应用的异常场景测试,比如:复制大文件过程中注销机器。
自动化脚本在系统关机、注销、重启之后是会停止运行的;此类用例可以做自动化,但是同样需要做专项方案,用例执行过程的处理逻辑完全不同。
后续自动化需要攻关的点:
- 自动化脚本在本机运行,自动化测试框架至少需要提供以下功能:
- 重启之后用例能自动运行;可以考虑将执行用例写成一个开机自启的服务;
- 能记录关机之前用例执行的位置,重启之后能从此位置开始执行;
- 像性能自动化一样,由服务端控制;
- 完全基于图形识别进行元素定位;
- 串口线控制键鼠稳定性;
## 4. 测试执行时间长
用例执行时间控制在2分钟以内极端情况不要超过5分钟所有用例的平均时长应该在1分钟左右
用例执行时间太长,编写用例、调试用例、执行用例、维护用例都非常的耗时,人力成本时间成本投入太高。
你想这条用例执行需要5分钟那你写这条用例的时间不可能一遍过写的过程中跑不通还得重跑至少15分钟不过分写完了还得在其他架构上调试半个小时过去了这还只是第一次写用例的时候后续如果用例维护过程中你可能需要经常投入相当长时间这样其实是失去了自动化的意义的。常规自动化测试就应该是快准狠。
## 5. 边缘性测试
有些功能模块本身是属于比较边缘性的,即极少用户会使用到的功能,这类功能模块不需要大规模实现自动化,一两个场景覆盖基本功能就行了,因此我们在挑选此类用例的时候可以结合整个功能模块的覆盖情况来决定。
## 6. 需要依赖人工介入的
自动化执行的过程中是没有人工介入的,如果这条用例是比如要人工介入的,那么就背离了自动化的意义。
比如光驱模块,光驱刻录是核心功能,但是光驱刻录之后光盘会弹出来,需要人工更换光盘,再手动推进光驱中。
这种功能模块即使做自动化,能涉及到的功能非常有限,而且不是核心功能,所以明显就不适合做自动化。
## 7. 难以实现的
用例所涉及到的方法实现起来可能有难度,甚至现阶段无法实现的,此类用例不适合做自动化。
比如影院测试画面清晰度、流畅度、截图录屏录制视频之后的视频是否存在卡顿等用例,现阶段还无法实现。
## 8. 功能不稳定
这个不是说还在开发阶段的功能,还在开发阶段的功能不稳定是正常的,这种我们可以等开发提测之后再写自动化用例。
功能不稳定指的是用例所涉及的功能,可能存在多种变化,每次执行用例可能断言的预期都不同。
## 9. 动态断言
用例执行过程中直到用例结束,一直是一个动态变化的过程,而且无法通过其他手段停下来;
比如截图录屏录制视频时右下角的录制时间是一直在变化的用例需要测试录制1分钟之后录制时间是刚好停在60秒
目前自动化用例执行还做不到时间精准控制,程序执行时间是有波动的,而且要适配多个平台,所以此类用例大概率会执行失败。特别是在性能较差的国产化架构上,此类用例不太可能稳定执行。
## 10. 探索性测试
探索性测试通常是一些不确定的操作,多变切复杂的测试场景,预期也可能是不确定的,简单讲就是骚操作太多了,因此不适合做自动化测试。
此类用例适合采用手工测试,是手工测试真正的价值体现。
## 11. 易用性测试
对于易用性的判断通常是主观的,对于自动化来讲很难去定义什么样的情况对用户是易用的,自动化需要有明确的可实现的预期。
# 二、适合做自动化的用例
前面讲了不适合做自动化的一些用例情况,有同学就说了,适合做自动化的用例不用讲了,就是不适合的反面。没毛病哈,适合做自动化的用例,我们大体还可以分为两类:
- 第一类:自动化效果好,应该尽可能实现的自动化用例;
- 第二类:自动化效果一般,需要投入更多精力才能实现的自动化用例;
以下介绍一些我们应该尽可能实现自动化的情况:
## 1. 操作相对简单
用例步骤相对较少,这种用例通常是一些路径很浅的用例,一般也是一些基础用例。用例编写、维护都可以轻松搞定。
## 2. 容易实现
现有技术是可实现的,没有难度,应该尽可能做自动化。
## 3. 经常用于回归测试
如果这条用例是每次回归测试必须要执行的用例,那么这条用例应该尽可能实现自动化。
回归测试时我们首先应该保证应用历史基本功能正常,所以那些每次在回归测试时都要执行的用例适合转化为自动化用例。
## 4. 功能稳定的核心功能
涉及核心功能的用例是最最重要的用例,也是我们交付时必须要保证质量的相关功能,因此应该尽可能的转化为自动化。
## 5. 输入数据测试
输入数据测试通常是检验被测应用接受有效数据、拒绝无效数据的能力。如:提交超长字符串、特殊字符串等等。
此类用例手工测试很难比较全面的覆盖到所有的输入情况,但是对于自动化来讲,此类用例操作步骤都是一样的,变化的仅是输入参数和断言结果,采用数据驱动,可以轻松实现。
## 6. 格式覆盖
原因同输入数据测试类用例一样,多种格式的覆盖也是一个很繁琐的事情,交给自动化来做再合适不过了。
比如影院对影片格式的检查、截图录屏对保存格式分辨率的检查。
## 7. 检查元素状态
查看被测应用的元素属性。如:图片的大小和排列;按钮的可用和不可用。

View File

@ -1,317 +0,0 @@
# AT 经验总结
> 欢迎所有人提交你在自动化测试方面的优秀实践经验,以帮助大家解决可能遇到的问题。
## 用例调试技巧
### 1. 日志
- 一定要先看报错,看 error 日志,通常能明确的告诉你具体哪里代码报错;
- 结合报错点前面的error、 info 和 debug 日志看否是正常。
### 2. 断点调试
- 方法报错:
- 在方法库中找到对应的方法,单独调用,看是否能正常执行;
- 通常单个方法的执行是比较简单的,如果单个方法报错,很快就能排查出问题;在方法内部打断点,使用 `Debug` 运行,看方法内部数据传递是否存在问题;
- 如果单个方法调用没问题,那么在用例中报错的方法前面打断点,使用 `Debug` 运行,看用例的业务逻辑和数据传递是否存在问题;
- 断言报错:
- 断言为数据断言,根据表达式进行断言语句进行修改;
- 文件生成类断言,查看是否需要加等待时间;
- 图像断言,在断言语句处打断点,使用 `Debug` 运行,用例运行到断言处会停止,查看此时断言的图片与用例执行的现场存在什么差异,此时也可以进行重新截图,从而替换新的图片;
### 3. 远程执行
- 远程执行指的是编辑器通过指定远程解释器执行自动化代码;
远程执行的好处是可以很方便的 `Debug` 运行,不用在测试机上打开编辑器,用例执行速度更快;
支持远程执行功能的编辑器:
- 专业版 `Pycharm`
- `VScode` ,需要使用插件 `Remote-SSH`
- 远程执行配置
`Pycharm` 为例:
`File` —> `Settings` —> `Project` —> `Python Interpreter` —> `右边设置按钮` —> `Add...` —> `SSH Interpreter` —> `New server configuration(填入host和username)` —> `Next` —> `password测试机密码` —> `Interpreter(选择远程解释器)` —> `Finish`
### 4. 环境清理
- 如果用例里面的 `teardown` 没有执行,大概率是因为 `setup` 里面代码报错,这两个是一对的,`setup` 里面报错,`teardown` 里面的代码不会执行;
- 目前我们已经将各应用的 `clean_all` 这个 `fixture` 改成了终结器,确保始终能执行到这步,但是用例里面的 `fixture`,还是需要我们小心处理;
- 要执行 `clean_all` 需要在编辑器运行参数加 `--clean yes`,写用例的时候请加上,不然你不确定用例执行之后的环境是否恢复;
- `setup` 可以不要,将 `setup` 放到用例里面是一种稳妥的做法,`teardown` 一定要。
### 5. 元素定位不准(坐标返回不对)
- 基于 `UI` 定位的方法,可能受到窗口 ID 的变化,导致坐标返回不准,默认取最新的一个窗口用于定位,但如果实际需要定位的不是最新的窗口,那么在用例中需要重新实例化方法类对象,并在类中传入对应的窗口序号;
- 基于属性定位的方法,目前遇到的笔记本上,由于屏幕缩放比例为 1.25,导致坐标返回不准,我们默认使用缩放比例为 1
- 基于图像定位的方法,如果当前屏幕中存在多个相同的目标元素,可能出现定位不准;支持通过参数控制,返回多个坐标;
- 基于 OCR 定位的方法,如果当前屏幕中存在多个相同的文字元素,可能出现定位不准;同样支持通过参数控制,返回多个坐标;
### 6. 键鼠操作不准
- 鼠标操作不生效,比如右键、双击无响应;
- 键盘操作不生效,或者延迟输入,比如用例需要输入“我是中国人”,实际只输入了“我国人”;
以上问题排除应用卡顿等问题,大概率是由于工具的问题,目前键鼠操作我们使用三个工具:`Dogtail` 提供的键鼠工具、`PyAutoGUI`、`Xdotool`
有同学可能要说为啥要用三个啊,用一个不就好了,简单讲就是各有优点各有缺点。
如果你遇到键鼠的问题,可以试试通过不同的工具操作;键盘输入延迟的问题,一般是因为输入速度太快了,系统没反应过来,常见于 `ARM``MIPS` 上,修改参数 delay_time 的值,单位为毫秒;
```python
# mouse_key.py
@classmethod
def input_message(cls, message, delay_time=300, interval=0.2):
"""
输入字符串
:param message: 输入的内容
:param delay_time: 延迟时间
:param interval:
:return:
"""
```
如果不是方法的问题,则需要继续和开发一起排除,是否为应用接受键鼠信号处理的问题,这类情况我们也是遇到过的,具体问题具体分析。
比如影院就重写了一个右键的方法:
```python
# base_widget.py
@classmethod
def right_click(cls, _x=None, _y=None):
"""
重写底层单击鼠标右键
解决影院右键触发release事件的问题右键主窗口会播放视频
"""
cls.mouse_down(_x, _y, button=3)
sleep(0.1)
cls.mouse_up(button=3)
```
## 终结器
```shell
# litaoa@uniontech.com
```
前置/后置步骤
Pytest 实现前置/后置步骤的方式有两种yield 和终结函数;
yield 实现yield前面为用例的前置步骤yield 后面为用例的后置步骤。
```python
@pytest.fixture
def clean_env():
print("setup")
yield
print("teardown")
```
终结函数实现,使用 request.addfinalizer 注册用例的后置步骤
```python
@pytest.fixture
def clean_env(request):
def clean():
print("teardown")
request.addfinalizer(clean)
print("setup")
```
yield的优缺点
优点代码简洁直观可使用yield在用例中获取前置步骤的返回值
缺点:若前置步骤中出现错误,则后置步骤不会执行
终结函数:
优点:前置步骤失败的话,后置步骤仍会执行且可以注册多个后置步骤(前提:需要在代码报错之前注册后置步骤),支持灵活使用后置条件
缺点:代码较为复杂,无法获取前置步骤的返回值(本人目前未实现)
总结在前置步骤保证绝对不会出错时使用yield更佳简便当前置步骤易出现问题时推荐使用终结函数。
场景:保险箱用例,前置步骤中开启保险箱,后置步骤删除保险箱。
```python
@pytest.fixture(scope="session", autouse=True)
def vault_fixture(request):
DfmWidget.reset_vault_by_cmd() # 1、重置保险箱
DdeDockPublicWidget().close_file_manager_by_cmd() # 2、关闭文管
DdeDockPublicWidget().open_file_manager_in_dock_by_attr() # 3、开启文管
vault = DfmWidget()
vault.create_file_vault() # 4、创建保险箱
def delete_vault(): # 8、删除保险箱的后置步骤
sleep(2)
DdeDockPublicWidget().open_file_manager_in_dock_by_attr()
vault = DfmWidget()
vault.delete_file_vault()
DfmWidget.reset_vault_by_cmd()
DdeDockPublicWidget().close_file_manager_by_cmd()
request.addfinalizer(delete_vault) # 5、注册后置步骤
DdeDockPublicWidget().close_file_manager_by_cmd() # 6、关闭文管
sleep(1)
DdeDockPublicWidget().open_file_manager_in_dock_by_attr() # 7、开启文管
```
代码按注释中的序号执行步骤:
- 代码在步骤 1 - 4 任意位置报错,则不会执行步骤 8因为未执行到步骤 5步骤8还未注册
- 代码在步骤 6 - 7 报错,仍会执行步骤 7因为在步骤 5 中已经将步骤 7 注册;
可以灵活注册后置步骤,能实现某个前置步骤执行之后,才会执行后置步骤。
## 启动应用的方式
```shell
# huangmingqiang@uniontech.com
```
1命令行启动
在 AT 代码中使用命令行启动应用,举例:
```python
os.popen("deepin-music")
```
这种方式启动存在一个问题,就是当使用 ssh 远程执行用例时,`dogtail` 无法获取到元素。
2通过 UI 操作启动
通过任务栏、启动器、桌面等 UI 方式启动,比如双击打开、右键打开等,这种操作方式不存在 ssh 远程执行用例时 `dogtail` 无法获取到元素的问题,也更加符合用户的操作行为。
## 文件选择框属性定位偶现无法找到
文件选择框存在一个问题,在调用文件选择框时,有一定的概率出现,界面已经渲染出来了,但是属性树并没有写入,导致通过属性无法找到元素,目前也没有很好的解决方案,为了用例稳定性,文件选择框的操作建议使用 UI 或者图片定位的方式,可以通过搜索内容固定文件位置。
```shell
# litaoa@uniontech.com
```
```python
desk = DdeDesktopPublicWidget()
# 选择视频目录
desk.click_videos_dir_in_desktop_plugs_by_ui()
sleep(1)
desk.ctrl_f()
sleep(1)
desk.input_message("元素名称")
sleep(0.5)
desk.enter()
sleep(1)
# 选择第一个文件
desk.click_list_view_btn_in_desktop_plugs_by_ui()
sleep(1)
desk.click_first_file_in_desktop_plugs_by_ui()
sleep(1)
# 文管插件中点击打开
desk.click_open_btn_in_desktop_plugs_by_ui()
```
## 应用启动
```shell
# mikigo
```
在UI自动化测试中一切操作的都是从应用启动开始的而在Linux桌面应用自动化测试中我们启动应用的方法有多种下面做一个简单的介绍
**【使用dogtail启动】**
dogtail提供了应用启动的方法在utils库中使用run方法启动
首先导入方法:
```python
from dogtail.utils import *
```
调用run方法
```python
run('deepin-music')
```
即可启动音乐
![img](https://img2020.cnblogs.com/blog/1898113/202012/1898113-20201218162414410-1539488857.png)
这种方法的优点是采用进程的方式直接启动不依赖与UI无论桌面或任务栏上是否存在应用图标都可以正常启动。
但是在实际项目中,仍然存在一个问题,
如果使用ssh远程调用或者 Jenkins 中执行测试脚本的时候,在 sniff 中会出现找不到应用经过分析可能是因为使用这种方法启动的时候实际是采用一个子进程启动了应用dogtail 无法识别到。
**【从任务栏启动】**
使用dogtail点击任务栏上的应用图标
通常有两种方法:
1使用dogtail点击任务栏上的应用图标。
2已知应用图标在任务栏上的位置然后使用鼠标点击对应坐标。
第二种方法的缺点是位置必须固定,如果移动位置就不行了,而使用第一种方法,无论位置在哪里,只要图标在任务栏上存在即可。
**【点击桌面图标启动】**
桌面图标目前是采用图像识别技术定位到应用图标的坐标然后通过pyauogui进行点击操作。
详细技术方案可以参考我的另外两篇博客:
[基于opencv的模板匹配实现图像识别返回在屏幕中的坐标](https://www.cnblogs.com/mikigo/p/13489143.html)
[Python三方库PyAutoGui的使用方法](https://www.cnblogs.com/mikigo/p/13182619.html)
**【从启动器启动(俗称开始菜单)】**
启动中启动的实现逻辑实际和任务栏上启动差不多。
首先需要使用鼠标点击任务栏上的启动器图标或者键盘super键将启动器呼出来
然后,在启动器中点击对应的图标,
但是这里有个问题,启动器中的应用列表,一页展示不完,所以如果我们要点击的应用图标不在第一页怎么办,通常解决方案有两种:
1需要进行向下滑动这里就涉及到相应的识别方案判断如果不在第一页就往下滑动翻页。
2启动器提供搜索的功能输入应用名称搜索然后进行点击。
从实际操作中来看,采用第二种方法的效率会高一点。
**【终端命令启动】**
在 Python 中,使用 `os.popen()``os.system()``subprocess.Popen()`,实现命令行启动,比如:
```python
import os
os.popen('deepin-music')
```
这种方式启动是比较简单的但是在实际项目中仍然存在远程执行脚本的时候dogtail 无法识别的问题。
**【总结】**
以上几种方法,各有优缺点,在实际项目中:
1如果需要在 Jenkins 中做持续集成,建议使用第二种任务栏启动的方法。
2如果不会采用远程执行的建议采用第一种或者最后一种方案。
3第三种和第四种启动方法通常在测试用例中会涉及到所以偶尔会用。
## 其他不为人知的细节
- 在一段时间内尽量编写同一个应用或模块的用例,能对该用例已有方法熟悉,避免过多重复业务代码的封装;
- 相同的场景下,各架构等待时间不同,建议使用框架提供的 sleep我们做了不同架构的倍数放大
- 编写用例时,尽量考虑到每一步异常后的环境恢复,需要建议这种意识,随时要考虑到,这步操作有没有可能出错,出错了改怎么办;
- 提交代码的时候注意不要把一些临时的测试资源提交进去了,比如测试了一个影片,有些同学习惯使用 `git add .` ,然后就全部提交到代码仓库了,这样即使后期把大文件删了,`.git` 文件里面也会很大,造成代码仓库变得十分臃肿。

View File

@ -1,7 +1 @@
---
hide:
- navigation
- toc.integrate
---
--8<-- "RELEASE.md"
<!--@include: ../RELEASE.md-->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,21 +0,0 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.03628 7.87818C4.75336 5.83955 6.15592 3.95466 8.16899 3.66815L33.6838 0.0367403C35.6969 -0.24977 37.5581 1.1706 37.841 3.20923L42.9637 40.1218C43.2466 42.1604 41.8441 44.0453 39.831 44.3319L14.3162 47.9633C12.3031 48.2498 10.4419 46.8294 10.159 44.7908L5.03628 7.87818Z" fill="url(#paint0_linear_1287_1214)"/>
<path d="M6.85877 7.6188C6.71731 6.59948 7.41859 5.65703 8.42512 5.51378L33.9399 1.88237C34.9465 1.73911 35.8771 2.4493 36.0186 3.46861L41.1412 40.3812C41.2827 41.4005 40.5814 42.343 39.5749 42.4862L14.0601 46.1176C13.0535 46.2609 12.1229 45.5507 11.9814 44.5314L6.85877 7.6188Z" fill="white"/>
<path d="M33.1857 14.9195L25.8505 34.1576C25.6991 34.5547 25.1763 34.63 24.9177 34.2919L12.3343 17.8339C12.0526 17.4655 12.3217 16.9339 12.7806 16.9524L22.9053 17.3607C22.9698 17.3633 23.0344 17.3541 23.0956 17.3337L32.5088 14.1992C32.9431 14.0546 33.3503 14.4878 33.1857 14.9195Z" fill="url(#paint1_linear_1287_1214)"/>
<path d="M27.0251 12.5756L19.9352 15.0427C19.8187 15.0832 19.7444 15.1986 19.7546 15.3231L20.3916 23.063C20.4066 23.2453 20.5904 23.3628 20.7588 23.2977L22.7226 22.5392C22.9064 22.4682 23.1021 22.6138 23.0905 22.8128L22.9102 25.8903C22.8982 26.0974 23.1093 26.2436 23.295 26.1567L24.4948 25.5953C24.6808 25.5084 24.892 25.6549 24.8795 25.8624L24.5855 30.6979C24.5671 31.0004 24.9759 31.1067 25.1013 30.8321L25.185 30.6487L29.4298 17.8014C29.5008 17.5863 29.2968 17.3809 29.0847 17.454L27.0519 18.1547C26.8609 18.2205 26.6675 18.0586 26.6954 17.8561L27.3823 12.8739C27.4103 12.6712 27.2163 12.5091 27.0251 12.5756Z" fill="url(#paint2_linear_1287_1214)"/>
<defs>
<linearGradient id="paint0_linear_1287_1214" x1="6.48163" y1="1.9759" x2="39.05" y2="48.2064" gradientUnits="userSpaceOnUse">
<stop stop-color="#49C7FF"/>
<stop offset="1" stop-color="#BD36FF"/>
</linearGradient>
<linearGradient id="paint1_linear_1287_1214" x1="11.8848" y1="16.4266" x2="26.7246" y2="31.4177" gradientUnits="userSpaceOnUse">
<stop stop-color="#41D1FF"/>
<stop offset="1" stop-color="#BD34FE"/>
</linearGradient>
<linearGradient id="paint2_linear_1287_1214" x1="21.8138" y1="13.7046" x2="26.2464" y2="28.8069" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFEA83"/>
<stop offset="0.0833333" stop-color="#FFDD35"/>
<stop offset="1" stop-color="#FFA800"/>
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,20 +0,0 @@
---
template: no_busuanzi.html
hide:
- date
- git-revision-date-localized
- navigation
- toc
- git-authors
comments: true
---
# 留言
<div>
<span style="color:#707070;font-size: small">
英雄不问出处,留言不管字数。
</span>
</div>

View File

@ -0,0 +1,36 @@
有趣YouQu是深度公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。
## 有趣YouQu能做什么
- [x] Linux 桌面应用 UI 自动化测试
- [x] Linux 桌面应用 D-Bus/Gsettings 接口自动化测试
- [x] 命令行自动化测试
- [x] HTTP 接口自动化测试
- [x] Web UI 自动化测试
- [ ] Linux 桌面应用性能自动化测试
<details>
<summary style="color: #FF9933">点击查看爱上 “有趣YouQu” 的 N 个理由</summary>
<ul>
<li>无处不在的代码补全,让编写自动化测试用例成为一种享受;</li>
<li>核心库提供了统一的接口,编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;</li>
<li>除了常用的属性定位、图像识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你;</li>
<li>对属性定位的方法进行了二次封装,将编写属性定位的方法变得简单而优雅;</li>
<li>对图像识别定位技术进行功能升级,除了支持单个坐标返回,还支持同一界面下多个相同元素返回多个坐标的功能;</li>
<li>提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情;</li>
<li>提供了功能强大的执行器入口,让你可以方便的在本地执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想;</li>
<li>提供远程执行的功能,可以控制多台机器并行跑,或者分布式跑,这种付费功能现在免费给你用;</li>
<li>提供自动输出日志的功能,你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》;</li>
<li>提供一键部署自动化测试环境的功能,让你再也不用为环境部署而烦恼;</li>
<li>提供自动生成多种报告的功能,你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能;</li>
<li>对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效;</li>
<li>不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行;</li>
<li>支持本地文件测试套执行、PMS 测试套执行、标签化执行方案,满足你各种场景下的执行需求;</li>
<li>支持基于深度学习的 OCR 功能,可定位可断言,中文识别的天花板;</li>
<li>完美兼容 Wayland 和 X11真正做到一套代码随处执行</li>
<li>支持多种方式的数据回填功能,其中异步回填的方案,完美解决了数据回填的耗时问题;</li>
<li>支持重启交互场景用例的执行,使用方法优雅简洁;</li>
</ul>
</details>

View File

@ -1,41 +1,4 @@
有趣YouQu是深度公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。
## 有趣YouQu能做什么
- [x] Linux 桌面应用 UI 自动化测试
- [x] Linux 桌面应用 D-Bus/Gsettings 接口自动化测试
- [x] 命令行自动化测试
- [x] HTTP 接口自动化测试
- [x] Web UI 自动化测试
- [ ] Linux 桌面应用性能自动化测试
<details>
<summary style="color: #FF9933">点击查看爱上 “有趣YouQu” 的 N 个理由</summary>
<ul>
<li>无处不在的代码补全,让编写自动化测试用例成为一种享受;</li>
<li>核心库提供了统一的接口,编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;</li>
<li>除了常用的属性定位、图像识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你;</li>
<li>对属性定位的方法进行了二次封装,将编写属性定位的方法变得简单而优雅;</li>
<li>对图像识别定位技术进行功能升级,除了支持单个坐标返回,还支持同一界面下多个相同元素返回多个坐标的功能;</li>
<li>提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情;</li>
<li>提供了功能强大的执行器入口,让你可以方便的在本地执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想;</li>
<li>提供远程执行的功能,可以控制多台机器并行跑,或者分布式跑,这种付费功能现在免费给你用;</li>
<li>提供自动输出日志的功能,你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》;</li>
<li>提供一键部署自动化测试环境的功能,让你再也不用为环境部署而烦恼;</li>
<li>提供自动生成多种报告的功能,你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能;</li>
<li>对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效;</li>
<li>不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行;</li>
<li>支持本地文件测试套执行、PMS 测试套执行、标签化执行方案,满足你各种场景下的执行需求;</li>
<li>支持基于深度学习的 OCR 功能,可定位可断言,中文识别的天花板;</li>
<li>完美兼容 Wayland 和 X11真正做到一套代码随处执行</li>
<li>支持多种方式的数据回填功能,其中异步回填的方案,完美解决了数据回填的耗时问题;</li>
<li>支持重启交互场景用例的执行,使用方法优雅简洁;</li>
</ul>
</details>
## 安装使用
从 PyPI 安装:
@ -180,7 +143,7 @@ $ youqu manage.py run --app apps/autotest_deepin_music --keywords "xxx" --tags "
</div>
更多参数请查看【[命令行参数](https://linuxdeepin.github.io/deepin-autotest-framework/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#21)】
更多参数请查看【[命令行参数](https://linuxdeepin.github.io/youqu/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#21)】
#### 2.2. 配置文件
@ -188,7 +151,7 @@ $ youqu manage.py run --app apps/autotest_deepin_music --keywords "xxx" --tags "
在配置文件 `setting/globalconfig.ini` 里面支持配置对执行的一些参数进行配置,配置完成之后,直接在命令行执行 `manage.py` 就好了。
详细配置项请查看【[配置项](https://linuxdeepin.github.io/deepin-autotest-framework/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#22)】
详细配置项请查看【[配置项](https://linuxdeepin.github.io/youqu/%E6%A1%86%E6%9E%B6%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E6%89%A7%E8%A1%8C%E7%AE%A1%E7%90%86%E5%99%A8/#22)】
### 3. 远程执行
@ -329,23 +292,23 @@ $ youqu manage.py remote -a ... --parallel no
## 贡献者
[贡献文档](https://github.com/linuxdeepin/deepin-autotest-framework/blob/master/CONTRIBUTING.md)
[贡献文档](https://github.com/linuxdeepin/youqu/blob/master/CONTRIBUTING.md)
--8<-- "docs/contributors.html"
## 开源许可证
有趣 在 [GPL-2.0-only](https://github.com/linuxdeepin/deepin-autotest-framework/blob/master/LICENSE) 下发布。
有趣 在 [GPL-2.0-only](https://github.com/linuxdeepin/youqu/blob/master/LICENSE) 下发布。
------------
[__Github Star History__]()
[![Stargazers over time](https://starchart.cc/linuxdeepin/deepin-autotest-framework.svg)](https://starchart.cc/linuxdeepin/deepin-autotest-framework)
[![Stargazers over time](https://starchart.cc/linuxdeepin/youqu.svg)](https://starchart.cc/linuxdeepin/youqu)
[__Gitee Info__]()
[![deepin-community/deepin-autotest-framework](https://gitee.com/deepin-community/deepin-autotest-framework/widgets/widget_card.svg?colors=4183c4,ffffff,ffffff,e3e9ed,666666,9b9b9b)](https://gitee.com/deepin-community/deepin-autotest-framework)
[![deepin-community/youqu](https://gitee.com/deepin-community/youqu/widgets/widget_card.svg?colors=4183c4,ffffff,ffffff,e3e9ed,666666,9b9b9b)](https://gitee.com/deepin-community/youqu)

View File

@ -1,626 +0,0 @@
# 智能化功能测试
![](https://pic.imgdb.cn/item/64f054c2661c6c8e54ff477b.png)
```python
# Attribution Chengdu Test Team
# Date 2021/08/20
```
仓库地址:[https://gitlabcd.uniontech.com/autotest/cd-desktop-aitest](ttps://gitlabcd.uniontech.com/autotest/cd-desktop-aitest)
## 一、方案概述
基于深度学习智能识别应用的元素控件,用于在自动化测试操作过程中的元素定位以及判断结果时的断言处理;自动化测试过程中,测试机上的画面通过采集盒传输到服务器上,服务器对视频画面进行智能识别后,服务器智能判断用例是否执行成功,然后对测试机下发下一步操作指令,测试机接受并执行下一步操作。
服务器与测试机之间的链接:
* 服务器通过 USB 串口设备USB-HID 协议)模拟鼠标键盘对测试机进行操作。
* 通过视频采集设备捕获测试机的实时画面传输给服务器。
服务器对采集的画面进行智能识别,识别其中的元素控件,并返回元素控件在屏幕中的坐标,服务器通过智能化分析,如果测试结果与预期一致将下一步操作指令通过串口模拟键鼠信号发送给测试机;如果测试结果与预期不一致将会进入中断处理及异常结果输出,继续执行后续场景,直至所有用例测试完成。
## 二、深度学习环境搭建
模型训练主要对 GPU 有要求,训练模型的机器显存不低于 6G其他配置无特殊要求。
**推荐性价比较高配置**
```shell
操作系统: UnionTech OS Desktop 20 Professional Linux version 4.19.0-desktop-amd64 (deepin@deepin-PC) (Uos 8.3.0.3-3+rebuild)
处理器: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz (八核 / 十六逻辑处理器)
主板: B460M-HDV(RD)
内存: 8GB(TF32D4U2S1MEH-8 DDR4 2933MHz (0.3ns))/8GB(TF32D4U2S1MEH-8 DDR4 2933MHz (0.3ns))
显示适配器: TU116 [GeForce GTX 1660]
```
### 1、虚拟环境安装
```shell
cd ~
wget -c https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh
```
一路回车
第一次提示输入 yes/no :输入 `yes`
继续一路回车
第二次提示:输入 `no`
```shell
cd ~/miniconda3/bin
sudo chmod 777 activate
```
激活conda环境
```shell
. ./activate
```
添加公司内网源
```shell
conda config --add channels bioconda
conda config --add channels conda-forge
```
如果是外网添加外网源
```shell
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/
```
如果要删除源
```shell
conda config --remove-key channels
```
### 2、安装依赖
#### 1创建虚拟环境
```shell
conda remove --name mmlab --all # 移除所有虚拟环境
```
```shell
conda create -n mmlab python=3.7
```
```shell
conda activate mmlab
```
#### 2安装 Pytorch
在mmlab虚拟环境中执行
```shell
pip install torch==1.7.0+cu101 torchvision==0.8.1+cu101 torchaudio==0.7.0 -f https://download.pytorch.org/whl/torch_stable.html -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
```
#### 3安装 MMCV
在mmlab虚拟环境中执行
```shell
pip install mmcv-full==1.3.3 -f https://download.openmmlab.com/mmcv/dist/cu101/torch1.7.0/index.html -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
```
#### 4安装显卡驱动
根据你的显卡下载对应驱动,比如我的显卡为 `GTX1660`,驱动版本为 430驱动下载地址https://www.nvidia.cn/Download/Find.aspx?lang=cn
```shell
CTRL+ALT+F2 进入tty
```
禁用 nouveau 驱动
```shell
sudo vim /etc/modprobe.d/blacklist-nouveau.conf
```
填入:
```shell
blacklist nouveau
options nouveau modeset=0
```
刷新配置文件
```shell
sudo update-initramfs -u
```
reboot 重启后再进入 tty
关闭图像界面,输入命令关闭图像界面
```shell
sudo service lightdm stop
```
安装驱动
```shell
sudo chmod a+x NVIDIA-Linux-x86_64-430.run
sudo ./NVIDIA-Linux-x86_64-430.run
```
reboot重启nvidia-smi查看安装状态。注意看下cuda版本10.1driver版。
## 三、数据标注
### 1、数据标注
标注之前需要先转换图片大小,并且以数字命名,每组命名递增
#### 1转换大小并重命名
rename_pic.py
```python
import os
import sys
import cv2
import time
import getpass
username = getpass.getuser()
source_path = f"/home/{username}/Desktop/right_menu" # 图片路径
source_dest = os.path.join('/'.join(source_path.split("/")[:-1]), 'tmp')
if not os.path.exists(source_dest):
os.mkdir(source_dest)
start_name = sys.argv[1]
file_name_list = list()
for file in os.listdir(source_path):
if file.endswith('.png'):
file_name_list.append(file)
start_name = int(start_name)
for file in file_name_list:
os.rename(os.path.join(source_path,file), os.path.join(source_path, f"{str(start_name)}.png"))
start_name += 1
time.sleep(1)
for file in os.listdir(source_path):
image = os.path.join(source_path, str(file))
src = cv2.imread(image)
result = cv2.resize(src, (960, 540))
resizeImage = os.path.join(source_dest, str(file))
print(resizeImage)
cv2.imwrite(str(resizeImage), result)
cv2.waitKey(0)
cv2.destroyAllWindows()
time.sleep(1)
os.system(f'rm -rf {source_path}/*')
os.system(f'mv {source_dest}/* {source_path}')
os.system(f'rm -rf {source_dest}')
print("下一个序号:", start_name)
```
根据终端输出的下一个序号的提示,执行 Python 文件的时候传参。
```shell
python rename_pic.py 249
```
#### 2工具标注
使用工具 labelImg 标注
```shell
sudo pip3 install PyQt5==5.13
sudo pip3 install labelImg
```
终端直接输入 labelImg回车
标注模式选择:`PascalVOC`
### 2、智能标注
打开屏幕录制软件,录制手动操作一次测试用例,然后将录制的视频进行分帧,然后对比前两帧图标相似度,剔除相似度过高的图片,在保证素材多样性的前提下,剔除重复多余的图片生成待标注的素材集,然后取出控件模板数据集,通过 OpenCV 模板匹配获取控件在待标注的素材图片中所在的左上、左下、右上、右下四处坐标,从而根据模板数据集生成标注数据。参考目录 AnnotationMaterial
#### 1模板数据集准备
1、在界面截取需要标注的元素控件放在目录下 AnnotationMaterial/template/img
2、维护控件名与元素控件的键对一个控件名可对应多个元素控件
```yaml
menu:
- menu.jpg
- menu1.jpg
- menu2.jpg
- menu3.jpg
```
#### 2素材集准备
录制视频或或屏幕截图放置目录 AnnotationMaterial/source
#### 3开始标注
```shell
python3 AnnotationMaterial/main.py
```
生成的标注数据存放在 AnnotationMaterial/result
## 四、MMDetection
### 1、 MMDetection 代码
MMDetection 是一个有名的深度学习目标检测开源项目,也是 `openMMlab` 的招牌项目,为什么选择它,小孩儿没娘说来话长,感兴趣可以自行深入了解;
你可以直接在 GitHub 上克隆代码,也可以直接使用咱们仓库下 Train 目录中代码Train 中的代码也是从 GitHub 上拉取的,不过我们根据项目需要做了一些二次开发,推荐直接使用它。
如果你想从 GitHub 上拉:
```shell
git clone https://github.com/open-mmlab/mmdetection.git
# 不能直接拉取主分支建议使用2.12版本不同的版本对应的mmcv版本是不同的
```
### 2、拉取 voc2coco 代码
```shell
git clone https://github.com/Tony607/voc2coco.git
```
### 3、转换 coco 数据集
将所有的图片和xml文件放入train2017从中挑选几组放入val2017测试集
```shell
cd mmdetection/data/coco
python voc2coco.py train2017 annotations/instances_train2017.json
python voc2coco.py val2017 annotations/instances_val2017.json
```
生成json文件
### 4、修改配置
**1读取模型名称**
```python
import json
module_name = []
with open('./instances_train2017.json', "r+") as f:
json_file = f.read()
json_dict = json.loads(json_file)
module_list = json_dict.get('categories')
for module_info in module_list:
name = module_info.get('name')
module_name.append(name)
print(module_name)
print("module_num:", len(module_name))
```
```shell
# 注意对比instances_train2017.json里面模型名称的顺序与CLASSES和coco_classes里面的顺序保持一致。
```
**2修改 faster_rcnn_r101_2x_coco.py**
`mmdetection/xianjin/faster_rcnn_r101_2x_coco.py`
修改46行`num_clasess`的值新增1个就 +1
**3修改 coco.py**
`mmdetection/mmdet/datasets/coco.py`
CLASSES = (),在里面添加模型名称;
**4修改 class_names.py**
`mmdetection/mmdet/core/evaluation/class_names.py`
`coco_classes` 里面添加模型名称;
### 5、缓存清理
删除 mmdetection/build 目录
```python
python setup.py install
```
### 6、训练模型
1指定自己配置的训练模型
```shell
python tools/train.py xianjin/faster_rcnn_r101_fpn_2x_coco.py --gpus 1
```
2查看训练结果的测试集结果
```shell
python tools/train.py xianjin/faster_rcnn_r101_fpn_2x_coco.py xianjin/epoch_24.pth --show
```
3查看训练结果的准确度
```shell
python tools/analysis_tools/analyze_logs.py plot_curve xianjin/20210530_011907.log.json --keys acc
```
### 7、快捷操作
```shell
python3 run.py
```
将以上 4 - 7 步操作整合成 run.py一键完成。
## 五、硬件环境
#### 1、设备清单
- 测试机至少一台;
- 服务端一台目前仅支持AMD架构
- 采集盒一个 ACASIS hdmi视频采集卡https://item.jd.com/10024310742602.html
- USB串口转USB键鼠协议线优胜电子科技USB串口转USB键鼠协议线B类https://item.taobao.com/item.htm?spm=a1z10.3-c.w4002-1385258877.57.7ea037891D6nKh&id=611894882981
#### 2、硬件环境搭建
- 采集盒HDMI 端连接测试机, USB 端连接到服务器上;
- USB 串口线,白色端连接服务器,黑色端连接测试机;
- 如果需要可以接USB延长线
- 测试机上可以不接显示器;
#### 3、推荐配置
执行用例的服务端对配置没有特殊要求,如果条件允许配置越高,识别速度用例执行速度越快。
```shell
处理器: Intel(R) Core(TM) i3-10100 CPU @ 3.60GHz (四核 / 八逻辑处理器)
主板: B460-N2(J)
内存: 8GB(TF32D4U2S1MEH-8 DDR4 3200MHz (0.3ns))
显示适配器: UHD Graphics 630
存储设备: FORESEE P900F256GBH (256 GB)/ST1000DM003-1SB102 (1.00 TB)
```
测试机上不执行任何脚本,具体配置根据测试需要决定。
## 六、USB_MK串口驱动方法
位于control_method目录下的usb_mk.py文件
1列出可通信的端口
```shell
python3 -m serial.tools.list_ports -v
```
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff5068.png)
2修改串口的权限
```shell
sudo chmod 777 /dev/ttyACM0
```
3实例化USB_MK
```python
import UsbMk
usb_mk = UsbMk("/dev/ttyACM0", 9600) # 设备默认9600为波特率控制传输速率
```
4USB串口设备默认波特率为9600经测试波特率9600准确性最好
### 1、键盘操作
1按下键盘按键
```python
usb_mk.press_key("enter") # 按下键盘enter键
```
2按下键盘按键并且不放
```python
usb_mk.press_key_down("enter") # 按下键盘enter键不放
```
3组合按键
```python
usb_mk.hot_key("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端
```
4组合按键不放
```python
usb_mk.hot_key_down("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端不放
```
5释放所有键盘按键
```python
usb_mk.key_up() # 释放所有键盘按键
```
6键盘输入字符串汉字会自动转成拼音输入
```python
usb_mk.hot_key("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端
usb_mk.input_text("reboot") # 输入字符串reboot
usb_mk.press_key("enter") # 按下键盘enter键
```
### 2、鼠标操作
1按下鼠标左键
```python
usb_mk.click() # 按下鼠标左键
```
2按下鼠标左键不放
```python
usb_mk.mouse_down() # 按下鼠标左键不放
```
3释放鼠标所有按键
```python
usb_mk.mouse_up() # 释放鼠标所有按键
```
3按下鼠标右键
```python
usb_mk.right_click() # 释放鼠标所有按键
```
4鼠标左键双击
```python
usb_mk.double_click() # 释放鼠标所有按键
```
5恢复鼠标至初始位置默认左上角
```python
usb_mk.move_to_init() # 恢复鼠标至初始位置,默认左上角
```
6移动鼠标至相对坐标
```python
usb_mk.move_rel(100, 200) # 鼠标向左边移动100个像素向下移动200个像素
```
7以屏幕左上角为圆心坐标移动鼠标至屏幕绝对坐标
```python
usb_mk.move_to(100, 200) # 鼠标移动至屏幕坐标100, 200
# 注因Linux系统不支持鼠标绝对路径所以会鼠标会先移动到初始位置
```
8按下鼠标左键拖动到绝对坐标位置
```python
usb_mk.drag_to(100, 200) # 按下鼠标拖动至屏幕坐标100, 200
# 注因Linux系统不支持鼠标绝对路径所以会鼠标会先移动到初始位置
```
9按下鼠标左键拖动到相对坐标位置
```python
usb_mk.drag_rel(100, 200) # 鼠标向左边移动100个像素向下移动200个像素
```
## 七、方法调用入参规则
### 1、基类
```python
class Base:
def __init__(self):
self._obj = image
self._usb = usb_mk
def find_element_by_ai(self, element):
return self._obj.find_element(element)
```
### 2、入参说明
图像识别方法入口为 Base 类下的 find_element_by_ai 。仅接受一个参数 element类型为 string。
可识别的 string 格式:
1大图标 图标大于 40 像素):识别某个大图标,例:
```python
Base().find_element_by_ai("window")
```
2大图标 / 小图标(图标小于 40 像素识别某个小图标window/search_btn
```python
Base().find_element_by_ai("window/search_btn")
```
3大图标 / OCR识别某个大图标内的文字menu/属性
```python
Base().find_element_by_ai("menu/属性")
```
4OCR全屏识别文字
```python
Base().find_element_by_ai("搜索")
```
## 八、隐藏鼠标
通过采集盒传输过来的视频流,在识别过程中可能受到鼠标影响,因此用例执行过程中需要隐藏鼠标。
屏蔽鼠标光标显示
```shell script
/etc/lightdm/lightdm.conf
```
在`[Seat:*]`下面添加参数
```shell script
xserver-command=X -bs -core -nocursor
```
## 九、智能自动化的意义
**1、改善 Acessibility 定位的稳定性问题**
Acessibility 属性定位存在偶尔失效的情况
1开发在做新需求开发时可能涉及到对属性标签的修改或者层级的调整可能造成自动化用例无法定位到元素。
- 比如1040阶段音乐重构的时候开发对部分属性和层级做了修改导致自动化用例定位方法80%需要修改。
- 开发新功能的时候偶尔也会对属性做调整遇到5次。
2目前主要使用Dogtail识别应用Acessibility属性进行定位是获取应用当前界面的属性tree在应用跳转后Dogtail存在无法及时获取当前属性列表的情况。
- 多媒体调用文管窗口的时候出现找不到文管里面元素的情况目前出现10+次。
- 应用设置页面的属性偶尔存在找不到的情况遇到5次。
3Dogtail工具本身存在问题有时定位元素的时候很慢让人无法接受目前出现过很多次。
- 执行用例的时候定位元素的时间比平常慢3倍出现4次。
**2、解决了使用绝对图像识别定位的容错性差的问题**
部分控件无法添加 Acessibility 属性从而使用图像识别定位出现的容错性差的问题。
1图像识别定位方法需要维护大量的目标图片资源在 UI 发生变化之后,会涉及到目标资源的替换,比较耗费人力。
2图像识别的定位方法对比精度比较搞如果UI 的变更会造成无法准确定位到,自动化脚本健壮性不足。
**3、使用机器分离解决了自动化脚本对应用的影响真实还原用户的使用场景**
机器分离的架构设计,保证了测试机的测试环境完全等同于用户,排除测试脚本的影响。
1目前的功能自动化是在测试机上直接运行自动化测试脚本加上用例执行过程中我们添加了一些进程监控、视频录制等功能自动化脚本本身会消耗一些系统资源无法还原真是的用户使用场景。
2性能测试需要排除其他程序的资源消耗影响性能自动化采用机器分离保证了性能数据的准确性。
以前的用例执行耗时没条在30秒左右现在用例耗时在10秒。
**4、解决了UI 调整导致定位失败的不稳定性问题**
1解决了因 UI 调整导致控件位置变化或色差变化后定位不准确的问题,只要控件文案和控件外边框无变化均可准确定位;
2目前也会采用基于UI的定位方案如果UI位置有调整会导致元素无法定位。
**5、简化了用例结构提升编写友好度**
1智能自动化识别元素的方法只有一个就是基于我们训练的模型识别视频流中的元素经过脚本封装之后在自动化用例中所有定位的操作都只需要调用这一个方法就行了编写自动化脚本的难度大大降低。
2也是由于调用方法简单在 UI 自动化测试框架中的分层结构将会减少,多继承的情况会减少,自动化代码的调用结构也会变得简单,而且功能测试同学编写自动化用例会更加容易上手。
以前写用例由于需要结合不同的模块调用不同的方法编写一条用例并完成调试的时间平均在20-30分钟现在写用例脚本能在5分钟左右完成。

View File

@ -1,803 +0,0 @@
# 智能化性能测试
![](https://pic.imgdb.cn/item/64f054c7661c6c8e54ff4be0.png)
~~~shell
# =============================================
# Attribution Chengdu Test Team
# Time : 2023/1/3
# =============================================
~~~
## 一、简述
智能化性能测试
通过自动化手段对应用进行性能测试,提供方便的环境部署、运行配置、用例编写等,用于桌面应用的冷热启动、资源拷贝、页面跳转等性能场景测试。
仓库地址:[https://gerrit.uniontech.com/admin/repos/autotest-perf-aitest](https://gerrit.uniontech.com/admin/repos/autotest-perf-aitest)
## 二、代码结构
```shell
autotest-perf-aitest
├── apps # 存放所有应用性能测试脚本
├── conftest.py # pytest hook相关方法
├── CURRENT # 版本内容
├── docs # 文档
│   ├── 键值对照表.pdf # 串口线code与按键的对照
│   ├── 性能自动化测试脚本执行器使用指南.md # 执行器脚本使用指南
│   ├── USB串口转USB键盘鼠标线协议文件V1.0.pdf # 串口协议
│   └── xserver-xorg-input-libinput-0.28.2.zip # Linux下绝对坐标操作依赖的源码可根据架构打包
├── manage.py # 功能主入口
├── pytest.ini # pytst 配置
├── README.md
├── setting # 设置
│   ├── client.ini # 测试机 IP 设置
│   ├── config.py # 全局配置
│   ├── dev_env.sh # 宿主机环境部署脚本
│   ├── docker-compose_no_relay.yml # 无继电器容器集群
│   ├── docker-compose.yml # 有继电器容器集群
│   ├── docker_login.sh # docker 登陆
│   ├── __init__.py
│   ├── res
│   │   ├── black.png # 全黑图片,用于修改壁纸
│   │   ├── xserver-xorg-input-libinput_0.28.2-2_5000.deb # 3A5000 架构鼠标绝对坐标依赖
│   │   ├── xserver-xorg-input-libinput_0.28.2-2_amd64.deb # amd 架构鼠标绝对坐标依赖
│   │   ├── xserver-xorg-input-libinput_0.28.2-2_arm64.deb # arm 架构鼠标绝对坐标依赖
│   │   ├── xserver-xorg-input-libinput_0.28.2-2_mips64.deb # mips 架构鼠标绝对坐标依赖
│   │   └── xserver-xorg-input-libinput_0.28.2-2_sw_64.deb # sw 架构鼠标绝对坐标依赖
│   ├── server.ini # 服务器配置
│   ├── setup.sh # 容器环境部署脚本
│   ├── template # 创建 app 基础脚本模板
│   │   └── app_template
│   │   ├── ${app_name}_widget.py-tpl
│   │   ├── control-tpl
│   │   ├── images
│   │   │   └── readme
│   │   ├── __init__.py-tpl
│   │   ├── test_${app_name}_01_scene.json-tpl
│   │   └── test_${app_name}_01_scene.py-tpl
│   └── uos_docker # 容器环境配置
│   ├── dockerfile
│   └── requirements.txt
└── src
├── analysis_save.py # 解析图片流结果,汇总生成 excel 报告
├── base_widget.py # 封装的基础操作,应用调用的主入口方法
├── cmdctl.py # 调用命令行使用
├── global_value.py # 全局变量
├── image_utils.py # 图片相关方法
├── __init__.py
├── logger_utils.py # 日志配置
├── pdocr.py # ocr 配置
├── public_method.py # 一些方便的封住
├── record.py # 录屏相关
├── rtk # 运行相关
│   ├── _base.py # 一些枚举
│   ├── __init__.py
│   ├── install_env.py # 安装环境
│   └── local_runner.py # 运行用例
├── serial_communication # 串口相关
│   ├── __init__.py
│   ├── power_control.py # 继电器操作,使用继电器连接主机电源,控制开关机
│   ├── serial_common.py # 串口公共方法
│   └── usb_mk.py # 键鼠操作基础封装
├── shortcut_key.py # 快捷键的封装
├── singleton.py # 单例模式
├── start_app.py # 创建 app
└── write_xlsx.py # 生成 excel
# __init__.py 文件为标识该目录是一个Python的模块包项目中的__init__.py均为空文件。
```
## 三、环境搭建
### 1、硬件环境
#### 1设备清单
- 测试机至少一台。
- 服务端一台。(仅支持 `AMD` 架构,若需其他架构,咨询相关开发人员)
- 采集盒一个。 `ACASIS` `HDMI` 视频采集盒https://item.jd.com/100013302599.html#crumb-wrap
- USB串口转USB键鼠协议线。优胜电子科技USB串口转USB键鼠协议线B类https://item.taobao.com/item.htm?spm=a1z10.3-c.w4002-1385258877.57.7ea037891D6nKh&id=611894882981
#### 2硬件环境搭建
- 采集盒,`HDMI` 端连接测试机, `USB` 端连接到服务器上。
- `USB` 串口线,白色端连接服务器,黑色端连接测试机(`USB3.0` 接口上)。
- 如果需要可以接 `USB` 延长线。
- 测试机上可以不接显示器。
#### 3服务端推荐配置
配置越高,解析速度越快。
```shell
处理器: Intel(R) Core(TM) i3-10100 CPU @ 3.60GHz (四核 / 八逻辑处理器)
主板: B460-N2(J)
内存: 8GB(TF32D4U2S1MEH-8 DDR4 3200MHz (0.3ns))
显示适配器: UHD Graphics 630
存储设备: FORESEE P900F256GBH (256 GB)/ST1000DM003-1SB102 (1.00 TB)
```
### 2、测试机环境搭建
- 打开控制中心,账户设置为【自动登录】和【无密码登录】,电源管理中使用电源全部设置为【从不】,开启开发者模式。
- 根据应用性能测试要求,导入相关测试资源,比如:导入相册、影院、音乐的测试资源。
- 在服务端打开相机应用后,将测试机桌面壁纸更换为纯色壁纸(注意,服务端需提前开启相机后再设置测试机壁纸,建议纯黑壁纸 `setting/res/black.png`
- 在文件管理器中,将选项 主菜单-设置-预览-图片预览 取消勾选(如不取消,会影响截图录屏应用的性能数据)
- 移动或删除系统 Logo ,排除桌面右下角 Logo 的影响(重启生效)。
```shell
sudo mv /usr/share/deepin/uos_logo.svg ~/Pictures/
```
- 安装鼠标绝对坐标操作依赖(必须安装!!)
- `AMD` 安装 `setting/res ` 目录下 `xserver-xorg-input-libinput_0.28.2-2_amd64.deb`
- `ARM` 安装 `setting/res ` 目录下 `xserver-xorg-input-libinput_0.28.2-2_arm64.deb`
- `MIPS` 安装 setting/`res ` 目录下 `xserver-xorg-input-libinput_0.28.2-2_mips64.deb`
- `3A5000` 安装 `setting/res ` 目录下 `xserver-xorg-input-libinput_0.28.2-2_5000.deb`
- 安装命令
```shell
sudo dkpg -i xserver-xorg-input-libinput_0.28.2-2_amd64.deb
```
安装时会提示已存在相同版本,请忽略,直接覆盖安装,安装完成后,必须重启主机才生效
### 3、服务端一键环境部署
环境搭建前必须先连接上 `USB` 串口线和采集盒。
宿主机环境安装
```shell
python3 manage.py install --env host
```
容器环境安装
```shell
python3 manage.py install --env docker
```
## 四、配置项
### 1、服务端配置
`setting/config/server.ini`
用于配置测试过程中的一些配置项,包含了所有服务端所有的可配置项。
- **本地无网络运行**
- 将配置项 `network=0` 即可开始测试。
- **本地有网络运行**
- 配置项 `network=1`
- (1)配置项 `client_alias=` 配置为你要测试的测试机别名,如 `Alias1` 测试机别名在 `setting/config/client.ini` 中进行配置,此时,直接运行 `python3 manager` 即可开始测试。
- (2)配置项 `client_alias=` 为空,测试机别名在 `config/client.ini` 中进行配置,此时,直接运行 `python3 manager --client_alias Alias1`,即可开始测试。(`Alias1` 为你配置的测试机别名)
- (1)和(2)只要使用其一即可。
- **有网络运行,且需要通过 `Jenkins` 上运行一个 `job` ,同时控制多台机器。**
- 配置项 `network=1`
- 配置项 `client_alias=` 不用配置,在运行 `run.sh` 的时候直接空格加别名即可,比如:测试机别名为 `Alias1` ,且已经在 `config/client.ini` 中配置了 `Alias1` 的`user` `ip` `password` ,则运行 `bash run.sh Alias1` 即可开始测试。
- 在 `Jenkins` `pipeline` 里面通过并行 `stage` 或并行调用下层任务的方式可以实现大规模的性能测试需求。
**详细配置项说明:**
```ini
;=============================== CASE CONFIG ===================================
[case]
;执行的应用名称
;为空表示执行 apps/ 目录下所有应用的用例
APP_NAME =
;执行包含关键词的用例
KEYWORDS =
;执行包含用例标签的用例
TAGS =
;1、KEYWORDS 和 TAGS 都为空表示执行 APP_NAME 的所有用例
;2、KEYWORDS 和 TAGS 都支持逻辑组合,即 and/or/not 的表达式, e.g. TAGS = L1 or smoke
[case_conf]
# 尾帧识别的方式stage按阶段划分ocr通过文案识别match 图片匹配ocr文案识别较慢不推荐使用
find_by = stage
# 最后一个稳定阶段的帧数识别
# 首帧存在后的第一个大于该配置帧数的阶段的首帧作为性能尾帧
final_stable_num=100
# 从该帧数开始识别文案或图片,减少分析时间
start_num = 150
# 识别的文案
text=
# 识别图片
match=apps/xxx/images/match.png
# 识别相似度
match_rate=0.9
# 用例操作执行之后,停止录屏之前的等待时间,单位秒
# 比如热启动用例从点击打开到停止录屏中间等待5秒
duration = 15
# 单条用例执行的次数
count = 5
# 稳定阶段划分的相似度
stable_similarity = 0.9997
[server]
# 调试模式=1为开启调试模式0为关闭。
# 调试模式下默认只执行一次用例,不关机
# 编写用例的过程中建议开启maintain。
MAINTAIN = 0
# 运行的环境docker容器环境host宿主机环境
ENV = docker
# 服务端密码
PASSWORD=1
# 指定测试机别名
# 测试机别名在 config/client.ini 中进行配置,比如:
# [AMD]
# ip=10.8.15.86
# user=uos
# 其中 AMD 为测试机别名则client_alias=AMD
CLIENT_ALIAS = x86Intel-i7
# 1 开启网络, 0 关闭网络
# 1服务端与测试机须在同一网段下你可以尝试在服务端通过ssh连接测试机如果可以连接说明网络正常。
# 2当input_type=FILE_NAME 时,必须开启网络。
NETWORK = 1
# 性能结果统计单位 毫秒—ms, 秒—s
UNIT=ms
# 测试机开机进入桌面后等待时间,单位/秒
STARTUP_DELAY = 60
# 1为删除缓存0为不删除缓存
# 用例执行完后会在report目录下生成智能解析的一些缓存图片。
CACHE = 0
# 默认为空报告会保存在项目下report目录中
# 指定报告目录则存放到指定目录。
REPORT_PATH = report
# 服务端从测试机获取的icon资源会缓存在项目下input目录中
INPUT = input/
# 1为测试完关机0为测试完不关机
SHUTDOWN = 0
# 解析进程数(不推荐修改)
# 3个进程解析视频已经能够满足即使增加进程数也不能减少整体耗时
# 另外还要看CPU核数是否支持。
PARSING_PROCESS = 3
# 1为使用继电器开关机0为使用reboot命令重启。依赖继电器硬件设备需要使用联系开发者
RELAY = 0
# 获取测试应用的版本, %s 占位应用名
# 如果该配置为空,则不获取应用的版本信息。
COMMAND = apt policy %s 2>/dev/null|grep "已安装"|awk -F "" "{print \$2}"
# 关机等待开启时间,单位秒
# 根据测试机性能不同,开关机耗时可能不同,根据实际测试机情况配置。
SHUTDOWN_DELAY = 30
# 可用于图像识别的图片格式,以英文逗号隔开。
# 该配置项不建议修改目前我们仅验证了jpg,jpeg,png这三种常用的图片格式。
INPUT_TYPES = jpg,jpeg,png
# 性能分析补帧,等于或低于该值的不稳定阶段视为稳定阶段,在最后计算性能结果时需要减掉。
UN_STAB_START = 3
# 服务端获取测试机图像的帧率,即每秒获取多少张测试机上的图像。
# 默认帧率为30帧/秒,该配置项不建议修改,可能会对解析结果造成偏差。
FPS = 30
# 以下场景类型会重启测试机,多种场景使用逗号隔开
SCENE = cold
;OCR服务端地址不可随意修改
OCR_SERVER_HOST = http://10.8.13.78:8890
#屏幕图片临时存放位置
SCREEN_CACHE = /tmp/screen
# =======================================
[log]
# 日志级别OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
# 用例执行过程中的一些日志输出log_cli=INFO表示 仅输出INFO及以上级别的日志。
LOG_LEVEL = DEBUG
# 日志文件保存路径
LOG_PATH= logs
# =======================================
[dockerhub]
# 容器登陆账号
DOCKER_USER = user
# 容器登陆密码
DOCKER_PASSWORD = User1234
```
### 2、测试机配置
`setting/config/client.ini`
用于配置测试机的信息。
- 有网络的情况下,服务端需要动态获取测试机上的一些资源,因此你需要写入 `测试机别名``user` 、`ip`、 `password`
```ini
# 测试机别名
[Alias1]
# 测试机ip
ip=10.8.15.86
# 测试机用户名
user=uos
```
命名建议:`AliasA1`、`AliasA2`、`AliasB1`、`AliasB2`,不要重名。
- 无网络情况下,仅需要关注测试机分辨率配置项 `width=``height=` 即可。
**详细配置项说明:**
```ini
[client]
# 默认测试机用户名密码ip
ip=
user=
# 测试机密码
password=1
# 测试机主题
theme=bloom
# 测试机icon目录
path=/usr/share/icons
# 系统desktop文件的存放目录UOS系统默认为/usr/share/applications
desktop_path=/usr/share/applications
# 用于判断测试机是否开机进入桌面的识别标识。
# 1、通过桌面图标识别。
# - type=FILE_NAME时服务器和测试机必须在同一局域网内。
# - power_on=dde-computer表示通过桌面计算机图标判断开机进入桌面。
# 2、通过本地图片作为开机识别。
# - type= 传入为图片格式type支持的类型包含在server.ini内配置项input_type=jpg,jpeg,png。
# - power_on= 传入的是本地图片的路径。
type=FILE_NAME
power_on=dde-computer
# 测试机分辨率配置(测试机连接采集盒,采集盒的分辨率)
height=1080
width=1920
[AliasA1]
ip=10.8.15.86
user=uos
# password=1 如果这里不写密码默认取上面client里面的password
[AliasA2]
ip=10.8.15.20
user=uos
# password=1 如果这里不写密码默认取上面client里面的password
```
### 3、场景个性化配置
随着测试场景的不断引入,发现现有服务端里的配置项并不适用于所有的性能场景,于是将服务端配置进行一个提取,可做单个场景的个性化配置,当然原来的服务端配置功能保留,只是当你配置了场景个性化配置后,优先使用个性化配置里面的内容,以下是对个性化配置的介绍。
目前每一个 py 文件对应一个性能测试场景,于是在同级目录下创建一个与之同名的 json 文件,作为个性化配置文件
```shell
apps
├── album
├── test_album_01_start.json # 个性化配置文件
└── test_album_01_start.py # 性能场景文件
```
以下是对 json 文件中配置的解释,若某项配置不需要,可以缺失,但不能为空;
```json
{
"title": "test_album_start", # 标题;必须
"app_name": "deepin-album", # 场景所属的应用;必须
"scene": "hot", # 场景别名;必须
"icon": ["deepin-album"], # 这条用例里面需要用到的所有icon用例执行之前会从测试机上拷贝所有需要用的icon到服务端用于图像识别。可缺失
# 注意列表中元素为应用desktop文件的文件名相册的desktop文件名为deepin-album.desktop
# 只需要写deepin-album即可“.desktop”已经在底层做了拼接。
"size": { # 图片对比的区域设置项,某些应用当前屏幕的部分区域需要将其去掉,可以设置此项,如果没有则可不写;可确实
"x-coordinate": 0, # 左上角横坐标
"y-coordinate": 0, # 左上角纵坐标
"width": 850, # 横向长度
"height": 1920 # 纵向高度
},
"count": 5, # 场景执行的次数;必须
"duration": 5, # 该条用例操作执行之后,停止录屏之前的等待时间,单位秒,针对于某些特定场景,该配置为可选项,覆盖 server.ini 中的配置;可缺失
"stable_similarity": 0.9997, # 性能场景分阶段时的图片相似度对比,前后图片低于该值,则分为不稳定阶段;可缺失
"find_by": "stage", # 尾帧识别的方式stage按阶段划分ocr通过文案识别match 图片匹配
"final_stable_num": 100, # 查找最后一个大于该值的稳定阶段的首帧作为性能的尾祯;可缺失
"start_num": 150,
"text": "", # ocr识别的文案
"match": "apps/xxx/images/match.png", # 图像匹配的图片文件路径
"match_rate": 0.9 # 匹配相似度
}
```
## 五、测试流程
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff5034.png)
## 六、用例编写及方法参数指引
### 1、用例实例说明
```python
# 标准库导入
from time import sleep
# 导入三方库pytest
import pytest
# 导入用例执行要用到的Widget类
from src.base_widget import BaseWidget
class TestStart:
# class级别的fixture测试用例执行之前执行。autouse=True 自动在当前作用域下使用。
@pytest.fixture(scope="class", autouse=True)
# 测试热启动之前需要预启动。
def application_pre_start(self):
# 入参规则在第2点中详细描述。
BaseWidget().right_click_element("deepin-album")
# 入参规则在第2点中详细描述。
BaseWidget().click_element("apps/autotest_deepin_album/picture/open.png", input_type="png")
sleep(2)
# 快捷键关闭窗口
BaseWidget().hot_key("alt", "f4")
sleep(2)
# 默认为function级别的fixture用例执行之前class级别fixture执行之后执行。
@pytest.fixture(autouse=True)
def setup_start(self):
# 右键点击 deepin-album 图标
BaseWidget().right_click_element("deepin-album")
# 移动到右键菜单中打开open.png
# 入参规则在第2点中详细描述。
BaseWidget().move_to(*BaseWidget().find_element("apps/autotest_deepin_album/picture/open.png", input_type="png"))
# 等待移动完成
sleep(0.5)
def test_album_start(self):
# 点击“打开”
BaseWidget().click()
```
### 2、方法参数说明
2.1、**`find_element` 方法**
```python
def find_element(element: str, input_type: str = "FILE_NAME", fill_color_position: tuple = (-1, -1), size: tuple = (25, 70)):
pass
```
- **参数 `element` 和 `input_type`**
**1通过应用 `icon` 识别元素**
- `input_type` 参数为默认参数,默认值为 `FIEL_NAME` ,表示通过应用 `icon` 寻找元素,此方法会动态获取测试机上的应用 `icon` 图标。
- 举例:默认情况下 `input_type ` 参数不需要传入, `find_element("deepin-album")`,表示通过 `deepin-album` 的应用 `icon` 来获取坐标,注意,此时传入的 `deepin-album` 参数实际是 `desktop`文件的文件名和2.3中的 `icon` 变量一致。
- 我们建议优先使用这种方法,但此方法依赖网络,请根据测试环境实际情况选择。
**2通过本地图片识别元素**
- 参数 `input_type` 传入图片格式,比如截取的本地图片格式为 `png`,那么 `input_type="png"`,此时参数 `element ` 传入图片的路径,建议存放在对应的产品 `apps/app/picture/` 目录下,路径为项目根目录下的相对路径。
- 举例:`find_element("apps/autotest_deepin_album/picture/open.png", input_type="png"))`,表示通过本地图片 `open.png` 识别元素。
- **参数 `fill_color_position`**
- `fill_color_position` 参数为默认参数,默认值为 `(-1, -1)``(-1, -1)` 表示取屏幕中右下角最后一个像素点作为填充坐标,在 `1920x1080` 屏幕分辨率下即实际坐标为 `(1919, 1079)` ,这样的写法可以适配不同大小的屏幕。
- 任务栏在屏幕不同方位:
- 任务栏在屏幕下方,从任务栏启动不需要传入该参数。
- 任务栏在屏幕左边,`fill_color_position=(1, 1)`
- 任务栏在屏幕右边,`fill_color_position=(-1, -1)`
- 任务栏在屏幕上边,`fill_color_position=(1, 1)`
- 从桌面启动应用,则需要传入除任务栏以外其他位置的坐标,比如(100, 100),只要这个坐标为除应用和任务栏区域都可以。
- 从启动器里面启动应用,需要填充的坐标为启动器区域。
注:通过应用 `icon` 识别时,从测试机获取的 `icon` 原文件为 `svg` 矢量图,转换为 `png` 之后需要填充边缘透明部分。
- **参数 `size`**
- `size` 参数为默认参数,默认值为 `(25, 70)`,表示测试机上 `dock` 栏上应用图标的大小范围。
- `UOS` 系统 `dock` 栏是可以上下拖动大小的,随着 `dock` 栏大小改变应用图标的范围为25到70之间。
- 如果你的测试机操作系统上 `dock` 栏大小不一样,可以根据实际情况传入大小范围。
2.2、`click_element`、 `right_click_element` `double_click_element` 这几个方法参数规则与 `find_element` 方法一样。他们实际上是在 `find_element` 方法基础之上做了二次封装,增加了鼠标的动作,如果你不想使用这几个方法,在用例中也可以通过 `find_element` 获取到坐标,然后将坐标传入到键鼠的方法中,可以实现同样的效果。
2.3、用例类中有个类变量 `icon = ["deepin-album"] ` 需要特殊说明,列表中的元素为这条用例里面需要用到的所有 `icon`,用例执行之前会从测试机上拷贝所有需要用的 `icon` 到服务端用于图像识别。列表中元素为应用 `desktop` 文件的文件名,相册的 `desktop` 文件名为 `deepin-album.desktop`,只需要写 `deepin-album` 即可,`.desktop ` 已经在底层做了拼接。
## 七、执行入口
### 1、用例组织
`setting/config/server.ini` 文件中 `APP_NAME= ` 字段为用例的执行的目录,默认为 `apps` 目录下所有用例。如果你想指定执行某一个应用的用例,你可以将该配置项指定到应用的用例目录,比如:`APP_NAME=deepin_album` 表示执行相册目录下的用例。
### 2、命令行参数
通过命令行参数配置参数
以下为 `python3 manage.py run` 提供的一些参数选项:
```shell
-a APP, --app APP 应用名称deepin-music
-k KEYWORDS, --keywords KEYWORDS
用例的关键词
-t TAGS, --tags TAGS 用例的标签
--log_level LOG_LEVEL 日志输出级别
--env {host,docker} 在宿主机或容器环境执行
--client_alias 选择测试机别名, 可选项为client.ini中已配置, 默认值为 zx-x86.
--count 指定用例执行次数
```
在一些 CI 环境下使用命令行参数会更加方便:
```shell
python3 manage.py run --app deepin-music --keywords "xxx" --tags "xxx" --env docker
```
注:在容器中执行时,若强制退出,容器并不会停止运行!
## 八、测试报告
### 1、Json 报告
自研视频解析工具会对单条用例执行一轮生成一个 `json` 文件,存放于 `report/{app_name}/{scene}/{run_num}` 目录下,命名格式为:
```shell
report.json
```
`json` 内容举例:
```json
[
{
"Stab1": {
"images": [1,2...150,151],
"startStub": 0,
"type": "Stab"
}
},
{
"Stab2": {
"images": [152,153...169,170],
"startStub": 1,
"type": "UnStab"
}
},
{
"Stab3": {
"images": [171,172...300,301],
"startStub": 0,
"type": "UnStab"
}
}
]
```
说明:
- `Stab` :表示解析过程中不同的阶段。
- `images` :表示每一帧的图片序号。
- `startStub` 为识别尾帧的阶段表示,如果 `"startStub": 1` ,说明尾帧出现在该阶段。
- `type``Stab``UnStab` ,表示稳定阶段或不稳定阶段。
各阶段有帧数补偿,默认补偿的帧数为 3 帧(可以通过 `server.ini` 里面 `un_stab_start=3` 进行配置),表示小于等于 3 帧的不稳定阶段视为稳定阶段,在最后计算性能结果时前后均需要减掉。
应用启动阶段就是在 `Stab2` 阶段启动时间为171 减 151 再减掉前后补偿帧数 6 帧,即 14 帧,视频帧率 30 帧/秒因此启动耗时为14 * 33 = 462 ms
### 2、Excel 报告
所有用例执行并解析完之后会 `report` 目录下生成一个汇总数据的 `Excel` 文件,文件名为:`{time}_perf_time.xlsx`。
注意,`report` 目录为可配置项,默认情况下会在项目根目录下生成,如果你将 `report`,指定到项目下其他路径,则会在对应的路径下生成 `json``Excel` 文件。
你也可以根据需要读取所有 `json` / `excel` 报告的数据,生成你自己想要的一些测试报告形式。
## 九、USB 串口驱动键鼠方法
位于 `src/utils/control/serial_communication` 目录下的 `usb_mk.py` 文件
```python
usb_mk = UsbMk()
```
### 1、键盘操作
1按下键盘按键
```python
usb_mk.press_key("enter") # 按下键盘enter键
```
2按下键盘按键并且不放
```python
usb_mk.press_key_down("enter") # 按下键盘enter键不放
```
3组合按键
```python
usb_mk.hot_key("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端
```
4组合按键不放
```python
usb_mk.hot_key_down("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端不放
```
5释放所有键盘按键
```python
usb_mk.key_up()
```
6键盘输入字符串支持传入汉字会自动转成拼音输入
```python
usb_mk.hot_key("ctrl", "alt", "T") # 按下组合按键ctrl+alt+T调起终端
usb_mk.input_text("reboot") # 输入字符串reboot
usb_mk.press_key("enter") # 按下键盘enter键
```
### 2、鼠标操作
1按下鼠标左键
```python
usb_mk.click()
```
2按下鼠标左键不放
```python
usb_mk.mouse_down()
```
3释放鼠标所有按键
```python
usb_mk.mouse_up()
```
4按下鼠标右键
```python
usb_mk.right_click()
```
5鼠标左键双击
```python
usb_mk.double_click()
```
6恢复鼠标至初始位置默认左上角
```python
usb_mk.move_to_init()
```
7移动鼠标至相对坐标
```python
usb_mk.move_rel(100, 200) # 鼠标向左边移动100个像素向下移动200个像素
```
8以屏幕左上角为圆心坐标移动鼠标至屏幕绝对坐标
```python
usb_mk.move_to(100, 200) # 鼠标移动至屏幕坐标100, 200
```
9按下鼠标左键拖动到绝对坐标位置
```python
usb_mk.drag_to(100, 200) # 按下鼠标拖动至屏幕坐标100, 200
```
10按下鼠标左键拖动到相对坐标位置
```python
usb_mk.drag_rel(100, 200) # 鼠标向左边移动100个像素向下移动200个像素
```
## 十、继电器控制主机开机/重启
(若不使用继电器,可忽略该步骤,执行时会通过命令 `reboot`
### 1、继电器设备
`LCUS-2` 型 双路 `USB` 智能串口控制继电器。
https://item.taobao.com/item.htm?spm=a1z09.2.0.0.41d72e8dUYx2pi&id=582653718178&_u=i25r20ia6a2e
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff5091.png)
### 2、USB 延长线
普通的 `USB` 线即可。
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff50a9.png)
### 3、杜邦线
3.1、`40P` 母对公杜邦线。
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff50db.png)
3.2、一母二公杜邦线。
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff5102.png)
### 4、安装图文教程
4.1、使用 `USB` 延长线连接控制端和继电器。
![](https://pic.imgdb.cn/item/64f054cb661c6c8e54ff5140.png)
4.2、在继电器常端和公共端均连接一根杜邦线。
![](https://pic.imgdb.cn/item/64f054cc661c6c8e54ff5182.png)
4.3、在主板上开机针和重启针上插上一母二公杜邦线。
![](https://pic.imgdb.cn/item/64f054cc661c6c8e54ff51c2.png)
4.4、将开机针外接的一母二公杜邦线的两根公线分别接入继电器的1路继电器如图 1左侧继电器和原电源开关。
4.5、将重启针外接的一母二公杜邦线的两根公线分别接入继电器的2路继电器如图 1 右侧继电器)和原电源开关。
![](https://pic.imgdb.cn/item/64f054cc661c6c8e54ff523e.png)
若想保留原电源开关的电源灯,可根据如上图所示,使用杜邦线连接主板上的电源灯和原电源开关
## 十一、常见问题说明
**1、**`ERROR: for uos Cannot restart container 2301b1a1395d7959ee6523d61b61c87084649af530786cdb8fb5b3ecbcbd1068: linux runtime spec devices: error gathering device information while adding custom device "/dev/ttyACM0": no such file or directory`
检查 USB 串口线连接状态,查看 `/dev/ttyACM0` 是否存在,若存在 `/dev/ttyACMn`n为任意数字重启电脑解决。
**2、**`Error response from daemon: Container 5e700fdc769e8c74666d68a7f2bc3de58268b4594cf88706609d59f8dbc7362d is not running`
容器启动失败
1检查哪一个容器未启动
```shell
sudo docker container ls # 列出运行中的 Docker 容器
```
![](https://pic.imgdb.cn/item/64f054cc661c6c8e54ff524b.png)
2缺少 uos 容器,检查 USB 串口连接线和采集盒连接线是否正常,重启后执行
```shell
bash install/setup.up # 重新完整部署环境
```
或执行
```shell
sudo docker-compose up -d --build # 仅重新构建 Docker 镜像
```
**3、**若部署时提示挂载 `ttyACM0`、`video0` 失败,请检查 USB 串口线及采集盒是否接触良好,若接触良好,重启即可解决。
4、若出现图片能识别但是鼠标未移动操作时安装绝对鼠标操作的依赖包见第三节第二小节测试机环境搭建安装完成后必须重启测试机。
5、由于通过采集卡获取的测试机实时画面包含了鼠标的样式所以对图片识别时鼠标若停留在图标上层则会对识别结果造成影响需要将鼠标移动至其他位置或者隐藏鼠标解决。
6、Excel 报告中测试场景列与用例中的不一致关键字scene、app_name、架构别名不能包含下划线和英文符号的圆括号。

View File

@ -1,60 +0,0 @@
---
hide:
- navigation
---
# 框架生态
## :fontawesome-brands-github: 插件生态
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px">
:fontawesome-brands-github:{ .lg .middle } __funnylog__ [:octicons-arrow-right-24: 详情](https://linuxdeepin.github.io/funnylog){target="_blank"}
一个简单易用、功能强大的日志工具,只需要加一个装饰器,就能自动日志输出类里面所有的方法的功能说明。
</div>
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px">
:fontawesome-brands-github:{ .lg .middle } __letmego__ [:octicons-arrow-right-24: 详情](https://linuxdeepin.github.io/letmego){target="_blank"}
一个控制 Python 函数执行的技术方案,目前主要应用场景是在自动化测试程序遇到不得不中断的场景下,如重启场景,需要实现自动化用例步骤执行过程中重启机器,机器重新启动之后,能再次继续紧接着重启前的用例步骤执行的功能。
</div>
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px">
:fontawesome-brands-github:{ .lg .middle } __pdocr-rpc__ [:octicons-arrow-right-24: 详情](https://linuxdeepin.github.io/pdocr-rpc/){target="_blank"}
基于 PaddleOCR 封装的 RPC 服务,包含客户端和服务端,客户端提供了一个简单易用的函数 ocr通过不同的参数控制返回不同的值。
</div>
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px">
:fontawesome-brands-github:{ .lg .middle } __image-center__ [:octicons-arrow-right-24: 详情](https://linuxdeepin.github.io/image-center/){target="_blank"}
图像识别定位某个元素在当前屏幕中的坐标,在自动化测试中获取到元素坐标之后,可以传入到键鼠工具,从而实现对目标元素的操作。
</div>
## :file_folder: 衍生工具
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px;">
:file_folder:{ .lg .middle } __工具库__ [:octicons-arrow-right-24: 详情](http://youqu.uniontech.com/tool/){target="_blank"}
各种工具Bug定级工具、备注模板、常用网址、内网激活等等
</div>
---
<div class="grid cards hvr-grow-shadow hvr-overline-from-center" markdown style="width: 850px;">
:file_folder:{ .lg .middle } __知识库__ [:octicons-arrow-right-24: 详情](http://youqu.uniontech.com/docs/){target="_blank"}
知识库网站
</div>

View File

@ -44,7 +44,7 @@ theme:
repo: fontawesome/brands/github
repo_name: YouQu
repo_url: https://github.com/linuxdeepin/deepin-autotest-framework
repo_url: https://github.com/linuxdeepin/youqu
markdown_extensions:
- toc:
@ -106,7 +106,7 @@ extra:
- icon: fontawesome/brands/python
link: https://pypi.org/project/youqu
name: pypi
homepage: https://linuxdeepin.github.io/deepin-autotest-framework
homepage: https://linuxdeepin.github.io/youqu
extra_javascript:
- '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js'

View File

@ -15,7 +15,7 @@
"medium-zoom": "^1.1.0",
"mermaid": "^9.1.0",
"vitepress-plugin-back-to-top": "^1.0.1",
"vitepress-plugin-comment-with-giscus": "^1.1.11",
"vitepress-plugin-comment-with-giscus": "^1.1.12",
"vitepress-plugin-mermaid": "^2.0.10"
}
}

View File

@ -17,7 +17,7 @@
# "pms_case_file_path": ""
#}
[repositories]
[[repositories]]
url = ""
branch_or_tag = ""
depth = ""

View File

@ -6,8 +6,8 @@ tmp_publish_dir_name=_youqu_publish_tmp_dir
cd ..
rm -rf ${tmp_publish_dir_name}
mkdir -p ${tmp_publish_dir_name}/youqu/apps/
ls deepin-autotest-framework | grep -v apps | grep -v public | grep -v report | xargs -i cp -r deepin-autotest-framework/{} ${tmp_publish_dir_name}/youqu/
cp deepin-autotest-framework/apps/__init__.py ${tmp_publish_dir_name}/youqu/apps/
ls youqu | grep -v apps | grep -v public | grep -v report | xargs -i cp -r youqu/{} ${tmp_publish_dir_name}/youqu/
cp youqu/apps/__init__.py ${tmp_publish_dir_name}/youqu/apps/
rm -rf ${tmp_publish_dir_name}/youqu/.idea
rm -rf ${tmp_publish_dir_name}/youqu/.vscode
rm -rf ${tmp_publish_dir_name}/youqu/.pytest_cache
@ -27,8 +27,8 @@ rm -rf ${tmp_publish_dir_name}/youqu/apps/autotest*
rm -rf ${tmp_publish_dir_name}/youqu/Pipfile
rm -rf ${tmp_publish_dir_name}/youqu/Pipfile.lock
rm -rf ${tmp_publish_dir_name}/youqu/ci_result.json
cp deepin-autotest-framework/pyproject.toml ${tmp_publish_dir_name}/
cp deepin-autotest-framework/src/startproject.py ${tmp_publish_dir_name}/youqu/
cp youqu/pyproject.toml ${tmp_publish_dir_name}/
cp youqu/src/startproject.py ${tmp_publish_dir_name}/youqu/
cd ${tmp_publish_dir_name}/
python3 -m build
#twine upload dist/*

View File

@ -9,7 +9,7 @@ authors = [
{ name = "mikigo", email = "huangmingqiang@uniontech.com" },
]
description = "deepin-autotest-framework"
description = "youqu"
readme = "youqu/README.md"
requires-python = ">=3.7"
classifiers = [
@ -32,5 +32,5 @@ packages = [
]
[project.urls]
Source = "https://github.com/linuxdeepin/deepin-autotest-framework"
Documentation = "https://linuxdeepin.github.io/deepin-autotest-framework"
Source = "https://github.com/linuxdeepin/youqu"
Documentation = "https://linuxdeepin.github.io/youqu"

View File

@ -252,8 +252,8 @@ class _GlobalConfig:
top_cmd = "top -b -d 3 -w 512"
GITHUB_URL = "https://github.com/linuxdeepin/deepin-autotest-framework"
DOCS_URL = "https://linuxdeepin.github.io/deepin-autotest-framework"
GITHUB_URL = "https://github.com/linuxdeepin/youqu"
DOCS_URL = "https://linuxdeepin.github.io/youqu"
PyPI_URL = "https://pypi.org/project/youqu"
LETMEGO_DEBUG = True

View File

@ -67,7 +67,7 @@ def _ssh(ip, password, user):
def _transfer_appname(ip, password, user, transfer_appname):
os.system(
f"sshpass -p '{password}' rsync -av -e ssh --exclude='__pycache__' "
f"{conf.APPS_PATH}/{transfer_appname} {user}@{ip}:~/{client_project_path}/apps/{transfer_appname}"
f"{conf.APPS_PATH}/{transfer_appname} {user}@{ip}:~/{client_project_path}/apps/"
)

View File

@ -43,11 +43,12 @@ class Remote(ShortCut, CmdCtl):
f"Remote(user='{self.user}', ip='{self.ip}', password='{self.password}').rctl.{item}({ar.rstrip(', ')})"
)
getattr(self.rctl, item)(*args, **kwargs)
value = getattr(self.rctl, item)(*args, **kwargs)
self.remote_method_has_arguments = True
if self.tmp_obj:
setattr(self.tmp_obj["cls_obj"], item, self.tmp_obj["item_obj"])
return value
return func

View File

@ -90,7 +90,7 @@ class LocalRunner:
logger("INFO")
try:
github_tags = RequestX().open_url(
f"https://api.github.com/repos/linuxdeepin/deepin-autotest-framework/tags",
f"https://api.github.com/repos/linuxdeepin/youqu/tags",
timeout=1
)
latest_tag = json.loads(github_tags)[0].get("name")