diff --git a/404.html b/404.html index 341b7f93..48f1ef8a 100644 --- a/404.html +++ b/404.html @@ -8,7 +8,7 @@ - + @@ -16,8 +16,8 @@ -
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
- +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.
+ \ No newline at end of file diff --git a/CONTRIBUTING.html b/CONTRIBUTING.html index 09ebeb87..eccc757d 100644 --- a/CONTRIBUTING.html +++ b/CONTRIBUTING.html @@ -8,20 +8,20 @@ - + - - - + + + -
Skip to content
📔 阅读量:

贡献,并且帮助我们改进

感谢您参与本项目,对于任何形式的贡献我们都欢迎;

目前我们欢迎以下方面的贡献:

帮助改进 YouQu 文档

欢迎任何微如错别字、大到添加章节帮助我们提高项目的 Pull Requests。

向 YouQu 提交 Issues

Issues 提交地址:https://github.com/linuxdeepin/youqu/issues

向 YouQu 仓库提交代码

底层基础能力的代码为上层业务服务,不应该把含有业务相关的代码提交到框架底层;

最后更新于:

- +
Skip to content
📔 阅读量:

贡献,并且帮助我们改进

感谢您参与本项目,对于任何形式的贡献我们都欢迎;

目前我们欢迎以下方面的贡献:

帮助改进 YouQu 文档

欢迎任何微如错别字、大到添加章节帮助我们提高项目的 Pull Requests。

向 YouQu 提交 Issues

Issues 提交地址:https://github.com/linuxdeepin/youqu/issues

向 YouQu 仓库提交代码

底层基础能力的代码为上层业务服务,不应该把含有业务相关的代码提交到框架底层;

最后更新于:

+ \ No newline at end of file diff --git a/RELEASE.html b/RELEASE.html index 2275002d..880e7a2f 100644 --- a/RELEASE.html +++ b/RELEASE.html @@ -8,19 +8,19 @@ - + - - - + + + -
Skip to content
📔 阅读量:

版本更新记录

2.6.8(2024/07/15)

New 🌟

  • git commit 功能增加显示明细数据。
  • 新增在所有属性中查找同名节点的功能。

2.6.7(2024/07/15)

Fix 🐛

  • 修复 Wayland 下窗管返回的 window_info 内获取应用名称的逻辑错误的问题。

2.6.6(2024/07/05)

New 🌟

  • git commit 统计功能新增 commit msg 信息获取。

Fix 🐛

  • 修复测试单驱动收集用例数量为 0 的问题;
  • 修复 Wayland 下窗管返回的应用名称错误的问题;

2.6.5(2024/06/11)

Fix 🐛

  • 修复用例失败截图添加到测试报告时报错的问题;

2.6.4(2024/06/07)

Fix 🐛

  • 由于窗管团队修改获取窗口信息的返回值,导致 Wayland 下相对位移定位方案报错,YouQu 进行适配。

2.6.3(2024/06/07)

New 🌟

  • 新增 ocr 范围识别;

Fix 🐛

  • 测试单驱动,手动回填模式报错;
  • 修改 Wayland 下中文写入剪贴版问题,改为使用 wl-copy 命令实现;
  • 修复远程交互控制测试机注销后 RPC 服务不响应的问题;

2.6.2(2024/05/29)

New 🌟

  • JSON 报告功能优化

    run 模式下:

    • /report/json/detail_report.json 包含每条 py 脚本的结果;
    • /report/json/summarize.json 根据 detail_report.json 计算的汇总数据;

    remote 模式下:

    • 收集远程测试机上所有的 /report/json/${timestr}_remote/detail_report_${IP}.json
    • 收集远程测试机上所有的 /report/json/${timestr}_remote/summarize_${IP}.json
    • 负载均衡驱动模式下自动汇总 summarize 数据:/report/json/${timestr}_remote/summarize.json
  • remote 模式新增参数:git_urlgit_usergit_passwordbranchdepth 用以控制拉取 git 仓库代码;

  • 由于 letmego 方案使用场景较少,默认环境中移除此模块,子项目需要时通过新增依赖机制进行安装;

  • 支持将测试结果回传给测试平台;

  • 文档更新:实践/HTTP接口自动化测试/创建一条完整的用例。@003307

  • YouQu 插件 pdocr-rpc 更新:支持Windows和MacOS,图片入参支持多种图片格式,并兼容不带文件后缀名入参方式。@CCrazyPeter

Fix 🐛

  • 修复测试单驱动执行报错的问题;
  • YouQu 插件 pdocr-rpc 修复服务器系统获取显示协议错误的问题;

2.6.1(2024/05/21)

这个版本中,我们成功在欧拉社区开源 src-openeuler ,后续将以 patch 的方式持续在欧拉社区进行代码更新,希望欧拉系统上使用到 YouQu 的同学们能给我们反馈使用情况。

此外,重点对统计 commit 功能进行了优化和 Bug 修复,此功能目前还处于内部灰度阶段,未来有希望成为 YouQu 的另一个亮点,能自动分析统计每次提交中包含的用例和方法的增删改的数据,数据汇报者统计者的利器。

New 🌟

  • 新增 skipif_not_xxx 条件跳过逻辑;PR #68 by @DarkLii
  • 对生成的 JSON 报告的路径、文件名称、报告内容进行了重新规划,将在下一个版本开发并发布;@mikigo
  • 文档更新:指南/框架必备/执行管理器,新增用例驱动方式章节,用以集中说明 YouQu 支持的驱动方式。@mikigo
  • YouQu 插件 image-center 更新:支持 WindowsMacOS,图片入参支持多种图片格式,并兼容不带文件后缀名入参方式。@CCrazyPeter

Fix 🐛

  • 修复统计 commit 数据中修复方法数量错误的问题;@mikigo

  • 修改 JSON 报告计算逻辑:@mikigo

    • 用例总数 = 通过数 + 失败数 (剔除跳过数)

    • 失败数:剔除跳过数

    • 跳过数:跳过用例数

    • 通过率 = 通过数 / 用例总数

  • 修复 env.sh 提示找不到 youqu-shell-rm 的问题,将删除虚拟环境的命令修改为:youqu-rm@mikigo

  • 修复统计 commit 功能 enddate 报错的问题;@mikigo

2.6.0(2024/05/14)

近期,YouQu 自动化测试框架迎来了一系列令人振奋的更新,这些更新不仅提升了框架的性能和稳定性,也拓展了其功能和适用范围。通过引入 OCR 服务集群化部署和模型 v4,我们显著提高了文本识别的准确性和效率。新增的链式调用函数接口使操作更加直观和便捷。

在功能创新方面,我们推出了 Web UI 自动化测试功能和远程交互式控制功能,为自动化测试提供了更加丰富和灵活的手段。同时,我们还增强了报告的功能,新增了生成的 json 结果以 py 维度统计,为测试数据的分析和解读提供了更多维度。

平台兼容适配性方面,我们对 openEuler 系统完成了适配,为后续开源到 openEuler 社区做好准备。

在问题修复方面,我们针对用户反馈的多个问题进行了积极的调查和解决,包括报告生成时的错误处理、远程调用的稳定性和兼容性等问题,这些修复进一步提升了用户体验,确保了框架的稳定性和可靠性。

总的来说,这一系列的更新标志着 YouQu 自动化测试框架在便捷性和稳定性方面迈出了重要的一步,我们坚信这些更新将极大地提升开发者和测试人员的效率,推动自动化测试技术向前发展。

New 🌟

  • OCR 服务性能优化,使用 OCR 服务集群化部署,框架自动做负载均衡,同时启用 OCR 识别模型 v4,进一步提高识别稳定性和准确性。@mikigo

  • YouQu OCR 新增支持链式调用函数接口,使用更方便更符合语义,原函数接口使用方法不变以保持兼容性。@mikigo

    python
    from src import OCR
    +    
    Skip to content
    📔 阅读量:

    版本更新记录

    2.6.9(2024/08/05)

    Fix 🐛

    • Cmd.sudo_run_cmd增加workdir功能
    • 将run_cmd固定shell默认指定为/bin/bash
    • 临时处理input_message方法,在wayland输入中文末尾多出空格的问题
    • 修改部署客户端设备youqu环境时,阻塞在密码输入
    • 扩展OCR断言支持区域断言,提升精准度,优化OCR识别范围筛选方法

    2.6.8(2024/07/15)

    New 🌟

    • git commit 功能增加显示明细数据。
    • 新增在所有属性中查找同名节点的功能。

    2.6.7(2024/07/15)

    Fix 🐛

    • 修复 Wayland 下窗管返回的 window_info 内获取应用名称的逻辑错误的问题。

    2.6.6(2024/07/05)

    New 🌟

    • git commit 统计功能新增 commit msg 信息获取。

    Fix 🐛

    • 修复测试单驱动收集用例数量为 0 的问题;
    • 修复 Wayland 下窗管返回的应用名称错误的问题;

    2.6.5(2024/06/11)

    Fix 🐛

    • 修复用例失败截图添加到测试报告时报错的问题;

    2.6.4(2024/06/07)

    Fix 🐛

    • 由于窗管团队修改获取窗口信息的返回值,导致 Wayland 下相对位移定位方案报错,YouQu 进行适配。

    2.6.3(2024/06/07)

    New 🌟

    • 新增 ocr 范围识别;

    Fix 🐛

    • 测试单驱动,手动回填模式报错;
    • 修改 Wayland 下中文写入剪贴版问题,改为使用 wl-copy 命令实现;
    • 修复远程交互控制测试机注销后 RPC 服务不响应的问题;

    2.6.2(2024/05/29)

    New 🌟

    • JSON 报告功能优化

      run 模式下:

      • /report/json/detail_report.json 包含每条 py 脚本的结果;
      • /report/json/summarize.json 根据 detail_report.json 计算的汇总数据;

      remote 模式下:

      • 收集远程测试机上所有的 /report/json/${timestr}_remote/detail_report_${IP}.json
      • 收集远程测试机上所有的 /report/json/${timestr}_remote/summarize_${IP}.json
      • 负载均衡驱动模式下自动汇总 summarize 数据:/report/json/${timestr}_remote/summarize.json
    • remote 模式新增参数:git_urlgit_usergit_passwordbranchdepth 用以控制拉取 git 仓库代码;

    • 由于 letmego 方案使用场景较少,默认环境中移除此模块,子项目需要时通过新增依赖机制进行安装;

    • 支持将测试结果回传给测试平台;

    • 文档更新:实践/HTTP接口自动化测试/创建一条完整的用例。@003307

    • YouQu 插件 pdocr-rpc 更新:支持Windows和MacOS,图片入参支持多种图片格式,并兼容不带文件后缀名入参方式。@CCrazyPeter

    Fix 🐛

    • 修复测试单驱动执行报错的问题;
    • YouQu 插件 pdocr-rpc 修复服务器系统获取显示协议错误的问题;

    2.6.1(2024/05/21)

    这个版本中,我们成功在欧拉社区开源 src-openeuler ,后续将以 patch 的方式持续在欧拉社区进行代码更新,希望欧拉系统上使用到 YouQu 的同学们能给我们反馈使用情况。

    此外,重点对统计 commit 功能进行了优化和 Bug 修复,此功能目前还处于内部灰度阶段,未来有希望成为 YouQu 的另一个亮点,能自动分析统计每次提交中包含的用例和方法的增删改的数据,数据汇报者统计者的利器。

    New 🌟

    • 新增 skipif_not_xxx 条件跳过逻辑;PR #68 by @DarkLii
    • 对生成的 JSON 报告的路径、文件名称、报告内容进行了重新规划,将在下一个版本开发并发布;@mikigo
    • 文档更新:指南/框架必备/执行管理器,新增用例驱动方式章节,用以集中说明 YouQu 支持的驱动方式。@mikigo
    • YouQu 插件 image-center 更新:支持 WindowsMacOS,图片入参支持多种图片格式,并兼容不带文件后缀名入参方式。@CCrazyPeter

    Fix 🐛

    • 修复统计 commit 数据中修复方法数量错误的问题;@mikigo

    • 修改 JSON 报告计算逻辑:@mikigo

      • 用例总数 = 通过数 + 失败数 (剔除跳过数)

      • 失败数:剔除跳过数

      • 跳过数:跳过用例数

      • 通过率 = 通过数 / 用例总数

    • 修复 env.sh 提示找不到 youqu-shell-rm 的问题,将删除虚拟环境的命令修改为:youqu-rm@mikigo

    • 修复统计 commit 功能 enddate 报错的问题;@mikigo

    2.6.0(2024/05/14)

    近期,YouQu 自动化测试框架迎来了一系列令人振奋的更新,这些更新不仅提升了框架的性能和稳定性,也拓展了其功能和适用范围。通过引入 OCR 服务集群化部署和模型 v4,我们显著提高了文本识别的准确性和效率。新增的链式调用函数接口使操作更加直观和便捷。

    在功能创新方面,我们推出了 Web UI 自动化测试功能和远程交互式控制功能,为自动化测试提供了更加丰富和灵活的手段。同时,我们还增强了报告的功能,新增了生成的 json 结果以 py 维度统计,为测试数据的分析和解读提供了更多维度。

    平台兼容适配性方面,我们对 openEuler 系统完成了适配,为后续开源到 openEuler 社区做好准备。

    在问题修复方面,我们针对用户反馈的多个问题进行了积极的调查和解决,包括报告生成时的错误处理、远程调用的稳定性和兼容性等问题,这些修复进一步提升了用户体验,确保了框架的稳定性和可靠性。

    总的来说,这一系列的更新标志着 YouQu 自动化测试框架在便捷性和稳定性方面迈出了重要的一步,我们坚信这些更新将极大地提升开发者和测试人员的效率,推动自动化测试技术向前发展。

    New 🌟

    • OCR 服务性能优化,使用 OCR 服务集群化部署,框架自动做负载均衡,同时启用 OCR 识别模型 v4,进一步提高识别稳定性和准确性。@mikigo

    • YouQu OCR 新增支持链式调用函数接口,使用更方便更符合语义,原函数接口使用方法不变以保持兼容性。@mikigo

      python
      from src import OCR
       
       # 新的函数接口ocrx,支持链式调用
       OCR.ocrx("确定").click()
      @@ -61,8 +61,8 @@
           pic_path = DeepinMusicWidget.save_temporary_picture(*DeepinMusicWidget().ui.btn_size("所有音乐按钮"))
           ...... # 中间操作
           self.assert_image_exit(pic_path)
  • allure 报告中定位问题除了日志、截图、录屏外,调用的函数增加了 step 步骤展示;@mikigo

  • env.sh 新增安装子项目 Python 三方依赖,在子项目根目录下写 requirement.txt 文件,env.sh 会自动加载;@mikigo

  • ocr 识别新增支持传入目标图片路径进行文字识别,减少因全屏识别时,其他文字的干扰;@mikigo

    • Python
      # 断言音乐的删除弹窗中,包含了“确认”的文字
      -self.assert_ocr_exist("确认", picture_abspath=DeepinMusicWidget.save_temporary_picture(*DeepinMusicWidget().ui.btn_size("删除弹窗")))
  • 断言函数的调用也会自动打印日志;@mikigo

  • env.sh 新增裁剪依赖的方案;@mikigo

Fix 🐛

  • 修复 Jenkins 环境下, apps 目录下子项目存在 auotest_deepin_xxx@tmp 目录,在传入 app_name 后无法执行用例的问题;@mikigo
  • 修复自动生成 case_list.csv 文件时,用例顺序被调整的问题;@mikigo
  • env.sh 环境安装移除 git 和 curl;@mikigo
  • 修复用例在 setup 阶段报错后,未写入 ci_result.json 的问题;@mikigo
  • 移除 uos_ci.py@mikigo

1.1.3(2022/10/28)

New 🌟

  • 新增图像断言成功输出匹配度;@mikigo
  • 新增环境安装 yaml 依赖;@mikigo
  • 新增测试套执行、数据回填兼容用例库ID和产品库ID;@mikigo
  • 新增测试结果表情显示,并优化了日志的排版;@mikigo
  • 新增 --top {number} 用于记录系统资源占用情况,日志生成到 report/logs/top.log@mikigo

Fix 🐛

  • 修复用例收集阶段报错,但终端没有错误日志输出的问题;@mikigo
  • 修改失败用例回溯日志为详细级别;@mikigo
  • 修复了执行进度未计算跳过用例的问题,并优化了进度获取的算法;@mikigo
  • 修复 env.sh 在 V23 环境下安装无法读取密码的问题;@mikigo
  • 修复了 pms 测试套执行或测试单执行时,用例ID兼容用例库ID和产品库ID;@mikigo
  • env.sh 里面 hub.deepin.com 更换成 it.uniontech.com;@mikigo
  • uos_ci.py 测试结果统计时,总数剔除 skip 的数量;@mikigo

1.1.2(2022/09/21)

New 🌟

  • 在没有安装 dogtail 的情况下,也能使用 sniff 工具;@mikigo

Fix 🐛

  • 修复持续集成流水线中没有安装 AT 环境执行 uos_ci.py 报错的问题;@mikigo

1.1.1(2022/09/19)

New 🌟

  • 新增执行进度显示,每条用例执行时日志输出当前进度:[当前指定第几条/用例总数];@mikigo
  • 新增终端输出用例执行结束之后所有失败用例的列表;@mikigo
  • 关闭终端输出捕获用例执行过程日志快照;@mikigo
  • 优化终端输出失败信息冗长为简要信息输出;@mikigo
  • 新增终端输出显示 10 个执行最慢的用例列表,并详细列出各个阶段的耗时;@mikigo
  • 失败重跑用例重跑之前延迟 1 秒;@mikigo
  • 新增收集阶段报错,仍然强制执行;@mikigo
  • 用例收集时仅在 apps 目录下进行,忽略 src,setting,public 目录;@mikigo
  • 新增 allure 报告备份功能,默认备份至 allure_back 目录下;@mikigo
  • manage.py新增参数 --lastfailed 用于只跑上次失败用例的功能;@mikigo

Fix 🐛

  • 修复了在没有指定应用名称执行时,xml 报告生成路径异常的问题;@mikigo
  • 修复了 uos_ci.py 传入 timeoutsession_timeout 不生效的问题;@mikigo

1.1.0(2022/09/16)

New 🌟

  • 新增PMS数据回填功能,支持多种数据回填模式;@mikigo
  • 优化了通过测试套件执行时PMS 爬虫的性能;@mikigo
  • 新增 .gitmodules 文件,用于标记所有子项目,方便统一拉取代码;@mikigo
  • env.sh 适配社区版上安装自动化环境;@mikigo
  • 增加执行过程中立即显示错误的功能;@mikigo
  • README.md 增加 Wayland 下使用、测试报告查看、常见问题等的文档说明;@mikigo
  • 增加了用例执行过程中对 setupcallteardown 进行日志分段;@mikigo

Fix 🐛

  • 修复了 确认修复 列没写表头,但写了 Fix 🐛ed-xxx 标签,出现的程序报错问题;@mikigo
  • 修复了同一应用内多个 csv 文件中 确认修复 列有的写了,有的没写,可能出现的程序报错的问题;@mikigo
  • 修复了 INFO 日志,显示为 DEBUG 的问题;修复了部分机器上 INFO 日志内容显示为红色的问题;@mikigo
  • 修复了用例收集阶段报错看不到详细信息的问题;@mikigo

1.0.2(2022/08/22)

New 🌟

  • 移除 loguru,替换为 logging,接口保持不变,上层用例不受影响;@mikigo
  • 默认开启 coredump@mikigo

Fix 🐛

  • 修复了三方库 loguru 偶现异常,导致程序中断的问题;@mikigo
  • 修复了第一次失败不会关闭文件选择框的问题;@mikigo

1.0.1(2022/08/12)

New 🌟

  • 新增 RELEASE.md 文件,用于记录历史发布版本的更新内容;@mikigo

  • 兼容 Wayland 模式下执行用例,上层用例不用管当前测试机执行环境,框架会自动根据当前环境走不同的代码逻辑;@mikigo

  • 由于需要修改 dogtail 源代码,因此将修改后的源码放入到核心库里面 src/depends/dogtail 后续版本不需要在系统中安装dogtail@mikigo

  • 如果应用库同样使用了系统安装的 dogtail 可能会报错,解决方案是将代码中的 import dogtail 修改为 from src.depends import dogtail ;@mikigo

Fix 🐛

  • 重跑失败之后才会关闭文件选择框,修改为失败之后会关闭文件选择框;@mikigo

最后更新于:

- +self.assert_ocr_exist("确认", picture_abspath=DeepinMusicWidget.save_temporary_picture(*DeepinMusicWidget().ui.btn_size("删除弹窗")))
  • 断言函数的调用也会自动打印日志;@mikigo

  • env.sh 新增裁剪依赖的方案;@mikigo

  • Fix 🐛

    1.1.3(2022/10/28)

    New 🌟

    Fix 🐛

    1.1.2(2022/09/21)

    New 🌟

    Fix 🐛

    1.1.1(2022/09/19)

    New 🌟

    Fix 🐛

    1.1.0(2022/09/16)

    New 🌟

    Fix 🐛

    1.0.2(2022/08/22)

    New 🌟

    Fix 🐛

    1.0.1(2022/08/12)

    New 🌟

    Fix 🐛

    + \ No newline at end of file diff --git a/SIG.html b/SIG.html index 6612a8f6..9a9b72d7 100644 --- a/SIG.html +++ b/SIG.html @@ -8,20 +8,20 @@ - + - - - + + + -
    Skip to content
    📔 阅读量:

    YouQu 官方兴趣小组


    致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。

    相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。


    YouQu官方兴趣小组

    最后更新于:

    - +
    Skip to content
    📔 阅读量:

    YouQu 官方兴趣小组


    致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。

    相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。


    YouQu官方兴趣小组

    最后更新于:

    + \ No newline at end of file diff --git a/assets/CONTRIBUTING.md.BE80_gXx.js b/assets/CONTRIBUTING.md.HEIFCxPI.js similarity index 96% rename from assets/CONTRIBUTING.md.BE80_gXx.js rename to assets/CONTRIBUTING.md.HEIFCxPI.js index 04232674..fc722509 100644 --- a/assets/CONTRIBUTING.md.BE80_gXx.js +++ b/assets/CONTRIBUTING.md.HEIFCxPI.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,U as o}from"./chunks/framework.DIzwIJpr.js";const q=JSON.parse('{"title":"贡献,并且帮助我们改进","description":"","frontmatter":{},"headers":[],"relativePath":"CONTRIBUTING.md","filePath":"CONTRIBUTING.md","lastUpdated":1722828555000}'),s={name:"CONTRIBUTING.md"},u=o('

    贡献,并且帮助我们改进

    感谢您参与本项目,对于任何形式的贡献我们都欢迎;

    目前我们欢迎以下方面的贡献:

    帮助改进 YouQu 文档

    欢迎任何微如错别字、大到添加章节帮助我们提高项目的 Pull Requests。

    向 YouQu 提交 Issues

    Issues 提交地址:https://github.com/linuxdeepin/youqu/issues

    向 YouQu 仓库提交代码

    底层基础能力的代码为上层业务服务,不应该把含有业务相关的代码提交到框架底层;

    ',9),r=[u];function i(n,l,h,c,d,_){return t(),a("div",null,r)}const m=e(s,[["render",i]]);export{q as __pageData,m as default}; +import{_ as e,c as a,o as t,U as o}from"./chunks/framework.DIzwIJpr.js";const q=JSON.parse('{"title":"贡献,并且帮助我们改进","description":"","frontmatter":{},"headers":[],"relativePath":"CONTRIBUTING.md","filePath":"CONTRIBUTING.md","lastUpdated":1722828751000}'),s={name:"CONTRIBUTING.md"},u=o('

    贡献,并且帮助我们改进

    感谢您参与本项目,对于任何形式的贡献我们都欢迎;

    目前我们欢迎以下方面的贡献:

    帮助改进 YouQu 文档

    欢迎任何微如错别字、大到添加章节帮助我们提高项目的 Pull Requests。

    向 YouQu 提交 Issues

    Issues 提交地址:https://github.com/linuxdeepin/youqu/issues

    向 YouQu 仓库提交代码

    底层基础能力的代码为上层业务服务,不应该把含有业务相关的代码提交到框架底层;

    ',9),r=[u];function i(n,l,h,c,d,_){return t(),a("div",null,r)}const m=e(s,[["render",i]]);export{q as __pageData,m as default}; diff --git a/assets/CONTRIBUTING.md.BE80_gXx.lean.js b/assets/CONTRIBUTING.md.HEIFCxPI.lean.js similarity index 85% rename from assets/CONTRIBUTING.md.BE80_gXx.lean.js rename to assets/CONTRIBUTING.md.HEIFCxPI.lean.js index 87a12769..2edb847f 100644 --- a/assets/CONTRIBUTING.md.BE80_gXx.lean.js +++ b/assets/CONTRIBUTING.md.HEIFCxPI.lean.js @@ -1 +1 @@ -import{_ as e,c as a,o as t,U as o}from"./chunks/framework.DIzwIJpr.js";const q=JSON.parse('{"title":"贡献,并且帮助我们改进","description":"","frontmatter":{},"headers":[],"relativePath":"CONTRIBUTING.md","filePath":"CONTRIBUTING.md","lastUpdated":1722828555000}'),s={name:"CONTRIBUTING.md"},u=o("",9),r=[u];function i(n,l,h,c,d,_){return t(),a("div",null,r)}const m=e(s,[["render",i]]);export{q as __pageData,m as default}; +import{_ as e,c as a,o as t,U as o}from"./chunks/framework.DIzwIJpr.js";const q=JSON.parse('{"title":"贡献,并且帮助我们改进","description":"","frontmatter":{},"headers":[],"relativePath":"CONTRIBUTING.md","filePath":"CONTRIBUTING.md","lastUpdated":1722828751000}'),s={name:"CONTRIBUTING.md"},u=o("",9),r=[u];function i(n,l,h,c,d,_){return t(),a("div",null,r)}const m=e(s,[["render",i]]);export{q as __pageData,m as default}; diff --git a/assets/RELEASE.md.DEam-HSA.js b/assets/RELEASE.md.DRw-SwT2.js similarity index 89% rename from assets/RELEASE.md.DEam-HSA.js rename to assets/RELEASE.md.DRw-SwT2.js index f02b51ed..c84f29e2 100644 --- a/assets/RELEASE.md.DEam-HSA.js +++ b/assets/RELEASE.md.DRw-SwT2.js @@ -1,4 +1,4 @@ -import{_ as e,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"版本更新记录","description":"","frontmatter":{},"headers":[],"relativePath":"RELEASE.md","filePath":"RELEASE.md","lastUpdated":1722828555000}'),r={name:"RELEASE.md"},o=t(`

    版本更新记录

    2.6.8(2024/07/15)

    New 🌟

    2.6.7(2024/07/15)

    Fix 🐛

    2.6.6(2024/07/05)

    New 🌟

    Fix 🐛

    2.6.5(2024/06/11)

    Fix 🐛

    2.6.4(2024/06/07)

    Fix 🐛

    2.6.3(2024/06/07)

    New 🌟

    Fix 🐛

    2.6.2(2024/05/29)

    New 🌟

    Fix 🐛

    2.6.1(2024/05/21)

    这个版本中,我们成功在欧拉社区开源 src-openeuler ,后续将以 patch 的方式持续在欧拉社区进行代码更新,希望欧拉系统上使用到 YouQu 的同学们能给我们反馈使用情况。

    此外,重点对统计 commit 功能进行了优化和 Bug 修复,此功能目前还处于内部灰度阶段,未来有希望成为 YouQu 的另一个亮点,能自动分析统计每次提交中包含的用例和方法的增删改的数据,数据汇报者统计者的利器。

    New 🌟

    Fix 🐛

    2.6.0(2024/05/14)

    近期,YouQu 自动化测试框架迎来了一系列令人振奋的更新,这些更新不仅提升了框架的性能和稳定性,也拓展了其功能和适用范围。通过引入 OCR 服务集群化部署和模型 v4,我们显著提高了文本识别的准确性和效率。新增的链式调用函数接口使操作更加直观和便捷。

    在功能创新方面,我们推出了 Web UI 自动化测试功能和远程交互式控制功能,为自动化测试提供了更加丰富和灵活的手段。同时,我们还增强了报告的功能,新增了生成的 json 结果以 py 维度统计,为测试数据的分析和解读提供了更多维度。

    平台兼容适配性方面,我们对 openEuler 系统完成了适配,为后续开源到 openEuler 社区做好准备。

    在问题修复方面,我们针对用户反馈的多个问题进行了积极的调查和解决,包括报告生成时的错误处理、远程调用的稳定性和兼容性等问题,这些修复进一步提升了用户体验,确保了框架的稳定性和可靠性。

    总的来说,这一系列的更新标志着 YouQu 自动化测试框架在便捷性和稳定性方面迈出了重要的一步,我们坚信这些更新将极大地提升开发者和测试人员的效率,推动自动化测试技术向前发展。

    New 🌟

    Fix 🐛

    1.1.3(2022/10/28)

    New 🌟

    Fix 🐛

    1.1.2(2022/09/21)

    New 🌟

    Fix 🐛

    1.1.1(2022/09/19)

    New 🌟

    Fix 🐛

    1.1.0(2022/09/16)

    New 🌟

    Fix 🐛

    1.0.2(2022/08/22)

    New 🌟

    Fix 🐛

    1.0.1(2022/08/12)

    New 🌟

    Fix 🐛

    `,287),s=[o];function l(n,h,p,g,c,d){return a(),i("div",null,s)}const m=e(r,[["render",l]]);export{u as __pageData,m as default}; +self.assert_ocr_exist("确认", picture_abspath=DeepinMusicWidget.save_temporary_picture(*DeepinMusicWidget().ui.btn_size("删除弹窗")))
  • 断言函数的调用也会自动打印日志;@mikigo

  • env.sh 新增裁剪依赖的方案;@mikigo

  • Fix 🐛

    1.1.3(2022/10/28)

    New 🌟

    Fix 🐛

    1.1.2(2022/09/21)

    New 🌟

    Fix 🐛

    1.1.1(2022/09/19)

    New 🌟

    Fix 🐛

    1.1.0(2022/09/16)

    New 🌟

    Fix 🐛

    1.0.2(2022/08/22)

    New 🌟

    Fix 🐛

    1.0.1(2022/08/12)

    New 🌟

    Fix 🐛

    `,290),s=[o];function l(n,h,p,g,c,d){return a(),i("div",null,s)}const m=e(r,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/RELEASE.md.DEam-HSA.lean.js b/assets/RELEASE.md.DRw-SwT2.lean.js similarity index 68% rename from assets/RELEASE.md.DEam-HSA.lean.js rename to assets/RELEASE.md.DRw-SwT2.lean.js index 5bee1d40..5b0c2e8e 100644 --- a/assets/RELEASE.md.DEam-HSA.lean.js +++ b/assets/RELEASE.md.DRw-SwT2.lean.js @@ -1 +1 @@ -import{_ as e,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"版本更新记录","description":"","frontmatter":{},"headers":[],"relativePath":"RELEASE.md","filePath":"RELEASE.md","lastUpdated":1722828555000}'),r={name:"RELEASE.md"},o=t("",287),s=[o];function l(n,h,p,g,c,d){return a(),i("div",null,s)}const m=e(r,[["render",l]]);export{u as __pageData,m as default}; +import{_ as e,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"版本更新记录","description":"","frontmatter":{},"headers":[],"relativePath":"RELEASE.md","filePath":"RELEASE.md","lastUpdated":1722828751000}'),r={name:"RELEASE.md"},o=t("",290),s=[o];function l(n,h,p,g,c,d){return a(),i("div",null,s)}const m=e(r,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/SIG.md.Bh8YEa0v.js b/assets/SIG.md.DLmEvgGN.js similarity index 94% rename from assets/SIG.md.Bh8YEa0v.js rename to assets/SIG.md.DLmEvgGN.js index b3d92d16..588c3413 100644 --- a/assets/SIG.md.Bh8YEa0v.js +++ b/assets/SIG.md.DLmEvgGN.js @@ -1 +1 @@ -import{_ as e,c as o,o as a,m as t,a as s}from"./chunks/framework.DIzwIJpr.js";const n="/youqu/wechat.jpg",Q=JSON.parse('{"title":"YouQu 官方兴趣小组","description":"","frontmatter":{},"headers":[],"relativePath":"SIG.md","filePath":"SIG.md","lastUpdated":1722828555000}'),c={name:"SIG.md"},l=t("h1",{id:"youqu-官方兴趣小组",tabindex:"-1"},[s("YouQu 官方兴趣小组 "),t("a",{class:"header-anchor",href:"#youqu-官方兴趣小组","aria-label":'Permalink to "YouQu 官方兴趣小组"'},"​")],-1),r=t("hr",null,null,-1),_=t("p",null,"致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。",-1),u=t("p",null,"相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。",-1),d=t("hr",null,null,-1),i=t("img",{src:n,width:"400",alt:"YouQu官方兴趣小组",align:"center/"},null,-1),h=[l,r,_,u,d,i];function p(m,f,x,S,g,G){return a(),o("div",null,h)}const Y=e(c,[["render",p]]);export{Q as __pageData,Y as default}; +import{_ as e,c as o,o as a,m as t,a as s}from"./chunks/framework.DIzwIJpr.js";const n="/youqu/wechat.jpg",Q=JSON.parse('{"title":"YouQu 官方兴趣小组","description":"","frontmatter":{},"headers":[],"relativePath":"SIG.md","filePath":"SIG.md","lastUpdated":1722828751000}'),c={name:"SIG.md"},l=t("h1",{id:"youqu-官方兴趣小组",tabindex:"-1"},[s("YouQu 官方兴趣小组 "),t("a",{class:"header-anchor",href:"#youqu-官方兴趣小组","aria-label":'Permalink to "YouQu 官方兴趣小组"'},"​")],-1),r=t("hr",null,null,-1),_=t("p",null,"致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。",-1),u=t("p",null,"相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。",-1),d=t("hr",null,null,-1),i=t("img",{src:n,width:"400",alt:"YouQu官方兴趣小组",align:"center/"},null,-1),h=[l,r,_,u,d,i];function p(m,f,x,S,g,G){return a(),o("div",null,h)}const Y=e(c,[["render",p]]);export{Q as __pageData,Y as default}; diff --git a/assets/SIG.md.Bh8YEa0v.lean.js b/assets/SIG.md.DLmEvgGN.lean.js similarity index 94% rename from assets/SIG.md.Bh8YEa0v.lean.js rename to assets/SIG.md.DLmEvgGN.lean.js index b3d92d16..588c3413 100644 --- a/assets/SIG.md.Bh8YEa0v.lean.js +++ b/assets/SIG.md.DLmEvgGN.lean.js @@ -1 +1 @@ -import{_ as e,c as o,o as a,m as t,a as s}from"./chunks/framework.DIzwIJpr.js";const n="/youqu/wechat.jpg",Q=JSON.parse('{"title":"YouQu 官方兴趣小组","description":"","frontmatter":{},"headers":[],"relativePath":"SIG.md","filePath":"SIG.md","lastUpdated":1722828555000}'),c={name:"SIG.md"},l=t("h1",{id:"youqu-官方兴趣小组",tabindex:"-1"},[s("YouQu 官方兴趣小组 "),t("a",{class:"header-anchor",href:"#youqu-官方兴趣小组","aria-label":'Permalink to "YouQu 官方兴趣小组"'},"​")],-1),r=t("hr",null,null,-1),_=t("p",null,"致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。",-1),u=t("p",null,"相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。",-1),d=t("hr",null,null,-1),i=t("img",{src:n,width:"400",alt:"YouQu官方兴趣小组",align:"center/"},null,-1),h=[l,r,_,u,d,i];function p(m,f,x,S,g,G){return a(),o("div",null,h)}const Y=e(c,[["render",p]]);export{Q as __pageData,Y as default}; +import{_ as e,c as o,o as a,m as t,a as s}from"./chunks/framework.DIzwIJpr.js";const n="/youqu/wechat.jpg",Q=JSON.parse('{"title":"YouQu 官方兴趣小组","description":"","frontmatter":{},"headers":[],"relativePath":"SIG.md","filePath":"SIG.md","lastUpdated":1722828751000}'),c={name:"SIG.md"},l=t("h1",{id:"youqu-官方兴趣小组",tabindex:"-1"},[s("YouQu 官方兴趣小组 "),t("a",{class:"header-anchor",href:"#youqu-官方兴趣小组","aria-label":'Permalink to "YouQu 官方兴趣小组"'},"​")],-1),r=t("hr",null,null,-1),_=t("p",null,"致力于为广大自动化技术爱好者提供一个交流、分享和成长的平台,在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题。",-1),u=t("p",null,"相信通过大家的共同努力,定能碰撞出智慧的火花,为自动化测试框架的发展和演进贡献力量。",-1),d=t("hr",null,null,-1),i=t("img",{src:n,width:"400",alt:"YouQu官方兴趣小组",align:"center/"},null,-1),h=[l,r,_,u,d,i];function p(m,f,x,S,g,G){return a(),o("div",null,h)}const Y=e(c,[["render",p]]);export{Q as __pageData,Y as default}; diff --git a/assets/app.BMmAF0JB.js b/assets/app.CErl3I3c.js similarity index 99% rename from assets/app.BMmAF0JB.js rename to assets/app.CErl3I3c.js index 4dfa8083..74376fe5 100644 --- a/assets/app.BMmAF0JB.js +++ b/assets/app.CErl3I3c.js @@ -1,5 +1,5 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/diagram-definition.ae1f7a29.BteD-_ze.js","assets/chunks/theme.B7K9K7dh.js","assets/chunks/framework.DIzwIJpr.js"])))=>i.map(i=>d[i]); -import{X as F_,j as V6,a6 as P_,a7 as Y_,a8 as j_,a9 as U_,aa as z_,ab as $_,ac as q_,ad as H_,ae as W_,af as V_,d as G_,u as X_,l as Z_,z as Q_,ag as K_,ah as J_,ai as tx,a4 as ex}from"./chunks/framework.DIzwIJpr.js";import{R as nx}from"./chunks/theme.B7K9K7dh.js";/*! For license information please see mermaid.esm.min.mjs.LICENSE.txt */var rx={1362:(M,Y,g)=>{M=g.nmd(M);var _=function(){var d=function(wt,ge,mt,It){for(mt=mt||{},It=wt.length;It--;mt[wt[It]]=ge);return mt},T=[1,3],y=[1,7],C=[1,8],S=[1,9],A=[1,10],I=[1,13],B=[1,12],j=[1,16,25],V=[1,20],X=[1,31],Q=[1,32],gt=[1,33],tt=[1,35],Lt=[1,38],it=[1,36],vt=[1,37],At=[1,39],Qt=[1,40],jt=[1,41],xt=[1,42],Yt=[1,45],Bt=[1,46],lt=[1,47],et=[1,48],st=[16,25],$=[1,62],Dt=[1,63],U=[1,64],Jt=[1,65],_t=[1,66],oe=[1,67],Se=[16,25,32,44,45,53,56,57,58,59,60,61,66,68],Fe=[16,25,30,32,44,45,49,53,56,57,58,59,60,61,66,68,83,84,85,86],he=[5,8,9,10,11,16,19,23,25],se=[53,83,84,85,86],fe=[53,60,61,83,84,85,86],_e=[53,56,57,58,59,83,84,85,86],De=[16,25,32],pe=[1,99],Me={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statments:5,direction:6,directive:7,direction_tb:8,direction_bt:9,direction_rl:10,direction_lr:11,graphConfig:12,openDirective:13,typeDirective:14,closeDirective:15,NEWLINE:16,":":17,argDirective:18,open_directive:19,type_directive:20,arg_directive:21,close_directive:22,CLASS_DIAGRAM:23,statements:24,EOF:25,statement:26,className:27,alphaNumToken:28,classLiteralName:29,GENERICTYPE:30,relationStatement:31,LABEL:32,classStatement:33,methodStatement:34,annotationStatement:35,clickStatement:36,cssClassStatement:37,acc_title:38,acc_title_value:39,acc_descr:40,acc_descr_value:41,acc_descr_multiline_value:42,CLASS:43,STYLE_SEPARATOR:44,STRUCT_START:45,members:46,STRUCT_STOP:47,ANNOTATION_START:48,ANNOTATION_END:49,MEMBER:50,SEPARATOR:51,relation:52,STR:53,relationType:54,lineType:55,AGGREGATION:56,EXTENSION:57,COMPOSITION:58,DEPENDENCY:59,LINE:60,DOTTED_LINE:61,CALLBACK:62,LINK:63,LINK_TARGET:64,CLICK:65,CALLBACK_NAME:66,CALLBACK_ARGS:67,HREF:68,CSSCLASS:69,commentToken:70,textToken:71,graphCodeTokens:72,textNoTagsToken:73,TAGSTART:74,TAGEND:75,"==":76,"--":77,PCT:78,DEFAULT:79,SPACE:80,MINUS:81,keywords:82,UNICODE_TEXT:83,NUM:84,ALPHA:85,BQUOTE_STR:86,$accept:0,$end:1},terminals_:{2:"error",5:"statments",8:"direction_tb",9:"direction_bt",10:"direction_rl",11:"direction_lr",16:"NEWLINE",17:":",19:"open_directive",20:"type_directive",21:"arg_directive",22:"close_directive",23:"CLASS_DIAGRAM",25:"EOF",30:"GENERICTYPE",32:"LABEL",38:"acc_title",39:"acc_title_value",40:"acc_descr",41:"acc_descr_value",42:"acc_descr_multiline_value",43:"CLASS",44:"STYLE_SEPARATOR",45:"STRUCT_START",47:"STRUCT_STOP",48:"ANNOTATION_START",49:"ANNOTATION_END",50:"MEMBER",51:"SEPARATOR",53:"STR",56:"AGGREGATION",57:"EXTENSION",58:"COMPOSITION",59:"DEPENDENCY",60:"LINE",61:"DOTTED_LINE",62:"CALLBACK",63:"LINK",64:"LINK_TARGET",65:"CLICK",66:"CALLBACK_NAME",67:"CALLBACK_ARGS",68:"HREF",69:"CSSCLASS",72:"graphCodeTokens",74:"TAGSTART",75:"TAGEND",76:"==",77:"--",78:"PCT",79:"DEFAULT",80:"SPACE",81:"MINUS",82:"keywords",83:"UNICODE_TEXT",84:"NUM",85:"ALPHA",86:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[3,1],[3,2],[6,1],[6,1],[6,1],[6,1],[4,1],[7,4],[7,6],[13,1],[14,1],[18,1],[15,1],[12,4],[24,1],[24,2],[24,3],[27,1],[27,1],[27,2],[27,2],[27,2],[26,1],[26,2],[26,1],[26,1],[26,1],[26,1],[26,1],[26,1],[26,1],[26,2],[26,2],[26,1],[33,2],[33,4],[33,5],[33,7],[35,4],[46,1],[46,2],[34,1],[34,2],[34,1],[34,1],[31,3],[31,4],[31,4],[31,5],[52,3],[52,2],[52,2],[52,1],[54,1],[54,1],[54,1],[54,1],[55,1],[55,1],[36,3],[36,4],[36,3],[36,4],[36,4],[36,5],[36,3],[36,4],[36,4],[36,5],[36,3],[36,4],[36,4],[36,5],[37,3],[70,1],[70,1],[71,1],[71,1],[71,1],[71,1],[71,1],[71,1],[71,1],[73,1],[73,1],[73,1],[73,1],[28,1],[28,1],[28,1],[29,1]],performAction:function(wt,ge,mt,It,St,nt,le){var Rt=nt.length-1;switch(St){case 5:It.setDirection("TB");break;case 6:It.setDirection("BT");break;case 7:It.setDirection("RL");break;case 8:It.setDirection("LR");break;case 12:It.parseDirective("%%{","open_directive");break;case 13:It.parseDirective(nt[Rt],"type_directive");break;case 14:nt[Rt]=nt[Rt].trim().replace(/'/g,'"'),It.parseDirective(nt[Rt],"arg_directive");break;case 15:It.parseDirective("}%%","close_directive","class");break;case 20:case 21:this.$=nt[Rt];break;case 22:this.$=nt[Rt-1]+nt[Rt];break;case 23:case 24:this.$=nt[Rt-1]+"~"+nt[Rt];break;case 25:It.addRelation(nt[Rt]);break;case 26:nt[Rt-1].title=It.cleanupLabel(nt[Rt]),It.addRelation(nt[Rt-1]);break;case 34:this.$=nt[Rt].trim(),It.setTitle(this.$);break;case 35:case 36:this.$=nt[Rt].trim(),It.setAccDescription(this.$);break;case 37:It.addClass(nt[Rt]);break;case 38:It.addClass(nt[Rt-2]),It.setCssClass(nt[Rt-2],nt[Rt]);break;case 39:It.addClass(nt[Rt-3]),It.addMembers(nt[Rt-3],nt[Rt-1]);break;case 40:It.addClass(nt[Rt-5]),It.setCssClass(nt[Rt-5],nt[Rt-3]),It.addMembers(nt[Rt-5],nt[Rt-1]);break;case 41:It.addAnnotation(nt[Rt],nt[Rt-2]);break;case 42:this.$=[nt[Rt]];break;case 43:nt[Rt].push(nt[Rt-1]),this.$=nt[Rt];break;case 44:case 46:case 47:break;case 45:It.addMember(nt[Rt-1],It.cleanupLabel(nt[Rt]));break;case 48:this.$={id1:nt[Rt-2],id2:nt[Rt],relation:nt[Rt-1],relationTitle1:"none",relationTitle2:"none"};break;case 49:this.$={id1:nt[Rt-3],id2:nt[Rt],relation:nt[Rt-1],relationTitle1:nt[Rt-2],relationTitle2:"none"};break;case 50:this.$={id1:nt[Rt-3],id2:nt[Rt],relation:nt[Rt-2],relationTitle1:"none",relationTitle2:nt[Rt-1]};break;case 51:this.$={id1:nt[Rt-4],id2:nt[Rt],relation:nt[Rt-2],relationTitle1:nt[Rt-3],relationTitle2:nt[Rt-1]};break;case 52:this.$={type1:nt[Rt-2],type2:nt[Rt],lineType:nt[Rt-1]};break;case 53:this.$={type1:"none",type2:nt[Rt],lineType:nt[Rt-1]};break;case 54:this.$={type1:nt[Rt-1],type2:"none",lineType:nt[Rt]};break;case 55:this.$={type1:"none",type2:"none",lineType:nt[Rt]};break;case 56:this.$=It.relationType.AGGREGATION;break;case 57:this.$=It.relationType.EXTENSION;break;case 58:this.$=It.relationType.COMPOSITION;break;case 59:this.$=It.relationType.DEPENDENCY;break;case 60:this.$=It.lineType.LINE;break;case 61:this.$=It.lineType.DOTTED_LINE;break;case 62:case 68:this.$=nt[Rt-2],It.setClickEvent(nt[Rt-1],nt[Rt]);break;case 63:case 69:this.$=nt[Rt-3],It.setClickEvent(nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-2],nt[Rt]);break;case 64:case 72:this.$=nt[Rt-2],It.setLink(nt[Rt-1],nt[Rt]);break;case 65:case 73:this.$=nt[Rt-3],It.setLink(nt[Rt-2],nt[Rt-1],nt[Rt]);break;case 66:case 74:this.$=nt[Rt-3],It.setLink(nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-2],nt[Rt]);break;case 67:case 75:this.$=nt[Rt-4],It.setLink(nt[Rt-3],nt[Rt-2],nt[Rt]),It.setTooltip(nt[Rt-3],nt[Rt-1]);break;case 70:this.$=nt[Rt-3],It.setClickEvent(nt[Rt-2],nt[Rt-1],nt[Rt]);break;case 71:this.$=nt[Rt-4],It.setClickEvent(nt[Rt-3],nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-3],nt[Rt]);break;case 76:It.setCssClass(nt[Rt-1],nt[Rt])}},table:[{3:1,4:2,5:T,6:4,7:5,8:y,9:C,10:S,11:A,12:6,13:11,19:I,23:B},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{3:14,4:2,5:T,6:4,7:5,8:y,9:C,10:S,11:A,12:6,13:11,19:I,23:B},{1:[2,9]},d(j,[2,5]),d(j,[2,6]),d(j,[2,7]),d(j,[2,8]),{14:15,20:[1,16]},{16:[1,17]},{20:[2,12]},{1:[2,4]},{15:18,17:[1,19],22:V},d([17,22],[2,13]),{6:30,7:29,8:y,9:C,10:S,11:A,13:11,19:I,24:21,26:22,27:34,28:43,29:44,31:23,33:24,34:25,35:26,36:27,37:28,38:X,40:Q,42:gt,43:tt,48:Lt,50:it,51:vt,62:At,63:Qt,65:jt,69:xt,83:Yt,84:Bt,85:lt,86:et},{16:[1,49]},{18:50,21:[1,51]},{16:[2,15]},{25:[1,52]},{16:[1,53],25:[2,17]},d(st,[2,25],{32:[1,54]}),d(st,[2,27]),d(st,[2,28]),d(st,[2,29]),d(st,[2,30]),d(st,[2,31]),d(st,[2,32]),d(st,[2,33]),{39:[1,55]},{41:[1,56]},d(st,[2,36]),d(st,[2,44],{52:57,54:60,55:61,32:[1,59],53:[1,58],56:$,57:Dt,58:U,59:Jt,60:_t,61:oe}),{27:68,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(st,[2,46]),d(st,[2,47]),{28:69,83:Yt,84:Bt,85:lt},{27:70,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:71,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:72,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{53:[1,73]},d(Se,[2,20],{28:43,29:44,27:74,30:[1,75],83:Yt,84:Bt,85:lt,86:et}),d(Se,[2,21],{30:[1,76]}),d(Fe,[2,90]),d(Fe,[2,91]),d(Fe,[2,92]),d([16,25,30,32,44,45,53,56,57,58,59,60,61,66,68],[2,93]),d(he,[2,10]),{15:77,22:V},{22:[2,14]},{1:[2,16]},{6:30,7:29,8:y,9:C,10:S,11:A,13:11,19:I,24:78,25:[2,18],26:22,27:34,28:43,29:44,31:23,33:24,34:25,35:26,36:27,37:28,38:X,40:Q,42:gt,43:tt,48:Lt,50:it,51:vt,62:At,63:Qt,65:jt,69:xt,83:Yt,84:Bt,85:lt,86:et},d(st,[2,26]),d(st,[2,34]),d(st,[2,35]),{27:79,28:43,29:44,53:[1,80],83:Yt,84:Bt,85:lt,86:et},{52:81,54:60,55:61,56:$,57:Dt,58:U,59:Jt,60:_t,61:oe},d(st,[2,45]),{55:82,60:_t,61:oe},d(se,[2,55],{54:83,56:$,57:Dt,58:U,59:Jt}),d(fe,[2,56]),d(fe,[2,57]),d(fe,[2,58]),d(fe,[2,59]),d(_e,[2,60]),d(_e,[2,61]),d(st,[2,37],{44:[1,84],45:[1,85]}),{49:[1,86]},{53:[1,87]},{53:[1,88]},{66:[1,89],68:[1,90]},{28:91,83:Yt,84:Bt,85:lt},d(Se,[2,22]),d(Se,[2,23]),d(Se,[2,24]),{16:[1,92]},{25:[2,19]},d(De,[2,48]),{27:93,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:94,28:43,29:44,53:[1,95],83:Yt,84:Bt,85:lt,86:et},d(se,[2,54],{54:96,56:$,57:Dt,58:U,59:Jt}),d(se,[2,53]),{28:97,83:Yt,84:Bt,85:lt},{46:98,50:pe},{27:100,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(st,[2,62],{53:[1,101]}),d(st,[2,64],{53:[1,103],64:[1,102]}),d(st,[2,68],{53:[1,104],67:[1,105]}),d(st,[2,72],{53:[1,107],64:[1,106]}),d(st,[2,76]),d(he,[2,11]),d(De,[2,50]),d(De,[2,49]),{27:108,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(se,[2,52]),d(st,[2,38],{45:[1,109]}),{47:[1,110]},{46:111,47:[2,42],50:pe},d(st,[2,41]),d(st,[2,63]),d(st,[2,65]),d(st,[2,66],{64:[1,112]}),d(st,[2,69]),d(st,[2,70],{53:[1,113]}),d(st,[2,73]),d(st,[2,74],{64:[1,114]}),d(De,[2,51]),{46:115,50:pe},d(st,[2,39]),{47:[2,43]},d(st,[2,67]),d(st,[2,71]),d(st,[2,75]),{47:[1,116]},d(st,[2,40])],defaultActions:{2:[2,1],3:[2,2],4:[2,3],6:[2,9],13:[2,12],14:[2,4],20:[2,15],51:[2,14],52:[2,16],78:[2,19],111:[2,43]},parseError:function(wt,ge){if(!ge.recoverable){var mt=new Error(wt);throw mt.hash=ge,mt}this.trace(wt)},parse:function(wt){var ge=this,mt=[0],It=[],St=[null],nt=[],le=this.table,Rt="",gn=0,Le=0,$e=0,Ge=2,en=1,nn=nt.slice.call(arguments,1),Ne=Object.create(this.lexer),qe={yy:{}};for(var on in this.yy)Object.prototype.hasOwnProperty.call(this.yy,on)&&(qe.yy[on]=this.yy[on]);Ne.setInput(wt,qe.yy),qe.yy.lexer=Ne,qe.yy.parser=this,Ne.yylloc===void 0&&(Ne.yylloc={});var Pe=Ne.yylloc;nt.push(Pe);var we=Ne.options&&Ne.options.ranges;function Ke(){var mn;return typeof(mn=It.pop()||Ne.lex()||en)!="number"&&(mn instanceof Array&&(mn=(It=mn).pop()),mn=ge.symbols_[mn]||mn),mn}typeof qe.yy.parseError=="function"?this.parseError=qe.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var yn,Qn,Qe,rn,Ar,Br,vn,En,pn,Tn={};;){if(Qe=mt[mt.length-1],this.defaultActions[Qe]?rn=this.defaultActions[Qe]:(yn==null&&(yn=Ke()),rn=le[Qe]&&le[Qe][yn]),rn===void 0||!rn.length||!rn[0]){var Dn="";for(Br in pn=[],le[Qe])this.terminals_[Br]&&Br>Ge&&pn.push("'"+this.terminals_[Br]+"'");Dn=Ne.showPosition?"Parse error on line "+(gn+1)+`: +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/diagram-definition.ae1f7a29.Cn2DCAkm.js","assets/chunks/theme.BIU4L49Z.js","assets/chunks/framework.DIzwIJpr.js"])))=>i.map(i=>d[i]); +import{X as F_,j as V6,a6 as P_,a7 as Y_,a8 as j_,a9 as U_,aa as z_,ab as $_,ac as q_,ad as H_,ae as W_,af as V_,d as G_,u as X_,l as Z_,z as Q_,ag as K_,ah as J_,ai as tx,a4 as ex}from"./chunks/framework.DIzwIJpr.js";import{R as nx}from"./chunks/theme.BIU4L49Z.js";/*! For license information please see mermaid.esm.min.mjs.LICENSE.txt */var rx={1362:(M,Y,g)=>{M=g.nmd(M);var _=function(){var d=function(wt,ge,mt,It){for(mt=mt||{},It=wt.length;It--;mt[wt[It]]=ge);return mt},T=[1,3],y=[1,7],C=[1,8],S=[1,9],A=[1,10],I=[1,13],B=[1,12],j=[1,16,25],V=[1,20],X=[1,31],Q=[1,32],gt=[1,33],tt=[1,35],Lt=[1,38],it=[1,36],vt=[1,37],At=[1,39],Qt=[1,40],jt=[1,41],xt=[1,42],Yt=[1,45],Bt=[1,46],lt=[1,47],et=[1,48],st=[16,25],$=[1,62],Dt=[1,63],U=[1,64],Jt=[1,65],_t=[1,66],oe=[1,67],Se=[16,25,32,44,45,53,56,57,58,59,60,61,66,68],Fe=[16,25,30,32,44,45,49,53,56,57,58,59,60,61,66,68,83,84,85,86],he=[5,8,9,10,11,16,19,23,25],se=[53,83,84,85,86],fe=[53,60,61,83,84,85,86],_e=[53,56,57,58,59,83,84,85,86],De=[16,25,32],pe=[1,99],Me={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statments:5,direction:6,directive:7,direction_tb:8,direction_bt:9,direction_rl:10,direction_lr:11,graphConfig:12,openDirective:13,typeDirective:14,closeDirective:15,NEWLINE:16,":":17,argDirective:18,open_directive:19,type_directive:20,arg_directive:21,close_directive:22,CLASS_DIAGRAM:23,statements:24,EOF:25,statement:26,className:27,alphaNumToken:28,classLiteralName:29,GENERICTYPE:30,relationStatement:31,LABEL:32,classStatement:33,methodStatement:34,annotationStatement:35,clickStatement:36,cssClassStatement:37,acc_title:38,acc_title_value:39,acc_descr:40,acc_descr_value:41,acc_descr_multiline_value:42,CLASS:43,STYLE_SEPARATOR:44,STRUCT_START:45,members:46,STRUCT_STOP:47,ANNOTATION_START:48,ANNOTATION_END:49,MEMBER:50,SEPARATOR:51,relation:52,STR:53,relationType:54,lineType:55,AGGREGATION:56,EXTENSION:57,COMPOSITION:58,DEPENDENCY:59,LINE:60,DOTTED_LINE:61,CALLBACK:62,LINK:63,LINK_TARGET:64,CLICK:65,CALLBACK_NAME:66,CALLBACK_ARGS:67,HREF:68,CSSCLASS:69,commentToken:70,textToken:71,graphCodeTokens:72,textNoTagsToken:73,TAGSTART:74,TAGEND:75,"==":76,"--":77,PCT:78,DEFAULT:79,SPACE:80,MINUS:81,keywords:82,UNICODE_TEXT:83,NUM:84,ALPHA:85,BQUOTE_STR:86,$accept:0,$end:1},terminals_:{2:"error",5:"statments",8:"direction_tb",9:"direction_bt",10:"direction_rl",11:"direction_lr",16:"NEWLINE",17:":",19:"open_directive",20:"type_directive",21:"arg_directive",22:"close_directive",23:"CLASS_DIAGRAM",25:"EOF",30:"GENERICTYPE",32:"LABEL",38:"acc_title",39:"acc_title_value",40:"acc_descr",41:"acc_descr_value",42:"acc_descr_multiline_value",43:"CLASS",44:"STYLE_SEPARATOR",45:"STRUCT_START",47:"STRUCT_STOP",48:"ANNOTATION_START",49:"ANNOTATION_END",50:"MEMBER",51:"SEPARATOR",53:"STR",56:"AGGREGATION",57:"EXTENSION",58:"COMPOSITION",59:"DEPENDENCY",60:"LINE",61:"DOTTED_LINE",62:"CALLBACK",63:"LINK",64:"LINK_TARGET",65:"CLICK",66:"CALLBACK_NAME",67:"CALLBACK_ARGS",68:"HREF",69:"CSSCLASS",72:"graphCodeTokens",74:"TAGSTART",75:"TAGEND",76:"==",77:"--",78:"PCT",79:"DEFAULT",80:"SPACE",81:"MINUS",82:"keywords",83:"UNICODE_TEXT",84:"NUM",85:"ALPHA",86:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[3,1],[3,2],[6,1],[6,1],[6,1],[6,1],[4,1],[7,4],[7,6],[13,1],[14,1],[18,1],[15,1],[12,4],[24,1],[24,2],[24,3],[27,1],[27,1],[27,2],[27,2],[27,2],[26,1],[26,2],[26,1],[26,1],[26,1],[26,1],[26,1],[26,1],[26,1],[26,2],[26,2],[26,1],[33,2],[33,4],[33,5],[33,7],[35,4],[46,1],[46,2],[34,1],[34,2],[34,1],[34,1],[31,3],[31,4],[31,4],[31,5],[52,3],[52,2],[52,2],[52,1],[54,1],[54,1],[54,1],[54,1],[55,1],[55,1],[36,3],[36,4],[36,3],[36,4],[36,4],[36,5],[36,3],[36,4],[36,4],[36,5],[36,3],[36,4],[36,4],[36,5],[37,3],[70,1],[70,1],[71,1],[71,1],[71,1],[71,1],[71,1],[71,1],[71,1],[73,1],[73,1],[73,1],[73,1],[28,1],[28,1],[28,1],[29,1]],performAction:function(wt,ge,mt,It,St,nt,le){var Rt=nt.length-1;switch(St){case 5:It.setDirection("TB");break;case 6:It.setDirection("BT");break;case 7:It.setDirection("RL");break;case 8:It.setDirection("LR");break;case 12:It.parseDirective("%%{","open_directive");break;case 13:It.parseDirective(nt[Rt],"type_directive");break;case 14:nt[Rt]=nt[Rt].trim().replace(/'/g,'"'),It.parseDirective(nt[Rt],"arg_directive");break;case 15:It.parseDirective("}%%","close_directive","class");break;case 20:case 21:this.$=nt[Rt];break;case 22:this.$=nt[Rt-1]+nt[Rt];break;case 23:case 24:this.$=nt[Rt-1]+"~"+nt[Rt];break;case 25:It.addRelation(nt[Rt]);break;case 26:nt[Rt-1].title=It.cleanupLabel(nt[Rt]),It.addRelation(nt[Rt-1]);break;case 34:this.$=nt[Rt].trim(),It.setTitle(this.$);break;case 35:case 36:this.$=nt[Rt].trim(),It.setAccDescription(this.$);break;case 37:It.addClass(nt[Rt]);break;case 38:It.addClass(nt[Rt-2]),It.setCssClass(nt[Rt-2],nt[Rt]);break;case 39:It.addClass(nt[Rt-3]),It.addMembers(nt[Rt-3],nt[Rt-1]);break;case 40:It.addClass(nt[Rt-5]),It.setCssClass(nt[Rt-5],nt[Rt-3]),It.addMembers(nt[Rt-5],nt[Rt-1]);break;case 41:It.addAnnotation(nt[Rt],nt[Rt-2]);break;case 42:this.$=[nt[Rt]];break;case 43:nt[Rt].push(nt[Rt-1]),this.$=nt[Rt];break;case 44:case 46:case 47:break;case 45:It.addMember(nt[Rt-1],It.cleanupLabel(nt[Rt]));break;case 48:this.$={id1:nt[Rt-2],id2:nt[Rt],relation:nt[Rt-1],relationTitle1:"none",relationTitle2:"none"};break;case 49:this.$={id1:nt[Rt-3],id2:nt[Rt],relation:nt[Rt-1],relationTitle1:nt[Rt-2],relationTitle2:"none"};break;case 50:this.$={id1:nt[Rt-3],id2:nt[Rt],relation:nt[Rt-2],relationTitle1:"none",relationTitle2:nt[Rt-1]};break;case 51:this.$={id1:nt[Rt-4],id2:nt[Rt],relation:nt[Rt-2],relationTitle1:nt[Rt-3],relationTitle2:nt[Rt-1]};break;case 52:this.$={type1:nt[Rt-2],type2:nt[Rt],lineType:nt[Rt-1]};break;case 53:this.$={type1:"none",type2:nt[Rt],lineType:nt[Rt-1]};break;case 54:this.$={type1:nt[Rt-1],type2:"none",lineType:nt[Rt]};break;case 55:this.$={type1:"none",type2:"none",lineType:nt[Rt]};break;case 56:this.$=It.relationType.AGGREGATION;break;case 57:this.$=It.relationType.EXTENSION;break;case 58:this.$=It.relationType.COMPOSITION;break;case 59:this.$=It.relationType.DEPENDENCY;break;case 60:this.$=It.lineType.LINE;break;case 61:this.$=It.lineType.DOTTED_LINE;break;case 62:case 68:this.$=nt[Rt-2],It.setClickEvent(nt[Rt-1],nt[Rt]);break;case 63:case 69:this.$=nt[Rt-3],It.setClickEvent(nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-2],nt[Rt]);break;case 64:case 72:this.$=nt[Rt-2],It.setLink(nt[Rt-1],nt[Rt]);break;case 65:case 73:this.$=nt[Rt-3],It.setLink(nt[Rt-2],nt[Rt-1],nt[Rt]);break;case 66:case 74:this.$=nt[Rt-3],It.setLink(nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-2],nt[Rt]);break;case 67:case 75:this.$=nt[Rt-4],It.setLink(nt[Rt-3],nt[Rt-2],nt[Rt]),It.setTooltip(nt[Rt-3],nt[Rt-1]);break;case 70:this.$=nt[Rt-3],It.setClickEvent(nt[Rt-2],nt[Rt-1],nt[Rt]);break;case 71:this.$=nt[Rt-4],It.setClickEvent(nt[Rt-3],nt[Rt-2],nt[Rt-1]),It.setTooltip(nt[Rt-3],nt[Rt]);break;case 76:It.setCssClass(nt[Rt-1],nt[Rt])}},table:[{3:1,4:2,5:T,6:4,7:5,8:y,9:C,10:S,11:A,12:6,13:11,19:I,23:B},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{3:14,4:2,5:T,6:4,7:5,8:y,9:C,10:S,11:A,12:6,13:11,19:I,23:B},{1:[2,9]},d(j,[2,5]),d(j,[2,6]),d(j,[2,7]),d(j,[2,8]),{14:15,20:[1,16]},{16:[1,17]},{20:[2,12]},{1:[2,4]},{15:18,17:[1,19],22:V},d([17,22],[2,13]),{6:30,7:29,8:y,9:C,10:S,11:A,13:11,19:I,24:21,26:22,27:34,28:43,29:44,31:23,33:24,34:25,35:26,36:27,37:28,38:X,40:Q,42:gt,43:tt,48:Lt,50:it,51:vt,62:At,63:Qt,65:jt,69:xt,83:Yt,84:Bt,85:lt,86:et},{16:[1,49]},{18:50,21:[1,51]},{16:[2,15]},{25:[1,52]},{16:[1,53],25:[2,17]},d(st,[2,25],{32:[1,54]}),d(st,[2,27]),d(st,[2,28]),d(st,[2,29]),d(st,[2,30]),d(st,[2,31]),d(st,[2,32]),d(st,[2,33]),{39:[1,55]},{41:[1,56]},d(st,[2,36]),d(st,[2,44],{52:57,54:60,55:61,32:[1,59],53:[1,58],56:$,57:Dt,58:U,59:Jt,60:_t,61:oe}),{27:68,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(st,[2,46]),d(st,[2,47]),{28:69,83:Yt,84:Bt,85:lt},{27:70,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:71,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:72,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{53:[1,73]},d(Se,[2,20],{28:43,29:44,27:74,30:[1,75],83:Yt,84:Bt,85:lt,86:et}),d(Se,[2,21],{30:[1,76]}),d(Fe,[2,90]),d(Fe,[2,91]),d(Fe,[2,92]),d([16,25,30,32,44,45,53,56,57,58,59,60,61,66,68],[2,93]),d(he,[2,10]),{15:77,22:V},{22:[2,14]},{1:[2,16]},{6:30,7:29,8:y,9:C,10:S,11:A,13:11,19:I,24:78,25:[2,18],26:22,27:34,28:43,29:44,31:23,33:24,34:25,35:26,36:27,37:28,38:X,40:Q,42:gt,43:tt,48:Lt,50:it,51:vt,62:At,63:Qt,65:jt,69:xt,83:Yt,84:Bt,85:lt,86:et},d(st,[2,26]),d(st,[2,34]),d(st,[2,35]),{27:79,28:43,29:44,53:[1,80],83:Yt,84:Bt,85:lt,86:et},{52:81,54:60,55:61,56:$,57:Dt,58:U,59:Jt,60:_t,61:oe},d(st,[2,45]),{55:82,60:_t,61:oe},d(se,[2,55],{54:83,56:$,57:Dt,58:U,59:Jt}),d(fe,[2,56]),d(fe,[2,57]),d(fe,[2,58]),d(fe,[2,59]),d(_e,[2,60]),d(_e,[2,61]),d(st,[2,37],{44:[1,84],45:[1,85]}),{49:[1,86]},{53:[1,87]},{53:[1,88]},{66:[1,89],68:[1,90]},{28:91,83:Yt,84:Bt,85:lt},d(Se,[2,22]),d(Se,[2,23]),d(Se,[2,24]),{16:[1,92]},{25:[2,19]},d(De,[2,48]),{27:93,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},{27:94,28:43,29:44,53:[1,95],83:Yt,84:Bt,85:lt,86:et},d(se,[2,54],{54:96,56:$,57:Dt,58:U,59:Jt}),d(se,[2,53]),{28:97,83:Yt,84:Bt,85:lt},{46:98,50:pe},{27:100,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(st,[2,62],{53:[1,101]}),d(st,[2,64],{53:[1,103],64:[1,102]}),d(st,[2,68],{53:[1,104],67:[1,105]}),d(st,[2,72],{53:[1,107],64:[1,106]}),d(st,[2,76]),d(he,[2,11]),d(De,[2,50]),d(De,[2,49]),{27:108,28:43,29:44,83:Yt,84:Bt,85:lt,86:et},d(se,[2,52]),d(st,[2,38],{45:[1,109]}),{47:[1,110]},{46:111,47:[2,42],50:pe},d(st,[2,41]),d(st,[2,63]),d(st,[2,65]),d(st,[2,66],{64:[1,112]}),d(st,[2,69]),d(st,[2,70],{53:[1,113]}),d(st,[2,73]),d(st,[2,74],{64:[1,114]}),d(De,[2,51]),{46:115,50:pe},d(st,[2,39]),{47:[2,43]},d(st,[2,67]),d(st,[2,71]),d(st,[2,75]),{47:[1,116]},d(st,[2,40])],defaultActions:{2:[2,1],3:[2,2],4:[2,3],6:[2,9],13:[2,12],14:[2,4],20:[2,15],51:[2,14],52:[2,16],78:[2,19],111:[2,43]},parseError:function(wt,ge){if(!ge.recoverable){var mt=new Error(wt);throw mt.hash=ge,mt}this.trace(wt)},parse:function(wt){var ge=this,mt=[0],It=[],St=[null],nt=[],le=this.table,Rt="",gn=0,Le=0,$e=0,Ge=2,en=1,nn=nt.slice.call(arguments,1),Ne=Object.create(this.lexer),qe={yy:{}};for(var on in this.yy)Object.prototype.hasOwnProperty.call(this.yy,on)&&(qe.yy[on]=this.yy[on]);Ne.setInput(wt,qe.yy),qe.yy.lexer=Ne,qe.yy.parser=this,Ne.yylloc===void 0&&(Ne.yylloc={});var Pe=Ne.yylloc;nt.push(Pe);var we=Ne.options&&Ne.options.ranges;function Ke(){var mn;return typeof(mn=It.pop()||Ne.lex()||en)!="number"&&(mn instanceof Array&&(mn=(It=mn).pop()),mn=ge.symbols_[mn]||mn),mn}typeof qe.yy.parseError=="function"?this.parseError=qe.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var yn,Qn,Qe,rn,Ar,Br,vn,En,pn,Tn={};;){if(Qe=mt[mt.length-1],this.defaultActions[Qe]?rn=this.defaultActions[Qe]:(yn==null&&(yn=Ke()),rn=le[Qe]&&le[Qe][yn]),rn===void 0||!rn.length||!rn[0]){var Dn="";for(Br in pn=[],le[Qe])this.terminals_[Br]&&Br>Ge&&pn.push("'"+this.terminals_[Br]+"'");Dn=Ne.showPosition?"Parse error on line "+(gn+1)+`: `+Ne.showPosition()+` Expecting `+pn.join(", ")+", got '"+(this.terminals_[yn]||yn)+"'":"Parse error on line "+(gn+1)+": Unexpected "+(yn==en?"end of input":"'"+(this.terminals_[yn]||yn)+"'"),this.parseError(Dn,{text:Ne.match,token:this.terminals_[yn]||yn,line:Ne.yylineno,loc:Pe,expected:pn})}if(rn[0]instanceof Array&&rn.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Qe+", token: "+yn);switch(rn[0]){case 1:mt.push(yn),St.push(Ne.yytext),nt.push(Ne.yylloc),mt.push(rn[1]),yn=null,Qn?(yn=Qn,Qn=null):(Le=Ne.yyleng,Rt=Ne.yytext,gn=Ne.yylineno,Pe=Ne.yylloc,$e>0);break;case 2:if(vn=this.productions_[rn[1]][1],Tn.$=St[St.length-vn],Tn._$={first_line:nt[nt.length-(vn||1)].first_line,last_line:nt[nt.length-1].last_line,first_column:nt[nt.length-(vn||1)].first_column,last_column:nt[nt.length-1].last_column},we&&(Tn._$.range=[nt[nt.length-(vn||1)].range[0],nt[nt.length-1].range[1]]),(Ar=this.performAction.apply(Tn,[Rt,Le,gn,qe.yy,rn[1],St,nt].concat(nn)))!==void 0)return Ar;vn&&(mt=mt.slice(0,-1*vn*2),St=St.slice(0,-1*vn),nt=nt.slice(0,-1*vn)),mt.push(this.productions_[rn[1]][0]),St.push(Tn.$),nt.push(Tn._$),En=le[mt[mt.length-2]][mt[mt.length-1]],mt.push(En);break;case 3:return!0}}return!0}},ee={EOF:1,parseError:function(wt,ge){if(!this.yy.parser)throw new Error(wt);this.yy.parser.parseError(wt,ge)},setInput:function(wt,ge){return this.yy=ge||this.yy||{},this._input=wt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var wt=this._input[0];return this.yytext+=wt,this.yyleng++,this.offset++,this.match+=wt,this.matched+=wt,wt.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),wt},unput:function(wt){var ge=wt.length,mt=wt.split(/(?:\r\n?|\n)/g);this._input=wt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-ge),this.offset-=ge;var It=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),mt.length-1&&(this.yylineno-=mt.length-1);var St=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:mt?(mt.length===It.length?this.yylloc.first_column:0)+It[It.length-mt.length].length-mt[0].length:this.yylloc.first_column-ge},this.options.ranges&&(this.yylloc.range=[St[0],St[0]+this.yyleng-ge]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). `+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(wt){this.unput(this.match.slice(wt))},pastInput:function(){var wt=this.matched.substr(0,this.matched.length-this.match.length);return(wt.length>20?"...":"")+wt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var wt=this.match;return wt.length<20&&(wt+=this._input.substr(0,20-wt.length)),(wt.substr(0,20)+(wt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var wt=this.pastInput(),ge=new Array(wt.length+1).join("-");return wt+this.upcomingInput()+` @@ -1229,4 +1229,4 @@ g.stateGroup line { `+qi),Ui&&(qi=Lt(qi,jr," "),qi=Lt(qi,Hn," ")),Ar&&hi?Ar.createHTML(qi):qi},nt.setConfig=function(Ft){rs(Ft),ti=!0},nt.clearConfig=function(){$r=null,ti=!1},nt.isValidAttribute=function(Ft,He,Re){$r||rs({});var fr=Gt(Ft),Ir=Gt(He);return $i(fr,Ir,Re)},nt.addHook=function(Ft,He){typeof He=="function"&&(Ln[Ft]=Ln[Ft]||[],Q(Ln[Ft],He))},nt.removeHook=function(Ft){Ln[Ft]&&X(Ln[Ft])},nt.removeHooks=function(Ft){Ln[Ft]&&(Ln[Ft]=[])},nt.removeAllHooks=function(){Ln={}},nt}()}()},8282:(M,Y,g)=>{var _=g(2354);M.exports={Graph:_.Graph,json:g(8974),alg:g(2440),version:_.version}},2842:(M,Y,g)=>{var _=g(9126);M.exports=function(d){var T,y={},C=[];function S(A){_.has(y,A)||(y[A]=!0,T.push(A),_.each(d.successors(A),S),_.each(d.predecessors(A),S))}return _.each(d.nodes(),function(A){T=[],S(A),T.length&&C.push(T)}),C}},3984:(M,Y,g)=>{var _=g(9126);function d(T,y,C,S,A,I){_.has(S,y)||(S[y]=!0,C||I.push(y),_.each(A(y),function(B){d(T,B,C,S,A,I)}),C&&I.push(y))}M.exports=function(T,y,C){_.isArray(y)||(y=[y]);var S=(T.isDirected()?T.successors:T.neighbors).bind(T),A=[],I={};return _.each(y,function(B){if(!T.hasNode(B))throw new Error("Graph does not have node: "+B);d(T,B,C==="post",I,S,A)}),A}},4847:(M,Y,g)=>{var _=g(3763),d=g(9126);M.exports=function(T,y,C){return d.transform(T.nodes(),function(S,A){S[A]=_(T,A,y,C)},{})}},3763:(M,Y,g)=>{var _=g(9126),d=g(9675);M.exports=function(y,C,S,A){return function(I,B,j,V){var X,Q,gt={},tt=new d,Lt=function(it){var vt=it.v!==X?it.v:it.w,At=gt[vt],Qt=j(it),jt=Q.distance+Qt;if(Qt<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+it+" Weight: "+Qt);jt0&&(X=tt.removeMin(),(Q=gt[X]).distance!==Number.POSITIVE_INFINITY);)V(X).forEach(Lt);return gt}(y,String(C),S||T,A||function(I){return y.outEdges(I)})};var T=_.constant(1)},9096:(M,Y,g)=>{var _=g(9126),d=g(5023);M.exports=function(T){return _.filter(d(T),function(y){return y.length>1||y.length===1&&T.hasEdge(y[0],y[0])})}},8924:(M,Y,g)=>{var _=g(9126);M.exports=function(T,y,C){return function(S,A,I){var B={},j=S.nodes();return j.forEach(function(V){B[V]={},B[V][V]={distance:0},j.forEach(function(X){V!==X&&(B[V][X]={distance:Number.POSITIVE_INFINITY})}),I(V).forEach(function(X){var Q=X.v===V?X.w:X.v,gt=A(X);B[V][Q]={distance:gt,predecessor:V}})}),j.forEach(function(V){var X=B[V];j.forEach(function(Q){var gt=B[Q];j.forEach(function(tt){var Lt=gt[V],it=X[tt],vt=gt[tt],At=Lt.distance+it.distance;At{M.exports={components:g(2842),dijkstra:g(3763),dijkstraAll:g(4847),findCycles:g(9096),floydWarshall:g(8924),isAcyclic:g(2707),postorder:g(8828),preorder:g(2648),prim:g(514),tarjan:g(5023),topsort:g(2166)}},2707:(M,Y,g)=>{var _=g(2166);M.exports=function(d){try{_(d)}catch(T){if(T instanceof _.CycleException)return!1;throw T}return!0}},8828:(M,Y,g)=>{var _=g(3984);M.exports=function(d,T){return _(d,T,"post")}},2648:(M,Y,g)=>{var _=g(3984);M.exports=function(d,T){return _(d,T,"pre")}},514:(M,Y,g)=>{var _=g(9126),d=g(771),T=g(9675);M.exports=function(y,C){var S,A=new d,I={},B=new T;function j(X){var Q=X.v===S?X.w:X.v,gt=B.priority(Q);if(gt!==void 0){var tt=C(X);tt0;){if(S=B.removeMin(),_.has(I,S))A.setEdge(S,I[S]);else{if(V)throw new Error("Input graph is not connected: "+y);V=!0}y.nodeEdges(S).forEach(j)}return A}},5023:(M,Y,g)=>{var _=g(9126);M.exports=function(d){var T=0,y=[],C={},S=[];function A(I){var B=C[I]={onStack:!0,lowlink:T,index:T++};if(y.push(I),d.successors(I).forEach(function(X){_.has(C,X)?C[X].onStack&&(B.lowlink=Math.min(B.lowlink,C[X].index)):(A(X),B.lowlink=Math.min(B.lowlink,C[X].lowlink))}),B.lowlink===B.index){var j,V=[];do j=y.pop(),C[j].onStack=!1,V.push(j);while(I!==j);S.push(V)}}return d.nodes().forEach(function(I){_.has(C,I)||A(I)}),S}},2166:(M,Y,g)=>{var _=g(9126);function d(y){var C={},S={},A=[];if(_.each(y.sinks(),function I(B){if(_.has(S,B))throw new T;_.has(C,B)||(S[B]=!0,C[B]=!0,_.each(y.predecessors(B),I),delete S[B],A.push(B))}),_.size(C)!==y.nodeCount())throw new T;return A}function T(){}M.exports=d,d.CycleException=T,T.prototype=new Error},9675:(M,Y,g)=>{var _=g(9126);function d(){this._arr=[],this._keyIndices={}}M.exports=d,d.prototype.size=function(){return this._arr.length},d.prototype.keys=function(){return this._arr.map(function(T){return T.key})},d.prototype.has=function(T){return _.has(this._keyIndices,T)},d.prototype.priority=function(T){var y=this._keyIndices[T];if(y!==void 0)return this._arr[y].priority},d.prototype.min=function(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key},d.prototype.add=function(T,y){var C=this._keyIndices;if(T=String(T),!_.has(C,T)){var S=this._arr,A=S.length;return C[T]=A,S.push({key:T,priority:y}),this._decrease(A),!0}return!1},d.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var T=this._arr.pop();return delete this._keyIndices[T.key],this._heapify(0),T.key},d.prototype.decrease=function(T,y){var C=this._keyIndices[T];if(y>this._arr[C].priority)throw new Error("New priority is greater than current priority. Key: "+T+" Old: "+this._arr[C].priority+" New: "+y);this._arr[C].priority=y,this._decrease(C)},d.prototype._heapify=function(T){var y=this._arr,C=2*T,S=C+1,A=T;C>1].priority{var _=g(9126);M.exports=T;var d="\0";function T(B){this._isDirected=!_.has(B,"directed")||B.directed,this._isMultigraph=!!_.has(B,"multigraph")&&B.multigraph,this._isCompound=!!_.has(B,"compound")&&B.compound,this._label=void 0,this._defaultNodeLabelFn=_.constant(void 0),this._defaultEdgeLabelFn=_.constant(void 0),this._nodes={},this._isCompound&&(this._parent={},this._children={},this._children["\0"]={}),this._in={},this._preds={},this._out={},this._sucs={},this._edgeObjs={},this._edgeLabels={}}function y(B,j){B[j]?B[j]++:B[j]=1}function C(B,j){--B[j]||delete B[j]}function S(B,j,V,X){var Q=""+j,gt=""+V;if(!B&&Q>gt){var tt=Q;Q=gt,gt=tt}return Q+""+gt+""+(_.isUndefined(X)?"\0":X)}function A(B,j,V,X){var Q=""+j,gt=""+V;if(!B&&Q>gt){var tt=Q;Q=gt,gt=tt}var Lt={v:Q,w:gt};return X&&(Lt.name=X),Lt}function I(B,j){return S(B,j.v,j.w,j.name)}T.prototype._nodeCount=0,T.prototype._edgeCount=0,T.prototype.isDirected=function(){return this._isDirected},T.prototype.isMultigraph=function(){return this._isMultigraph},T.prototype.isCompound=function(){return this._isCompound},T.prototype.setGraph=function(B){return this._label=B,this},T.prototype.graph=function(){return this._label},T.prototype.setDefaultNodeLabel=function(B){return _.isFunction(B)||(B=_.constant(B)),this._defaultNodeLabelFn=B,this},T.prototype.nodeCount=function(){return this._nodeCount},T.prototype.nodes=function(){return _.keys(this._nodes)},T.prototype.sources=function(){var B=this;return _.filter(this.nodes(),function(j){return _.isEmpty(B._in[j])})},T.prototype.sinks=function(){var B=this;return _.filter(this.nodes(),function(j){return _.isEmpty(B._out[j])})},T.prototype.setNodes=function(B,j){var V=arguments,X=this;return _.each(B,function(Q){V.length>1?X.setNode(Q,j):X.setNode(Q)}),this},T.prototype.setNode=function(B,j){return _.has(this._nodes,B)?(arguments.length>1&&(this._nodes[B]=j),this):(this._nodes[B]=arguments.length>1?j:this._defaultNodeLabelFn(B),this._isCompound&&(this._parent[B]=d,this._children[B]={},this._children["\0"][B]=!0),this._in[B]={},this._preds[B]={},this._out[B]={},this._sucs[B]={},++this._nodeCount,this)},T.prototype.node=function(B){return this._nodes[B]},T.prototype.hasNode=function(B){return _.has(this._nodes,B)},T.prototype.removeNode=function(B){var j=this;if(_.has(this._nodes,B)){var V=function(X){j.removeEdge(j._edgeObjs[X])};delete this._nodes[B],this._isCompound&&(this._removeFromParentsChildList(B),delete this._parent[B],_.each(this.children(B),function(X){j.setParent(X)}),delete this._children[B]),_.each(_.keys(this._in[B]),V),delete this._in[B],delete this._preds[B],_.each(_.keys(this._out[B]),V),delete this._out[B],delete this._sucs[B],--this._nodeCount}return this},T.prototype.setParent=function(B,j){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(_.isUndefined(j))j=d;else{for(var V=j+="";!_.isUndefined(V);V=this.parent(V))if(V===B)throw new Error("Setting "+j+" as parent of "+B+" would create a cycle");this.setNode(j)}return this.setNode(B),this._removeFromParentsChildList(B),this._parent[B]=j,this._children[j][B]=!0,this},T.prototype._removeFromParentsChildList=function(B){delete this._children[this._parent[B]][B]},T.prototype.parent=function(B){if(this._isCompound){var j=this._parent[B];if(j!==d)return j}},T.prototype.children=function(B){if(_.isUndefined(B)&&(B=d),this._isCompound){var j=this._children[B];if(j)return _.keys(j)}else{if(B===d)return this.nodes();if(this.hasNode(B))return[]}},T.prototype.predecessors=function(B){var j=this._preds[B];if(j)return _.keys(j)},T.prototype.successors=function(B){var j=this._sucs[B];if(j)return _.keys(j)},T.prototype.neighbors=function(B){var j=this.predecessors(B);if(j)return _.union(j,this.successors(B))},T.prototype.isLeaf=function(B){return(this.isDirected()?this.successors(B):this.neighbors(B)).length===0},T.prototype.filterNodes=function(B){var j=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});j.setGraph(this.graph());var V=this;_.each(this._nodes,function(gt,tt){B(tt)&&j.setNode(tt,gt)}),_.each(this._edgeObjs,function(gt){j.hasNode(gt.v)&&j.hasNode(gt.w)&&j.setEdge(gt,V.edge(gt))});var X={};function Q(gt){var tt=V.parent(gt);return tt===void 0||j.hasNode(tt)?(X[gt]=tt,tt):tt in X?X[tt]:Q(tt)}return this._isCompound&&_.each(j.nodes(),function(gt){j.setParent(gt,Q(gt))}),j},T.prototype.setDefaultEdgeLabel=function(B){return _.isFunction(B)||(B=_.constant(B)),this._defaultEdgeLabelFn=B,this},T.prototype.edgeCount=function(){return this._edgeCount},T.prototype.edges=function(){return _.values(this._edgeObjs)},T.prototype.setPath=function(B,j){var V=this,X=arguments;return _.reduce(B,function(Q,gt){return X.length>1?V.setEdge(Q,gt,j):V.setEdge(Q,gt),gt}),this},T.prototype.setEdge=function(){var B,j,V,X,Q=!1,gt=arguments[0];typeof gt=="object"&>!==null&&"v"in gt?(B=gt.v,j=gt.w,V=gt.name,arguments.length===2&&(X=arguments[1],Q=!0)):(B=gt,j=arguments[1],V=arguments[3],arguments.length>2&&(X=arguments[2],Q=!0)),B=""+B,j=""+j,_.isUndefined(V)||(V=""+V);var tt=S(this._isDirected,B,j,V);if(_.has(this._edgeLabels,tt))return Q&&(this._edgeLabels[tt]=X),this;if(!_.isUndefined(V)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(B),this.setNode(j),this._edgeLabels[tt]=Q?X:this._defaultEdgeLabelFn(B,j,V);var Lt=A(this._isDirected,B,j,V);return B=Lt.v,j=Lt.w,Object.freeze(Lt),this._edgeObjs[tt]=Lt,y(this._preds[j],B),y(this._sucs[B],j),this._in[j][tt]=Lt,this._out[B][tt]=Lt,this._edgeCount++,this},T.prototype.edge=function(B,j,V){var X=arguments.length===1?I(this._isDirected,arguments[0]):S(this._isDirected,B,j,V);return this._edgeLabels[X]},T.prototype.hasEdge=function(B,j,V){var X=arguments.length===1?I(this._isDirected,arguments[0]):S(this._isDirected,B,j,V);return _.has(this._edgeLabels,X)},T.prototype.removeEdge=function(B,j,V){var X=arguments.length===1?I(this._isDirected,arguments[0]):S(this._isDirected,B,j,V),Q=this._edgeObjs[X];return Q&&(B=Q.v,j=Q.w,delete this._edgeLabels[X],delete this._edgeObjs[X],C(this._preds[j],B),C(this._sucs[B],j),delete this._in[j][X],delete this._out[B][X],this._edgeCount--),this},T.prototype.inEdges=function(B,j){var V=this._in[B];if(V){var X=_.values(V);return j?_.filter(X,function(Q){return Q.v===j}):X}},T.prototype.outEdges=function(B,j){var V=this._out[B];if(V){var X=_.values(V);return j?_.filter(X,function(Q){return Q.w===j}):X}},T.prototype.nodeEdges=function(B,j){var V=this.inEdges(B,j);if(V)return V.concat(this.outEdges(B,j))}},2354:(M,Y,g)=>{M.exports={Graph:g(771),version:g(9631)}},8974:(M,Y,g)=>{var _=g(9126),d=g(771);function T(C){return _.map(C.nodes(),function(S){var A=C.node(S),I=C.parent(S),B={v:S};return _.isUndefined(A)||(B.value=A),_.isUndefined(I)||(B.parent=I),B})}function y(C){return _.map(C.edges(),function(S){var A=C.edge(S),I={v:S.v,w:S.w};return _.isUndefined(S.name)||(I.name=S.name),_.isUndefined(A)||(I.value=A),I})}M.exports={write:function(C){var S={options:{directed:C.isDirected(),multigraph:C.isMultigraph(),compound:C.isCompound()},nodes:T(C),edges:y(C)};return _.isUndefined(C.graph())||(S.value=_.clone(C.graph())),S},read:function(C){var S=new d(C.options).setGraph(C.value);return _.each(C.nodes,function(A){S.setNode(A.v,A.value),A.parent&&S.setParent(A.v,A.parent)}),_.each(C.edges,function(A){S.setEdge({v:A.v,w:A.w,name:A.name},A.value)}),S}}},9126:(M,Y,g)=>{var _;try{_={clone:g(6678),constant:g(5703),each:g(6073),filter:g(3105),has:g(8721),isArray:g(1469),isEmpty:g(1609),isFunction:g(3560),isUndefined:g(2353),keys:g(3674),map:g(5161),reduce:g(4061),size:g(4238),transform:g(8718),union:g(3386),values:g(2628)}}catch{}_||(_=window._),M.exports=_},9631:M=>{M.exports="2.1.8"},8552:(M,Y,g)=>{var _=g(852)(g(5639),"DataView");M.exports=_},1989:(M,Y,g)=>{var _=g(1789),d=g(401),T=g(7667),y=g(1327),C=g(1866);function S(A){var I=-1,B=A==null?0:A.length;for(this.clear();++I{var _=g(7040),d=g(4125),T=g(2117),y=g(7518),C=g(4705);function S(A){var I=-1,B=A==null?0:A.length;for(this.clear();++I{var _=g(852)(g(5639),"Map");M.exports=_},3369:(M,Y,g)=>{var _=g(4785),d=g(1285),T=g(6e3),y=g(9916),C=g(5265);function S(A){var I=-1,B=A==null?0:A.length;for(this.clear();++I{var _=g(852)(g(5639),"Promise");M.exports=_},8525:(M,Y,g)=>{var _=g(852)(g(5639),"Set");M.exports=_},8668:(M,Y,g)=>{var _=g(3369),d=g(619),T=g(2385);function y(C){var S=-1,A=C==null?0:C.length;for(this.__data__=new _;++S{var _=g(8407),d=g(7465),T=g(3779),y=g(7599),C=g(4758),S=g(4309);function A(I){var B=this.__data__=new _(I);this.size=B.size}A.prototype.clear=d,A.prototype.delete=T,A.prototype.get=y,A.prototype.has=C,A.prototype.set=S,M.exports=A},2705:(M,Y,g)=>{var _=g(5639).Symbol;M.exports=_},1149:(M,Y,g)=>{var _=g(5639).Uint8Array;M.exports=_},577:(M,Y,g)=>{var _=g(852)(g(5639),"WeakMap");M.exports=_},6874:M=>{M.exports=function(Y,g,_){switch(_.length){case 0:return Y.call(g);case 1:return Y.call(g,_[0]);case 2:return Y.call(g,_[0],_[1]);case 3:return Y.call(g,_[0],_[1],_[2])}return Y.apply(g,_)}},7412:M=>{M.exports=function(Y,g){for(var _=-1,d=Y==null?0:Y.length;++_{M.exports=function(Y,g){for(var _=-1,d=Y==null?0:Y.length,T=0,y=[];++_{var _=g(2118);M.exports=function(d,T){return!(d==null||!d.length)&&_(d,T,0)>-1}},1196:M=>{M.exports=function(Y,g,_){for(var d=-1,T=Y==null?0:Y.length;++d{var _=g(2545),d=g(5694),T=g(1469),y=g(4144),C=g(5776),S=g(6719),A=Object.prototype.hasOwnProperty;M.exports=function(I,B){var j=T(I),V=!j&&d(I),X=!j&&!V&&y(I),Q=!j&&!V&&!X&&S(I),gt=j||V||X||Q,tt=gt?_(I.length,String):[],Lt=tt.length;for(var it in I)!B&&!A.call(I,it)||gt&&(it=="length"||X&&(it=="offset"||it=="parent")||Q&&(it=="buffer"||it=="byteLength"||it=="byteOffset")||C(it,Lt))||tt.push(it);return tt}},9932:M=>{M.exports=function(Y,g){for(var _=-1,d=Y==null?0:Y.length,T=Array(d);++_{M.exports=function(Y,g){for(var _=-1,d=g.length,T=Y.length;++_{M.exports=function(Y,g,_,d){var T=-1,y=Y==null?0:Y.length;for(d&&y&&(_=Y[++T]);++T{M.exports=function(Y,g){for(var _=-1,d=Y==null?0:Y.length;++_{var _=g(371)("length");M.exports=_},6556:(M,Y,g)=>{var _=g(9465),d=g(7813);M.exports=function(T,y,C){(C!==void 0&&!d(T[y],C)||C===void 0&&!(y in T))&&_(T,y,C)}},4865:(M,Y,g)=>{var _=g(9465),d=g(7813),T=Object.prototype.hasOwnProperty;M.exports=function(y,C,S){var A=y[C];T.call(y,C)&&d(A,S)&&(S!==void 0||C in y)||_(y,C,S)}},8470:(M,Y,g)=>{var _=g(7813);M.exports=function(d,T){for(var y=d.length;y--;)if(_(d[y][0],T))return y;return-1}},4037:(M,Y,g)=>{var _=g(8363),d=g(3674);M.exports=function(T,y){return T&&_(y,d(y),T)}},3886:(M,Y,g)=>{var _=g(8363),d=g(1704);M.exports=function(T,y){return T&&_(y,d(y),T)}},9465:(M,Y,g)=>{var _=g(8777);M.exports=function(d,T,y){T=="__proto__"&&_?_(d,T,{configurable:!0,enumerable:!0,value:y,writable:!0}):d[T]=y}},5990:(M,Y,g)=>{var _=g(6384),d=g(7412),T=g(4865),y=g(4037),C=g(3886),S=g(4626),A=g(278),I=g(8805),B=g(1911),j=g(8234),V=g(6904),X=g(4160),Q=g(3824),gt=g(9148),tt=g(8517),Lt=g(1469),it=g(4144),vt=g(6688),At=g(3218),Qt=g(2928),jt=g(3674),xt=g(1704),Yt="[object Arguments]",Bt="[object Function]",lt="[object Object]",et={};et[Yt]=et["[object Array]"]=et["[object ArrayBuffer]"]=et["[object DataView]"]=et["[object Boolean]"]=et["[object Date]"]=et["[object Float32Array]"]=et["[object Float64Array]"]=et["[object Int8Array]"]=et["[object Int16Array]"]=et["[object Int32Array]"]=et["[object Map]"]=et["[object Number]"]=et[lt]=et["[object RegExp]"]=et["[object Set]"]=et["[object String]"]=et["[object Symbol]"]=et["[object Uint8Array]"]=et["[object Uint8ClampedArray]"]=et["[object Uint16Array]"]=et["[object Uint32Array]"]=!0,et["[object Error]"]=et[Bt]=et["[object WeakMap]"]=!1,M.exports=function st($,Dt,U,Jt,_t,oe){var Se,Fe=1&Dt,he=2&Dt,se=4&Dt;if(U&&(Se=_t?U($,Jt,_t,oe):U($)),Se!==void 0)return Se;if(!At($))return $;var fe=Lt($);if(fe){if(Se=Q($),!Fe)return A($,Se)}else{var _e=X($),De=_e==Bt||_e=="[object GeneratorFunction]";if(it($))return S($,Fe);if(_e==lt||_e==Yt||De&&!_t){if(Se=he||De?{}:tt($),!Fe)return he?B($,C(Se,$)):I($,y(Se,$))}else{if(!et[_e])return _t?$:{};Se=gt($,_e,Fe)}}oe||(oe=new _);var pe=oe.get($);if(pe)return pe;oe.set($,Se),Qt($)?$.forEach(function(ee){Se.add(st(ee,Dt,U,ee,$,oe))}):vt($)&&$.forEach(function(ee,xe){Se.set(xe,st(ee,Dt,U,xe,$,oe))});var Me=fe?void 0:(se?he?V:j:he?xt:jt)($);return d(Me||$,function(ee,xe){Me&&(ee=$[xe=ee]),T(Se,xe,st(ee,Dt,U,xe,$,oe))}),Se}},3118:(M,Y,g)=>{var _=g(3218),d=Object.create,T=function(){function y(){}return function(C){if(!_(C))return{};if(d)return d(C);y.prototype=C;var S=new y;return y.prototype=void 0,S}}();M.exports=T},9881:(M,Y,g)=>{var _=g(7816),d=g(9291)(_);M.exports=d},6029:(M,Y,g)=>{var _=g(3448);M.exports=function(d,T,y){for(var C=-1,S=d.length;++C{var _=g(9881);M.exports=function(d,T){var y=[];return _(d,function(C,S,A){T(C,S,A)&&y.push(C)}),y}},1848:M=>{M.exports=function(Y,g,_,d){for(var T=Y.length,y=_+(d?1:-1);d?y--:++y{var _=g(2488),d=g(7285);M.exports=function T(y,C,S,A,I){var B=-1,j=y.length;for(S||(S=d),I||(I=[]);++B0&&S(V)?C>1?T(V,C-1,S,A,I):_(I,V):A||(I[I.length]=V)}return I}},8483:(M,Y,g)=>{var _=g(5063)();M.exports=_},7816:(M,Y,g)=>{var _=g(8483),d=g(3674);M.exports=function(T,y){return T&&_(T,y,d)}},7786:(M,Y,g)=>{var _=g(1811),d=g(327);M.exports=function(T,y){for(var C=0,S=(y=_(y,T)).length;T!=null&&C{var _=g(2488),d=g(1469);M.exports=function(T,y,C){var S=y(T);return d(T)?S:_(S,C(T))}},4239:(M,Y,g)=>{var _=g(2705),d=g(9607),T=g(2333),y=_?_.toStringTag:void 0;M.exports=function(C){return C==null?C===void 0?"[object Undefined]":"[object Null]":y&&y in Object(C)?d(C):T(C)}},3325:M=>{M.exports=function(Y,g){return Y>g}},8565:M=>{var Y=Object.prototype.hasOwnProperty;M.exports=function(g,_){return g!=null&&Y.call(g,_)}},13:M=>{M.exports=function(Y,g){return Y!=null&&g in Object(Y)}},2118:(M,Y,g)=>{var _=g(1848),d=g(2722),T=g(2351);M.exports=function(y,C,S){return C==C?T(y,C,S):_(y,d,S)}},9454:(M,Y,g)=>{var _=g(4239),d=g(7005);M.exports=function(T){return d(T)&&_(T)=="[object Arguments]"}},939:(M,Y,g)=>{var _=g(2492),d=g(7005);M.exports=function T(y,C,S,A,I){return y===C||(y==null||C==null||!d(y)&&!d(C)?y!=y&&C!=C:_(y,C,S,A,T,I))}},2492:(M,Y,g)=>{var _=g(6384),d=g(7114),T=g(8351),y=g(6096),C=g(4160),S=g(1469),A=g(4144),I=g(6719),B="[object Arguments]",j="[object Array]",V="[object Object]",X=Object.prototype.hasOwnProperty;M.exports=function(Q,gt,tt,Lt,it,vt){var At=S(Q),Qt=S(gt),jt=At?j:C(Q),xt=Qt?j:C(gt),Yt=(jt=jt==B?V:jt)==V,Bt=(xt=xt==B?V:xt)==V,lt=jt==xt;if(lt&&A(Q)){if(!A(gt))return!1;At=!0,Yt=!1}if(lt&&!Yt)return vt||(vt=new _),At||I(Q)?d(Q,gt,tt,Lt,it,vt):T(Q,gt,jt,tt,Lt,it,vt);if(!(1&tt)){var et=Yt&&X.call(Q,"__wrapped__"),st=Bt&&X.call(gt,"__wrapped__");if(et||st){var $=et?Q.value():Q,Dt=st?gt.value():gt;return vt||(vt=new _),it($,Dt,tt,Lt,vt)}}return!!lt&&(vt||(vt=new _),y(Q,gt,tt,Lt,it,vt))}},5588:(M,Y,g)=>{var _=g(4160),d=g(7005);M.exports=function(T){return d(T)&&_(T)=="[object Map]"}},2958:(M,Y,g)=>{var _=g(6384),d=g(939);M.exports=function(T,y,C,S){var A=C.length,I=A,B=!S;if(T==null)return!I;for(T=Object(T);A--;){var j=C[A];if(B&&j[2]?j[1]!==T[j[0]]:!(j[0]in T))return!1}for(;++A{M.exports=function(Y){return Y!=Y}},8458:(M,Y,g)=>{var _=g(3560),d=g(5346),T=g(3218),y=g(346),C=/^\[object .+?Constructor\]$/,S=Function.prototype,A=Object.prototype,I=S.toString,B=A.hasOwnProperty,j=RegExp("^"+I.call(B).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");M.exports=function(V){return!(!T(V)||d(V))&&(_(V)?j:C).test(y(V))}},9221:(M,Y,g)=>{var _=g(4160),d=g(7005);M.exports=function(T){return d(T)&&_(T)=="[object Set]"}},8749:(M,Y,g)=>{var _=g(4239),d=g(1780),T=g(7005),y={};y["[object Float32Array]"]=y["[object Float64Array]"]=y["[object Int8Array]"]=y["[object Int16Array]"]=y["[object Int32Array]"]=y["[object Uint8Array]"]=y["[object Uint8ClampedArray]"]=y["[object Uint16Array]"]=y["[object Uint32Array]"]=!0,y["[object Arguments]"]=y["[object Array]"]=y["[object ArrayBuffer]"]=y["[object Boolean]"]=y["[object DataView]"]=y["[object Date]"]=y["[object Error]"]=y["[object Function]"]=y["[object Map]"]=y["[object Number]"]=y["[object Object]"]=y["[object RegExp]"]=y["[object Set]"]=y["[object String]"]=y["[object WeakMap]"]=!1,M.exports=function(C){return T(C)&&d(C.length)&&!!y[_(C)]}},7206:(M,Y,g)=>{var _=g(1573),d=g(6432),T=g(6557),y=g(1469),C=g(9601);M.exports=function(S){return typeof S=="function"?S:S==null?T:typeof S=="object"?y(S)?d(S[0],S[1]):_(S):C(S)}},280:(M,Y,g)=>{var _=g(5726),d=g(6916),T=Object.prototype.hasOwnProperty;M.exports=function(y){if(!_(y))return d(y);var C=[];for(var S in Object(y))T.call(y,S)&&S!="constructor"&&C.push(S);return C}},313:(M,Y,g)=>{var _=g(3218),d=g(5726),T=g(3498),y=Object.prototype.hasOwnProperty;M.exports=function(C){if(!_(C))return T(C);var S=d(C),A=[];for(var I in C)(I!="constructor"||!S&&y.call(C,I))&&A.push(I);return A}},433:M=>{M.exports=function(Y,g){return Y{var _=g(9881),d=g(8612);M.exports=function(T,y){var C=-1,S=d(T)?Array(T.length):[];return _(T,function(A,I,B){S[++C]=y(A,I,B)}),S}},1573:(M,Y,g)=>{var _=g(2958),d=g(1499),T=g(2634);M.exports=function(y){var C=d(y);return C.length==1&&C[0][2]?T(C[0][0],C[0][1]):function(S){return S===y||_(S,y,C)}}},6432:(M,Y,g)=>{var _=g(939),d=g(7361),T=g(9095),y=g(5403),C=g(9162),S=g(2634),A=g(327);M.exports=function(I,B){return y(I)&&C(B)?S(A(I),B):function(j){var V=d(j,I);return V===void 0&&V===B?T(j,I):_(B,V,3)}}},2980:(M,Y,g)=>{var _=g(6384),d=g(6556),T=g(8483),y=g(9783),C=g(3218),S=g(1704),A=g(6390);M.exports=function I(B,j,V,X,Q){B!==j&&T(j,function(gt,tt){if(Q||(Q=new _),C(gt))y(B,j,tt,V,I,X,Q);else{var Lt=X?X(A(B,tt),gt,tt+"",B,j,Q):void 0;Lt===void 0&&(Lt=gt),d(B,tt,Lt)}},S)}},9783:(M,Y,g)=>{var _=g(6556),d=g(4626),T=g(7133),y=g(278),C=g(8517),S=g(5694),A=g(1469),I=g(9246),B=g(4144),j=g(3560),V=g(3218),X=g(8630),Q=g(6719),gt=g(6390),tt=g(3678);M.exports=function(Lt,it,vt,At,Qt,jt,xt){var Yt=gt(Lt,vt),Bt=gt(it,vt),lt=xt.get(Bt);if(lt)_(Lt,vt,lt);else{var et=jt?jt(Yt,Bt,vt+"",Lt,it,xt):void 0,st=et===void 0;if(st){var $=A(Bt),Dt=!$&&B(Bt),U=!$&&!Dt&&Q(Bt);et=Bt,$||Dt||U?A(Yt)?et=Yt:I(Yt)?et=y(Yt):Dt?(st=!1,et=d(Bt,!0)):U?(st=!1,et=T(Bt,!0)):et=[]:X(Bt)||S(Bt)?(et=Yt,S(Yt)?et=tt(Yt):V(Yt)&&!j(Yt)||(et=C(Bt))):st=!1}st&&(xt.set(Bt,et),Qt(et,Bt,At,jt,xt),xt.delete(Bt)),_(Lt,vt,et)}}},9556:(M,Y,g)=>{var _=g(9932),d=g(7786),T=g(7206),y=g(9199),C=g(1131),S=g(1717),A=g(5022),I=g(6557),B=g(1469);M.exports=function(j,V,X){V=V.length?_(V,function(tt){return B(tt)?function(Lt){return d(Lt,tt.length===1?tt[0]:tt)}:tt}):[I];var Q=-1;V=_(V,S(T));var gt=y(j,function(tt,Lt,it){return{criteria:_(V,function(vt){return vt(tt)}),index:++Q,value:tt}});return C(gt,function(tt,Lt){return A(tt,Lt,X)})}},5970:(M,Y,g)=>{var _=g(3012),d=g(9095);M.exports=function(T,y){return _(T,y,function(C,S){return d(T,S)})}},3012:(M,Y,g)=>{var _=g(7786),d=g(611),T=g(1811);M.exports=function(y,C,S){for(var A=-1,I=C.length,B={};++A{M.exports=function(Y){return function(g){return g==null?void 0:g[Y]}}},9152:(M,Y,g)=>{var _=g(7786);M.exports=function(d){return function(T){return _(T,d)}}},98:M=>{var Y=Math.ceil,g=Math.max;M.exports=function(_,d,T,y){for(var C=-1,S=g(Y((d-_)/(T||1)),0),A=Array(S);S--;)A[y?S:++C]=_,_+=T;return A}},107:M=>{M.exports=function(Y,g,_,d,T){return T(Y,function(y,C,S){_=d?(d=!1,y):g(_,y,C,S)}),_}},5976:(M,Y,g)=>{var _=g(6557),d=g(5357),T=g(61);M.exports=function(y,C){return T(d(y,C,_),y+"")}},611:(M,Y,g)=>{var _=g(4865),d=g(1811),T=g(5776),y=g(3218),C=g(327);M.exports=function(S,A,I,B){if(!y(S))return S;for(var j=-1,V=(A=d(A,S)).length,X=V-1,Q=S;Q!=null&&++j{var _=g(5703),d=g(8777),T=g(6557),y=d?function(C,S){return d(C,"toString",{configurable:!0,enumerable:!1,value:_(S),writable:!0})}:T;M.exports=y},1131:M=>{M.exports=function(Y,g){var _=Y.length;for(Y.sort(g);_--;)Y[_]=Y[_].value;return Y}},2545:M=>{M.exports=function(Y,g){for(var _=-1,d=Array(Y);++_{var _=g(2705),d=g(9932),T=g(1469),y=g(3448),C=_?_.prototype:void 0,S=C?C.toString:void 0;M.exports=function A(I){if(typeof I=="string")return I;if(T(I))return d(I,A)+"";if(y(I))return S?S.call(I):"";var B=I+"";return B=="0"&&1/I==-1/0?"-0":B}},7561:(M,Y,g)=>{var _=g(7990),d=/^\s+/;M.exports=function(T){return T&&T.slice(0,_(T)+1).replace(d,"")}},1717:M=>{M.exports=function(Y){return function(g){return Y(g)}}},5652:(M,Y,g)=>{var _=g(8668),d=g(7443),T=g(1196),y=g(4757),C=g(3593),S=g(1814);M.exports=function(A,I,B){var j=-1,V=d,X=A.length,Q=!0,gt=[],tt=gt;if(B)Q=!1,V=T;else if(X>=200){var Lt=I?null:C(A);if(Lt)return S(Lt);Q=!1,V=y,tt=new _}else tt=I?[]:gt;t:for(;++j{var _=g(9932);M.exports=function(d,T){return _(T,function(y){return d[y]})}},1757:M=>{M.exports=function(Y,g,_){for(var d=-1,T=Y.length,y=g.length,C={};++d{M.exports=function(Y,g){return Y.has(g)}},4290:(M,Y,g)=>{var _=g(6557);M.exports=function(d){return typeof d=="function"?d:_}},1811:(M,Y,g)=>{var _=g(1469),d=g(5403),T=g(5514),y=g(9833);M.exports=function(C,S){return _(C)?C:d(C,S)?[C]:T(y(C))}},4318:(M,Y,g)=>{var _=g(1149);M.exports=function(d){var T=new d.constructor(d.byteLength);return new _(T).set(new _(d)),T}},4626:(M,Y,g)=>{M=g.nmd(M);var _=g(5639),d=Y&&!Y.nodeType&&Y,T=d&&M&&!M.nodeType&&M,y=T&&T.exports===d?_.Buffer:void 0,C=y?y.allocUnsafe:void 0;M.exports=function(S,A){if(A)return S.slice();var I=S.length,B=C?C(I):new S.constructor(I);return S.copy(B),B}},7157:(M,Y,g)=>{var _=g(4318);M.exports=function(d,T){var y=T?_(d.buffer):d.buffer;return new d.constructor(y,d.byteOffset,d.byteLength)}},3147:M=>{var Y=/\w*$/;M.exports=function(g){var _=new g.constructor(g.source,Y.exec(g));return _.lastIndex=g.lastIndex,_}},419:(M,Y,g)=>{var _=g(2705),d=_?_.prototype:void 0,T=d?d.valueOf:void 0;M.exports=function(y){return T?Object(T.call(y)):{}}},7133:(M,Y,g)=>{var _=g(4318);M.exports=function(d,T){var y=T?_(d.buffer):d.buffer;return new d.constructor(y,d.byteOffset,d.length)}},6393:(M,Y,g)=>{var _=g(3448);M.exports=function(d,T){if(d!==T){var y=d!==void 0,C=d===null,S=d==d,A=_(d),I=T!==void 0,B=T===null,j=T==T,V=_(T);if(!B&&!V&&!A&&d>T||A&&I&&j&&!B&&!V||C&&I&&j||!y&&j||!S)return 1;if(!C&&!A&&!V&&d{var _=g(6393);M.exports=function(d,T,y){for(var C=-1,S=d.criteria,A=T.criteria,I=S.length,B=y.length;++C=B?j:j*(y[C]=="desc"?-1:1)}return d.index-T.index}},278:M=>{M.exports=function(Y,g){var _=-1,d=Y.length;for(g||(g=Array(d));++_{var _=g(4865),d=g(9465);M.exports=function(T,y,C,S){var A=!C;C||(C={});for(var I=-1,B=y.length;++I{var _=g(8363),d=g(9551);M.exports=function(T,y){return _(T,d(T),y)}},1911:(M,Y,g)=>{var _=g(8363),d=g(1442);M.exports=function(T,y){return _(T,d(T),y)}},4429:(M,Y,g)=>{var _=g(5639)["__core-js_shared__"];M.exports=_},1750:(M,Y,g)=>{var _=g(5976),d=g(6612);M.exports=function(T){return _(function(y,C){var S=-1,A=C.length,I=A>1?C[A-1]:void 0,B=A>2?C[2]:void 0;for(I=T.length>3&&typeof I=="function"?(A--,I):void 0,B&&d(C[0],C[1],B)&&(I=A<3?void 0:I,A=1),y=Object(y);++S{var _=g(8612);M.exports=function(d,T){return function(y,C){if(y==null)return y;if(!_(y))return d(y,C);for(var S=y.length,A=T?S:-1,I=Object(y);(T?A--:++A{M.exports=function(Y){return function(g,_,d){for(var T=-1,y=Object(g),C=d(g),S=C.length;S--;){var A=C[Y?S:++T];if(_(y[A],A,y)===!1)break}return g}}},7740:(M,Y,g)=>{var _=g(7206),d=g(8612),T=g(3674);M.exports=function(y){return function(C,S,A){var I=Object(C);if(!d(C)){var B=_(S,3);C=T(C),S=function(V){return B(I[V],V,I)}}var j=y(C,S,A);return j>-1?I[B?C[j]:j]:void 0}}},7445:(M,Y,g)=>{var _=g(98),d=g(6612),T=g(8601);M.exports=function(y){return function(C,S,A){return A&&typeof A!="number"&&d(C,S,A)&&(S=A=void 0),C=T(C),S===void 0?(S=C,C=0):S=T(S),A=A===void 0?C{var _=g(8525),d=g(308),T=g(1814),y=_&&1/T(new _([,-0]))[1]==1/0?function(C){return new _(C)}:d;M.exports=y},8777:(M,Y,g)=>{var _=g(852),d=function(){try{var T=_(Object,"defineProperty");return T({},"",{}),T}catch{}}();M.exports=d},7114:(M,Y,g)=>{var _=g(8668),d=g(2908),T=g(4757);M.exports=function(y,C,S,A,I,B){var j=1&S,V=y.length,X=C.length;if(V!=X&&!(j&&X>V))return!1;var Q=B.get(y),gt=B.get(C);if(Q&>)return Q==C&>==y;var tt=-1,Lt=!0,it=2&S?new _:void 0;for(B.set(y,C),B.set(C,y);++tt{var _=g(2705),d=g(1149),T=g(7813),y=g(7114),C=g(8776),S=g(1814),A=_?_.prototype:void 0,I=A?A.valueOf:void 0;M.exports=function(B,j,V,X,Q,gt,tt){switch(V){case"[object DataView]":if(B.byteLength!=j.byteLength||B.byteOffset!=j.byteOffset)return!1;B=B.buffer,j=j.buffer;case"[object ArrayBuffer]":return!(B.byteLength!=j.byteLength||!gt(new d(B),new d(j)));case"[object Boolean]":case"[object Date]":case"[object Number]":return T(+B,+j);case"[object Error]":return B.name==j.name&&B.message==j.message;case"[object RegExp]":case"[object String]":return B==j+"";case"[object Map]":var Lt=C;case"[object Set]":var it=1&X;if(Lt||(Lt=S),B.size!=j.size&&!it)return!1;var vt=tt.get(B);if(vt)return vt==j;X|=2,tt.set(B,j);var At=y(Lt(B),Lt(j),X,Q,gt,tt);return tt.delete(B),At;case"[object Symbol]":if(I)return I.call(B)==I.call(j)}return!1}},6096:(M,Y,g)=>{var _=g(8234),d=Object.prototype.hasOwnProperty;M.exports=function(T,y,C,S,A,I){var B=1&C,j=_(T),V=j.length;if(V!=_(y).length&&!B)return!1;for(var X=V;X--;){var Q=j[X];if(!(B?Q in y:d.call(y,Q)))return!1}var gt=I.get(T),tt=I.get(y);if(gt&&tt)return gt==y&&tt==T;var Lt=!0;I.set(T,y),I.set(y,T);for(var it=B;++X{var _=g(5564),d=g(5357),T=g(61);M.exports=function(y){return T(d(y,void 0,_),y+"")}},1957:(M,Y,g)=>{var _=typeof g.g=="object"&&g.g&&g.g.Object===Object&&g.g;M.exports=_},8234:(M,Y,g)=>{var _=g(8866),d=g(9551),T=g(3674);M.exports=function(y){return _(y,T,d)}},6904:(M,Y,g)=>{var _=g(8866),d=g(1442),T=g(1704);M.exports=function(y){return _(y,T,d)}},5050:(M,Y,g)=>{var _=g(7019);M.exports=function(d,T){var y=d.__data__;return _(T)?y[typeof T=="string"?"string":"hash"]:y.map}},1499:(M,Y,g)=>{var _=g(9162),d=g(3674);M.exports=function(T){for(var y=d(T),C=y.length;C--;){var S=y[C],A=T[S];y[C]=[S,A,_(A)]}return y}},852:(M,Y,g)=>{var _=g(8458),d=g(7801);M.exports=function(T,y){var C=d(T,y);return _(C)?C:void 0}},5924:(M,Y,g)=>{var _=g(5569)(Object.getPrototypeOf,Object);M.exports=_},9607:(M,Y,g)=>{var _=g(2705),d=Object.prototype,T=d.hasOwnProperty,y=d.toString,C=_?_.toStringTag:void 0;M.exports=function(S){var A=T.call(S,C),I=S[C];try{S[C]=void 0;var B=!0}catch{}var j=y.call(S);return B&&(A?S[C]=I:delete S[C]),j}},9551:(M,Y,g)=>{var _=g(4963),d=g(479),T=Object.prototype.propertyIsEnumerable,y=Object.getOwnPropertySymbols,C=y?function(S){return S==null?[]:(S=Object(S),_(y(S),function(A){return T.call(S,A)}))}:d;M.exports=C},1442:(M,Y,g)=>{var _=g(2488),d=g(5924),T=g(9551),y=g(479),C=Object.getOwnPropertySymbols?function(S){for(var A=[];S;)_(A,T(S)),S=d(S);return A}:y;M.exports=C},4160:(M,Y,g)=>{var _=g(8552),d=g(7071),T=g(3818),y=g(8525),C=g(577),S=g(4239),A=g(346),I="[object Map]",B="[object Promise]",j="[object Set]",V="[object WeakMap]",X="[object DataView]",Q=A(_),gt=A(d),tt=A(T),Lt=A(y),it=A(C),vt=S;(_&&vt(new _(new ArrayBuffer(1)))!=X||d&&vt(new d)!=I||T&&vt(T.resolve())!=B||y&&vt(new y)!=j||C&&vt(new C)!=V)&&(vt=function(At){var Qt=S(At),jt=Qt=="[object Object]"?At.constructor:void 0,xt=jt?A(jt):"";if(xt)switch(xt){case Q:return X;case gt:return I;case tt:return B;case Lt:return j;case it:return V}return Qt}),M.exports=vt},7801:M=>{M.exports=function(Y,g){return Y==null?void 0:Y[g]}},222:(M,Y,g)=>{var _=g(1811),d=g(5694),T=g(1469),y=g(5776),C=g(1780),S=g(327);M.exports=function(A,I,B){for(var j=-1,V=(I=_(I,A)).length,X=!1;++j{var Y=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]");M.exports=function(g){return Y.test(g)}},1789:(M,Y,g)=>{var _=g(4536);M.exports=function(){this.__data__=_?_(null):{},this.size=0}},401:M=>{M.exports=function(Y){var g=this.has(Y)&&delete this.__data__[Y];return this.size-=g?1:0,g}},7667:(M,Y,g)=>{var _=g(4536),d=Object.prototype.hasOwnProperty;M.exports=function(T){var y=this.__data__;if(_){var C=y[T];return C==="__lodash_hash_undefined__"?void 0:C}return d.call(y,T)?y[T]:void 0}},1327:(M,Y,g)=>{var _=g(4536),d=Object.prototype.hasOwnProperty;M.exports=function(T){var y=this.__data__;return _?y[T]!==void 0:d.call(y,T)}},1866:(M,Y,g)=>{var _=g(4536);M.exports=function(d,T){var y=this.__data__;return this.size+=this.has(d)?0:1,y[d]=_&&T===void 0?"__lodash_hash_undefined__":T,this}},3824:M=>{var Y=Object.prototype.hasOwnProperty;M.exports=function(g){var _=g.length,d=new g.constructor(_);return _&&typeof g[0]=="string"&&Y.call(g,"index")&&(d.index=g.index,d.input=g.input),d}},9148:(M,Y,g)=>{var _=g(4318),d=g(7157),T=g(3147),y=g(419),C=g(7133);M.exports=function(S,A,I){var B=S.constructor;switch(A){case"[object ArrayBuffer]":return _(S);case"[object Boolean]":case"[object Date]":return new B(+S);case"[object DataView]":return d(S,I);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return C(S,I);case"[object Map]":case"[object Set]":return new B;case"[object Number]":case"[object String]":return new B(S);case"[object RegExp]":return T(S);case"[object Symbol]":return y(S)}}},8517:(M,Y,g)=>{var _=g(3118),d=g(5924),T=g(5726);M.exports=function(y){return typeof y.constructor!="function"||T(y)?{}:_(d(y))}},7285:(M,Y,g)=>{var _=g(2705),d=g(5694),T=g(1469),y=_?_.isConcatSpreadable:void 0;M.exports=function(C){return T(C)||d(C)||!!(y&&C&&C[y])}},5776:M=>{var Y=/^(?:0|[1-9]\d*)$/;M.exports=function(g,_){var d=typeof g;return!!(_=_??9007199254740991)&&(d=="number"||d!="symbol"&&Y.test(g))&&g>-1&&g%1==0&&g<_}},6612:(M,Y,g)=>{var _=g(7813),d=g(8612),T=g(5776),y=g(3218);M.exports=function(C,S,A){if(!y(A))return!1;var I=typeof S;return!!(I=="number"?d(A)&&T(S,A.length):I=="string"&&S in A)&&_(A[S],C)}},5403:(M,Y,g)=>{var _=g(1469),d=g(3448),T=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,y=/^\w*$/;M.exports=function(C,S){if(_(C))return!1;var A=typeof C;return!(A!="number"&&A!="symbol"&&A!="boolean"&&C!=null&&!d(C))||y.test(C)||!T.test(C)||S!=null&&C in Object(S)}},7019:M=>{M.exports=function(Y){var g=typeof Y;return g=="string"||g=="number"||g=="symbol"||g=="boolean"?Y!=="__proto__":Y===null}},5346:(M,Y,g)=>{var _,d=g(4429),T=(_=/[^.]+$/.exec(d&&d.keys&&d.keys.IE_PROTO||""))?"Symbol(src)_1."+_:"";M.exports=function(y){return!!T&&T in y}},5726:M=>{var Y=Object.prototype;M.exports=function(g){var _=g&&g.constructor;return g===(typeof _=="function"&&_.prototype||Y)}},9162:(M,Y,g)=>{var _=g(3218);M.exports=function(d){return d==d&&!_(d)}},7040:M=>{M.exports=function(){this.__data__=[],this.size=0}},4125:(M,Y,g)=>{var _=g(8470),d=Array.prototype.splice;M.exports=function(T){var y=this.__data__,C=_(y,T);return!(C<0||(C==y.length-1?y.pop():d.call(y,C,1),--this.size,0))}},2117:(M,Y,g)=>{var _=g(8470);M.exports=function(d){var T=this.__data__,y=_(T,d);return y<0?void 0:T[y][1]}},7518:(M,Y,g)=>{var _=g(8470);M.exports=function(d){return _(this.__data__,d)>-1}},4705:(M,Y,g)=>{var _=g(8470);M.exports=function(d,T){var y=this.__data__,C=_(y,d);return C<0?(++this.size,y.push([d,T])):y[C][1]=T,this}},4785:(M,Y,g)=>{var _=g(1989),d=g(8407),T=g(7071);M.exports=function(){this.size=0,this.__data__={hash:new _,map:new(T||d),string:new _}}},1285:(M,Y,g)=>{var _=g(5050);M.exports=function(d){var T=_(this,d).delete(d);return this.size-=T?1:0,T}},6e3:(M,Y,g)=>{var _=g(5050);M.exports=function(d){return _(this,d).get(d)}},9916:(M,Y,g)=>{var _=g(5050);M.exports=function(d){return _(this,d).has(d)}},5265:(M,Y,g)=>{var _=g(5050);M.exports=function(d,T){var y=_(this,d),C=y.size;return y.set(d,T),this.size+=y.size==C?0:1,this}},8776:M=>{M.exports=function(Y){var g=-1,_=Array(Y.size);return Y.forEach(function(d,T){_[++g]=[T,d]}),_}},2634:M=>{M.exports=function(Y,g){return function(_){return _!=null&&_[Y]===g&&(g!==void 0||Y in Object(_))}}},4523:(M,Y,g)=>{var _=g(8306);M.exports=function(d){var T=_(d,function(C){return y.size===500&&y.clear(),C}),y=T.cache;return T}},4536:(M,Y,g)=>{var _=g(852)(Object,"create");M.exports=_},6916:(M,Y,g)=>{var _=g(5569)(Object.keys,Object);M.exports=_},3498:M=>{M.exports=function(Y){var g=[];if(Y!=null)for(var _ in Object(Y))g.push(_);return g}},1167:(M,Y,g)=>{M=g.nmd(M);var _=g(1957),d=Y&&!Y.nodeType&&Y,T=d&&M&&!M.nodeType&&M,y=T&&T.exports===d&&_.process,C=function(){try{return T&&T.require&&T.require("util").types||y&&y.binding&&y.binding("util")}catch{}}();M.exports=C},2333:M=>{var Y=Object.prototype.toString;M.exports=function(g){return Y.call(g)}},5569:M=>{M.exports=function(Y,g){return function(_){return Y(g(_))}}},5357:(M,Y,g)=>{var _=g(6874),d=Math.max;M.exports=function(T,y,C){return y=d(y===void 0?T.length-1:y,0),function(){for(var S=arguments,A=-1,I=d(S.length-y,0),B=Array(I);++A{var _=g(1957),d=typeof self=="object"&&self&&self.Object===Object&&self,T=_||d||Function("return this")();M.exports=T},6390:M=>{M.exports=function(Y,g){if((g!=="constructor"||typeof Y[g]!="function")&&g!="__proto__")return Y[g]}},619:M=>{M.exports=function(Y){return this.__data__.set(Y,"__lodash_hash_undefined__"),this}},2385:M=>{M.exports=function(Y){return this.__data__.has(Y)}},1814:M=>{M.exports=function(Y){var g=-1,_=Array(Y.size);return Y.forEach(function(d){_[++g]=d}),_}},61:(M,Y,g)=>{var _=g(6560),d=g(1275)(_);M.exports=d},1275:M=>{var Y=Date.now;M.exports=function(g){var _=0,d=0;return function(){var T=Y(),y=16-(T-d);if(d=T,y>0){if(++_>=800)return arguments[0]}else _=0;return g.apply(void 0,arguments)}}},7465:(M,Y,g)=>{var _=g(8407);M.exports=function(){this.__data__=new _,this.size=0}},3779:M=>{M.exports=function(Y){var g=this.__data__,_=g.delete(Y);return this.size=g.size,_}},7599:M=>{M.exports=function(Y){return this.__data__.get(Y)}},4758:M=>{M.exports=function(Y){return this.__data__.has(Y)}},4309:(M,Y,g)=>{var _=g(8407),d=g(7071),T=g(3369);M.exports=function(y,C){var S=this.__data__;if(S instanceof _){var A=S.__data__;if(!d||A.length<199)return A.push([y,C]),this.size=++S.size,this;S=this.__data__=new T(A)}return S.set(y,C),this.size=S.size,this}},2351:M=>{M.exports=function(Y,g,_){for(var d=_-1,T=Y.length;++d{var _=g(8983),d=g(2689),T=g(1903);M.exports=function(y){return d(y)?T(y):_(y)}},5514:(M,Y,g)=>{var _=g(4523),d=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,T=/\\(\\)?/g,y=_(function(C){var S=[];return C.charCodeAt(0)===46&&S.push(""),C.replace(d,function(A,I,B,j){S.push(B?j.replace(T,"$1"):I||A)}),S});M.exports=y},327:(M,Y,g)=>{var _=g(3448);M.exports=function(d){if(typeof d=="string"||_(d))return d;var T=d+"";return T=="0"&&1/d==-1/0?"-0":T}},346:M=>{var Y=Function.prototype.toString;M.exports=function(g){if(g!=null){try{return Y.call(g)}catch{}try{return g+""}catch{}}return""}},7990:M=>{var Y=/\s/;M.exports=function(g){for(var _=g.length;_--&&Y.test(g.charAt(_)););return _}},1903:M=>{var Y="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",g="\\ud83c[\\udffb-\\udfff]",_="[^\\ud800-\\udfff]",d="(?:\\ud83c[\\udde6-\\uddff]){2}",T="[\\ud800-\\udbff][\\udc00-\\udfff]",y="(?:"+Y+"|"+g+")?",C="[\\ufe0e\\ufe0f]?",S=C+y+"(?:\\u200d(?:"+[_,d,T].join("|")+")"+C+y+")*",A="(?:"+[_+Y+"?",Y,d,T,"[\\ud800-\\udfff]"].join("|")+")",I=RegExp(g+"(?="+g+")|"+A+S,"g");M.exports=function(B){for(var j=I.lastIndex=0;I.test(B);)++j;return j}},6678:(M,Y,g)=>{var _=g(5990);M.exports=function(d){return _(d,4)}},361:(M,Y,g)=>{var _=g(5990);M.exports=function(d){return _(d,5)}},5703:M=>{M.exports=function(Y){return function(){return Y}}},1747:(M,Y,g)=>{var _=g(5976),d=g(7813),T=g(6612),y=g(1704),C=Object.prototype,S=C.hasOwnProperty,A=_(function(I,B){I=Object(I);var j=-1,V=B.length,X=V>2?B[2]:void 0;for(X&&T(B[0],B[1],X)&&(V=1);++j{M.exports=g(4486)},7813:M=>{M.exports=function(Y,g){return Y===g||Y!=Y&&g!=g}},3105:(M,Y,g)=>{var _=g(4963),d=g(760),T=g(7206),y=g(1469);M.exports=function(C,S){return(y(C)?_:d)(C,T(S,3))}},3311:(M,Y,g)=>{var _=g(7740)(g(998));M.exports=_},998:(M,Y,g)=>{var _=g(1848),d=g(7206),T=g(554),y=Math.max;M.exports=function(C,S,A){var I=C==null?0:C.length;if(!I)return-1;var B=A==null?0:T(A);return B<0&&(B=y(I+B,0)),_(C,d(S,3),B)}},5564:(M,Y,g)=>{var _=g(1078);M.exports=function(d){return d!=null&&d.length?_(d,1):[]}},4486:(M,Y,g)=>{var _=g(7412),d=g(9881),T=g(4290),y=g(1469);M.exports=function(C,S){return(y(C)?_:d)(C,T(S))}},2620:(M,Y,g)=>{var _=g(8483),d=g(4290),T=g(1704);M.exports=function(y,C){return y==null?y:_(y,d(C),T)}},7361:(M,Y,g)=>{var _=g(7786);M.exports=function(d,T,y){var C=d==null?void 0:_(d,T);return C===void 0?y:C}},8721:(M,Y,g)=>{var _=g(8565),d=g(222);M.exports=function(T,y){return T!=null&&d(T,y,_)}},9095:(M,Y,g)=>{var _=g(13),d=g(222);M.exports=function(T,y){return T!=null&&d(T,y,_)}},6557:M=>{M.exports=function(Y){return Y}},5694:(M,Y,g)=>{var _=g(9454),d=g(7005),T=Object.prototype,y=T.hasOwnProperty,C=T.propertyIsEnumerable,S=_(function(){return arguments}())?_:function(A){return d(A)&&y.call(A,"callee")&&!C.call(A,"callee")};M.exports=S},1469:M=>{var Y=Array.isArray;M.exports=Y},8612:(M,Y,g)=>{var _=g(3560),d=g(1780);M.exports=function(T){return T!=null&&d(T.length)&&!_(T)}},9246:(M,Y,g)=>{var _=g(8612),d=g(7005);M.exports=function(T){return d(T)&&_(T)}},4144:(M,Y,g)=>{M=g.nmd(M);var _=g(5639),d=g(5062),T=Y&&!Y.nodeType&&Y,y=T&&M&&!M.nodeType&&M,C=y&&y.exports===T?_.Buffer:void 0,S=(C?C.isBuffer:void 0)||d;M.exports=S},1609:(M,Y,g)=>{var _=g(280),d=g(4160),T=g(5694),y=g(1469),C=g(8612),S=g(4144),A=g(5726),I=g(6719),B=Object.prototype.hasOwnProperty;M.exports=function(j){if(j==null)return!0;if(C(j)&&(y(j)||typeof j=="string"||typeof j.splice=="function"||S(j)||I(j)||T(j)))return!j.length;var V=d(j);if(V=="[object Map]"||V=="[object Set]")return!j.size;if(A(j))return!_(j).length;for(var X in j)if(B.call(j,X))return!1;return!0}},3560:(M,Y,g)=>{var _=g(4239),d=g(3218);M.exports=function(T){if(!d(T))return!1;var y=_(T);return y=="[object Function]"||y=="[object GeneratorFunction]"||y=="[object AsyncFunction]"||y=="[object Proxy]"}},1780:M=>{M.exports=function(Y){return typeof Y=="number"&&Y>-1&&Y%1==0&&Y<=9007199254740991}},6688:(M,Y,g)=>{var _=g(5588),d=g(1717),T=g(1167),y=T&&T.isMap,C=y?d(y):_;M.exports=C},3218:M=>{M.exports=function(Y){var g=typeof Y;return Y!=null&&(g=="object"||g=="function")}},7005:M=>{M.exports=function(Y){return Y!=null&&typeof Y=="object"}},8630:(M,Y,g)=>{var _=g(4239),d=g(5924),T=g(7005),y=Function.prototype,C=Object.prototype,S=y.toString,A=C.hasOwnProperty,I=S.call(Object);M.exports=function(B){if(!T(B)||_(B)!="[object Object]")return!1;var j=d(B);if(j===null)return!0;var V=A.call(j,"constructor")&&j.constructor;return typeof V=="function"&&V instanceof V&&S.call(V)==I}},2928:(M,Y,g)=>{var _=g(9221),d=g(1717),T=g(1167),y=T&&T.isSet,C=y?d(y):_;M.exports=C},7037:(M,Y,g)=>{var _=g(4239),d=g(1469),T=g(7005);M.exports=function(y){return typeof y=="string"||!d(y)&&T(y)&&_(y)=="[object String]"}},3448:(M,Y,g)=>{var _=g(4239),d=g(7005);M.exports=function(T){return typeof T=="symbol"||d(T)&&_(T)=="[object Symbol]"}},6719:(M,Y,g)=>{var _=g(8749),d=g(1717),T=g(1167),y=T&&T.isTypedArray,C=y?d(y):_;M.exports=C},2353:M=>{M.exports=function(Y){return Y===void 0}},3674:(M,Y,g)=>{var _=g(4636),d=g(280),T=g(8612);M.exports=function(y){return T(y)?_(y):d(y)}},1704:(M,Y,g)=>{var _=g(4636),d=g(313),T=g(8612);M.exports=function(y){return T(y)?_(y,!0):d(y)}},928:M=>{M.exports=function(Y){var g=Y==null?0:Y.length;return g?Y[g-1]:void 0}},5161:(M,Y,g)=>{var _=g(9932),d=g(7206),T=g(9199),y=g(1469);M.exports=function(C,S){return(y(C)?_:T)(C,d(S,3))}},6604:(M,Y,g)=>{var _=g(9465),d=g(7816),T=g(7206);M.exports=function(y,C){var S={};return C=T(C,3),d(y,function(A,I,B){_(S,I,C(A,I,B))}),S}},6162:(M,Y,g)=>{var _=g(6029),d=g(3325),T=g(6557);M.exports=function(y){return y&&y.length?_(y,T,d):void 0}},8306:(M,Y,g)=>{var _=g(3369);function d(T,y){if(typeof T!="function"||y!=null&&typeof y!="function")throw new TypeError("Expected a function");var C=function(){var S=arguments,A=y?y.apply(this,S):S[0],I=C.cache;if(I.has(A))return I.get(A);var B=T.apply(this,S);return C.cache=I.set(A,B)||I,B};return C.cache=new(d.Cache||_),C}d.Cache=_,M.exports=d},3857:(M,Y,g)=>{var _=g(2980),d=g(1750)(function(T,y,C){_(T,y,C)});M.exports=d},3632:(M,Y,g)=>{var _=g(6029),d=g(433),T=g(6557);M.exports=function(y){return y&&y.length?_(y,T,d):void 0}},2762:(M,Y,g)=>{var _=g(6029),d=g(7206),T=g(433);M.exports=function(y,C){return y&&y.length?_(y,d(C,2),T):void 0}},308:M=>{M.exports=function(){}},7771:(M,Y,g)=>{var _=g(5639);M.exports=function(){return _.Date.now()}},9722:(M,Y,g)=>{var _=g(5970),d=g(9021)(function(T,y){return T==null?{}:_(T,y)});M.exports=d},9601:(M,Y,g)=>{var _=g(371),d=g(9152),T=g(5403),y=g(327);M.exports=function(C){return T(C)?_(y(C)):d(C)}},6026:(M,Y,g)=>{var _=g(7445)();M.exports=_},4061:(M,Y,g)=>{var _=g(2663),d=g(9881),T=g(7206),y=g(107),C=g(1469);M.exports=function(S,A,I){var B=C(S)?_:y,j=arguments.length<3;return B(S,T(A,4),I,j,d)}},4238:(M,Y,g)=>{var _=g(280),d=g(4160),T=g(8612),y=g(7037),C=g(8016);M.exports=function(S){if(S==null)return 0;if(T(S))return y(S)?C(S):S.length;var A=d(S);return A=="[object Map]"||A=="[object Set]"?S.size:_(S).length}},9734:(M,Y,g)=>{var _=g(1078),d=g(9556),T=g(5976),y=g(6612),C=T(function(S,A){if(S==null)return[];var I=A.length;return I>1&&y(S,A[0],A[1])?A=[]:I>2&&y(A[0],A[1],A[2])&&(A=[A[0]]),d(S,_(A,1),[])});M.exports=C},479:M=>{M.exports=function(){return[]}},5062:M=>{M.exports=function(){return!1}},8601:(M,Y,g)=>{var _=g(4841);M.exports=function(d){return d?(d=_(d))===1/0||d===-1/0?17976931348623157e292*(d<0?-1:1):d==d?d:0:d===0?d:0}},554:(M,Y,g)=>{var _=g(8601);M.exports=function(d){var T=_(d),y=T%1;return T==T?y?T-y:T:0}},4841:(M,Y,g)=>{var _=g(7561),d=g(3218),T=g(3448),y=/^[-+]0x[0-9a-f]+$/i,C=/^0b[01]+$/i,S=/^0o[0-7]+$/i,A=parseInt;M.exports=function(I){if(typeof I=="number")return I;if(T(I))return NaN;if(d(I)){var B=typeof I.valueOf=="function"?I.valueOf():I;I=d(B)?B+"":B}if(typeof I!="string")return I===0?I:+I;I=_(I);var j=C.test(I);return j||S.test(I)?A(I.slice(2),j?2:8):y.test(I)?NaN:+I}},3678:(M,Y,g)=>{var _=g(8363),d=g(1704);M.exports=function(T){return _(T,d(T))}},9833:(M,Y,g)=>{var _=g(531);M.exports=function(d){return d==null?"":_(d)}},8718:(M,Y,g)=>{var _=g(7412),d=g(3118),T=g(7816),y=g(7206),C=g(5924),S=g(1469),A=g(4144),I=g(3560),B=g(3218),j=g(6719);M.exports=function(V,X,Q){var gt=S(V),tt=gt||A(V)||j(V);if(X=y(X,4),Q==null){var Lt=V&&V.constructor;Q=tt?gt?new Lt:[]:B(V)&&I(Lt)?d(C(V)):{}}return(tt?_:T)(V,function(it,vt,At){return X(Q,it,vt,At)}),Q}},3386:(M,Y,g)=>{var _=g(1078),d=g(5976),T=g(5652),y=g(9246),C=d(function(S){return T(_(S,1,y,!0))});M.exports=C},3955:(M,Y,g)=>{var _=g(9833),d=0;M.exports=function(T){var y=++d;return _(T)+y}},2628:(M,Y,g)=>{var _=g(7415),d=g(3674);M.exports=function(T){return T==null?[]:_(T,d(T))}},7287:(M,Y,g)=>{var _=g(4865),d=g(1757);M.exports=function(T,y){return d(T||[],y||[],_)}},9234:()=>{},1748:(M,Y,g)=>{var _={"./locale":9234,"./locale.js":9234};function d(y){var C=T(y);return g(C)}function T(y){if(!g.o(_,y)){var C=new Error("Cannot find module '"+y+"'");throw C.code="MODULE_NOT_FOUND",C}return _[y]}d.keys=function(){return Object.keys(_)},d.resolve=T,M.exports=d,d.id=1748},1941:function(M,Y,g){(M=g.nmd(M)).exports=function(){var _,d;function T(){return _.apply(null,arguments)}function y(k){return k instanceof Array||Object.prototype.toString.call(k)==="[object Array]"}function C(k){return k!=null&&Object.prototype.toString.call(k)==="[object Object]"}function S(k){return k===void 0}function A(k){return typeof k=="number"||Object.prototype.toString.call(k)==="[object Number]"}function I(k){return k instanceof Date||Object.prototype.toString.call(k)==="[object Date]"}function B(k,O){var W,ot=[];for(W=0;W>>0,ot=0;otAr(k)?(de=k+1,Be-Ar(k)):(de=k,Be),{year:de,dayOfYear:Ce}}function ln(k,O,W){var ot,Vt,de=_n(k.year(),O,W),Ce=Math.floor((k.dayOfYear()-de-1)/7)+1;return Ce<1?ot=Ce+Fn(Vt=k.year()-1,O,W):Ce>Fn(k.year(),O,W)?(ot=Ce-Fn(k.year(),O,W),Vt=k.year()+1):(Vt=k.year(),ot=Ce),{week:ot,year:Vt}}function Fn(k,O,W){var ot=_n(k,O,W),Vt=_n(k+1,O,W);return(Ar(k)-ot+Vt)/7}function bn(k,O){return k.slice(O,7).concat(k.slice(0,O))}ee("w",["ww",2],"wo","week"),ee("W",["WW",2],"Wo","isoWeek"),oe("week","w"),oe("isoWeek","W"),se("week",5),se("isoWeek",5),we("w",le),we("ww",le,mt),we("W",le),we("WW",le,mt),rn(["w","ww","W","WW"],function(k,O,W,ot){O[ot.substr(0,1)]=xt(k)}),ee("d",0,"do","day"),ee("dd",0,0,function(k){return this.localeData().weekdaysMin(this,k)}),ee("ddd",0,0,function(k){return this.localeData().weekdaysShort(this,k)}),ee("dddd",0,0,function(k){return this.localeData().weekdays(this,k)}),ee("e",0,0,"weekday"),ee("E",0,0,"isoWeekday"),oe("day","d"),oe("weekday","e"),oe("isoWeekday","E"),se("day",11),se("weekday",11),se("isoWeekday",11),we("d",le),we("e",le),we("E",le),we("dd",function(k,O){return O.weekdaysMinRegex(k)}),we("ddd",function(k,O){return O.weekdaysShortRegex(k)}),we("dddd",function(k,O){return O.weekdaysRegex(k)}),rn(["dd","ddd","dddd"],function(k,O,W,ot){var Vt=W._locale.weekdaysParse(k,ot,W._strict);Vt!=null?O.d=Vt:Q(W).invalidWeekday=k}),rn(["d","e","E"],function(k,O,W,ot){O[ot]=xt(k)});var Aa="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),vo="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),ji="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Rn=on,va=on,Ui=on;function Or(){function k(Je,Cn){return Cn.length-Je.length}var O,W,ot,Vt,de,Ce=[],Be=[],Ie=[],ze=[];for(O=0;O<7;O++)W=X([2e3,1]).day(O),ot=this.weekdaysMin(W,""),Vt=this.weekdaysShort(W,""),de=this.weekdays(W,""),Ce.push(ot),Be.push(Vt),Ie.push(de),ze.push(ot),ze.push(Vt),ze.push(de);for(Ce.sort(k),Be.sort(k),Ie.sort(k),ze.sort(k),O=0;O<7;O++)Be[O]=yn(Be[O]),Ie[O]=yn(Ie[O]),ze[O]=yn(ze[O]);this._weekdaysRegex=new RegExp("^("+ze.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+Ie.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+Be.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+Ce.join("|")+")","i")}function ti(){return this.hours()%12||12}function Xr(k,O){ee(k,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),O)})}function Zr(k,O){return O._meridiemParse}ee("H",["HH",2],0,"hour"),ee("h",["hh",2],0,ti),ee("k",["kk",2],0,function(){return this.hours()||24}),ee("hmm",0,0,function(){return""+ti.apply(this)+fe(this.minutes(),2)}),ee("hmmss",0,0,function(){return""+ti.apply(this)+fe(this.minutes(),2)+fe(this.seconds(),2)}),ee("Hmm",0,0,function(){return""+this.hours()+fe(this.minutes(),2)}),ee("Hmmss",0,0,function(){return""+this.hours()+fe(this.minutes(),2)+fe(this.seconds(),2)}),Xr("a",!0),Xr("A",!1),oe("hour","h"),se("hour",13),we("a",Zr),we("A",Zr),we("H",le),we("h",le),we("k",le),we("HH",le,mt),we("hh",le,mt),we("kk",le,mt),we("hmm",Rt),we("hmmss",gn),we("Hmm",Rt),we("Hmmss",gn),Qe(["H","HH"],3),Qe(["k","kk"],function(k,O,W){var ot=xt(k);O[3]=ot===24?0:ot}),Qe(["a","A"],function(k,O,W){W._isPm=W._locale.isPM(k),W._meridiem=k}),Qe(["h","hh"],function(k,O,W){O[3]=xt(k),Q(W).bigHour=!0}),Qe("hmm",function(k,O,W){var ot=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot)),Q(W).bigHour=!0}),Qe("hmmss",function(k,O,W){var ot=k.length-4,Vt=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot,2)),O[5]=xt(k.substr(Vt)),Q(W).bigHour=!0}),Qe("Hmm",function(k,O,W){var ot=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot))}),Qe("Hmmss",function(k,O,W){var ot=k.length-4,Vt=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot,2)),O[5]=xt(k.substr(Vt))});var Ur,hi=pn("Hours",!0),fi={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ln,monthsShort:jr,week:{dow:0,doy:6},weekdays:Aa,weekdaysMin:ji,weekdaysShort:vo,meridiemParse:/[ap]\.?m?\.?/i},cr={},zr={};function ei(k){return k&&k.toLowerCase().replace("_","-")}function Qr(k){var O=null;if(!cr[k]&&M&&M.exports)try{O=Ur._abbr,g(1748)("./"+k),Ci(O)}catch{}return cr[k]}function Ci(k,O){var W;return k&&((W=S(O)?Sr(k):Va(k,O))?Ur=W:typeof console<"u"&&console.warn&&console.warn("Locale "+k+" not found. Did you forget to load it?")),Ur._abbr}function Va(k,O){if(O===null)return delete cr[k],null;var W,ot=fi;if(O.abbr=k,cr[k]!=null)$("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),ot=cr[k]._config;else if(O.parentLocale!=null)if(cr[O.parentLocale]!=null)ot=cr[O.parentLocale]._config;else{if((W=Qr(O.parentLocale))==null)return zr[O.parentLocale]||(zr[O.parentLocale]=[]),zr[O.parentLocale].push({name:k,config:O}),null;ot=W._config}return cr[k]=new Jt(U(ot,O)),zr[k]&&zr[k].forEach(function(Vt){Va(Vt.name,Vt.config)}),Ci(k),cr[k]}function Sr(k){var O;if(k&&k._locale&&k._locale._abbr&&(k=k._locale._abbr),!k)return Ur;if(!y(k)){if(O=Qr(k))return O;k=[k]}return function(W){for(var ot,Vt,de,Ce,Be=0;Be=ot&&Yt(Ce,Vt,!0)>=ot-1)break;ot--}Be++}return Ur}(k)}function Ga(k){var O,W=k._a;return W&&Q(k).overflow===-2&&(O=W[1]<0||11mn(W[0],W[1])?2:W[3]<0||24Fn(Cn,yr,Fr)?Q(ze)._overflowWeeks=!0:xa!=null?Q(ze)._overflowWeekday=!0:(ur=Wn(Cn,wn,dr,yr,Fr),ze._a[0]=ur.year,ze._dayOfYear=ur.dayOfYear)}(k),k._dayOfYear!=null&&(de=Xa(k._a[0],ot[0]),(k._dayOfYear>Ar(de)||k._dayOfYear===0)&&(Q(k)._overflowDayOfYear=!0),W=Bn(de,0,k._dayOfYear),k._a[1]=W.getUTCMonth(),k._a[2]=W.getUTCDate()),O=0;O<3&&k._a[O]==null;++O)k._a[O]=Ce[O]=ot[O];for(;O<7;O++)k._a[O]=Ce[O]=k._a[O]==null?O===2?1:0:k._a[O];k._a[3]===24&&k._a[4]===0&&k._a[5]===0&&k._a[6]===0&&(k._nextDay=!0,k._a[3]=0),k._d=(k._useUTC?Bn:function(ze,Je,Cn,wn,dr,yr,Fr){var ur;return ze<100&&0<=ze?(ur=new Date(ze+400,Je,Cn,wn,dr,yr,Fr),isFinite(ur.getFullYear())&&ur.setFullYear(ze)):ur=new Date(ze,Je,Cn,wn,dr,yr,Fr),ur}).apply(null,Ce),Vt=k._useUTC?k._d.getUTCDay():k._d.getDay(),k._tzm!=null&&k._d.setUTCMinutes(k._d.getUTCMinutes()-k._tzm),k._nextDay&&(k._a[3]=24),k._w&&k._w.d!==void 0&&k._w.d!==Vt&&(Q(k).weekdayMismatch=!0)}}var fn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,On=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ke=/Z|[+-]\d\d(?::?\d\d)?/,Oe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],sr=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ut=/^\/?Date\((\-?\d+)/i;function Ma(k){var O,W,ot,Vt,de,Ce,Be=k._i,Ie=fn.exec(Be)||On.exec(Be);if(Ie){for(Q(k).iso=!0,O=0,W=Oe.length;OW.valueOf():W.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Ue.isLocal=function(){return!!this.isValid()&&!this._isUTC},Ue.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Ue.isUtc=oi,Ue.isUTC=oi,Ue.zoneAbbr=function(){return this._isUTC?"UTC":""},Ue.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Ue.dates=lt("dates accessor is deprecated. Use date instead.",Du),Ue.months=lt("months accessor is deprecated. Use month instead",Vn),Ue.years=lt("years accessor is deprecated. Use year instead",En),Ue.zone=lt("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(k,O){return k!=null?(typeof k!="string"&&(k=-k),this.utcOffset(k,O),this):-this.utcOffset()}),Ue.isDSTShifted=lt("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!S(this._isDSTShifted))return this._isDSTShifted;var k={};if(it(k,this),(k=rs(k))._a){var O=k._isUTC?X(k._a):jn(k._a);this._isDSTShifted=this.isValid()&&0{function Y(d){if(typeof d!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(d))}function g(d,T){for(var y,C="",S=0,A=-1,I=0,B=0;B<=d.length;++B){if(B2){var j=C.lastIndexOf("/");if(j!==C.length-1){j===-1?(C="",S=0):S=(C=C.slice(0,j)).length-1-C.lastIndexOf("/"),A=B,I=0;continue}}else if(C.length===2||C.length===1){C="",S=0,A=B,I=0;continue}}T&&(C.length>0?C+="/..":C="..",S=2)}else C.length>0?C+="/"+d.slice(A+1,B):C=d.slice(A+1,B),S=B-A-1;A=B,I=0}else y===46&&I!==-1?++I:I=-1}return C}var _={resolve:function(){for(var d,T="",y=!1,C=arguments.length-1;C>=-1&&!y;C--){var S;C>=0?S=arguments[C]:(d===void 0&&(d=process.cwd()),S=d),Y(S),S.length!==0&&(T=S+"/"+T,y=S.charCodeAt(0)===47)}return T=g(T,!y),y?T.length>0?"/"+T:"/":T.length>0?T:"."},normalize:function(d){if(Y(d),d.length===0)return".";var T=d.charCodeAt(0)===47,y=d.charCodeAt(d.length-1)===47;return(d=g(d,!T)).length!==0||T||(d="."),d.length>0&&y&&(d+="/"),T?"/"+d:d},isAbsolute:function(d){return Y(d),d.length>0&&d.charCodeAt(0)===47},join:function(){if(arguments.length===0)return".";for(var d,T=0;T0&&(d===void 0?d=y:d+="/"+y)}return d===void 0?".":_.normalize(d)},relative:function(d,T){if(Y(d),Y(T),d===T||(d=_.resolve(d))===(T=_.resolve(T)))return"";for(var y=1;yB){if(T.charCodeAt(A+V)===47)return T.slice(A+V+1);if(V===0)return T.slice(A+V)}else S>B&&(d.charCodeAt(y+V)===47?j=V:V===0&&(j=0));break}var X=d.charCodeAt(y+V);if(X!==T.charCodeAt(A+V))break;X===47&&(j=V)}var Q="";for(V=y+j+1;V<=C;++V)V!==C&&d.charCodeAt(V)!==47||(Q.length===0?Q+="..":Q+="/..");return Q.length>0?Q+T.slice(A+j):(A+=j,T.charCodeAt(A)===47&&++A,T.slice(A))},_makeLong:function(d){return d},dirname:function(d){if(Y(d),d.length===0)return".";for(var T=d.charCodeAt(0),y=T===47,C=-1,S=!0,A=d.length-1;A>=1;--A)if((T=d.charCodeAt(A))===47){if(!S){C=A;break}}else S=!1;return C===-1?y?"/":".":y&&C===1?"//":d.slice(0,C)},basename:function(d,T){if(T!==void 0&&typeof T!="string")throw new TypeError('"ext" argument must be a string');Y(d);var y,C=0,S=-1,A=!0;if(T!==void 0&&T.length>0&&T.length<=d.length){if(T.length===d.length&&T===d)return"";var I=T.length-1,B=-1;for(y=d.length-1;y>=0;--y){var j=d.charCodeAt(y);if(j===47){if(!A){C=y+1;break}}else B===-1&&(A=!1,B=y+1),I>=0&&(j===T.charCodeAt(I)?--I==-1&&(S=y):(I=-1,S=B))}return C===S?S=B:S===-1&&(S=d.length),d.slice(C,S)}for(y=d.length-1;y>=0;--y)if(d.charCodeAt(y)===47){if(!A){C=y+1;break}}else S===-1&&(A=!1,S=y+1);return S===-1?"":d.slice(C,S)},extname:function(d){Y(d);for(var T=-1,y=0,C=-1,S=!0,A=0,I=d.length-1;I>=0;--I){var B=d.charCodeAt(I);if(B!==47)C===-1&&(S=!1,C=I+1),B===46?T===-1?T=I:A!==1&&(A=1):T!==-1&&(A=-1);else if(!S){y=I+1;break}}return T===-1||C===-1||A===0||A===1&&T===C-1&&T===y+1?"":d.slice(T,C)},format:function(d){if(d===null||typeof d!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof d);return function(T,y){var C=y.dir||y.root,S=y.base||(y.name||"")+(y.ext||"");return C?C===y.root?C+S:C+"/"+S:S}(0,d)},parse:function(d){Y(d);var T={root:"",dir:"",base:"",ext:"",name:""};if(d.length===0)return T;var y,C=d.charCodeAt(0),S=C===47;S?(T.root="/",y=1):y=0;for(var A=-1,I=0,B=-1,j=!0,V=d.length-1,X=0;V>=y;--V)if((C=d.charCodeAt(V))!==47)B===-1&&(j=!1,B=V+1),C===46?A===-1?A=V:X!==1&&(X=1):A!==-1&&(X=-1);else if(!j){I=V+1;break}return A===-1||B===-1||X===0||X===1&&A===B-1&&A===I+1?B!==-1&&(T.base=T.name=I===0&&S?d.slice(1,B):d.slice(I,B)):(I===0&&S?(T.name=d.slice(1,A),T.base=d.slice(1,B)):(T.name=d.slice(I,A),T.base=d.slice(I,B)),T.ext=d.slice(A,B)),I>0?T.dir=d.slice(0,I-1):S&&(T.dir="/"),T},sep:"/",delimiter:":",win32:null,posix:null};_.posix=_,M.exports=_},8218:()=>{},8009:()=>{},5354:()=>{},6878:()=>{},8183:()=>{},1428:()=>{},4551:()=>{},8800:()=>{},1993:()=>{},3069:()=>{},9143:()=>{}},G6={};function ts(M){var Y=G6[M];if(Y!==void 0)return Y.exports;var g=G6[M]={id:M,loaded:!1,exports:{}};return rx[M].call(g.exports,g,g.exports,ts),g.loaded=!0,g.exports}ts.c=G6,ts.n=M=>{var Y=M&&M.__esModule?()=>M.default:()=>M;return ts.d(Y,{a:Y}),Y},ts.d=(M,Y)=>{for(var g in Y)ts.o(Y,g)&&!ts.o(M,g)&&Object.defineProperty(M,g,{enumerable:!0,get:Y[g]})},ts.g=function(){if(typeof globalThis=="object")return globalThis;try{return this||new Function("return this")()}catch{if(typeof window=="object")return window}}(),ts.o=(M,Y)=>Object.prototype.hasOwnProperty.call(M,Y),ts.r=M=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(M,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(M,"__esModule",{value:!0})},ts.nmd=M=>(M.paths=[],M.children||(M.children=[]),M);var v_=ts(ts.s=8968).Z;const b_="mindmap",ix=M=>M.match(/^\s*mindmap/)!==null,ax=async()=>{const{diagram:M}=await F_(async()=>{const{diagram:Y}=await import("./chunks/diagram-definition.ae1f7a29.BteD-_ze.js");return{diagram:Y}},__vite__mapDeps([0,1,2]));return{id:b_,diagram:M}},ox={id:b_,detector:ix,loader:ax};(async()=>{try{v_.registerExternalDiagrams&&await v_.registerExternalDiagrams([ox])}catch(M){console.error(M)}})();function __(M){if(M.extends){const Y=__(M.extends);return{...Y,...M,async enhanceApp(g){Y.enhanceApp&&await Y.enhanceApp(g),M.enhanceApp&&await M.enhanceApp(g)}}}return M}const Qd=__(nx),sx=G_({name:"VitePressApp",setup(){const{site:M,lang:Y,dir:g}=X_();return Z_(()=>{Q_(()=>{document.documentElement.lang=Y.value,document.documentElement.dir=g.value})}),M.value.router.prefetchLinks&&K_(),J_(),tx(),Qd.setup&&Qd.setup(),()=>ex(Qd.Layout)}});async function cx(){const M=lx(),Y=ux();Y.provide(Y_,M);const g=j_(M.route);return Y.provide(U_,g),Y.component("Content",z_),Y.component("ClientOnly",$_),Object.defineProperties(Y.config.globalProperties,{$frontmatter:{get(){return g.frontmatter.value}},$params:{get(){return g.page.value.params}}}),Qd.enhanceApp&&await Qd.enhanceApp({app:Y,router:M,siteData:q_}),{app:Y,router:M,data:g}}function ux(){return H_(sx)}function lx(){let M=V6,Y;return W_(g=>{let _=V_(g),d=null;return _&&(M&&(Y=_),(M||Y===_)&&(_=_.replace(/\.js$/,".lean.js")),d=import(_)),V6&&(M=!1),d},Qd.NotFound)}V6&&cx().then(({app:M,router:Y,data:g})=>{Y.go().then(()=>{P_(Y.route,g.site),M.mount("#app")})});export{cx as createApp}; +`+new Error().stack),W=!1}return O.apply(this,arguments)},O)}var et,st={};function $(k,O){T.deprecationHandler!=null&&T.deprecationHandler(k,O),st[k]||(Bt(O),st[k]=!0)}function Dt(k){return k instanceof Function||Object.prototype.toString.call(k)==="[object Function]"}function U(k,O){var W,ot=V({},k);for(W in O)j(O,W)&&(C(k[W])&&C(O[W])?(ot[W]={},V(ot[W],k[W]),V(ot[W],O[W])):O[W]!=null?ot[W]=O[W]:delete ot[W]);for(W in k)j(k,W)&&!j(O,W)&&C(k[W])&&(ot[W]=V({},ot[W]));return ot}function Jt(k){k!=null&&this.set(k)}T.suppressDeprecationWarnings=!1,T.deprecationHandler=null,et=Object.keys?Object.keys:function(k){var O,W=[];for(O in k)j(k,O)&&W.push(O);return W};var _t={};function oe(k,O){var W=k.toLowerCase();_t[W]=_t[W+"s"]=_t[O]=k}function Se(k){return typeof k=="string"?_t[k]||_t[k.toLowerCase()]:void 0}function Fe(k){var O,W,ot={};for(W in k)j(k,W)&&(O=Se(W))&&(ot[O]=k[W]);return ot}var he={};function se(k,O){he[k]=O}function fe(k,O,W){var ot=""+Math.abs(k),Vt=O-ot.length;return(0<=k?W?"+":"":"-")+Math.pow(10,Math.max(0,Vt)).toString().substr(1)+ot}var _e=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,De=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,pe={},Me={};function ee(k,O,W,ot){var Vt=ot;typeof ot=="string"&&(Vt=function(){return this[ot]()}),k&&(Me[k]=Vt),O&&(Me[O[0]]=function(){return fe(Vt.apply(this,arguments),O[1],O[2])}),W&&(Me[W]=function(){return this.localeData().ordinal(Vt.apply(this,arguments),k)})}function xe(k,O){return k.isValid()?(O=wt(O,k.localeData()),pe[O]=pe[O]||function(W){var ot,Vt,de,Ce=W.match(_e);for(ot=0,Vt=Ce.length;otAr(k)?(de=k+1,Be-Ar(k)):(de=k,Be),{year:de,dayOfYear:Ce}}function ln(k,O,W){var ot,Vt,de=_n(k.year(),O,W),Ce=Math.floor((k.dayOfYear()-de-1)/7)+1;return Ce<1?ot=Ce+Fn(Vt=k.year()-1,O,W):Ce>Fn(k.year(),O,W)?(ot=Ce-Fn(k.year(),O,W),Vt=k.year()+1):(Vt=k.year(),ot=Ce),{week:ot,year:Vt}}function Fn(k,O,W){var ot=_n(k,O,W),Vt=_n(k+1,O,W);return(Ar(k)-ot+Vt)/7}function bn(k,O){return k.slice(O,7).concat(k.slice(0,O))}ee("w",["ww",2],"wo","week"),ee("W",["WW",2],"Wo","isoWeek"),oe("week","w"),oe("isoWeek","W"),se("week",5),se("isoWeek",5),we("w",le),we("ww",le,mt),we("W",le),we("WW",le,mt),rn(["w","ww","W","WW"],function(k,O,W,ot){O[ot.substr(0,1)]=xt(k)}),ee("d",0,"do","day"),ee("dd",0,0,function(k){return this.localeData().weekdaysMin(this,k)}),ee("ddd",0,0,function(k){return this.localeData().weekdaysShort(this,k)}),ee("dddd",0,0,function(k){return this.localeData().weekdays(this,k)}),ee("e",0,0,"weekday"),ee("E",0,0,"isoWeekday"),oe("day","d"),oe("weekday","e"),oe("isoWeekday","E"),se("day",11),se("weekday",11),se("isoWeekday",11),we("d",le),we("e",le),we("E",le),we("dd",function(k,O){return O.weekdaysMinRegex(k)}),we("ddd",function(k,O){return O.weekdaysShortRegex(k)}),we("dddd",function(k,O){return O.weekdaysRegex(k)}),rn(["dd","ddd","dddd"],function(k,O,W,ot){var Vt=W._locale.weekdaysParse(k,ot,W._strict);Vt!=null?O.d=Vt:Q(W).invalidWeekday=k}),rn(["d","e","E"],function(k,O,W,ot){O[ot]=xt(k)});var Aa="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),vo="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),ji="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Rn=on,va=on,Ui=on;function Or(){function k(Je,Cn){return Cn.length-Je.length}var O,W,ot,Vt,de,Ce=[],Be=[],Ie=[],ze=[];for(O=0;O<7;O++)W=X([2e3,1]).day(O),ot=this.weekdaysMin(W,""),Vt=this.weekdaysShort(W,""),de=this.weekdays(W,""),Ce.push(ot),Be.push(Vt),Ie.push(de),ze.push(ot),ze.push(Vt),ze.push(de);for(Ce.sort(k),Be.sort(k),Ie.sort(k),ze.sort(k),O=0;O<7;O++)Be[O]=yn(Be[O]),Ie[O]=yn(Ie[O]),ze[O]=yn(ze[O]);this._weekdaysRegex=new RegExp("^("+ze.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+Ie.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+Be.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+Ce.join("|")+")","i")}function ti(){return this.hours()%12||12}function Xr(k,O){ee(k,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),O)})}function Zr(k,O){return O._meridiemParse}ee("H",["HH",2],0,"hour"),ee("h",["hh",2],0,ti),ee("k",["kk",2],0,function(){return this.hours()||24}),ee("hmm",0,0,function(){return""+ti.apply(this)+fe(this.minutes(),2)}),ee("hmmss",0,0,function(){return""+ti.apply(this)+fe(this.minutes(),2)+fe(this.seconds(),2)}),ee("Hmm",0,0,function(){return""+this.hours()+fe(this.minutes(),2)}),ee("Hmmss",0,0,function(){return""+this.hours()+fe(this.minutes(),2)+fe(this.seconds(),2)}),Xr("a",!0),Xr("A",!1),oe("hour","h"),se("hour",13),we("a",Zr),we("A",Zr),we("H",le),we("h",le),we("k",le),we("HH",le,mt),we("hh",le,mt),we("kk",le,mt),we("hmm",Rt),we("hmmss",gn),we("Hmm",Rt),we("Hmmss",gn),Qe(["H","HH"],3),Qe(["k","kk"],function(k,O,W){var ot=xt(k);O[3]=ot===24?0:ot}),Qe(["a","A"],function(k,O,W){W._isPm=W._locale.isPM(k),W._meridiem=k}),Qe(["h","hh"],function(k,O,W){O[3]=xt(k),Q(W).bigHour=!0}),Qe("hmm",function(k,O,W){var ot=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot)),Q(W).bigHour=!0}),Qe("hmmss",function(k,O,W){var ot=k.length-4,Vt=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot,2)),O[5]=xt(k.substr(Vt)),Q(W).bigHour=!0}),Qe("Hmm",function(k,O,W){var ot=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot))}),Qe("Hmmss",function(k,O,W){var ot=k.length-4,Vt=k.length-2;O[3]=xt(k.substr(0,ot)),O[4]=xt(k.substr(ot,2)),O[5]=xt(k.substr(Vt))});var Ur,hi=pn("Hours",!0),fi={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ln,monthsShort:jr,week:{dow:0,doy:6},weekdays:Aa,weekdaysMin:ji,weekdaysShort:vo,meridiemParse:/[ap]\.?m?\.?/i},cr={},zr={};function ei(k){return k&&k.toLowerCase().replace("_","-")}function Qr(k){var O=null;if(!cr[k]&&M&&M.exports)try{O=Ur._abbr,g(1748)("./"+k),Ci(O)}catch{}return cr[k]}function Ci(k,O){var W;return k&&((W=S(O)?Sr(k):Va(k,O))?Ur=W:typeof console<"u"&&console.warn&&console.warn("Locale "+k+" not found. Did you forget to load it?")),Ur._abbr}function Va(k,O){if(O===null)return delete cr[k],null;var W,ot=fi;if(O.abbr=k,cr[k]!=null)$("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),ot=cr[k]._config;else if(O.parentLocale!=null)if(cr[O.parentLocale]!=null)ot=cr[O.parentLocale]._config;else{if((W=Qr(O.parentLocale))==null)return zr[O.parentLocale]||(zr[O.parentLocale]=[]),zr[O.parentLocale].push({name:k,config:O}),null;ot=W._config}return cr[k]=new Jt(U(ot,O)),zr[k]&&zr[k].forEach(function(Vt){Va(Vt.name,Vt.config)}),Ci(k),cr[k]}function Sr(k){var O;if(k&&k._locale&&k._locale._abbr&&(k=k._locale._abbr),!k)return Ur;if(!y(k)){if(O=Qr(k))return O;k=[k]}return function(W){for(var ot,Vt,de,Ce,Be=0;Be=ot&&Yt(Ce,Vt,!0)>=ot-1)break;ot--}Be++}return Ur}(k)}function Ga(k){var O,W=k._a;return W&&Q(k).overflow===-2&&(O=W[1]<0||11mn(W[0],W[1])?2:W[3]<0||24Fn(Cn,yr,Fr)?Q(ze)._overflowWeeks=!0:xa!=null?Q(ze)._overflowWeekday=!0:(ur=Wn(Cn,wn,dr,yr,Fr),ze._a[0]=ur.year,ze._dayOfYear=ur.dayOfYear)}(k),k._dayOfYear!=null&&(de=Xa(k._a[0],ot[0]),(k._dayOfYear>Ar(de)||k._dayOfYear===0)&&(Q(k)._overflowDayOfYear=!0),W=Bn(de,0,k._dayOfYear),k._a[1]=W.getUTCMonth(),k._a[2]=W.getUTCDate()),O=0;O<3&&k._a[O]==null;++O)k._a[O]=Ce[O]=ot[O];for(;O<7;O++)k._a[O]=Ce[O]=k._a[O]==null?O===2?1:0:k._a[O];k._a[3]===24&&k._a[4]===0&&k._a[5]===0&&k._a[6]===0&&(k._nextDay=!0,k._a[3]=0),k._d=(k._useUTC?Bn:function(ze,Je,Cn,wn,dr,yr,Fr){var ur;return ze<100&&0<=ze?(ur=new Date(ze+400,Je,Cn,wn,dr,yr,Fr),isFinite(ur.getFullYear())&&ur.setFullYear(ze)):ur=new Date(ze,Je,Cn,wn,dr,yr,Fr),ur}).apply(null,Ce),Vt=k._useUTC?k._d.getUTCDay():k._d.getDay(),k._tzm!=null&&k._d.setUTCMinutes(k._d.getUTCMinutes()-k._tzm),k._nextDay&&(k._a[3]=24),k._w&&k._w.d!==void 0&&k._w.d!==Vt&&(Q(k).weekdayMismatch=!0)}}var fn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,On=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,ke=/Z|[+-]\d\d(?::?\d\d)?/,Oe=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],sr=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ut=/^\/?Date\((\-?\d+)/i;function Ma(k){var O,W,ot,Vt,de,Ce,Be=k._i,Ie=fn.exec(Be)||On.exec(Be);if(Ie){for(Q(k).iso=!0,O=0,W=Oe.length;OW.valueOf():W.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Ue.isLocal=function(){return!!this.isValid()&&!this._isUTC},Ue.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Ue.isUtc=oi,Ue.isUTC=oi,Ue.zoneAbbr=function(){return this._isUTC?"UTC":""},Ue.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Ue.dates=lt("dates accessor is deprecated. Use date instead.",Du),Ue.months=lt("months accessor is deprecated. Use month instead",Vn),Ue.years=lt("years accessor is deprecated. Use year instead",En),Ue.zone=lt("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(k,O){return k!=null?(typeof k!="string"&&(k=-k),this.utcOffset(k,O),this):-this.utcOffset()}),Ue.isDSTShifted=lt("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!S(this._isDSTShifted))return this._isDSTShifted;var k={};if(it(k,this),(k=rs(k))._a){var O=k._isUTC?X(k._a):jn(k._a);this._isDSTShifted=this.isValid()&&0{function Y(d){if(typeof d!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(d))}function g(d,T){for(var y,C="",S=0,A=-1,I=0,B=0;B<=d.length;++B){if(B2){var j=C.lastIndexOf("/");if(j!==C.length-1){j===-1?(C="",S=0):S=(C=C.slice(0,j)).length-1-C.lastIndexOf("/"),A=B,I=0;continue}}else if(C.length===2||C.length===1){C="",S=0,A=B,I=0;continue}}T&&(C.length>0?C+="/..":C="..",S=2)}else C.length>0?C+="/"+d.slice(A+1,B):C=d.slice(A+1,B),S=B-A-1;A=B,I=0}else y===46&&I!==-1?++I:I=-1}return C}var _={resolve:function(){for(var d,T="",y=!1,C=arguments.length-1;C>=-1&&!y;C--){var S;C>=0?S=arguments[C]:(d===void 0&&(d=process.cwd()),S=d),Y(S),S.length!==0&&(T=S+"/"+T,y=S.charCodeAt(0)===47)}return T=g(T,!y),y?T.length>0?"/"+T:"/":T.length>0?T:"."},normalize:function(d){if(Y(d),d.length===0)return".";var T=d.charCodeAt(0)===47,y=d.charCodeAt(d.length-1)===47;return(d=g(d,!T)).length!==0||T||(d="."),d.length>0&&y&&(d+="/"),T?"/"+d:d},isAbsolute:function(d){return Y(d),d.length>0&&d.charCodeAt(0)===47},join:function(){if(arguments.length===0)return".";for(var d,T=0;T0&&(d===void 0?d=y:d+="/"+y)}return d===void 0?".":_.normalize(d)},relative:function(d,T){if(Y(d),Y(T),d===T||(d=_.resolve(d))===(T=_.resolve(T)))return"";for(var y=1;yB){if(T.charCodeAt(A+V)===47)return T.slice(A+V+1);if(V===0)return T.slice(A+V)}else S>B&&(d.charCodeAt(y+V)===47?j=V:V===0&&(j=0));break}var X=d.charCodeAt(y+V);if(X!==T.charCodeAt(A+V))break;X===47&&(j=V)}var Q="";for(V=y+j+1;V<=C;++V)V!==C&&d.charCodeAt(V)!==47||(Q.length===0?Q+="..":Q+="/..");return Q.length>0?Q+T.slice(A+j):(A+=j,T.charCodeAt(A)===47&&++A,T.slice(A))},_makeLong:function(d){return d},dirname:function(d){if(Y(d),d.length===0)return".";for(var T=d.charCodeAt(0),y=T===47,C=-1,S=!0,A=d.length-1;A>=1;--A)if((T=d.charCodeAt(A))===47){if(!S){C=A;break}}else S=!1;return C===-1?y?"/":".":y&&C===1?"//":d.slice(0,C)},basename:function(d,T){if(T!==void 0&&typeof T!="string")throw new TypeError('"ext" argument must be a string');Y(d);var y,C=0,S=-1,A=!0;if(T!==void 0&&T.length>0&&T.length<=d.length){if(T.length===d.length&&T===d)return"";var I=T.length-1,B=-1;for(y=d.length-1;y>=0;--y){var j=d.charCodeAt(y);if(j===47){if(!A){C=y+1;break}}else B===-1&&(A=!1,B=y+1),I>=0&&(j===T.charCodeAt(I)?--I==-1&&(S=y):(I=-1,S=B))}return C===S?S=B:S===-1&&(S=d.length),d.slice(C,S)}for(y=d.length-1;y>=0;--y)if(d.charCodeAt(y)===47){if(!A){C=y+1;break}}else S===-1&&(A=!1,S=y+1);return S===-1?"":d.slice(C,S)},extname:function(d){Y(d);for(var T=-1,y=0,C=-1,S=!0,A=0,I=d.length-1;I>=0;--I){var B=d.charCodeAt(I);if(B!==47)C===-1&&(S=!1,C=I+1),B===46?T===-1?T=I:A!==1&&(A=1):T!==-1&&(A=-1);else if(!S){y=I+1;break}}return T===-1||C===-1||A===0||A===1&&T===C-1&&T===y+1?"":d.slice(T,C)},format:function(d){if(d===null||typeof d!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof d);return function(T,y){var C=y.dir||y.root,S=y.base||(y.name||"")+(y.ext||"");return C?C===y.root?C+S:C+"/"+S:S}(0,d)},parse:function(d){Y(d);var T={root:"",dir:"",base:"",ext:"",name:""};if(d.length===0)return T;var y,C=d.charCodeAt(0),S=C===47;S?(T.root="/",y=1):y=0;for(var A=-1,I=0,B=-1,j=!0,V=d.length-1,X=0;V>=y;--V)if((C=d.charCodeAt(V))!==47)B===-1&&(j=!1,B=V+1),C===46?A===-1?A=V:X!==1&&(X=1):A!==-1&&(X=-1);else if(!j){I=V+1;break}return A===-1||B===-1||X===0||X===1&&A===B-1&&A===I+1?B!==-1&&(T.base=T.name=I===0&&S?d.slice(1,B):d.slice(I,B)):(I===0&&S?(T.name=d.slice(1,A),T.base=d.slice(1,B)):(T.name=d.slice(I,A),T.base=d.slice(I,B)),T.ext=d.slice(A,B)),I>0?T.dir=d.slice(0,I-1):S&&(T.dir="/"),T},sep:"/",delimiter:":",win32:null,posix:null};_.posix=_,M.exports=_},8218:()=>{},8009:()=>{},5354:()=>{},6878:()=>{},8183:()=>{},1428:()=>{},4551:()=>{},8800:()=>{},1993:()=>{},3069:()=>{},9143:()=>{}},G6={};function ts(M){var Y=G6[M];if(Y!==void 0)return Y.exports;var g=G6[M]={id:M,loaded:!1,exports:{}};return rx[M].call(g.exports,g,g.exports,ts),g.loaded=!0,g.exports}ts.c=G6,ts.n=M=>{var Y=M&&M.__esModule?()=>M.default:()=>M;return ts.d(Y,{a:Y}),Y},ts.d=(M,Y)=>{for(var g in Y)ts.o(Y,g)&&!ts.o(M,g)&&Object.defineProperty(M,g,{enumerable:!0,get:Y[g]})},ts.g=function(){if(typeof globalThis=="object")return globalThis;try{return this||new Function("return this")()}catch{if(typeof window=="object")return window}}(),ts.o=(M,Y)=>Object.prototype.hasOwnProperty.call(M,Y),ts.r=M=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(M,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(M,"__esModule",{value:!0})},ts.nmd=M=>(M.paths=[],M.children||(M.children=[]),M);var v_=ts(ts.s=8968).Z;const b_="mindmap",ix=M=>M.match(/^\s*mindmap/)!==null,ax=async()=>{const{diagram:M}=await F_(async()=>{const{diagram:Y}=await import("./chunks/diagram-definition.ae1f7a29.Cn2DCAkm.js");return{diagram:Y}},__vite__mapDeps([0,1,2]));return{id:b_,diagram:M}},ox={id:b_,detector:ix,loader:ax};(async()=>{try{v_.registerExternalDiagrams&&await v_.registerExternalDiagrams([ox])}catch(M){console.error(M)}})();function __(M){if(M.extends){const Y=__(M.extends);return{...Y,...M,async enhanceApp(g){Y.enhanceApp&&await Y.enhanceApp(g),M.enhanceApp&&await M.enhanceApp(g)}}}return M}const Qd=__(nx),sx=G_({name:"VitePressApp",setup(){const{site:M,lang:Y,dir:g}=X_();return Z_(()=>{Q_(()=>{document.documentElement.lang=Y.value,document.documentElement.dir=g.value})}),M.value.router.prefetchLinks&&K_(),J_(),tx(),Qd.setup&&Qd.setup(),()=>ex(Qd.Layout)}});async function cx(){const M=lx(),Y=ux();Y.provide(Y_,M);const g=j_(M.route);return Y.provide(U_,g),Y.component("Content",z_),Y.component("ClientOnly",$_),Object.defineProperties(Y.config.globalProperties,{$frontmatter:{get(){return g.frontmatter.value}},$params:{get(){return g.page.value.params}}}),Qd.enhanceApp&&await Qd.enhanceApp({app:Y,router:M,siteData:q_}),{app:Y,router:M,data:g}}function ux(){return H_(sx)}function lx(){let M=V6,Y;return W_(g=>{let _=V_(g),d=null;return _&&(M&&(Y=_),(M||Y===_)&&(_=_.replace(/\.js$/,".lean.js")),d=import(_)),V6&&(M=!1),d},Qd.NotFound)}V6&&cx().then(({app:M,router:Y,data:g})=>{Y.go().then(()=>{P_(Y.route,g.site),M.mount("#app")})});export{cx as createApp}; diff --git a/assets/chunks/@localSearchIndexroot.CQo7c1MN.js b/assets/chunks/@localSearchIndexroot.CQo7c1MN.js deleted file mode 100644 index 1a556eab..00000000 --- a/assets/chunks/@localSearchIndexroot.CQo7c1MN.js +++ /dev/null @@ -1 +0,0 @@ -const t='{"documentCount":304,"nextId":304,"documentIds":{"0":"/youqu/CONTRIBUTING.html#贡献-并且帮助我们改进","1":"/youqu/CONTRIBUTING.html#帮助改进-youqu-文档","2":"/youqu/CONTRIBUTING.html#向-youqu-提交-issues","3":"/youqu/CONTRIBUTING.html#向-youqu-仓库提交代码","4":"/youqu/RELEASE.html#版本更新记录","5":"/youqu/RELEASE.html#_2-6-8-2024-07-15","6":"/youqu/RELEASE.html#_2-6-7-2024-07-15","7":"/youqu/RELEASE.html#_2-6-6-2024-07-05","8":"/youqu/RELEASE.html#_2-6-5-2024-06-11","9":"/youqu/RELEASE.html#_2-6-4-2024-06-07","10":"/youqu/RELEASE.html#_2-6-3-2024-06-07","11":"/youqu/RELEASE.html#_2-6-2-2024-05-29","12":"/youqu/RELEASE.html#_2-6-1-2024-05-21","13":"/youqu/RELEASE.html#_2-6-0-2024-05-14","14":"/youqu/RELEASE.html#_2-5-5-2024-05-10","15":"/youqu/RELEASE.html#_2-5-4-2024-05-08","16":"/youqu/RELEASE.html#_2-5-3-2024-04-24","17":"/youqu/RELEASE.html#_2-5-2-2024-03-27","18":"/youqu/RELEASE.html#_2-5-1-2024-03-14","19":"/youqu/RELEASE.html#_2-5-0-2024-03-04","20":"/youqu/RELEASE.html#_2-4-6-2024-02-26","21":"/youqu/RELEASE.html#_2-4-5-2024-01-20","22":"/youqu/RELEASE.html#_2-4-4-2024-01-19","23":"/youqu/RELEASE.html#_2-4-2-2023-12-27","24":"/youqu/RELEASE.html#_2-4-1-2023-12-26","25":"/youqu/RELEASE.html#_2-4-0-2023-12-22","26":"/youqu/RELEASE.html#_2-3-7-2023-12-15","27":"/youqu/RELEASE.html#_2-3-6-2023-12-13","28":"/youqu/RELEASE.html#_2-3-5-2023-12-04","29":"/youqu/RELEASE.html#_2-3-4-2023-12-04","30":"/youqu/RELEASE.html#_2-3-3-2023-11-22","31":"/youqu/RELEASE.html#_2-3-2-2023-11-14","32":"/youqu/RELEASE.html#_2-3-1-2023-11-08","33":"/youqu/RELEASE.html#_2-3-0-2023-10-27","34":"/youqu/RELEASE.html#_2-2-4-2023-10-16","35":"/youqu/RELEASE.html#_2-2-3-2023-09-15","36":"/youqu/RELEASE.html#_2-2-1-2023-09-13","37":"/youqu/RELEASE.html#_2-2-0-2023-09-05","38":"/youqu/RELEASE.html#_2-1-5-2023-08-31","39":"/youqu/RELEASE.html#_2-1-2-2023-08-22","40":"/youqu/RELEASE.html#_2-1-0-2023-08-18","41":"/youqu/RELEASE.html#_2-0-0-2023-08-16","42":"/youqu/RELEASE.html#_1-3-0-2023-07-10","43":"/youqu/RELEASE.html#_1-2-9-2023-06-26","44":"/youqu/RELEASE.html#_1-2-8-2023-06-09","45":"/youqu/RELEASE.html#_1-2-7-2023-06-08","46":"/youqu/RELEASE.html#_1-2-6-2023-06-07","47":"/youqu/RELEASE.html#_1-2-5-2023-05-16","48":"/youqu/RELEASE.html#_1-2-4-2023-02-27","49":"/youqu/RELEASE.html#_1-2-3-2023-02-27","50":"/youqu/RELEASE.html#_1-2-2-2023-02-08","51":"/youqu/RELEASE.html#_1-2-1-2023-01-06","52":"/youqu/RELEASE.html#_1-2-0-2022-12-30","53":"/youqu/RELEASE.html#_1-1-4-2022-12-14","54":"/youqu/RELEASE.html#_1-1-3-2022-10-28","55":"/youqu/RELEASE.html#_1-1-2-2022-09-21","56":"/youqu/RELEASE.html#_1-1-1-2022-09-19","57":"/youqu/RELEASE.html#_1-1-0-2022-09-16","58":"/youqu/RELEASE.html#_1-0-2-2022-08-22","59":"/youqu/RELEASE.html#_1-0-1-2022-08-12","60":"/youqu/SIG.html#youqu-官方兴趣小组","61":"/youqu/实践/DBus接口自动化测试/创建APP工程.html#创建一个-app-工程","62":"/youqu/实践/DBus接口自动化测试/创建APP工程.html#编辑器打开","63":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#创建一条完整的用例","64":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#封装用例步骤的方法","65":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#编写用例","66":"/youqu/实践/DBus接口自动化测试/初始化项目.html#linux-dbus-接口自动化测试","67":"/youqu/实践/DBus接口自动化测试/初始化项目.html#安装","68":"/youqu/实践/DBus接口自动化测试/初始化项目.html#创建一个项目","69":"/youqu/实践/DBus接口自动化测试/初始化项目.html#部署环境","70":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#创建一个-app-工程","71":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#修改","72":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#再次执行-env-sh","73":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#创建一条完整的用例","74":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#封装用例步骤的方法","75":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#编写用例","76":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#http-接口自动化测试","77":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#安装","78":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#创建一个项目","79":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#部署环境","80":"/youqu/实践/Linux桌面UI自动化测试/创建APP工程.html#创建一个-app-工程","81":"/youqu/实践/Linux桌面UI自动化测试/创建APP工程.html#编辑器打开","82":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#创建一条完整的用例","83":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#用例步骤","84":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#封装用例步骤的方法","85":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#编写用例","86":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#linux-桌面-ui-自动化测试","87":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#安装","88":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#创建一个项目","89":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#部署环境","90":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#远程交互式控制","91":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#逻辑示意图","92":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#标识文件","93":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#方法编写","94":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#用例编写","95":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#创建一条完整的用例","96":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#用例步骤","97":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#封装用例步骤的方法","98":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#编写用例","99":"/youqu/实践/WebUI自动化测试/创建APP工程.html#创建一个-app-工程","100":"/youqu/实践/WebUI自动化测试/创建APP工程.html#修改","101":"/youqu/实践/WebUI自动化测试/创建APP工程.html#再次执行-env-sh","102":"/youqu/实践/WebUI自动化测试/创建APP工程.html#编辑器打开","103":"/youqu/实践/WebUI自动化测试/初始化项目.html#web-ui-自动化测试","104":"/youqu/实践/WebUI自动化测试/初始化项目.html#安装","105":"/youqu/实践/WebUI自动化测试/初始化项目.html#创建一个项目","106":"/youqu/实践/WebUI自动化测试/初始化项目.html#部署环境","107":"/youqu/实践/命令行自动化测试/创建APP工程.html#创建一个-app-工程","108":"/youqu/实践/命令行自动化测试/创建APP工程.html#编辑器打开","109":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#创建一条完整的用例","110":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#封装用例步骤的方法","111":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#编写用例","112":"/youqu/实践/命令行自动化测试/初始化项目.html#命令行自动化测试","113":"/youqu/实践/命令行自动化测试/初始化项目.html#安装","114":"/youqu/实践/命令行自动化测试/初始化项目.html#创建一个项目","115":"/youqu/实践/命令行自动化测试/初始化项目.html#部署环境","116":"/youqu/指南/元素定位/OCR识别.html#ocr识别","117":"/youqu/指南/元素定位/OCR识别.html#背景","118":"/youqu/指南/元素定位/OCR识别.html#实现原理","119":"/youqu/指南/元素定位/OCR识别.html#使用说明","120":"/youqu/指南/元素定位/OCR识别.html#rpc服务端部署","121":"/youqu/指南/元素定位/OCR识别.html#负载均衡","122":"/youqu/指南/元素定位/OCR识别.html#为什么基于-nginx-的负载均衡方案不能满足业务需求","123":"/youqu/指南/元素定位/OCR识别.html#youqu-的解决方案","124":"/youqu/指南/元素定位/OCR识别.html#链式调用","125":"/youqu/指南/元素定位/去干扰识别.html#去干扰识别","126":"/youqu/指南/元素定位/去干扰识别.html#现有右键菜单定位的方案及问题","127":"/youqu/指南/元素定位/去干扰识别.html#_1-步长操作法","128":"/youqu/指南/元素定位/去干扰识别.html#_2-常规图像识别法","129":"/youqu/指南/元素定位/去干扰识别.html#_3-相对位移法","130":"/youqu/指南/元素定位/去干扰识别.html#_4-属性定位","131":"/youqu/指南/元素定位/去干扰识别.html#去干扰识别-1","132":"/youqu/指南/元素定位/图像识别.html#图像识别","133":"/youqu/指南/元素定位/图像识别.html#常规识别","134":"/youqu/指南/元素定位/图像识别.html#气泡识别","135":"/youqu/指南/元素定位/图像识别.html#不依赖-opencv-的图像识别方案","136":"/youqu/指南/元素定位/图像识别.html#_1-自研图像识别技术","137":"/youqu/指南/元素定位/图像识别.html#_2-基于-rpc-服务实现图像识别","138":"/youqu/指南/元素定位/图像识别.html#动态图像识别","139":"/youqu/指南/元素定位/属性定位.html#属性定位","140":"/youqu/指南/元素定位/属性定位.html#背景","141":"/youqu/指南/元素定位/属性定位.html#sniff-嗅探器-使用","142":"/youqu/指南/元素定位/属性定位.html#元素操作","143":"/youqu/指南/元素定位/属性定位.html#框架封装","144":"/youqu/指南/元素定位/属性定位.html#方法明细","145":"/youqu/指南/元素定位/相对坐标定位.html#相对坐标定位","146":"/youqu/指南/元素定位/相对坐标定位.html#背景","147":"/youqu/指南/元素定位/相对坐标定位.html#实现原理","148":"/youqu/指南/元素定位/相对坐标定位.html#使用方法","149":"/youqu/指南/元素定位/相对坐标定位.html#方法明细","150":"/youqu/指南/框架必备/Ruff代码检查.html#ruff","151":"/youqu/指南/框架必备/Ruff代码检查.html#安装","152":"/youqu/指南/框架必备/Ruff代码检查.html#代码检查","153":"/youqu/指南/框架必备/Ruff代码检查.html#代码格式化","154":"/youqu/指南/框架必备/Ruff代码检查.html#配置","155":"/youqu/指南/框架必备/执行管理器.html#执行管理器-manage-py","156":"/youqu/指南/框架必备/执行管理器.html#如何使用","157":"/youqu/指南/框架必备/执行管理器.html#本地执行","158":"/youqu/指南/框架必备/执行管理器.html#_1-命令行参数","159":"/youqu/指南/框架必备/执行管理器.html#_2-配置文件","160":"/youqu/指南/框架必备/执行管理器.html#远程执行","161":"/youqu/指南/框架必备/执行管理器.html#_1-多机器分布式异步执行","162":"/youqu/指南/框架必备/执行管理器.html#_2-多机器分布式异步负载均衡执行","163":"/youqu/指南/框架必备/执行管理器.html#用例驱动方式","164":"/youqu/指南/框架必备/执行管理器.html#指定执行某一个用例","165":"/youqu/指南/框架必备/执行管理器.html#指定某个目录执行","166":"/youqu/指南/框架必备/执行管理器.html#执行某个app工程的所有用例","167":"/youqu/指南/框架必备/执行管理器.html#根据关键词执行","168":"/youqu/指南/框架必备/执行管理器.html#根据标签执行","169":"/youqu/指南/框架必备/执行管理器.html#批量用例id驱动执行","170":"/youqu/指南/框架必备/执行管理器.html#测试单驱动执行","171":"/youqu/指南/框架必备/执行管理器.html#测试套件驱动执行","172":"/youqu/指南/框架必备/执行管理器.html#本地用例文件驱动执行","173":"/youqu/指南/框架必备/断言.html#断言","174":"/youqu/指南/框架必备/断言.html#用例中使用方法","175":"/youqu/指南/框架必备/断言.html#方法明细","176":"/youqu/指南/框架必备/测试报告.html#测试报告","177":"/youqu/指南/框架必备/测试报告.html#目录结构","178":"/youqu/指南/框架必备/测试报告.html#定制报告","179":"/youqu/指南/框架必备/测试报告.html#查看报告","180":"/youqu/指南/框架必备/键鼠操作.html#键鼠操作","181":"/youqu/指南/框架必备/键鼠操作.html#常规键鼠操作","182":"/youqu/指南/框架必备/键鼠操作.html#特殊场景键鼠操作","183":"/youqu/指南/框架必备/键鼠操作.html#方法明细","184":"/youqu/指南/特色功能/Wayland适配.html#wayland-适配","185":"/youqu/指南/特色功能/WebUI.html#webui","186":"/youqu/指南/特色功能/WebUI.html#实践方法","187":"/youqu/指南/特色功能/WebUI.html#断言方法","188":"/youqu/指南/特色功能/全自动日志.html#全自动日志——funnylog","189":"/youqu/指南/特色功能/全自动日志.html#背景","190":"/youqu/指南/特色功能/全自动日志.html#实现原理","191":"/youqu/指南/特色功能/全自动日志.html#日志配置","192":"/youqu/指南/特色功能/全自动日志.html#使用方法","193":"/youqu/指南/特色功能/失败录屏.html#失败录屏","194":"/youqu/指南/特色功能/数据回填.html#pms数据回填","195":"/youqu/指南/特色功能/数据回填.html#本机执行时回填","196":"/youqu/指南/特色功能/数据回填.html#远程执行时回填","197":"/youqu/指南/特色功能/数据回填.html#可能遇到的-问题","198":"/youqu/指南/特色功能/标签化管理.html#标签化管理","199":"/youqu/指南/特色功能/标签化管理.html#标签说明","200":"/youqu/指南/特色功能/标签化管理.html#操作步骤","201":"/youqu/指南/特色功能/标签化管理.html#跳过用例","202":"/youqu/指南/特色功能/标签化管理.html#_1-固定跳过","203":"/youqu/指南/特色功能/标签化管理.html#_2-条件判断跳过","204":"/youqu/指南/特色功能/标签化管理.html#确认修复","205":"/youqu/指南/特色功能/标签化管理.html#废弃用例","206":"/youqu/指南/特色功能/标签化管理.html#设计思路","207":"/youqu/指南/特色功能/标签化管理.html#csv文件格式","208":"/youqu/指南/特色功能/标签导出.html#导出csv文件","209":"/youqu/指南/特色功能/标签自动同步.html#标签自动同步","210":"/youqu/指南/特色功能/标签自动同步.html#自动同步脚本-id-到-csv-文件","211":"/youqu/指南/特色功能/标签自动同步.html#从-pms-自动同步标签到-csv","212":"/youqu/指南/特色功能/远程交互式控制.html#远程交互式控制","213":"/youqu/指南/特色功能/远程交互式控制.html#slaves对象提供远程机器信息","214":"/youqu/指南/特色功能/远程交互式控制.html#_3个remote远程对象","215":"/youqu/指南/特色功能/远程交互式控制.html#remote-rdog","216":"/youqu/指南/特色功能/远程交互式控制.html#remote-rctl","217":"/youqu/指南/特色功能/远程交互式控制.html#跨过-rctl-直接调用","218":"/youqu/指南/特色功能/远程交互式控制.html#remote-rctl-plus","219":"/youqu/指南/特色功能/远程交互式控制.html#代码补全","220":"/youqu/指南/特色功能/重启类场景.html#重启类场景","221":"/youqu/指南/特色功能/重启类场景.html#使用方法","222":"/youqu/指南/特色功能/重启类场景.html#用例注意事项","223":"/youqu/指南/特色功能/重启类场景.html#驱动执行","224":"/youqu/指南/特色功能/重启类场景.html#执行环境","225":"/youqu/指南/环境/全局配置.html#全局配置-setting-conf","226":"/youqu/指南/环境/全局配置.html#配置文件","227":"/youqu/指南/环境/全局配置.html#配置对象获取","228":"/youqu/指南/环境/全局配置.html#app工程配置对象","229":"/youqu/指南/环境/全局配置.html#全局配置项明细","230":"/youqu/指南/环境/环境部署.html#环境部署-env-sh","231":"/youqu/指南/环境/环境部署.html#安装","232":"/youqu/指南/环境/环境部署.html#定制依赖","233":"/youqu/指南/环境/环境部署.html#_1-新增依赖","234":"/youqu/指南/环境/环境部署.html#_2-裁剪依赖","235":"/youqu/指南/环境/环境部署.html#开发环境部署","236":"/youqu/指南/环境/环境部署.html#虚拟环境解释器","237":"/youqu/指南/环境/环境部署.html#激活虚拟环境","238":"/youqu/指南/环境/环境部署.html#删除虚拟环境","239":"/youqu/指南/环境/环境部署.html#依赖治理","240":"/youqu/指南/简介/YouQu是什么.html#youqu-是什么","241":"/youqu/指南/简介/YouQu是什么.html#youqu-能做什么","242":"/youqu/指南/简介/YouQu是什么.html#爱上-youqu-的-n-个理由","243":"/youqu/指南/简介/YouQu是什么.html#开源许可证","244":"/youqu/指南/简介/快速开始.html#快速开始","245":"/youqu/指南/简介/快速开始.html#安装","246":"/youqu/指南/简介/快速开始.html#创建项目","247":"/youqu/指南/简介/快速开始.html#安装依赖","248":"/youqu/指南/简介/快速开始.html#创建-app-工程","249":"/youqu/指南/简介/快速开始.html#运行","250":"/youqu/指南/简介/快速开始.html#_1-执行管理器","251":"/youqu/指南/简介/快速开始.html#_2-本地执行","252":"/youqu/指南/简介/快速开始.html#_2-1-命令行参数","253":"/youqu/指南/简介/快速开始.html#_2-2-配置文件","254":"/youqu/指南/简介/快速开始.html#_3-远程执行","255":"/youqu/指南/简介/快速开始.html#_3-1-远程多机器分布式异步执行","256":"/youqu/指南/简介/快速开始.html#_3-2-远程多机器分布式异步负载均衡执行","257":"/youqu/规划/框架设计/AT基础框架设计方案.html#at-基础框架设计方案","258":"/youqu/规划/框架设计/AT基础框架设计方案.html#一、目标","259":"/youqu/规划/框架设计/AT基础框架设计方案.html#二、设计方案","260":"/youqu/规划/框架设计/AT基础框架设计方案.html#_1、统一概念","261":"/youqu/规划/框架设计/AT基础框架设计方案.html#_2、架构图","262":"/youqu/规划/框架设计/AT基础框架设计方案.html#_3、目录结构","263":"/youqu/规划/框架设计/AT基础框架设计方案.html#三、详细方案","264":"/youqu/规划/框架设计/AT基础框架设计方案.html#_1、应用库-apps","265":"/youqu/规划/框架设计/AT基础框架设计方案.html#_2、核心库-src","266":"/youqu/规划/框架设计/AT基础框架设计方案.html#_3、公共方法库-public","267":"/youqu/规划/框架设计/AT基础框架设计方案.html#_4、conftest-py","268":"/youqu/规划/框架设计/AT基础框架设计方案.html#_5、setting","269":"/youqu/规划/未来规划.html#未来规划","270":"/youqu/规划/未来规划.html#💡-桌面应用性能自动化测试","271":"/youqu/规划/未来规划.html#需优化解决的性能自动化问题","272":"/youqu/规划/未来规划.html#方案","273":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#自动化测试架构设计规划","274":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#一、背景介绍","275":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、原有架构介绍","276":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、自动化的应用","277":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_3、存在的问题","278":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#二、方案设计","279":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、架构设计","280":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、设计思路","281":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#三、详细方案","282":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、用例解耦","283":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、公共库建设","284":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_3、用例标签化管理","285":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_4、用例执行","286":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_5、自动化测试平台","287":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#四、实施计划","288":"/youqu/规划/框架设计/AT应用库设计方案.html#at-应用库设计方案","289":"/youqu/规划/框架设计/AT应用库设计方案.html#一、目标","290":"/youqu/规划/框架设计/AT应用库设计方案.html#二、方案设计","291":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、分层设计图","292":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、目录结构","293":"/youqu/规划/框架设计/AT应用库设计方案.html#三、详细方案","294":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、基类-base-widget-py","295":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、操作层","296":"/youqu/规划/框架设计/AT应用库设计方案.html#_3、应用层","297":"/youqu/规划/框架设计/AT应用库设计方案.html#_4、逻辑举例","298":"/youqu/规划/框架设计/AT应用库设计方案.html#四、工程改造实施步骤","299":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、基础框架代码拉取","300":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、调整工程目录","301":"/youqu/规划/框架设计/AT应用库设计方案.html#_3、实现核心库接口","302":"/youqu/规划/框架设计/AT应用库设计方案.html#_4、路径处理","303":"/youqu/规划/框架设计/AT应用库设计方案.html#_5、调试和编写用例"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[2,1,4],"1":[3,2,5],"2":[4,2,9],"3":[3,2,3],"4":[1,1,1],"5":[7,1,7],"6":[7,1,9],"7":[6,1,16],"8":[7,1,4],"9":[7,1,9],"10":[7,1,20],"11":[6,1,56],"12":[7,1,84],"13":[7,1,80],"14":[6,1,17],"15":[7,1,51],"16":[7,1,81],"17":[6,1,34],"18":[7,1,48],"19":[7,1,18],"20":[7,1,34],"21":[7,1,20],"22":[6,1,24],"23":[6,1,13],"24":[7,1,21],"25":[7,1,50],"26":[7,1,56],"27":[7,1,69],"28":[7,1,11],"29":[7,1,23],"30":[6,1,37],"31":[6,1,30],"32":[7,1,20],"33":[7,1,39],"34":[6,1,76],"35":[6,1,14],"36":[6,1,20],"37":[6,1,13],"38":[7,1,27],"39":[6,1,38],"40":[7,1,61],"41":[6,1,203],"42":[7,1,19],"43":[7,1,25],"44":[7,1,9],"45":[7,1,22],"46":[7,1,31],"47":[7,1,82],"48":[7,1,7],"49":[7,1,45],"50":[6,1,50],"51":[6,1,45],"52":[7,1,33],"53":[6,1,169],"54":[6,1,51],"55":[6,1,19],"56":[5,1,52],"57":[6,1,53],"58":[7,1,18],"59":[6,1,31],"60":[2,1,7],"61":[3,1,64],"62":[1,3,5],"63":[1,1,2],"64":[1,1,60],"65":[1,1,42],"66":[3,1,9],"67":[1,3,7],"68":[1,3,33],"69":[1,3,24],"70":[3,1,64],"71":[1,3,41],"72":[3,3,7],"73":[1,1,2],"74":[1,1,198],"75":[1,1,70],"76":[2,1,16],"77":[1,2,7],"78":[1,2,33],"79":[1,2,24],"80":[3,1,64],"81":[1,3,5],"82":[1,1,2],"83":[1,1,5],"84":[1,1,64],"85":[1,1,61],"86":[4,1,20],"87":[1,4,7],"88":[1,4,33],"89":[1,4,24],"90":[1,1,2],"91":[1,1,1],"92":[1,1,25],"93":[1,1,63],"94":[1,1,35],"95":[1,1,4],"96":[1,1,3],"97":[1,1,38],"98":[1,1,111],"99":[3,1,64],"100":[1,3,50],"101":[3,3,11],"102":[1,3,5],"103":[3,1,22],"104":[1,3,7],"105":[1,3,33],"106":[1,3,24],"107":[3,1,64],"108":[1,3,5],"109":[1,1,4],"110":[1,1,39],"111":[1,1,50],"112":[1,1,6],"113":[1,1,7],"114":[1,1,33],"115":[1,1,24],"116":[1,1,1],"117":[1,1,18],"118":[1,1,24],"119":[1,1,159],"120":[1,1,5],"121":[1,1,9],"122":[3,2,33],"123":[2,2,15],"124":[1,1,20],"125":[1,1,2],"126":[1,1,5],"127":[2,2,39],"128":[2,2,16],"129":[2,2,41],"130":[2,2,11],"131":[1,1,81],"132":[1,1,21],"133":[1,1,202],"134":[1,1,72],"135":[3,1,1],"136":[2,4,150],"137":[4,4,141],"138":[1,1,53],"139":[1,1,1],"140":[1,1,27],"141":[3,1,45],"142":[1,1,66],"143":[1,1,49],"144":[1,1,250],"145":[1,1,1],"146":[1,1,33],"147":[1,1,95],"148":[1,1,70],"149":[1,1,306],"150":[1,1,8],"151":[1,1,4],"152":[1,1,15],"153":[1,1,15],"154":[1,1,212],"155":[3,1,14],"156":[1,3,43],"157":[1,3,7],"158":[2,4,152],"159":[2,4,15],"160":[1,3,10],"161":[2,4,112],"162":[2,4,42],"163":[1,3,1],"164":[1,4,19],"165":[1,4,23],"166":[1,4,10],"167":[1,4,28],"168":[1,4,23],"169":[1,4,11],"170":[1,4,20],"171":[1,4,20],"172":[1,4,21],"173":[1,1,4],"174":[1,1,37],"175":[1,1,439],"176":[1,1,1],"177":[1,1,57],"178":[1,1,22],"179":[1,1,41],"180":[1,1,16],"181":[1,1,36],"182":[1,1,25],"183":[1,1,347],"184":[2,1,61],"185":[1,1,50],"186":[1,1,5],"187":[1,1,24],"188":[2,1,1],"189":[1,2,39],"190":[1,2,24],"191":[1,2,34],"192":[1,2,100],"193":[1,1,42],"194":[1,1,4],"195":[1,1,85],"196":[1,1,45],"197":[3,1,18],"198":[1,1,1],"199":[1,1,66],"200":[1,1,42],"201":[1,1,14],"202":[2,2,18],"203":[2,2,162],"204":[1,1,82],"205":[1,1,21],"206":[1,1,18],"207":[1,1,8],"208":[1,1,39],"209":[1,1,1],"210":[5,1,46],"211":[4,1,79],"212":[1,1,13],"213":[1,1,53],"214":[1,1,1],"215":[2,2,39],"216":[2,2,35],"217":[3,4,27],"218":[3,2,43],"219":[1,1,8],"220":[1,1,11],"221":[1,1,13],"222":[1,1,72],"223":[1,1,9],"224":[1,1,11],"225":[3,1,1],"226":[1,3,38],"227":[1,3,24],"228":[1,3,16],"229":[1,3,491],"230":[3,1,1],"231":[1,3,23],"232":[1,3,1],"233":[2,4,36],"234":[2,4,31],"235":[1,3,17],"236":[1,3,14],"237":[1,3,8],"238":[1,3,5],"239":[1,3,28],"240":[3,1,16],"241":[3,3,16],"242":[5,3,63],"243":[1,3,7],"244":[1,1,1],"245":[1,1,28],"246":[1,1,16],"247":[1,1,29],"248":[3,1,92],"249":[1,1,1],"250":[2,2,7],"251":[2,2,6],"252":[3,4,153],"253":[2,4,12],"254":[2,2,10],"255":[3,4,115],"256":[3,4,31],"257":[2,1,1],"258":[2,2,11],"259":[2,2,1],"260":[2,4,45],"261":[2,4,11],"262":[2,4,71],"263":[2,2,1],"264":[4,4,9],"265":[4,4,89],"266":[4,4,70],"267":[3,4,29],"268":[2,4,35],"269":[1,1,1],"270":[2,1,1],"271":[1,3,35],"272":[1,3,31],"273":[1,1,60],"274":[2,1,3],"275":[2,3,32],"276":[2,3,27],"277":[2,3,45],"278":[2,1,5],"279":[2,3,3],"280":[2,3,191],"281":[2,1,1],"282":[2,3,40],"283":[2,3,43],"284":[2,3,77],"285":[2,3,31],"286":[2,3,37],"287":[2,1,54],"288":[2,1,1],"289":[2,2,5],"290":[2,2,7],"291":[2,4,11],"292":[2,4,49],"293":[2,2,1],"294":[6,4,33],"295":[2,4,66],"296":[2,4,49],"297":[2,4,56],"298":[2,2,1],"299":[2,4,14],"300":[2,4,65],"301":[2,4,35],"302":[2,4,34],"303":[2,4,6]},"averageFieldLength":[2.5065789473684226,1.825657894736842,40.072368421052666],"storedFields":{"0":{"title":"贡献,并且帮助我们改进","titles":[]},"1":{"title":"帮助改进 YouQu 文档","titles":["贡献,并且帮助我们改进"]},"2":{"title":"向 YouQu 提交 Issues","titles":["贡献,并且帮助我们改进"]},"3":{"title":"向 YouQu 仓库提交代码","titles":["贡献,并且帮助我们改进"]},"4":{"title":"版本更新记录","titles":[]},"5":{"title":"2.6.8(2024/07/15)","titles":["版本更新记录"]},"6":{"title":"2.6.7(2024/07/15)","titles":["版本更新记录"]},"7":{"title":"2.6.6(2024/07/05)","titles":["版本更新记录"]},"8":{"title":"2.6.5(2024/06/11)","titles":["版本更新记录"]},"9":{"title":"2.6.4(2024/06/07)","titles":["版本更新记录"]},"10":{"title":"2.6.3(2024/06/07)","titles":["版本更新记录"]},"11":{"title":"2.6.2(2024/05/29)","titles":["版本更新记录"]},"12":{"title":"2.6.1(2024/05/21)","titles":["版本更新记录"]},"13":{"title":"2.6.0(2024/05/14)","titles":["版本更新记录"]},"14":{"title":"2.5.5(2024/05/10)","titles":["版本更新记录"]},"15":{"title":"2.5.4(2024/05/08)","titles":["版本更新记录"]},"16":{"title":"2.5.3(2024/04/24)","titles":["版本更新记录"]},"17":{"title":"2.5.2(2024/03/27)","titles":["版本更新记录"]},"18":{"title":"2.5.1(2024/03/14)","titles":["版本更新记录"]},"19":{"title":"2.5.0(2024/03/04)","titles":["版本更新记录"]},"20":{"title":"2.4.6(2024/02/26)","titles":["版本更新记录"]},"21":{"title":"2.4.5(2024/01/20)","titles":["版本更新记录"]},"22":{"title":"2.4.4(2024/01/19)","titles":["版本更新记录"]},"23":{"title":"2.4.2(2023/12/27)","titles":["版本更新记录"]},"24":{"title":"2.4.1(2023/12/26)","titles":["版本更新记录"]},"25":{"title":"2.4.0(2023/12/22)","titles":["版本更新记录"]},"26":{"title":"2.3.7(2023/12/15)","titles":["版本更新记录"]},"27":{"title":"2.3.6(2023/12/13)","titles":["版本更新记录"]},"28":{"title":"2.3.5(2023/12/04)","titles":["版本更新记录"]},"29":{"title":"2.3.4(2023/12/04)","titles":["版本更新记录"]},"30":{"title":"2.3.3(2023/11/22)","titles":["版本更新记录"]},"31":{"title":"2.3.2(2023/11/14)","titles":["版本更新记录"]},"32":{"title":"2.3.1(2023/11/08)","titles":["版本更新记录"]},"33":{"title":"2.3.0(2023/10/27)","titles":["版本更新记录"]},"34":{"title":"2.2.4(2023/10/16)","titles":["版本更新记录"]},"35":{"title":"2.2.3(2023/09/15)","titles":["版本更新记录"]},"36":{"title":"2.2.1(2023/09/13)","titles":["版本更新记录"]},"37":{"title":"2.2.0(2023/09/05)","titles":["版本更新记录"]},"38":{"title":"2.1.5(2023/08/31)","titles":["版本更新记录"]},"39":{"title":"2.1.2(2023/08/22)","titles":["版本更新记录"]},"40":{"title":"2.1.0(2023/08/18)","titles":["版本更新记录"]},"41":{"title":"2.0.0(2023/08/16)","titles":["版本更新记录"]},"42":{"title":"1.3.0(2023/07/10)","titles":["版本更新记录"]},"43":{"title":"1.2.9(2023/06/26)","titles":["版本更新记录"]},"44":{"title":"1.2.8(2023/06/09)","titles":["版本更新记录"]},"45":{"title":"1.2.7(2023/06/08)","titles":["版本更新记录"]},"46":{"title":"1.2.6(2023/06/07)","titles":["版本更新记录"]},"47":{"title":"1.2.5(2023/05/16)","titles":["版本更新记录"]},"48":{"title":"1.2.4(2023/02/27)","titles":["版本更新记录"]},"49":{"title":"1.2.3(2023/02/27)","titles":["版本更新记录"]},"50":{"title":"1.2.2(2023/02/08)","titles":["版本更新记录"]},"51":{"title":"1.2.1(2023/01/06)","titles":["版本更新记录"]},"52":{"title":"1.2.0(2022/12/30)","titles":["版本更新记录"]},"53":{"title":"1.1.4(2022/12/14)","titles":["版本更新记录"]},"54":{"title":"1.1.3(2022/10/28)","titles":["版本更新记录"]},"55":{"title":"1.1.2(2022/09/21)","titles":["版本更新记录"]},"56":{"title":"1.1.1(2022/09/19)","titles":["版本更新记录"]},"57":{"title":"1.1.0(2022/09/16)","titles":["版本更新记录"]},"58":{"title":"1.0.2(2022/08/22)","titles":["版本更新记录"]},"59":{"title":"1.0.1(2022/08/12)","titles":["版本更新记录"]},"60":{"title":"YouQu 官方兴趣小组","titles":[]},"61":{"title":"创建一个 APP 工程","titles":[]},"62":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"63":{"title":"创建一条完整的用例","titles":[]},"64":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"65":{"title":"编写用例","titles":["创建一条完整的用例"]},"66":{"title":"Linux DBus 接口自动化测试","titles":[]},"67":{"title":"安装","titles":["Linux DBus 接口自动化测试"]},"68":{"title":"创建一个项目","titles":["Linux DBus 接口自动化测试"]},"69":{"title":"部署环境","titles":["Linux DBus 接口自动化测试"]},"70":{"title":"创建一个 APP 工程","titles":[]},"71":{"title":"修改","titles":["创建一个 APP 工程"]},"72":{"title":"再次执行 env.sh","titles":["创建一个 APP 工程"]},"73":{"title":"创建一条完整的用例","titles":[]},"74":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"75":{"title":"编写用例","titles":["创建一条完整的用例"]},"76":{"title":"HTTP 接口自动化测试","titles":[]},"77":{"title":"安装","titles":["HTTP 接口自动化测试"]},"78":{"title":"创建一个项目","titles":["HTTP 接口自动化测试"]},"79":{"title":"部署环境","titles":["HTTP 接口自动化测试"]},"80":{"title":"创建一个 APP 工程","titles":[]},"81":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"82":{"title":"创建一条完整的用例","titles":[]},"83":{"title":"用例步骤","titles":["创建一条完整的用例"]},"84":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"85":{"title":"编写用例","titles":["创建一条完整的用例"]},"86":{"title":"Linux 桌面 UI 自动化测试","titles":[]},"87":{"title":"安装","titles":["Linux 桌面 UI 自动化测试"]},"88":{"title":"创建一个项目","titles":["Linux 桌面 UI 自动化测试"]},"89":{"title":"部署环境","titles":["Linux 桌面 UI 自动化测试"]},"90":{"title":"远程交互式控制","titles":[]},"91":{"title":"逻辑示意图","titles":["远程交互式控制"]},"92":{"title":"标识文件","titles":["远程交互式控制"]},"93":{"title":"方法编写","titles":["远程交互式控制"]},"94":{"title":"用例编写","titles":["远程交互式控制"]},"95":{"title":"创建一条完整的用例","titles":[]},"96":{"title":"用例步骤","titles":["创建一条完整的用例"]},"97":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"98":{"title":"编写用例","titles":["创建一条完整的用例"]},"99":{"title":"创建一个 APP 工程","titles":[]},"100":{"title":"修改","titles":["创建一个 APP 工程"]},"101":{"title":"再次执行 env.sh","titles":["创建一个 APP 工程"]},"102":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"103":{"title":"Web UI 自动化测试","titles":[]},"104":{"title":"安装","titles":["Web UI 自动化测试"]},"105":{"title":"创建一个项目","titles":["Web UI 自动化测试"]},"106":{"title":"部署环境","titles":["Web UI 自动化测试"]},"107":{"title":"创建一个 APP 工程","titles":[]},"108":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"109":{"title":"创建一条完整的用例","titles":[]},"110":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"111":{"title":"编写用例","titles":["创建一条完整的用例"]},"112":{"title":"命令行自动化测试","titles":[]},"113":{"title":"安装","titles":["命令行自动化测试"]},"114":{"title":"创建一个项目","titles":["命令行自动化测试"]},"115":{"title":"部署环境","titles":["命令行自动化测试"]},"116":{"title":"OCR识别","titles":[]},"117":{"title":"背景","titles":["OCR识别"]},"118":{"title":"实现原理","titles":["OCR识别"]},"119":{"title":"使用说明","titles":["OCR识别"]},"120":{"title":"RPC服务端部署","titles":["OCR识别"]},"121":{"title":"负载均衡","titles":["OCR识别"]},"122":{"title":"为什么基于 Nginx 的负载均衡方案不能满足业务需求","titles":["OCR识别","负载均衡"]},"123":{"title":"YouQu 的解决方案","titles":["OCR识别","负载均衡"]},"124":{"title":"链式调用","titles":["OCR识别"]},"125":{"title":"去干扰识别","titles":[]},"126":{"title":"现有右键菜单定位的方案及问题","titles":["去干扰识别"]},"127":{"title":"1. 步长操作法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"128":{"title":"2. 常规图像识别法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"129":{"title":"3. 相对位移法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"130":{"title":"4. 属性定位","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"131":{"title":"去干扰识别","titles":["去干扰识别"]},"132":{"title":"图像识别","titles":[]},"133":{"title":"常规识别","titles":["图像识别"]},"134":{"title":"气泡识别","titles":["图像识别"]},"135":{"title":"不依赖 OpenCV 的图像识别方案","titles":["图像识别"]},"136":{"title":"1. 自研图像识别技术","titles":["图像识别","不依赖 OpenCV 的图像识别方案"]},"137":{"title":"2. 基于 RPC 服务实现图像识别","titles":["图像识别","不依赖 OpenCV 的图像识别方案"]},"138":{"title":"动态图像识别","titles":["图像识别"]},"139":{"title":"属性定位","titles":[]},"140":{"title":"背景","titles":["属性定位"]},"141":{"title":"sniff(嗅探器)使用","titles":["属性定位"]},"142":{"title":"元素操作","titles":["属性定位"]},"143":{"title":"框架封装","titles":["属性定位"]},"144":{"title":"方法明细","titles":["属性定位"]},"145":{"title":"相对坐标定位","titles":[]},"146":{"title":"背景","titles":["相对坐标定位"]},"147":{"title":"实现原理","titles":["相对坐标定位"]},"148":{"title":"使用方法","titles":["相对坐标定位"]},"149":{"title":"方法明细","titles":["相对坐标定位"]},"150":{"title":"Ruff","titles":[]},"151":{"title":"安装","titles":["Ruff"]},"152":{"title":"代码检查","titles":["Ruff"]},"153":{"title":"代码格式化","titles":["Ruff"]},"154":{"title":"配置","titles":["Ruff"]},"155":{"title":"执行管理器 - manage.py","titles":[]},"156":{"title":"如何使用","titles":["执行管理器 - manage.py"]},"157":{"title":"本地执行","titles":["执行管理器 - manage.py"]},"158":{"title":"1. 命令行参数","titles":["执行管理器 - manage.py","本地执行"]},"159":{"title":"2. 配置文件","titles":["执行管理器 - manage.py","本地执行"]},"160":{"title":"远程执行","titles":["执行管理器 - manage.py"]},"161":{"title":"1. 多机器分布式异步执行","titles":["执行管理器 - manage.py","远程执行"]},"162":{"title":"2. 多机器分布式异步负载均衡执行","titles":["执行管理器 - manage.py","远程执行"]},"163":{"title":"用例驱动方式","titles":["执行管理器 - manage.py"]},"164":{"title":"指定执行某一个用例","titles":["执行管理器 - manage.py","用例驱动方式"]},"165":{"title":"指定某个目录执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"166":{"title":"执行某个APP工程的所有用例","titles":["执行管理器 - manage.py","用例驱动方式"]},"167":{"title":"根据关键词执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"168":{"title":"根据标签执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"169":{"title":"批量用例ID驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"170":{"title":"测试单驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"171":{"title":"测试套件驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"172":{"title":"本地用例文件驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"173":{"title":"断言","titles":[]},"174":{"title":"用例中使用方法","titles":["断言"]},"175":{"title":"方法明细","titles":["断言"]},"176":{"title":"测试报告","titles":[]},"177":{"title":"目录结构","titles":["测试报告"]},"178":{"title":"定制报告","titles":["测试报告"]},"179":{"title":"查看报告","titles":["测试报告"]},"180":{"title":"键鼠操作","titles":[]},"181":{"title":"常规键鼠操作","titles":["键鼠操作"]},"182":{"title":"特殊场景键鼠操作","titles":["键鼠操作"]},"183":{"title":"方法明细","titles":["键鼠操作"]},"184":{"title":"Wayland 适配","titles":[]},"185":{"title":"WebUI","titles":[]},"186":{"title":"实践方法","titles":["WebUI"]},"187":{"title":"断言方法","titles":["WebUI"]},"188":{"title":"全自动日志——funnylog","titles":[]},"189":{"title":"背景","titles":["全自动日志——funnylog"]},"190":{"title":"实现原理","titles":["全自动日志——funnylog"]},"191":{"title":"日志配置","titles":["全自动日志——funnylog"]},"192":{"title":"使用方法","titles":["全自动日志——funnylog"]},"193":{"title":"失败录屏","titles":[]},"194":{"title":"PMS数据回填","titles":[]},"195":{"title":"本机执行时回填","titles":["PMS数据回填"]},"196":{"title":"远程执行时回填","titles":["PMS数据回填"]},"197":{"title":"可能遇到的“问题”","titles":["PMS数据回填"]},"198":{"title":"标签化管理","titles":[]},"199":{"title":"标签说明","titles":["标签化管理"]},"200":{"title":"操作步骤","titles":["标签化管理"]},"201":{"title":"跳过用例","titles":["标签化管理"]},"202":{"title":"1. 固定跳过","titles":["标签化管理","跳过用例"]},"203":{"title":"2. 条件判断跳过","titles":["标签化管理","跳过用例"]},"204":{"title":"确认修复","titles":["标签化管理"]},"205":{"title":"废弃用例","titles":["标签化管理"]},"206":{"title":"设计思路","titles":["标签化管理"]},"207":{"title":"CSV文件格式","titles":["标签化管理"]},"208":{"title":"导出CSV文件","titles":[]},"209":{"title":"标签自动同步","titles":[]},"210":{"title":"自动同步脚本 ID 到 CSV 文件","titles":["标签自动同步"]},"211":{"title":"从 PMS 自动同步标签到 CSV","titles":["标签自动同步"]},"212":{"title":"远程交互式控制","titles":[]},"213":{"title":"slaves对象提供远程机器信息","titles":["远程交互式控制"]},"214":{"title":"3个Remote远程对象","titles":["远程交互式控制"]},"215":{"title":"Remote.rdog","titles":["远程交互式控制","3个Remote远程对象"]},"216":{"title":"Remote.rctl","titles":["远程交互式控制","3个Remote远程对象"]},"217":{"title":"跨过 rctl 直接调用","titles":["远程交互式控制","3个Remote远程对象","Remote.rctl"]},"218":{"title":"Remote.rctl_plus","titles":["远程交互式控制","3个Remote远程对象"]},"219":{"title":"代码补全","titles":["远程交互式控制"]},"220":{"title":"重启类场景","titles":[]},"221":{"title":"使用方法","titles":["重启类场景"]},"222":{"title":"用例注意事项","titles":["重启类场景"]},"223":{"title":"驱动执行","titles":["重启类场景"]},"224":{"title":"执行环境","titles":["重启类场景"]},"225":{"title":"全局配置 - setting.conf","titles":[]},"226":{"title":"配置文件","titles":["全局配置 - setting.conf"]},"227":{"title":"配置对象获取","titles":["全局配置 - setting.conf"]},"228":{"title":"APP工程配置对象","titles":["全局配置 - setting.conf"]},"229":{"title":"全局配置项明细","titles":["全局配置 - setting.conf"]},"230":{"title":"环境部署 - env.sh","titles":[]},"231":{"title":"安装","titles":["环境部署 - env.sh"]},"232":{"title":"定制依赖","titles":["环境部署 - env.sh"]},"233":{"title":"1. 新增依赖","titles":["环境部署 - env.sh","定制依赖"]},"234":{"title":"2. 裁剪依赖","titles":["环境部署 - env.sh","定制依赖"]},"235":{"title":"开发环境部署","titles":["环境部署 - env.sh"]},"236":{"title":"虚拟环境解释器","titles":["环境部署 - env.sh"]},"237":{"title":"激活虚拟环境","titles":["环境部署 - env.sh"]},"238":{"title":"删除虚拟环境","titles":["环境部署 - env.sh"]},"239":{"title":"依赖治理","titles":["环境部署 - env.sh"]},"240":{"title":"YouQu 是什么?","titles":[]},"241":{"title":"YouQu 能做什么?","titles":["YouQu 是什么?"]},"242":{"title":"爱上 YouQu 的 N 个理由","titles":["YouQu 是什么?"]},"243":{"title":"开源许可证","titles":["YouQu 是什么?"]},"244":{"title":"快速开始","titles":[]},"245":{"title":"安装","titles":["快速开始"]},"246":{"title":"创建项目","titles":["快速开始"]},"247":{"title":"安装依赖","titles":["快速开始"]},"248":{"title":"创建 APP 工程","titles":["快速开始"]},"249":{"title":"运行","titles":["快速开始"]},"250":{"title":"1. 执行管理器","titles":["快速开始","运行"]},"251":{"title":"2. 本地执行","titles":["快速开始","运行"]},"252":{"title":"2.1. 命令行参数","titles":["快速开始","运行","2. 本地执行"]},"253":{"title":"2.2. 配置文件","titles":["快速开始","运行","2. 本地执行"]},"254":{"title":"3. 远程执行","titles":["快速开始","运行"]},"255":{"title":"3.1. 远程多机器分布式异步执行","titles":["快速开始","运行","3. 远程执行"]},"256":{"title":"3.2. 远程多机器分布式异步负载均衡执行","titles":["快速开始","运行","3. 远程执行"]},"257":{"title":"AT 基础框架设计方案","titles":[]},"258":{"title":"一、目标","titles":["AT 基础框架设计方案"]},"259":{"title":"二、设计方案","titles":["AT 基础框架设计方案"]},"260":{"title":"1、统一概念","titles":["AT 基础框架设计方案","二、设计方案"]},"261":{"title":"2、架构图","titles":["AT 基础框架设计方案","二、设计方案"]},"262":{"title":"3、目录结构","titles":["AT 基础框架设计方案","二、设计方案"]},"263":{"title":"三、详细方案","titles":["AT 基础框架设计方案"]},"264":{"title":"1、应用库(apps)","titles":["AT 基础框架设计方案","三、详细方案"]},"265":{"title":"2、核心库(src)","titles":["AT 基础框架设计方案","三、详细方案"]},"266":{"title":"3、公共方法库(public)","titles":["AT 基础框架设计方案","三、详细方案"]},"267":{"title":"4、conftest.py","titles":["AT 基础框架设计方案","三、详细方案"]},"268":{"title":"5、setting","titles":["AT 基础框架设计方案","三、详细方案"]},"269":{"title":"未来规划","titles":[]},"270":{"title":"💡 桌面应用性能自动化测试","titles":["未来规划"]},"271":{"title":"需优化解决的性能自动化问题","titles":["未来规划","💡 桌面应用性能自动化测试"]},"272":{"title":"方案","titles":["未来规划","💡 桌面应用性能自动化测试"]},"273":{"title":"自动化测试架构设计规划","titles":[]},"274":{"title":"一、背景介绍","titles":["自动化测试架构设计规划"]},"275":{"title":"1、原有架构介绍","titles":["自动化测试架构设计规划","一、背景介绍"]},"276":{"title":"2、自动化的应用","titles":["自动化测试架构设计规划","一、背景介绍"]},"277":{"title":"3、存在的问题","titles":["自动化测试架构设计规划","一、背景介绍"]},"278":{"title":"二、方案设计","titles":["自动化测试架构设计规划"]},"279":{"title":"1、架构设计","titles":["自动化测试架构设计规划","二、方案设计"]},"280":{"title":"2、设计思路","titles":["自动化测试架构设计规划","二、方案设计"]},"281":{"title":"三、详细方案","titles":["自动化测试架构设计规划"]},"282":{"title":"1、用例解耦","titles":["自动化测试架构设计规划","三、详细方案"]},"283":{"title":"2、公共库建设","titles":["自动化测试架构设计规划","三、详细方案"]},"284":{"title":"3、用例标签化管理","titles":["自动化测试架构设计规划","三、详细方案"]},"285":{"title":"4、用例执行","titles":["自动化测试架构设计规划","三、详细方案"]},"286":{"title":"5、自动化测试平台","titles":["自动化测试架构设计规划","三、详细方案"]},"287":{"title":"四、实施计划","titles":["自动化测试架构设计规划"]},"288":{"title":"AT 应用库设计方案","titles":[]},"289":{"title":"一、目标","titles":["AT 应用库设计方案"]},"290":{"title":"二、方案设计","titles":["AT 应用库设计方案"]},"291":{"title":"1、分层设计图","titles":["AT 应用库设计方案","二、方案设计"]},"292":{"title":"2、目录结构","titles":["AT 应用库设计方案","二、方案设计"]},"293":{"title":"三、详细方案","titles":["AT 应用库设计方案"]},"294":{"title":"1、基类(base_widget.py)","titles":["AT 应用库设计方案","三、详细方案"]},"295":{"title":"2、操作层","titles":["AT 应用库设计方案","三、详细方案"]},"296":{"title":"3、应用层","titles":["AT 应用库设计方案","三、详细方案"]},"297":{"title":"4、逻辑举例","titles":["AT 应用库设计方案","三、详细方案"]},"298":{"title":"四、工程改造实施步骤","titles":["AT 应用库设计方案"]},"299":{"title":"1、基础框架代码拉取","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"300":{"title":"2、调整工程目录","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"301":{"title":"3、实现核心库接口","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"302":{"title":"4、路径处理","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"303":{"title":"5、调试和编写用例","titles":["AT 应用库设计方案","四、工程改造实施步骤"]}},"dirtCount":0,"index":[["资源路径",{"2":{"302":1}}],["吧",{"2":{"302":1}}],["想清楚这个方法是干什么的",{"2":{"301":1}}],["别想了",{"2":{"300":1}}],["尽可能",{"2":{"300":1}}],["尽量使用编辑器进行相应的调整",{"2":{"300":1}}],["尽量使用标准库或系统预装库来实现功能",{"2":{"239":1}}],["逻辑举例",{"0":{"297":1}}],["逻辑示意图",{"0":{"91":1}}],["避免方法重名",{"2":{"295":1}}],["界面元素直接与元素名称相同",{"2":{"295":1}}],["界面ui也进行了优化调整",{"2":{"16":1}}],["保险箱弹窗",{"2":{"295":1}}],["保存临时图片的路径",{"2":{"229":1}}],["保存临时图片",{"2":{"138":1}}],["弹窗",{"2":{"295":1}}],["抽取操作层的一些基础方法",{"2":{"294":1}}],["抽取其中重要功能模块",{"2":{"261":1}}],["层划分",{"2":{"291":1}}],["难度也是最大的",{"2":{"290":1}}],["难以集中维护",{"2":{"206":1}}],["落地运行",{"2":{"287":1}}],["静态扫描问题清零",{"2":{"287":1}}],["静态方法",{"2":{"192":1}}],["爬取",{"2":{"287":1}}],["爬虫的性能",{"2":{"57":1}}],["音视频应用代码解耦",{"2":{"287":1}}],["音乐的操作方法类",{"2":{"282":1}}],["音乐用例",{"2":{"222":1}}],["音乐业务层",{"2":{"221":1}}],["音乐",{"2":{"93":1,"266":1}}],["计划结束时间",{"2":{"287":2}}],["计划开始时间",{"2":{"287":2}}],["计算元素按钮坐标",{"2":{"147":1}}],["计算收集用例数量剔除",{"2":{"20":1}}],["计算的汇总数据",{"2":{"11":1}}],["阶段目标",{"2":{"287":2}}],["阶段报错后",{"2":{"53":1}}],["四",{"0":{"287":1,"298":1},"1":{"299":1,"300":1,"301":1,"302":1,"303":1}}],["研发同学等",{"2":{"286":1}}],["研发经理郑幼戈",{"2":{"41":1}}],["镜像下载接口",{"2":{"286":1}}],["镜像版本及下载地址",{"2":{"286":1}}],["镜像版本等",{"2":{"178":1}}],["镜像安装模块等",{"2":{"286":1}}],["又能在资源有限的情况下覆盖了所有的架构",{"2":{"285":1}}],["既能保证执行了所有的用例",{"2":{"285":1}}],["缩短执行总时间",{"2":{"285":1}}],["属于公共方法的则调用",{"2":{"283":1}}],["属性树",{"2":{"140":1}}],["属性定位模块",{"2":{"280":1}}],["属性定位",{"0":{"130":1,"139":1},"1":{"140":1,"141":1,"142":1,"143":1,"144":1},"2":{"146":1}}],["漏洞扫描",{"2":{"285":1}}],["漏洞扫描用例都可以单独触发",{"2":{"280":1}}],["漏洞扫描用例",{"2":{"280":1}}],["漏洞扫描等",{"2":{"280":1}}],["供上层调用",{"2":{"280":1}}],["供用例层使用",{"2":{"16":1}}],["部分模块会涉及到新功能开发",{"2":{"280":1}}],["部署",{"2":{"276":1}}],["部署环境",{"0":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["压测自动化",{"2":{"277":1}}],["压力",{"2":{"199":1}}],["删掉跳过用例的代码",{"2":{"277":1}}],["删除确认弹窗",{"2":{"295":1}}],["删除虚拟环境",{"0":{"238":1}}],["删除弹窗",{"2":{"53":1}}],["费时费力",{"2":{"277":1}}],["很多场景下我们还需要根据用例的等级",{"2":{"277":1}}],["很明显",{"2":{"185":1}}],["很明显不适用于这类元素定位方案",{"2":{"146":1}}],["旨在回归测试时执行自动化测试用例",{"2":{"276":1}}],["验收测试",{"2":{"276":1}}],["持续集成流水线",{"2":{"276":1}}],["流程",{"2":{"276":1}}],["流水线上跑的是",{"2":{"204":1}}],["流水线的用例",{"2":{"199":1}}],["专注于业务功能逻辑",{"2":{"275":1}}],["专项测试等",{"2":{"273":1}}],["业内比较流行的实现方案是使用",{"2":{"286":1}}],["业内为了解决版本冲突问题一般都会使用",{"2":{"41":1}}],["业务层",{"2":{"280":1}}],["业务层根据实际业务需求",{"2":{"280":1}}],["业务逻辑层",{"2":{"275":1}}],["回归测试今年规划建设中",{"2":{"276":1}}],["回归测试",{"2":{"273":1,"276":1}}],["回填数据时",{"2":{"32":1}}],["冒烟测试",{"2":{"273":1,"280":1}}],["天",{"2":{"273":1}}],["天提升至",{"2":{"273":1}}],["天真",{"2":{"189":1}}],["平均编写一条用例从",{"2":{"273":1}}],["平台上的指令实际上都是通过下发给执行器",{"2":{"280":1}}],["平台不跳过",{"2":{"203":1}}],["平台跳过",{"2":{"203":1}}],["平台自动化测试的老演员了",{"2":{"112":1}}],["平台默认登陆账号是超级管理员及密码",{"2":{"74":1}}],["平台",{"2":{"74":1}}],["平台兼容适配性方面",{"2":{"13":1}}],["契合应用独立发布特性",{"2":{"273":1}}],["消除",{"2":{"273":1}}],["消除应用间的耦合关系",{"2":{"260":1}}],["意义",{"2":{"273":1}}],["意思是可以通过",{"2":{"152":1}}],["符合",{"2":{"273":1}}],["符号将两个方法分开",{"2":{"203":1}}],["符号",{"2":{"203":3}}],["符号连接",{"2":{"203":1}}],["符号隔开即可",{"2":{"21":1}}],["运用场景提供支撑",{"2":{"273":1}}],["运行",{"0":{"249":1},"1":{"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1}}],["运行速度",{"2":{"185":1}}],["形成一套独立于应用间的公共方法库",{"2":{"273":1}}],["形式",{"2":{"20":1,"233":1}}],["顶配版",{"2":{"272":1}}],["外部应用的操作方法",{"2":{"283":1}}],["外部机器异步解析",{"2":{"272":1}}],["外部开发者肯定访问不到内网的文档",{"2":{"41":1}}],["低配版",{"2":{"272":1}}],["手上有什么设备就用什么方案",{"2":{"272":1}}],["手动回填",{"2":{"195":1,"229":1}}],["手动回填模式报错",{"2":{"10":1}}],["团队中普遍人员代码能力不强",{"2":{"271":1}}],["强制依赖串口线",{"2":{"271":1}}],["强大的日志和报告输出等特色功能",{"2":{"240":1}}],["需实现自动解析",{"2":{"287":1}}],["需优化解决的性能自动化问题",{"0":{"271":1}}],["需要重命名文件或目录",{"2":{"300":1}}],["需要移动",{"2":{"300":1}}],["需要对自动化架构及各功能模块进行重新设计规划",{"2":{"278":1}}],["需要调用多个应用的方法模块",{"2":{"277":1}}],["需要传递参数的采用对象组合",{"2":{"265":1}}],["需要传入参数",{"2":{"218":1}}],["需要你可以在你想要发送的时间点手动触发回填",{"2":{"229":1}}],["需要处理实例化存在异常",{"2":{"222":1}}],["需要各位看官稍微品一品",{"2":{"204":1}}],["需要在每个函数里面主动编写日志输出代码",{"2":{"189":1}}],["需要使用ctrl+shift+v",{"2":{"183":1}}],["需要查找的元素名称",{"2":{"144":1}}],["需要安装deb包的本地路径",{"2":{"158":1,"252":1}}],["需要安装",{"2":{"64":1}}],["需要流水线上把这个参数加上",{"2":{"41":1}}],["根目录下的",{"2":{"267":1}}],["根据业务需要",{"2":{"284":1,"291":1}}],["根据业务需求封装接口业务方法",{"2":{"74":1}}],["根据现有业务需要",{"2":{"199":1}}],["根据标签执行",{"0":{"168":1}}],["根据关键词执行",{"0":{"167":1}}],["根据文件执行用例",{"2":{"158":1,"252":1}}],["根据右下角的坐标按钮的截图区域",{"2":{"149":1}}],["根据右下角的坐标按钮的中心坐标",{"2":{"149":1}}],["根据右上角的坐标按钮的截图区域",{"2":{"149":1}}],["根据右上角的坐标按钮的中心坐标",{"2":{"149":1}}],["根据左下角的坐标按钮的截图区域",{"2":{"149":1}}],["根据左下角的坐标按钮的中心坐标",{"2":{"149":1}}],["根据左上角的坐标按钮的截图区域",{"2":{"149":1}}],["根据左上角的坐标按钮的中心坐标",{"2":{"149":1}}],["根据应用程序中控件元素的相对坐标",{"2":{"149":1}}],["根据应用窗口在屏幕中的位置大小",{"2":{"147":1}}],["根据配置重试次数",{"2":{"133":1}}],["根据匹配度返回坐标",{"2":{"50":1,"133":1,"137":1}}],["根据获取",{"2":{"29":1}}],["根据",{"2":{"11":1}}],["作用和",{"2":{"267":1}}],["作为自动化测试的一个基础框架",{"2":{"258":1}}],["作为标记该用例是否已经修复",{"2":{"204":1}}],["作为变量输出出来了",{"2":{"192":1}}],["作为一个比较新的工具",{"2":{"185":1}}],["作为服务端",{"2":{"161":1,"255":1}}],["命名规则",{"2":{"266":1}}],["命令自动创建",{"2":{"248":1}}],["命令创建一个项目",{"2":{"246":1}}],["命令创建文件",{"2":{"109":1,"110":1,"111":1}}],["命令会生成在",{"2":{"245":1}}],["命令无法使用",{"2":{"245":1}}],["命令无法接收带空格的参数的问题",{"2":{"33":1}}],["命令行",{"2":{"213":1}}],["命令行执行",{"2":{"208":1}}],["命令行传递参数",{"2":{"204":1}}],["命令行传参",{"2":{"195":1}}],["命令行触发",{"2":{"195":1}}],["命令行参数的方式",{"2":{"210":1}}],["命令行参数的优先级高于配置文件配置",{"2":{"156":1}}],["命令行参数",{"0":{"158":1,"252":1}}],["命令行参数指定次数",{"2":{"53":1}}],["命令行使用方式和前面一样",{"2":{"195":1}}],["命令行使用",{"2":{"156":1}}],["命令行自动化测试是",{"2":{"112":1}}],["命令行自动化测试",{"0":{"112":1},"1":{"113":1,"114":1,"115":1},"2":{"241":1}}],["命令",{"2":{"43":1,"160":1,"254":1}}],["命令报错无法找到",{"2":{"34":1}}],["命令报错",{"2":{"25":1}}],["命令实现",{"2":{"10":1}}],["侧边栏",{"2":{"266":1}}],["构造函数的原因是通过参数构造应用",{"2":{"265":1}}],["构建地区",{"2":{"158":1,"252":1}}],["构建了一整套通用的",{"2":{"103":1}}],["见第二章节第3段目录结构内容",{"2":{"264":1}}],["局部配置了执行的用例标签",{"2":{"280":2}}],["局部配置未配置",{"2":{"280":1}}],["局部配置",{"2":{"262":2,"292":2}}],["具体要执行哪一种同样通过参数来控制",{"2":{"285":1}}],["具体功能模块及说明会在下面第四个章节详细描述",{"2":{"260":1}}],["具有可扩展性和复用性",{"2":{"275":1}}],["具有一定的模板作用",{"2":{"266":1}}],["具有较高的重复度",{"2":{"189":1}}],["灵魂",{"2":{"260":1}}],["各个模块只继承基类",{"2":{"295":1}}],["各个应用之间",{"2":{"280":1}}],["各个应用自己的仓库",{"2":{"260":1}}],["各标签所使用对应的字段名称",{"2":{"280":1}}],["各应用都有自己的迭代节奏",{"2":{"277":1}}],["各应用作为其中的一个模块",{"2":{"277":1}}],["各应用之间存在耦合",{"2":{"277":1}}],["各应用",{"2":{"273":1}}],["各应用方法里面不存在被多个应用调用的情况",{"2":{"273":1}}],["各应用能跟随自身迭代周期独立维护",{"2":{"273":1}}],["各种用例标签",{"2":{"202":1,"203":1,"204":1,"205":1,"284":1}}],["优美的执行日志",{"2":{"260":1}}],["优化终端输出失败信息冗长为简要信息输出",{"2":{"56":1}}],["优化执行",{"2":{"50":1}}],["优化远程执行",{"2":{"43":1}}],["优化基于",{"2":{"39":1}}],["优化了通过测试套件执行时pms",{"2":{"57":1}}],["优化了等待的日志输出",{"2":{"46":1}}],["优化了在线文档内容和排版",{"2":{"36":1}}],["优化了",{"2":{"35":1,"38":1,"43":1,"47":1}}],["优化数据回填逻辑",{"2":{"31":1}}],["优化",{"2":{"22":1}}],["统一成研",{"2":{"273":1}}],["统一概念",{"0":{"260":1}}],["统计功能新增",{"2":{"7":1}}],["二",{"0":{"259":1,"278":1,"290":1},"1":{"260":1,"261":1,"262":1,"279":1,"280":1,"291":1,"292":1}}],["数字",{"2":{"248":1}}],["数据格式为一个二维列表",{"2":{"136":1}}],["数据权限",{"2":{"74":1}}],["数据回填的触发者",{"2":{"229":1}}],["数据回填必须关联pms测试单",{"2":{"229":1}}],["数据回填也完成了",{"2":{"195":1}}],["数据回填主要有三种方式",{"2":{"195":1}}],["数据回填",{"2":{"158":1,"252":1}}],["数据回填兼容用例库id和产品库id",{"2":{"54":1}}],["数据回填时",{"2":{"31":1}}],["数据错误的问题",{"2":{"33":1}}],["数据中修复方法数量错误的问题",{"2":{"12":1}}],["数据汇报者统计者的利器",{"2":{"12":1}}],["数据",{"2":{"11":1,"148":1}}],["快速开始",{"0":{"244":1},"1":{"245":1,"246":1,"247":1,"248":1,"249":1,"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1},"2":{"299":1}}],["快捷键启动终端",{"2":{"216":1}}],["快捷键",{"2":{"183":1}}],["快捷键模块",{"2":{"181":1}}],["随处执行",{"2":{"242":1}}],["随着自动化用例数量的增加",{"2":{"285":1}}],["随着",{"2":{"121":1}}],["真正做到一套代码",{"2":{"242":1}}],["真的非常擅长构建",{"2":{"86":1}}],["硬件兼容",{"2":{"242":1}}],["软硬件兼容",{"2":{"242":1}}],["五彩斑斓的黑",{"2":{"242":1}}],["颜值也绝对在线",{"2":{"242":1}}],["满足你对执行器所有的幻想",{"2":{"242":1}}],["让他们觉得难度有点大",{"2":{"271":1}}],["让定位问题精准高效",{"2":{"242":1}}],["让你可以专注于用例和方法的编写维护",{"2":{"248":1}}],["让你可以方便的在本地执行",{"2":{"242":1}}],["让你再也不用为环境部署而烦恼",{"2":{"242":1}}],["让你能像调用本地方法一样调用远程方法",{"2":{"219":1}}],["让编写自动化测试用例成为一种享受",{"2":{"242":1}}],["爱上",{"0":{"242":1}}],["🌏",{"2":{"241":1}}],["🌟",{"2":{"5":1,"7":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"29":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"41":1,"47":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1}}],["☑",{"2":{"241":5}}],["💡",{"0":{"270":1},"1":{"271":1,"272":1}}],["🕷️",{"2":{"241":1}}],["🚀",{"2":{"241":1}}],["🚌",{"2":{"241":1}}],["💻",{"2":{"241":1}}],["🔥",{"2":{"240":1}}],["🐛ed",{"2":{"57":1}}],["🐛",{"2":{"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1}}],["面向服务的架构设计",{"2":{"239":1}}],["应该尽量将三方库里面使用到的部分剥离出来使用",{"2":{"239":1}}],["应用仓库",{"2":{"292":1}}],["应用解耦",{"2":{"287":6}}],["应用下载接口",{"2":{"286":1}}],["应用版本及下载地址",{"2":{"286":1}}],["应用层",{"0":{"296":1},"2":{"280":1}}],["应用层根据实际测试需求",{"2":{"280":1}}],["应用自己的方法库",{"2":{"280":1}}],["应用内局部配置",{"2":{"280":1}}],["应用内局部配置模块",{"2":{"280":1}}],["应用内包含多个测试类型",{"2":{"280":1}}],["应用间用例解耦",{"2":{"273":1}}],["应用",{"2":{"273":1}}],["应用库的仓库命名应该是长这样的",{"2":{"299":1}}],["应用库的架构设计可以参考",{"2":{"264":1}}],["应用库架构图",{"2":{"291":1}}],["应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计",{"2":{"289":1}}],["应用库里面方法基类",{"2":{"265":1}}],["应用库里面使用的时候在",{"2":{"265":1}}],["应用库设计方案",{"0":{"288":1},"1":{"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1},"2":{"264":1}}],["应用库详细目录结构请看应用库设计方案",{"2":{"262":1}}],["应用库",{"0":{"264":1},"2":{"184":1,"260":1,"262":1}}],["应用库只需要维护一套用例脚本即可",{"2":{"184":1}}],["应用库配置文件",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["应用窗口数量",{"2":{"175":1}}],["应用进程数量与期望",{"2":{"175":1}}],["应用进程数量是否为",{"2":{"175":1}}],["应用名",{"2":{"280":1}}],["应用名字",{"2":{"175":3}}],["应用名称",{"2":{"158":1,"252":1}}],["应用包名",{"2":{"149":3}}],["应用中会有相应的光标锁定",{"2":{"141":1}}],["应用的元素",{"2":{"144":2}}],["应用的自动化测试同样可以通过",{"2":{"140":1}}],["应用的方法基类",{"2":{"64":1,"84":1}}],["应用方法主类",{"2":{"84":2}}],["始终保持最少的依赖项",{"2":{"239":1}}],["激活虚拟环境",{"0":{"237":1}}],["存放一个",{"2":{"234":1}}],["存在耦合关系的方法",{"2":{"282":1}}],["存在的问题",{"0":{"277":1}}],["存在跳过标签则用例也不会被执行",{"2":{"202":1}}],["存在系统安全管控的问题",{"2":{"44":1}}],["裁剪依赖",{"0":{"234":1},"2":{"234":1}}],["起始日期",{"2":{"229":1}}],["无工程化设计的缺陷",{"2":{"273":1}}],["无处不在的代码补全",{"2":{"242":1}}],["无需添加",{"2":{"229":1}}],["无法整合性能自动化",{"2":{"277":1}}],["无法精准的划分用例范围",{"2":{"277":1}}],["无法使用上述的键鼠工具",{"2":{"182":1}}],["无法使用的问题",{"2":{"41":1}}],["无法定位到",{"2":{"130":1}}],["无法停止程序运行的问题",{"2":{"49":1}}],["无法连接",{"2":{"49":1}}],["无法管理",{"2":{"41":1}}],["无法收集到用例的问题",{"2":{"35":1}}],["无法获取到",{"2":{"17":1}}],["配合send",{"2":{"229":1}}],["配置模块",{"2":{"280":1}}],["配置的值",{"2":{"227":1}}],["配置对象获取",{"0":{"227":1}}],["配置完之后",{"2":{"195":1}}],["配置完成之后",{"2":{"159":1,"253":1}}],["配置",{"0":{"154":1}}],["配置方法",{"2":{"148":1}}],["配置说明",{"2":{"98":1}}],["配置项的值",{"2":{"133":1}}],["配置项",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"156":1,"231":1,"247":1}}],["配置项不生效",{"2":{"25":1}}],["配置python源的几种方法",{"2":{"42":1}}],["配置文件里面",{"2":{"226":1}}],["配置文件方式",{"2":{"210":1,"211":1}}],["配置文件其他相关配置项详细说明",{"2":{"161":1,"255":1}}],["配置文件在",{"2":{"156":1}}],["配置文件",{"0":{"159":1,"226":1,"253":1},"2":{"34":1,"68":1,"78":1,"88":1,"105":1,"114":1,"147":1,"148":1,"156":2,"195":1,"213":1,"226":2,"268":2}}],["配置文件中不管是否配置均不生效",{"2":{"156":1}}],["配置文件中",{"2":{"25":1,"227":1}}],["链接",{"2":{"229":1}}],["链式调用",{"0":{"124":1}}],["套件",{"2":{"229":1}}],["한국어",{"2":{"229":1}}],["日产出用例从",{"2":{"273":1}}],["日本語",{"2":{"229":1}}],["日志模板语法",{"2":{"192":1}}],["日志模块",{"2":{"280":1}}],["日志模块增加白名单",{"2":{"47":1}}],["日志模块修改为函数执行之前打印日志",{"2":{"47":1}}],["日志相关配置",{"2":{"191":1,"229":1}}],["日志配置",{"0":{"191":1}}],["日志文件",{"2":{"177":1}}],["日志输出不仅内容丰富",{"2":{"242":1}}],["日志输出级别",{"2":{"158":1,"252":1}}],["日志输出安装的版本",{"2":{"45":1}}],["日志内容显示为红色的问题",{"2":{"57":1}}],["日志生成到",{"2":{"54":1}}],["日志",{"2":{"26":1,"57":1}}],["русский",{"2":{"229":1}}],["网络重试次数",{"2":{"229":2}}],["网络加速方式加载",{"2":{"38":1}}],["生成的报告类型",{"2":{"226":1,"268":1}}],["生成的html报告",{"2":{"177":1}}],["譬如",{"2":{"226":1,"268":1}}],["跨过",{"0":{"217":1}}],["└─",{"2":{"213":1,"229":2}}],["└──",{"2":{"61":6,"68":1,"70":6,"71":5,"78":1,"80":6,"88":1,"92":2,"99":6,"100":5,"105":1,"107":6,"114":1,"177":10,"248":6,"262":6,"280":3,"292":2}}],["┼─",{"2":{"213":1,"229":2}}],["┌─",{"2":{"213":1,"229":2}}],["附属的测试机",{"2":{"213":1,"229":1}}],["交互的基础能力",{"2":{"212":1}}],["操作的对象是什么",{"2":{"301":1}}],["操作层",{"0":{"295":1},"2":{"301":1}}],["操作层文件名均以",{"2":{"282":1}}],["操作易上手",{"2":{"240":1}}],["操作系统的自动化测试框架",{"2":{"240":1}}],["操作或命令行操作",{"2":{"212":1}}],["操作步骤",{"0":{"200":1}}],["必须要配置的配置项",{"2":{"211":1,"229":1}}],["必须且只能传入其中一组",{"2":{"175":4}}],["节点下指定",{"2":{"211":1}}],["行话叫不要重复造轮子",{"2":{"239":1}}],["行未删除的问题",{"2":{"210":1}}],["行删掉",{"2":{"210":1}}],["到",{"0":{"210":1},"2":{"210":1}}],["于是乎将所有标签使用",{"2":{"206":1}}],["废弃原因",{"2":{"205":1}}],["废弃用例",{"0":{"205":1},"2":{"199":2,"205":2}}],["该列存在",{"2":{"205":1}}],["把配置模块写好",{"2":{"301":1}}],["把",{"2":{"204":1}}],["把每个菜单选项单独截图保存",{"2":{"128":1}}],["另一个需求又不想修复了立马解除跳过",{"2":{"204":1}}],["另外",{"2":{"41":1}}],["干掉",{"2":{"204":1}}],["干嘛不用",{"2":{"136":1}}],["历史",{"2":{"204":1}}],["跑",{"2":{"204":1}}],["已修复",{"2":{"204":2,"205":1}}],["已废弃",{"2":{"199":2,"205":1}}],["固定填入字段为",{"2":{"204":1}}],["固定跳过",{"0":{"202":1}}],["针对某些用例",{"2":{"205":1}}],["针对于某些用例修复后",{"2":{"204":1}}],["针对常规场景及一些特殊场景探索出了一些实用且有效的方案",{"2":{"132":1}}],["剔除中横线和",{"2":{"203":2}}],["剔除跳过数",{"2":{"12":2}}],["若外层执行器也配置了执行标签",{"2":{"280":1}}],["若",{"2":{"229":1}}],["若需要多个",{"2":{"203":1}}],["若函数需要多个参数",{"2":{"203":1}}],["若否则执行用例",{"2":{"203":1}}],["若是",{"2":{"203":1}}],["拼接",{"2":{"203":1}}],["受新需求影响跳过的用例不好维护",{"2":{"277":1}}],["受到某新需求影响",{"2":{"202":1,"204":1,"205":1,"284":1}}],["受安全管控的问题",{"2":{"42":1}}],["转的用例",{"2":{"199":1}}],["预留",{"2":{"199":1}}],["预期值",{"2":{"175":4}}],["安全自动化等专项测试",{"2":{"277":1}}],["安全",{"2":{"199":1}}],["安装部署",{"2":{"247":1}}],["安装依赖",{"0":{"247":1}}],["安装过程耗时等等问题",{"2":{"239":1}}],["安装下载目录下的deb包",{"2":{"229":1}}],["安装它是个很麻烦的事情",{"2":{"118":1}}],["安装速度起飞",{"2":{"41":1}}],["安装之后会自动生成一个系统命令",{"2":{"41":1}}],["安装",{"0":{"67":1,"77":1,"87":1,"104":1,"113":1,"151":1,"231":1,"245":1},"2":{"41":2,"42":1,"43":2,"44":1,"67":1,"69":1,"77":1,"79":1,"87":1,"89":1,"104":1,"106":1,"113":1,"115":1,"245":1}}],["安装包是比较臃肿的",{"2":{"40":1}}],["性能测试等不同测试类型的用例是分开执行的",{"2":{"285":1}}],["性能测试",{"2":{"280":2}}],["性能自动化支持以下功能",{"2":{"272":1}}],["性能",{"2":{"199":1}}],["怎么办呢",{"2":{"204":1}}],["怎么回填一次之后",{"2":{"197":1}}],["怎么解决这个问题呢",{"2":{"131":1}}],["直到所有用例执行结束",{"2":{"195":1}}],["直白的讲就是",{"2":{"195":1}}],["直接点左下角的",{"2":{"300":1}}],["直接在编辑器里面",{"2":{"300":1}}],["直接在用例里面继承",{"2":{"296":1}}],["直接在命令行执行",{"2":{"159":1,"253":1}}],["直接调用",{"0":{"217":1}}],["直接把",{"2":{"204":1}}],["直接修复了对吧",{"2":{"152":1}}],["直接",{"2":{"41":1,"301":1}}],["直接用",{"2":{"40":1}}],["直接拆分字符串可能会导致结果列表的最后一个元素为空字符串",{"2":{"30":1}}],["异步回填",{"2":{"195":1}}],["没关系",{"2":{"266":1,"301":1}}],["没错",{"2":{"192":1}}],["没有名称的就取一个好听易懂的名字",{"2":{"295":1}}],["没有参数的使用继承",{"2":{"265":1}}],["没有进入系统",{"2":{"182":1}}],["没有做相关适配",{"2":{"40":1}}],["没有用到全局配置",{"2":{"24":1}}],["细心的同学可能还发现了一个小细节",{"2":{"192":1}}],["展示在",{"2":{"192":1}}],["终端输出的日志级别",{"2":{"191":1,"229":1}}],["终止坐标",{"2":{"183":4}}],["批量跳过",{"2":{"260":1}}],["批量跳过和批量条件跳过的功能",{"2":{"242":1}}],["批量执行时",{"2":{"191":1,"229":1}}],["批量用例id驱动执行",{"0":{"169":1}}],["给后续其他应用改造提供切实可行的思路和方案",{"2":{"290":1}}],["给想要尝试或者愿意尝试的人员造成了一些困扰",{"2":{"271":1}}],["给符合条件的函数",{"2":{"190":1}}],["给定位环境安装失败带来困难",{"2":{"27":1}}],["核心",{"2":{"277":1}}],["核心层各功能模块保持独立性",{"2":{"280":1}}],["核心层主要服务于操作层",{"2":{"275":1}}],["核心层",{"2":{"275":2,"280":1}}],["核心模块",{"2":{"261":1}}],["核心库自动化测试所要用的到所有底层核心功能",{"2":{"260":1}}],["核心库",{"0":{"265":1},"2":{"260":2,"262":1}}],["核心原理",{"2":{"190":1}}],["核心是在网页的",{"2":{"140":1}}],["那可能需要修改大量涉及到资源路径的地方",{"2":{"302":1}}],["那你只需要修改这一个地方就好了",{"2":{"302":1}}],["那你就需要导入十个",{"2":{"265":1}}],["那些好不容易尝试用起来的人员",{"2":{"271":1}}],["那此用例为失败",{"2":{"196":1}}],["那真是妙啊~",{"2":{"189":1}}],["那么工程改造就全部完成了",{"2":{"303":1}}],["那么你可能不会用到这里面的功能",{"2":{"266":1}}],["那么你需要显示的导入这个模块",{"2":{"265":1}}],["那么一定要注意多个",{"2":{"233":1}}],["那么流水线上执行时这条用例仍然是跳过的状态",{"2":{"204":1}}],["那么也就可以判断图片切换是成功的",{"2":{"138":1}}],["那么在测试切换壁纸或者切换图片的场景时就会存在一个问题",{"2":{"138":1}}],["那么实际上",{"2":{"133":1,"147":1}}],["那么通过",{"2":{"131":1}}],["省略代码部分",{"2":{"189":1}}],["全量测试",{"2":{"280":1}}],["全称为",{"2":{"260":1}}],["全自动日志",{"0":{"188":1},"1":{"189":1,"190":1,"191":1,"192":1}}],["全局替换的方式任然无法保证真的全局被替换了",{"2":{"302":1}}],["全局替换",{"2":{"302":1}}],["全局搜索代码解耦",{"2":{"287":1}}],["全局",{"2":{"161":1,"255":1}}],["全局配置未配置",{"2":{"280":1}}],["全局配置了执行的用例标签",{"2":{"280":2}}],["全局配置和局部配置的策略如下",{"2":{"280":1}}],["全局配置项",{"2":{"280":1}}],["全局配置项明细",{"0":{"229":1}}],["全局配置模块",{"2":{"226":1,"262":1,"268":1,"280":1}}],["全局配置",{"0":{"225":1},"1":{"226":1,"227":1,"228":1,"229":1},"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["稳定性",{"2":{"185":1}}],["稳定性好的元素定位方案",{"2":{"146":1}}],["智能定位",{"2":{"185":1}}],["✔",{"2":{"185":8}}],["✗",{"2":{"185":6}}],["剩下",{"2":{"185":1}}],["排除",{"2":{"185":2}}],["排序方式",{"2":{"127":1}}],["市面上耳熟能详的可用于",{"2":{"185":1}}],["市面上甚至有完全基于图像识别的自动化测试框架",{"2":{"132":1}}],["驱动",{"2":{"235":1}}],["驱动浏览器实现",{"2":{"185":1}}],["驱动执行的时候加",{"2":{"223":1}}],["驱动执行",{"0":{"223":1},"2":{"165":1}}],["完美兼容",{"2":{"242":1}}],["完全通过命令行参数传入",{"2":{"211":1}}],["完全没必要专门拉新分支进行",{"2":{"184":1}}],["完善",{"2":{"185":1}}],["完成新框架使用培训",{"2":{"287":1}}],["完成全局和局部配置的具体方案和逻辑实现",{"2":{"287":1}}],["完成标签化管理和执行",{"2":{"287":5}}],["完成公共方法的抽取整合",{"2":{"273":1}}],["完成",{"2":{"13":1}}],["简单讲就是",{"2":{"184":1}}],["简化项目根目录下文件目录结构",{"2":{"15":1}}],["清理",{"2":{"229":1}}],["清理环境",{"2":{"158":1,"252":1}}],["清空表单",{"2":{"183":2}}],["框选",{"2":{"183":1}}],["框架扩展性不足",{"2":{"277":1}}],["框架只提供",{"2":{"271":1}}],["框架统一提供断言语句",{"2":{"187":1}}],["框架会调用",{"2":{"280":1}}],["框架会根据执行时状态自动判断走不同的逻辑",{"2":{"184":1}}],["框架会自动根据当前环境走不同的代码逻辑",{"2":{"59":1}}],["框架核心库也针对性的做了适配",{"2":{"184":1}}],["框架的运行逻辑",{"2":{"280":1}}],["框架的固定配置文件",{"2":{"267":1}}],["框架的断言库",{"2":{"174":1}}],["框架的很多网络相关功能都是基于此模块实现",{"2":{"76":1}}],["框架封装",{"0":{"143":1}}],["框架默认的配置为",{"2":{"133":1}}],["框架提供导出指定标签用例的功能",{"2":{"208":1}}],["框架提供的标签功能",{"2":{"206":1}}],["框架提供的接口非常简洁",{"2":{"143":1}}],["框架提供了一个图像识别的底层接口",{"2":{"133":1}}],["框架提供灵活可配置的浏览器对象",{"2":{"103":1}}],["框架基于",{"2":{"132":1}}],["框架代码示意",{"2":{"119":1}}],["框架里面只需要调用对应的",{"2":{"118":1}}],["框架还提供一个fixture对象",{"2":{"98":1,"229":1}}],["框架从设计之初",{"2":{"86":1}}],["框架根据全局的",{"2":{"50":1}}],["框架自动回填",{"2":{"229":1}}],["框架自动加载",{"2":{"43":1}}],["框架自动做负载均衡",{"2":{"13":1}}],["框架先做异常处理",{"2":{"31":1}}],["框架移除从",{"2":{"31":1}}],["框架为",{"2":{"16":1}}],["框架必备",{"2":{"12":1,"14":1}}],["项目",{"2":{"248":1}}],["项目根目录下运行",{"2":{"231":1}}],["项目标识文件",{"2":{"100":2}}],["项",{"2":{"183":2}}],["组合按键释放",{"2":{"183":1}}],["组合按键按下不放",{"2":{"183":1}}],["组合键",{"2":{"142":1}}],["放到",{"2":{"283":1}}],["放松",{"2":{"183":1}}],["放松按键",{"2":{"183":1}}],["放入子项目的at代码即可",{"2":{"41":1}}],["间隔",{"2":{"183":1}}],["临时处理",{"2":{"183":1}}],["粘贴内容后会在末尾会多出一个空格",{"2":{"183":1}}],["延迟时间",{"2":{"183":1}}],["滚动鼠标滚轮",{"2":{"183":1}}],["滚轮数",{"2":{"183":1}}],["滚轮",{"2":{"142":1}}],["松开鼠标",{"2":{"183":1}}],["松开鼠标左键",{"2":{"183":1}}],["键盘组合键",{"2":{"183":1}}],["键盘组合按键操作",{"2":{"183":1}}],["键盘按键",{"2":{"183":3}}],["键盘上指定的按键",{"2":{"183":1}}],["键",{"2":{"183":1}}],["键不放",{"2":{"183":1}}],["键鼠信号模拟模块",{"2":{"280":1}}],["键鼠的基本操作模块",{"2":{"181":1}}],["键鼠操作模块",{"2":{"280":1}}],["键鼠操作模块集成了多个键鼠操作的方案",{"2":{"180":1}}],["键鼠操作的基础方操作模块",{"2":{"275":1}}],["键鼠操作",{"0":{"180":1},"1":{"181":1,"182":1,"183":1}}],["键鼠工具没有鼠标相对移动方法",{"2":{"38":1}}],["键鼠控制方案",{"2":{"32":1}}],["处按住鼠标",{"2":{"183":1}}],["处理那种没有关联关系",{"2":{"302":1}}],["处理这个问题",{"2":{"154":1}}],["处理",{"2":{"26":2}}],["拖拽的相对位置y",{"2":{"183":1}}],["拖拽的相对位置x",{"2":{"183":1}}],["拖拽的时长",{"2":{"183":1}}],["拖拽后等待的时间",{"2":{"183":1}}],["拖拽到的位置y",{"2":{"183":1}}],["拖拽到的位置x",{"2":{"183":1}}],["拖拽到指定位置",{"2":{"183":2}}],["三",{"0":{"263":1,"281":1,"293":1},"1":{"264":1,"265":1,"266":1,"267":1,"268":1,"282":1,"283":1,"284":1,"285":1,"286":1,"294":1,"295":1,"296":1,"297":1}}],["三击鼠标左键",{"2":{"183":1}}],["三方依赖",{"2":{"53":1}}],["三方包",{"2":{"41":1}}],["速度",{"2":{"183":2}}],["特别是在一些配置较低的机器上会很明显",{"2":{"193":1}}],["特别是一些示例",{"2":{"185":1}}],["特殊场景键鼠操作",{"0":{"182":1}}],["特有的",{"2":{"168":1}}],["任何应用接入进来都能快速方便的进行方法和用例编写",{"2":{"260":1}}],["任何应用都能很方便的接入进来",{"2":{"258":1}}],["任何模块当然是希望越简洁通用越好",{"2":{"180":1}}],["任斌",{"2":{"25":1}}],["好用",{"2":{"258":1}}],["好像用不到这么多键鼠操作的东西吧",{"2":{"180":1}}],["好处是参数路径可以在终端补全",{"2":{"49":1}}],["地址",{"2":{"178":1}}],["地址修改为域名",{"2":{"51":1}}],["录屏模块",{"2":{"280":1}}],["录屏是要占用系统资源的",{"2":{"193":1}}],["录屏其实是一种视频形式的日志",{"2":{"193":1}}],["录屏",{"2":{"177":1}}],["录屏外",{"2":{"53":1}}],["缺失",{"2":{"175":2}}],["缺少",{"2":{"175":2}}],["主界面区域划分",{"2":{"295":1}}],["主要通过用例的关键词",{"2":{"277":1}}],["主要封装的底层功能实现",{"2":{"275":1}}],["主要是为了减少代码量",{"2":{"260":1}}],["主要提供配置文件读取",{"2":{"226":1,"268":1}}],["主要配置一些全局的配置项",{"2":{"226":1,"268":1}}],["主题颜色占屏幕总体颜色占比低于60",{"2":{"175":1}}],["主动传入",{"2":{"24":1}}],["深色",{"2":{"175":2}}],["浅色",{"2":{"175":2}}],["建议你使用",{"2":{"302":1}}],["建议分模块",{"2":{"200":1,"284":1}}],["建议最大化窗口",{"2":{"175":1}}],["建议现在上方工具栏点击",{"2":{"141":1}}],["共享文件夹名称",{"2":{"175":2}}],["路径处理",{"0":{"302":1}}],["路径组装方法",{"2":{"294":1}}],["路径",{"2":{"175":6}}],["期望尺寸",{"2":{"175":1}}],["期望结果",{"2":{"175":2}}],["期望的主题",{"2":{"175":1}}],["期望的进程数量",{"2":{"175":1}}],["期望元素不存在",{"2":{"175":1}}],["期望元素存在",{"2":{"175":1}}],["期望不存在文件路径",{"2":{"175":1}}],["期望存在文件路径",{"2":{"175":1}}],["期望界面不存在模板图片",{"2":{"175":1}}],["期望界面存在模板图片",{"2":{"175":1}}],["屏幕上匹配不存在图片",{"2":{"175":1}}],["屏幕上匹配图片",{"2":{"175":2}}],["屏幕恰好出现了两个",{"2":{"131":1}}],["例",{"2":{"175":3}}],["例如`ch`",{"2":{"119":1}}],["例如",{"2":{"86":1,"149":2,"175":2,"189":1,"200":1,"203":1}}],["表格中的用例编号",{"2":{"287":1}}],["表格打开进行编辑",{"2":{"280":1}}],["表达式",{"2":{"167":1,"168":1}}],["表示所有用例执行完成之后逐个回填",{"2":{"229":1}}],["表示所有测试机并行跑",{"2":{"161":1,"255":1}}],["表示逐条异步回填",{"2":{"229":1}}],["表示记录前3个进程",{"2":{"229":1}}],["表示重跑",{"2":{"229":1}}],["表示执行标签带有",{"2":{"229":1}}],["表示导出",{"2":{"208":1}}],["表示用例的id",{"2":{"200":1}}],["表示用例第1次执行失败之后开始录屏",{"2":{"193":2}}],["表示用例第",{"2":{"41":1,"229":1}}],["表示上线到",{"2":{"199":1}}],["表示不回填",{"2":{"229":1}}],["表示不管用例成功或失败都录屏",{"2":{"193":1}}],["表示不做分辨率校验",{"2":{"41":1,"229":1}}],["表示识别任意一个目标字符",{"2":{"175":1}}],["表示识别所有目标字符",{"2":{"175":1}}],["表示测试机分布式执行",{"2":{"161":1,"255":1}}],["表示扫描当前目录下所有的代码",{"2":{"152":1}}],["表示",{"2":{"134":1,"199":1,"284":1}}],["表示大图为截取的屏幕截图",{"2":{"133":1}}],["表示只返回识别到的第一个",{"2":{"133":1}}],["拿第",{"2":{"162":1,"256":1}}],["拿到整个屏幕的大图",{"2":{"133":1}}],["号机执行",{"2":{"162":2,"256":2}}],["台",{"2":{"162":1,"256":1}}],["台机器执行相同的用例",{"2":{"161":1,"255":1}}],["似乎有点难以理解",{"2":{"162":1,"256":1}}],["请提",{"2":{"182":1}}],["请查看配置文件中的注释内容",{"2":{"161":1,"255":1}}],["请手动开启",{"2":{"161":1,"255":1}}],["请求",{"2":{"137":1}}],["请求被分发到两台不同的服务器上",{"2":{"122":1}}],["请求成功",{"2":{"75":1}}],["记得加上参数",{"2":{"161":1,"255":1}}],["记录top命令查询的系统资源占用情况",{"2":{"229":1}}],["记录youqu当前的版本",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["记录依赖youqu的版本",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["除了常用的属性定位",{"2":{"242":1}}],["除了上面这种导入方式",{"2":{"227":1}}],["除了文档方面",{"2":{"185":1}}],["除了这些特有参数以外",{"2":{"161":1,"255":1}}],["除了通过",{"2":{"41":1}}],["搭建测试环境",{"2":{"161":1,"229":1,"255":1}}],["搭建了一个",{"2":{"137":1}}],["控制远程",{"2":{"161":1,"255":1}}],["控件名称",{"2":{"149":1}}],["控件名",{"2":{"149":2}}],["控件长宽",{"2":{"149":4}}],["控件右下角相对于窗口右下角的纵向距离",{"2":{"149":2}}],["控件右下角相对于窗口右下角的横向距离",{"2":{"149":2}}],["控件右上角相对于窗口右上角的纵向距离",{"2":{"149":2}}],["控件右上角相对于窗口右上角的横向距离",{"2":{"149":2}}],["控件左下角相对于窗口左下角的纵向距离",{"2":{"149":2}}],["控件左下角相对于窗口左下角的横向距离",{"2":{"149":2}}],["控件左上角相对于窗口左上角的纵向距离",{"2":{"149":2}}],["控件左上角相对于窗口左上角的横向距离",{"2":{"149":2}}],["控件的中心坐标",{"2":{"149":8}}],["控件高度",{"2":{"149":8}}],["控件宽度",{"2":{"149":8}}],["入参还支持",{"2":{"158":1}}],["过程中记录top命令中的值",{"2":{"158":1,"252":1}}],["过去我们调研和使用过的元素定位操作方法有",{"2":{"126":1}}],["过去咱们",{"2":{"41":1}}],["过去咱们都是使用这样的命令来驱动执行",{"2":{"41":1}}],["过去一段时间咱们经常出现的",{"2":{"41":1}}],["触发者",{"2":{"158":1,"252":1}}],["仅仅用于用例中导入方便",{"2":{"296":1}}],["仅用于属性定位相关操作",{"2":{"215":1}}],["仅驱动执行这一条用例",{"2":{"164":1}}],["仅执行上次失败用例",{"2":{"158":1,"252":1}}],["仅通过skip跳过用例",{"2":{"158":1,"229":1,"252":1}}],["仅支持x11下使用",{"2":{"133":1,"137":1}}],["仅支持传入工程名称的全称",{"2":{"34":1}}],["绝对位置",{"2":{"183":1}}],["绝对路径",{"2":{"149":1}}],["绝大部分的配置项均在",{"2":{"156":1}}],["举例",{"2":{"156":1,"284":2}}],["脚本id",{"2":{"199":1,"202":1,"203":1}}],["脚本",{"2":{"199":1}}],["脚本的结果",{"2":{"11":1}}],["脚手架等功能",{"2":{"155":1}}],["写",{"2":{"265":1}}],["写法",{"2":{"158":1}}],["写入json文件",{"2":{"158":3,"252":3}}],["写入错误代码",{"2":{"154":1}}],["写日志文件报权限不够的问题",{"2":{"17":1}}],["官方在线文档",{"2":{"220":1}}],["官方不支持",{"2":{"185":1}}],["官方表示是可以直接替代",{"2":{"153":1}}],["官方兴趣小组",{"0":{"60":1}}],["效果一定能惊讶到你",{"2":{"242":1}}],["效果会持续优化",{"2":{"178":1}}],["效果很不错对吧",{"2":{"153":1}}],["效果非常好",{"2":{"146":1}}],["接收一个字典",{"2":{"175":2}}],["接下来就可以进行代码格式化",{"2":{"153":1}}],["接口操作模块",{"2":{"275":1,"280":1}}],["接口操作的模块",{"2":{"66":1}}],["接口从而控制远程机器执行用例步骤",{"2":{"212":1}}],["接口",{"2":{"199":1}}],["接口就行了",{"2":{"118":1}}],["接口请求",{"2":{"122":1}}],["接口请求成功",{"2":{"75":1}}],["接口请求创建管理员",{"2":{"75":1}}],["接口测试",{"2":{"75":1,"185":1}}],["接口业务层",{"2":{"74":1}}],["接口的测试",{"2":{"66":1}}],["接口自动化测试是一个传统测试类型",{"2":{"76":1}}],["接口自动化测试",{"0":{"66":1,"76":1},"1":{"67":1,"68":1,"69":1,"77":1,"78":1,"79":1},"2":{"241":2}}],["接口保持不变",{"2":{"58":1}}],["接口改变",{"2":{"49":1}}],["问题",{"0":{"197":1},"2":{"153":1}}],["说明我们代码中没有",{"2":{"153":1}}],["说明图片已经切换了",{"2":{"138":1}}],["格式文件可以方便的使用",{"2":{"280":1}}],["格式化这块",{"2":{"153":1}}],["格式化工具",{"2":{"150":1}}],["格局没打开",{"2":{"185":1}}],["格局小了",{"2":{"136":1}}],["长宽",{"2":{"149":1}}],["长时间不输出日志连接中断的问题",{"2":{"47":1}}],["负数向上",{"2":{"183":1}}],["负数向左",{"2":{"183":1}}],["负数为向下",{"2":{"183":1}}],["负数为下移动",{"2":{"149":2}}],["负数为左移动",{"2":{"149":2}}],["负载均衡",{"0":{"121":1},"1":{"122":1,"123":1}}],["负载均衡驱动模式下自动汇总",{"2":{"11":1}}],["正数向下",{"2":{"183":1}}],["正数向右",{"2":{"183":1}}],["正数为向上",{"2":{"183":1}}],["正数为上移动",{"2":{"149":2}}],["正数为右移动",{"2":{"149":2}}],["正式启用",{"2":{"37":1}}],["高配",{"2":{"272":1}}],["高配版",{"2":{"272":1}}],["高",{"2":{"149":1}}],["高度",{"2":{"50":1,"133":1,"137":1,"138":1,"175":2}}],["您可以在任意目录下",{"2":{"246":1}}],["您可以使用",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"231":1,"247":1}}],["您想要获取的窗口为",{"2":{"149":1}}],["窗口的实际大小",{"2":{"175":1}}],["窗口的期望大小",{"2":{"175":1}}],["窗口的基本信息",{"2":{"149":1}}],["窗口置顶并聚焦",{"2":{"149":2}}],["窗口编号列表",{"2":{"149":1}}],["窗口数量",{"2":{"149":1}}],["窗口中心坐标",{"2":{"149":1}}],["窗口右下角坐标",{"2":{"149":1}}],["窗口右上角坐标",{"2":{"149":1}}],["窗口左边界中心坐标",{"2":{"149":1}}],["窗口左下角坐标",{"2":{"149":1}}],["窗口左上角坐标",{"2":{"149":2}}],["窗口宽高等",{"2":{"149":1}}],["窗口信息",{"2":{"149":1}}],["窗管研发",{"2":{"39":1}}],["窗管获取窗口信息的接口",{"2":{"22":1}}],["拉动改变窗口大小时",{"2":{"148":1}}],["读",{"2":{"147":1}}],["读取",{"2":{"206":1}}],["读取小图和大图的rgb值",{"2":{"136":1}}],["读取配置文件config",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["设置界面弹窗",{"2":{"295":1}}],["设计理念",{"2":{"291":1}}],["设计方案",{"0":{"259":1},"1":{"260":1,"261":1,"262":1}}],["设计模式",{"2":{"248":1,"265":1}}],["设计思路",{"0":{"206":1,"280":1}}],["设计稿上点击",{"2":{"147":1}}],["设计图上获取数据",{"2":{"148":1}}],["设计图上获取",{"2":{"147":1}}],["设计图上的源数据修改对应坐标数据就好",{"2":{"146":1}}],["设计图中我们是可以获取到元素按钮相对于应用边框的距离的",{"2":{"147":1}}],["设备类型",{"2":{"34":1,"199":2}}],["带鱼屏",{"2":{"146":1}}],["宽",{"2":{"149":1}}],["宽屏",{"2":{"146":1}}],["宽度",{"2":{"50":1,"133":1,"137":1,"138":1,"175":2}}],["递归查找应用界面的元素",{"2":{"144":1}}],["递归查找子节点",{"2":{"144":2}}],["查找图片",{"2":{"192":2}}],["查找到的元素对象的列表",{"2":{"144":1}}],["查找界面元素",{"2":{"144":1}}],["查找元素的个数与期望一致",{"2":{"175":1}}],["查找元素",{"2":{"144":1}}],["查看每个方法被调用的路径和被调用次数",{"2":{"282":1}}],["查看机器的cpu型号",{"2":{"203":2}}],["查看方法和前面本地执行查看的方法一样",{"2":{"179":1}}],["查看报告",{"0":{"179":1}}],["查看子命令的帮助",{"2":{"156":1}}],["查看它的帮助",{"2":{"156":1}}],["查看",{"2":{"142":1}}],["查看应用的标签",{"2":{"141":1}}],["^",{"2":{"144":1,"154":1,"175":2}}],["位置是在元素的中心",{"2":{"144":1}}],["|",{"2":{"144":1,"183":1,"192":2,"203":4,"222":1}}],["播放所有",{"2":{"147":5}}],["播放",{"2":{"143":1}}],["双击鼠标左键",{"2":{"183":1}}],["双击元素",{"2":{"144":1}}],["双击",{"2":{"142":1}}],["双击等等",{"2":{"131":1}}],["库里面的",{"2":{"142":1}}],["元素等待",{"2":{"185":1}}],["元素个数",{"2":{"175":1}}],["元素不应存在",{"2":{"175":1}}],["元素不存在",{"2":{"175":1}}],["元素的定位和操作方法层",{"2":{"275":1}}],["元素的相对位置和参考系",{"2":{"149":1}}],["元素的对象",{"2":{"143":1,"144":1}}],["元素按钮相对于参考系位置是不变的",{"2":{"148":1}}],["元素按钮相对于应用窗口边界的位置大小",{"2":{"147":1}}],["元素对象名称",{"2":{"295":1}}],["元素对象",{"2":{"144":2}}],["元素定位操作的一些公共方法",{"2":{"294":1}}],["元素定位和操作方法层",{"2":{"275":1}}],["元素定位",{"2":{"144":2}}],["元素定位的问题就转换为",{"2":{"133":1}}],["元素双击",{"2":{"144":1}}],["元素点击",{"2":{"144":1}}],["元素右上角坐标",{"2":{"144":1}}],["元素",{"2":{"144":2}}],["元素大小",{"2":{"144":1}}],["元素左上角坐标",{"2":{"144":2}}],["元素名称",{"2":{"144":2}}],["元素中心坐标",{"2":{"143":1,"144":1}}],["元素操作",{"0":{"142":1}}],["首先想到的就是去搜索看有没有现成的工具直接能用",{"2":{"239":1}}],["首先需要将配置",{"2":{"211":1,"229":1}}],["首先",{"2":{"141":1,"204":1}}],["首先这里的主要操作对象是任务栏",{"2":{"84":1}}],["启动",{"2":{"141":1}}],["启用",{"2":{"20":1}}],["嗅探器",{"0":{"141":1}}],["借助开源工具",{"2":{"140":1}}],["树",{"2":{"140":1}}],["树上查找元素",{"2":{"140":1}}],["树里怎么也找不到",{"2":{"130":1}}],["示意图如下",{"2":{"147":1}}],["示意图",{"2":{"138":1}}],["示例",{"2":{"119":1,"175":2,"177":1,"199":1,"202":1,"203":1,"204":1}}],["壁纸顺序不同",{"2":{"138":1}}],["动作开头",{"2":{"295":1}}],["动作函数的函数对象",{"2":{"131":1}}],["动分配给各个测试机执行",{"2":{"161":1,"255":1}}],["动态加载核心层",{"2":{"280":1}}],["动态获取一些常量",{"2":{"226":1,"268":1}}],["动态获取元素在当前屏幕中的位置",{"2":{"146":1}}],["动态添加标签到用例中",{"2":{"206":1}}],["动态添加日志装饰器",{"2":{"190":1}}],["动态给该类下所有的函数及父类函数添加日志装饰器",{"2":{"190":1}}],["动态图像识别",{"0":{"138":1}}],["客户端",{"2":{"272":2}}],["客户端对象提供的",{"2":{"219":1}}],["客户端代码示意",{"2":{"137":1}}],["客户端使用",{"2":{"137":1}}],["注释的写法等等",{"2":{"266":1}}],["注册自启服务",{"2":{"229":1}}],["注册了",{"2":{"137":1}}],["注意这些修改是会影响到用例代码里面的",{"2":{"301":1}}],["注意是动词",{"2":{"295":1}}],["注意",{"2":{"156":1,"161":1,"175":2,"192":1,"193":1,"229":1,"246":1,"255":1,"300":2,"302":1}}],["注意用例继承了用例基类",{"2":{"85":1}}],["来区分用例是否为核心用例",{"2":{"277":1}}],["来标记这条用例已经修复了",{"2":{"204":1}}],["来实现",{"2":{"137":1}}],["来表示的",{"2":{"129":1}}],["许多语言都是支持的",{"2":{"137":1}}],["我也推荐使用这种方式进行重命名",{"2":{"302":1}}],["我说的是",{"2":{"300":1}}],["我想恢复跳过执行",{"2":{"204":1}}],["我之前就只用",{"2":{"180":1}}],["我用大白话举例描述下",{"2":{"162":1,"256":1}}],["我认为还是可以接受的",{"2":{"136":1}}],["我们是将所有应用看成是一个整体",{"2":{"277":1}}],["我们框架中有不少核心功能都是在这里面进行开发的",{"2":{"267":1}}],["我们还自己设计了一款终端输出主题叫",{"2":{"242":1}}],["我们还提供基于",{"2":{"242":1}}],["我们还增强了报告的功能",{"2":{"13":1}}],["我们采用最新的",{"2":{"204":1}}],["我们采用的方案是",{"2":{"134":1}}],["我们设计出了",{"2":{"189":1}}],["我们发现",{"2":{"189":1}}],["我们从一些方面做对比",{"2":{"185":1}}],["我们提供了另外一种解决方案",{"2":{"182":1}}],["我们推荐第一种使用方法",{"2":{"181":1}}],["我们推出了",{"2":{"13":1}}],["我们需要对",{"2":{"154":1}}],["我们需要截取某个元素的小图进行识别",{"2":{"133":1}}],["我们就可以对元素进行相应的操作",{"2":{"142":1}}],["我们通过索引可以取得元素",{"2":{"142":1}}],["我们只要保证自动化测试用例中",{"2":{"141":1}}],["我们只能创建一个空的同名文件",{"2":{"26":1}}],["我们称之为属性定位",{"2":{"140":1}}],["我们再拿着这张小图在当前屏幕中进行图像识别",{"2":{"138":1}}],["我们截取了当前图片中比较有代表性的位置",{"2":{"138":1}}],["我们基于",{"2":{"137":1}}],["我们的方案每次识别在",{"2":{"136":1}}],["我们承认这套方案",{"2":{"136":1}}],["我们也能实现其功能",{"2":{"136":1}}],["我们也联合研发同学一起解决此问题",{"2":{"130":1}}],["我们自己实现主要有几方面原因",{"2":{"136":1}}],["我们可以轻松的获取到按钮",{"2":{"147":1}}],["我们可以通过传入元素的",{"2":{"142":1}}],["我们可以通过将图片的每个像素的rgb值",{"2":{"136":1}}],["我们可以对元素进行获取",{"2":{"140":1}}],["我们可以截取到整个屏幕的图片",{"2":{"133":1}}],["我们约定将用于元素定位的图片资源放到",{"2":{"133":1}}],["我们实现了图像定位的功能",{"2":{"133":1}}],["我们在",{"2":{"179":1}}],["我们在长时间的思考和摸索中",{"2":{"132":1}}],["我们在右键菜单识别上的突破和创新",{"2":{"131":1}}],["我们最开始想到的方案就是通过属性定位",{"2":{"130":1}}],["我们并不推荐这种操作方案",{"2":{"129":1}}],["我们并不希望直接在",{"2":{"118":1}}],["我们想到将它做成一个",{"2":{"118":1}}],["我们使用",{"2":{"117":1,"204":1}}],["我们计划使用",{"2":{"52":1}}],["我们认为取",{"2":{"23":1}}],["我们坚信这些更新将极大地提升开发者和测试人员的效率",{"2":{"13":1}}],["我们针对用户反馈的多个问题进行了积极的调查和解决",{"2":{"13":1}}],["我们对",{"2":{"13":1,"178":1}}],["我们显著提高了文本识别的准确性和效率",{"2":{"13":1}}],["我们成功在欧拉社区开源",{"2":{"12":1}}],["整体仍然遵循",{"2":{"291":1}}],["整体的框架设计在",{"2":{"261":1}}],["整体识别效果来讲",{"2":{"136":1}}],["整个字符串中可以任意截取字符作为关键词",{"2":{"167":1,"229":1}}],["整合公共库",{"2":{"258":1}}],["整合",{"2":{"15":1}}],["左边视图区域",{"2":{"295":1}}],["左",{"2":{"183":2}}],["左下角按钮的截取区域左上角",{"2":{"149":1}}],["左下角按钮的中心坐标",{"2":{"149":1}}],["左下角的坐标",{"2":{"149":1}}],["左下",{"2":{"148":1}}],["左上",{"2":{"148":1}}],["左上角按钮的截取区域左上角",{"2":{"149":1}}],["左上角按钮的中心坐标",{"2":{"149":1}}],["左上角坐标",{"2":{"149":2}}],["左上角",{"2":{"147":1,"175":4}}],["左上角相对于屏幕左上角",{"2":{"147":1}}],["左上角纵坐标",{"2":{"50":1,"133":1,"137":1,"138":1}}],["左上角横坐标",{"2":{"50":1,"133":1,"137":1,"138":1}}],["左键",{"2":{"142":1,"144":1,"183":2}}],["左右",{"2":{"136":2}}],["虽然识别准确率没问题",{"2":{"136":1}}],["虽然操作很简单",{"2":{"118":1}}],["呢",{"2":{"136":1}}],["甚至有些就没有说明",{"2":{"185":1}}],["甚至有些应用支持自定义菜单",{"2":{"127":1}}],["甚至有没有可能在一些架构上压根儿就不能安装使用",{"2":{"136":1}}],["成功",{"2":{"136":1}}],["减少功能测试的重复劳动力",{"2":{"276":1}}],["减少方法重复编写",{"2":{"273":1}}],["减少应用库代码量和方法维护",{"2":{"258":1}}],["减少环境依赖对于任何软件工程都非常重要",{"2":{"136":1}}],["减少环境依赖",{"2":{"136":1}}],["减少因全屏识别时",{"2":{"53":1}}],["小了",{"2":{"136":1}}],["小图的rgb值",{"2":{"136":1}}],["小图",{"2":{"133":1}}],["都支持逻辑组合",{"2":{"229":1}}],["都为空表示执行",{"2":{"229":1}}],["都是通过",{"2":{"219":1}}],["都不需要再写日志代码",{"2":{"192":1}}],["都还不够好",{"2":{"185":1}}],["都没有匹配到",{"2":{"136":1}}],["都将小图所有的rgb与对应大图的值进行匹配",{"2":{"136":1}}],["赋值给一个变量small",{"2":{"136":1}}],["则调用本应用目录下重写的外部应用方法",{"2":{"283":1}}],["则这个方法存在耦合关系",{"2":{"282":1}}],["则按照局部配置执行",{"2":{"280":1}}],["则按照全局配置执行",{"2":{"280":2}}],["则会按照全局配置执行用例",{"2":{"280":1}}],["则在",{"2":{"283":1}}],["则在外部应用下新建一个",{"2":{"282":1}}],["则在执行时只会执行局部配置已配置的",{"2":{"280":1}}],["则在此列备注具体的跳过原因",{"2":{"202":1,"284":1}}],["则失败用例数达到",{"2":{"229":1}}],["则操作复杂",{"2":{"206":1}}],["则用例不会执行",{"2":{"205":1}}],["则用例不执行",{"2":{"203":1}}],["则新增一列标签名为",{"2":{"205":1}}],["则代码不会执行该条用例",{"2":{"204":1}}],["则执行该用例",{"2":{"203":1}}],["则跳过用例不执行",{"2":{"203":1}}],["则说明大图中不存在小图",{"2":{"136":1}}],["则此时返回小图在大图中的坐标点",{"2":{"136":1}}],["则移动到下一个坐标点",{"2":{"136":1}}],["则匹配成功",{"2":{"136":1}}],["则输出以",{"2":{"30":1}}],["与",{"2":{"175":4}}],["与期望",{"2":{"175":6}}],["与期望个数",{"2":{"175":1}}],["与本地",{"2":{"155":1}}],["与整个屏幕中的rgb进行对比",{"2":{"136":1}}],["与命令行的交互也是相对容易的",{"2":{"112":1}}],["帧",{"2":{"134":1}}],["适应不断丰富的测试场景",{"2":{"278":1}}],["适合在生产环境运行",{"2":{"271":1}}],["适用于各种屏幕分辨率",{"2":{"146":1}}],["适用于查找多个同名称元素",{"2":{"144":1}}],["适用于气泡类的断言",{"2":{"134":1,"175":1}}],["适配",{"0":{"184":1},"2":{"184":1}}],["适配社区版上安装自动化环境",{"2":{"57":1}}],["适配最新的接口",{"2":{"22":1}}],["肯定有至少一张图片能捕捉到气泡",{"2":{"134":1}}],["出现一下就消失",{"2":{"134":1}}],["出现的程序报错问题",{"2":{"57":1}}],["气泡识别指的是",{"2":{"134":1}}],["气泡识别",{"0":{"134":1},"2":{"134":1}}],["函数",{"2":{"199":1,"267":1}}],["函数功能说明中",{"2":{"192":1}}],["函数说明以及函数操作日志",{"2":{"189":1}}],["函数名的重命名都尽量采用这种方案",{"2":{"300":1}}],["函数名",{"2":{"203":1}}],["函数名与参数之间用",{"2":{"203":1}}],["函数名等等都可以做为关键词",{"2":{"167":1,"229":1}}],["函数名称为",{"2":{"203":1}}],["函数名称",{"2":{"71":1,"100":1}}],["函数的所有功能",{"2":{"133":1}}],["取决于应用的用例复杂度",{"2":{"200":1,"284":1}}],["取中间的名称作为",{"2":{"200":1}}],["取全局配置",{"2":{"133":1}}],["取消收藏",{"2":{"119":2}}],["取消收藏字体",{"2":{"119":1}}],["坐标的元素定位模块",{"2":{"275":1}}],["坐标",{"2":{"149":1,"175":10,"294":1}}],["坐标元组",{"2":{"133":1}}],["坐标没有拆包的问题",{"2":{"46":1}}],["隐式等待",{"2":{"133":1}}],["某些用例会因为不同的环境判断用例是否执行",{"2":{"203":1}}],["某些场景下要定位的元素是一些会消失的小弹窗",{"2":{"134":1}}],["某些场景下",{"2":{"133":1}}],["某个元素图片的截图称为",{"2":{"133":1}}],["通常来讲如果你需要使用到其中某一个功能模块",{"2":{"265":1}}],["通常是这样的",{"2":{"189":1}}],["通常在",{"2":{"133":1}}],["通过页面上的一些功能选项进行对应测试任务的管理或触发",{"2":{"286":1}}],["通过编辑器",{"2":{"282":1}}],["通过相应的配置项进行配置",{"2":{"280":1}}],["通过核心层提供一个基础能力",{"2":{"280":1}}],["通过图像识别的元素定位模块",{"2":{"275":1}}],["通过串口线连接控制",{"2":{"272":1}}],["通过远程网络连接控制",{"2":{"272":1}}],["通过服务接口",{"2":{"239":1}}],["通过以下几个配置来控制",{"2":{"211":1}}],["通过命令行参数的方式执行优先级总是最高的",{"2":{"210":1}}],["通过命令行参数配置参数",{"2":{"158":1}}],["通过一下几个配置来控制",{"2":{"210":1}}],["通过获取该函数返回的布尔值",{"2":{"203":1}}],["通过子线程去做第一条用例的数据回填",{"2":{"195":1}}],["通过观察前面的例子",{"2":{"192":1}}],["通过日志输出器将其输出即可",{"2":{"190":1}}],["通过给类加上一个装饰器",{"2":{"190":1}}],["通过经验观察",{"2":{"189":1}}],["通过ocr在范围",{"2":{"175":5}}],["通过ocr未识别到",{"2":{"119":2}}],["通过配置文件配置参数",{"2":{"159":1,"253":1}}],["通过配置元素的x",{"2":{"149":1}}],["通过层级获取元素",{"2":{"144":1}}],["通过属性进行元素定位和操作",{"2":{"144":1}}],["通过属性定位的方式",{"2":{"282":1,"283":1}}],["通过属性定位的元素定位模块",{"2":{"275":1}}],["通过属性定位",{"2":{"84":3}}],["通过返回",{"2":{"137":1}}],["通过前后图片的对比",{"2":{"131":1}}],["通过维护菜单选项",{"2":{"129":1}}],["通过使用键盘上下键",{"2":{"127":1}}],["通过键盘的",{"2":{"127":1}}],["通过",{"2":{"119":1,"136":1,"190":2,"227":1,"275":1,"280":1}}],["通过任务栏打开文件管理器",{"2":{"85":1}}],["通过类名开头",{"2":{"47":1}}],["通过选项来控制安装逻辑",{"2":{"15":1}}],["通过引入",{"2":{"13":1}}],["通过率",{"2":{"12":1}}],["通过数",{"2":{"12":2}}],["详细方案",{"0":{"263":1,"281":1,"293":1},"1":{"264":1,"265":1,"266":1,"267":1,"268":1,"282":1,"283":1,"284":1,"285":1,"286":1,"294":1,"295":1,"296":1,"297":1}}],["详细技术方案",{"2":{"220":1}}],["详细源代码请查看",{"2":{"147":1}}],["详细代码请查看",{"2":{"143":1}}],["详细代码太长不贴了",{"2":{"133":1}}],["详细记录的问题",{"2":{"17":1}}],["截取当前屏幕实时图像保存路径",{"2":{"229":1}}],["截取的左侧字符串作为函数名",{"2":{"203":1}}],["截取屏幕图片的间隔时间",{"2":{"134":1,"175":1}}],["截取屏幕图片的时间",{"2":{"134":2,"175":1}}],["截取屏幕上指定区域图片",{"2":{"133":1,"137":1,"138":1,"229":1}}],["截图的最大次数",{"2":{"134":1}}],["截图",{"2":{"53":1}}],["否则会提示无法连接",{"2":{"161":1,"255":1}}],["否则使用传入的图片",{"2":{"133":1,"137":1}}],["否则走服务",{"2":{"40":1}}],["大多数情况下",{"2":{"239":1}}],["大图的rgb值",{"2":{"136":1}}],["大图默认情况下是截取整个屏幕",{"2":{"133":1}}],["大图",{"2":{"133":2,"137":1}}],["大到添加章节帮助我们提高项目的",{"2":{"1":1}}],["要使用核心库的功能",{"2":{"265":1}}],["要安装deb包的路径",{"2":{"229":1}}],["要导出用例的标签",{"2":{"208":1}}],["要用到的元素都添加了标签即可",{"2":{"141":1}}],["要特殊说明的是",{"2":{"137":1}}],["要识别的模板图片",{"2":{"134":1,"175":1}}],["要识别的图片路径",{"2":{"119":1,"175":2}}],["要获取到目标元素在屏幕中的位置",{"2":{"133":1}}],["等所有用例执行完之后",{"2":{"195":1}}],["等等",{"2":{"184":1,"226":1,"268":1}}],["等建了不同的目录",{"2":{"179":1}}],["等",{"2":{"132":1,"175":1,"226":1,"268":1}}],["等待文件管理器启动",{"2":{"85":1}}],["从功能上将是属于核心库",{"2":{"267":1}}],["从基础框架根目录开始",{"2":{"229":1}}],["从",{"0":{"211":1},"2":{"245":1}}],["从第二列开始及之后的列",{"2":{"200":1,"284":1}}],["从而触发自动化测试任务",{"2":{"280":1}}],["从而减轻应用库代码的维护工作",{"2":{"266":1}}],["从而减少大量日志代码量和重复编写",{"2":{"189":1}}],["从而避免全量引入三方库",{"2":{"239":1}}],["从而进行定位操作",{"2":{"140":1}}],["从上面的例子也可以看出来",{"2":{"189":1}}],["从上到下",{"2":{"183":3}}],["从某个坐标开始画线",{"2":{"183":1}}],["从下到上",{"2":{"183":2}}],["从业务上将处理起来比较麻烦",{"2":{"131":1}}],["从理论上此方案是可行的",{"2":{"129":1}}],["复制",{"2":{"131":3,"183":1}}],["几乎所有多媒体应用都需要通过文管加载资源",{"2":{"283":1}}],["几乎在各方面碾压",{"2":{"185":1}}],["几乎都是指的",{"2":{"156":1}}],["几乎是最优的方案",{"2":{"131":1}}],["几乎满足了所有的断言场景",{"2":{"85":1,"173":1}}],["非常遗憾",{"2":{"130":1}}],["非常重要",{"2":{"100":1}}],["维护用例及其方法",{"2":{"289":1}}],["维护起来有难度",{"2":{"277":1}}],["维护起来有点麻烦",{"2":{"129":1}}],["维护和执行",{"2":{"273":1}}],["维护非常的方便",{"2":{"146":1}}],["维度统计",{"2":{"13":1,"15":1}}],["菜单顺序改变",{"2":{"129":1}}],["菜单选项的坐标计算方法为",{"2":{"129":1}}],["菜单选项的宽",{"2":{"129":1}}],["菜单选项的变化是很大的",{"2":{"127":1}}],["变化的影响",{"2":{"131":1}}],["变化的是菜单的长度",{"2":{"129":1}}],["变更类需求的影响",{"2":{"128":1}}],["鼠标从当前位置拖拽到相对坐标",{"2":{"183":1}}],["鼠标从当前位置拖拽到坐标",{"2":{"183":1}}],["鼠标三连击坐标",{"2":{"183":1}}],["鼠标左键双击坐标",{"2":{"183":1}}],["鼠标右键坐标",{"2":{"183":1}}],["鼠标当前的坐标",{"2":{"183":1}}],["鼠标和键盘的常用操作",{"2":{"183":1}}],["鼠标移动相对坐标位置",{"2":{"183":1}}],["鼠标移动至",{"2":{"183":1}}],["鼠标移动到元素上",{"2":{"144":1}}],["鼠标移动到元素中心位置",{"2":{"142":1}}],["鼠标移至元素",{"2":{"144":1}}],["鼠标中健",{"2":{"144":1}}],["鼠标悬停",{"2":{"142":1}}],["鼠标在桌面不同位置点击右键",{"2":{"129":1}}],["鼠标的当前坐标是可以获取到的",{"2":{"129":1}}],["鼠标点击右键的时候",{"2":{"129":1}}],["且支持用例标签可扩展",{"2":{"280":1}}],["且要方便能使用",{"2":{"207":1}}],["且大小写不敏感",{"2":{"167":1,"229":1}}],["且能明确表示这个元素按钮的名称",{"2":{"148":1}}],["且效率极高",{"2":{"146":1}}],["且包含上面介绍的",{"2":{"133":1}}],["且听我慢慢道来",{"2":{"132":1}}],["且容易受到字体",{"2":{"128":1}}],["且远程操作方法实现了编辑器代码补全",{"2":{"16":1}}],["常量",{"2":{"294":1}}],["常见的场景为在不同架构上判断是否执行",{"2":{"203":1}}],["常见问题等的文档说明",{"2":{"57":1}}],["常规键鼠操作",{"0":{"181":1}}],["常规识别很好理解",{"2":{"133":1}}],["常规识别",{"0":{"133":1}}],["常规图像识别法",{"0":{"128":1}}],["一次导入",{"2":{"265":1}}],["一",{"0":{"258":1,"274":1,"289":1},"1":{"275":1,"276":1,"277":1}}],["一键部署环境",{"2":{"242":1}}],["一切我们给你搞定了",{"2":{"242":1}}],["一些用例资源需要根据",{"2":{"302":1}}],["一些业务层相关的变量",{"2":{"294":1}}],["一些团队并不能找到那么多机器",{"2":{"271":1}}],["一些支持人工修改或自定义的配置项都在",{"2":{"226":1}}],["一些特殊场景下",{"2":{"182":1}}],["一二级bug自动化",{"2":{"199":2}}],["一个应用的功能测试",{"2":{"280":1}}],["一个应用含有大量的操作函数",{"2":{"189":1}}],["一个需求是想修复了立马解除跳过",{"2":{"204":1}}],["一个函数里面至少包含一条日志信息",{"2":{"189":1}}],["一个选项现在的步长是",{"2":{"127":1}}],["一只鸟",{"2":{"138":1}}],["一起技术报国",{"2":{"136":1}}],["一般情况下不涉及修改",{"2":{"134":1}}],["一般不对上层提供调用",{"2":{"133":1}}],["一般是固定的",{"2":{"129":1}}],["一句话讲就是",{"2":{"133":1}}],["一种是面向服务",{"2":{"40":1}}],["按钮",{"2":{"300":1}}],["按钮无效的问题",{"2":{"34":1}}],["按照我们提供给你的接口写用例的操作方法就好了",{"2":{"301":1}}],["按照我们一贯的风格",{"2":{"211":1}}],["按照",{"2":{"300":1}}],["按照文件管理器的界面区域划分为",{"2":{"295":1}}],["按照应用划分存放",{"2":{"260":1}}],["按照注释解决即可",{"2":{"184":1}}],["按照这样的规律将这一行每移动一个坐标点",{"2":{"136":1}}],["按下",{"2":{"183":1}}],["按住键盘按键不放",{"2":{"183":1}}],["按住鼠标键不放",{"2":{"183":1}}],["按住鼠标左键",{"2":{"183":1}}],["按",{"2":{"127":1}}],["按键",{"2":{"127":1}}],["步长操作法",{"0":{"127":1}}],["步骤展示",{"2":{"53":1}}],["种方式传入",{"2":{"213":1}}],["种",{"2":{"126":1}}],["现有跳过用例的方式是在用例脚本里面给用例添加装饰器",{"2":{"284":1}}],["现有右键菜单定位的方案及问题",{"0":{"126":1},"1":{"127":1,"128":1,"129":1,"130":1}}],["现at框架架构图",{"2":{"279":1}}],["现在应用走独立发布",{"2":{"277":1}}],["现在远程机器有",{"2":{"162":1,"256":1}}],["现在将开发到命令行参数",{"2":{"41":1}}],["现在开源到",{"2":{"41":1}}],["去掉用例序号后的字符串",{"2":{"200":1}}],["去掉末尾空格",{"2":{"183":1}}],["去掉批量执行前收集用例的步骤",{"2":{"53":1}}],["去干扰图像识别",{"2":{"131":1}}],["去干扰识别",{"0":{"125":1,"131":1},"1":{"126":1,"127":1,"128":1,"129":1,"130":1,"131":1}}],["段是一样的",{"2":{"122":1}}],["段做哈希",{"2":{"122":1}}],["轮询算法做负载均衡会出现两次",{"2":{"122":1}}],["第一列为用例的",{"2":{"284":1}}],["第一列为脚本",{"2":{"200":1}}],["第一个为",{"2":{"149":1}}],["第二天跑的时候同一个机器上会执行昨天没有执行到的用例",{"2":{"285":1}}],["第二条用例开始跑的时候",{"2":{"195":1}}],["第二种是原生",{"2":{"40":1}}],["第",{"2":{"122":2,"183":2}}],["单独的应用仓库",{"2":{"262":2}}],["单条用例的超时时间",{"2":{"229":1}}],["单条用例超时时间",{"2":{"158":1,"226":1,"252":1,"268":1}}],["单位为秒",{"2":{"229":1}}],["单位是秒",{"2":{"134":1}}],["单位秒",{"2":{"134":1,"175":5}}],["单击鼠标右键",{"2":{"183":1}}],["单击鼠标滚轮中间",{"2":{"183":2}}],["单击",{"2":{"131":1,"142":1}}],["单台服务远不能满足业务需求",{"2":{"121":1}}],["单词的地方都修改成",{"2":{"71":1,"100":1}}],["选择右键菜单中的子菜单选项",{"2":{"183":1}}],["选择右键菜单中的选项",{"2":{"183":2}}],["选择桌面右键菜单中的选项",{"2":{"183":2}}],["选择未收藏字体",{"2":{"119":1}}],["选中目标之后",{"2":{"127":1}}],["选项传入密码",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"231":1,"247":1}}],["选项用于传递系统密码",{"2":{"17":1}}],["字母",{"2":{"248":1}}],["字典字段",{"2":{"175":2}}],["字体间距等等需求变更都会影响",{"2":{"128":1}}],["字体大小",{"2":{"128":1}}],["字体管理器界面右侧详情列表",{"2":{"119":1}}],["字段作为判断依据",{"2":{"27":1}}],["收藏字体",{"2":{"119":2}}],["收藏",{"2":{"119":1}}],["收集远程测试机上所有的",{"2":{"11":2}}],["右边视图区域",{"2":{"295":1}}],["右",{"2":{"183":2}}],["右侧就会出现该元素按钮的",{"2":{"148":1}}],["右侧♥",{"2":{"119":1}}],["右下角",{"2":{"175":4}}],["右下角按钮的截取区域左上角",{"2":{"149":1}}],["右下角按钮的中心坐标",{"2":{"149":1}}],["右下角的坐标",{"2":{"149":1}}],["右下",{"2":{"148":1}}],["右上角按钮的截取区域左上角",{"2":{"149":1}}],["右上角按钮的中心坐标",{"2":{"149":1}}],["右上角的坐标",{"2":{"149":1}}],["右上角坐标",{"2":{"144":1}}],["右上",{"2":{"148":1}}],["右键菜单在鼠标的左上",{"2":{"129":1}}],["右键菜单可能出现在鼠标的四个方向",{"2":{"129":1}}],["右键菜单出现的位置是不同的",{"2":{"129":1}}],["右键菜单的元素定位是一个难点",{"2":{"126":1}}],["右键菜单显示",{"2":{"119":1}}],["右键",{"2":{"119":1,"142":1,"144":1,"183":2}}],["右键不生效的问题",{"2":{"46":1}}],["监听客户端请求",{"2":{"119":1}}],["`docstring",{"2":{"154":1}}],["`",{"2":{"154":1}}],["`c901`",{"2":{"154":1}}],["`ch`",{"2":{"119":1,"175":2}}],["`w`",{"2":{"154":1}}],["`e`",{"2":{"154":1}}],["`en`",{"2":{"119":2,"175":2}}],["`f`",{"2":{"154":1}}],["`fr`",{"2":{"119":2,"175":2}}],["`japan`",{"2":{"119":2,"175":2}}],["`korean`",{"2":{"119":2,"175":2}}],["`german`",{"2":{"119":2,"175":2}}],["匹配元素个数",{"2":{"175":1}}],["匹配元素的格式",{"2":{"175":3}}],["匹配相似度",{"2":{"175":2}}],["匹配结果索引",{"2":{"144":1}}],["匹配格式",{"2":{"144":1}}],["匹配失败",{"2":{"136":1}}],["匹配小图里面所有的坐标点",{"2":{"136":1}}],["匹配小图在屏幕中的坐标",{"2":{"133":1,"137":1}}],["匹配从大图的坐标",{"2":{"136":1}}],["匹配度",{"2":{"119":1,"133":1,"137":1,"175":2}}],["匹配模式",{"2":{"18":1}}],["实施计划",{"0":{"287":1}}],["实例",{"2":{"192":1}}],["实例方法",{"2":{"190":1}}],["实际上",{"2":{"227":1}}],["实际尺寸",{"2":{"175":1}}],["实际结果",{"2":{"175":2}}],["实际占比",{"2":{"175":1}}],["实际窗口大小",{"2":{"175":1}}],["实现核心库接口",{"0":{"301":1}}],["实现一个前后端分离的系统",{"2":{"286":1}}],["实现细节",{"2":{"220":1}}],["实现步骤",{"2":{"190":1}}],["实现了一个中间件用以在用例跑测过程中对",{"2":{"123":1}}],["实现原理",{"0":{"118":1,"147":1,"190":1}}],["实践方法",{"0":{"186":1}}],["实践",{"2":{"11":1}}],["你也可以在小弹窗中修改全局替换为局部目录下替换",{"2":{"302":1}}],["你也可以不去管配置文件",{"2":{"211":1}}],["你需要按照核心库方法的调用",{"2":{"301":1}}],["你可千万别直接删了修改名称",{"2":{"300":1}}],["你可以从业务逻辑出发",{"2":{"301":1}}],["你可以参考文件管理器的实际工程代码",{"2":{"301":1}}],["你可以参考上面的设计理念来写",{"2":{"301":1}}],["你可以快速的开始你的",{"2":{"248":1}}],["你可以选择在不同的阶段进行数据回填",{"2":{"229":1}}],["你可以根据自己喜欢选择用哪个",{"2":{"227":1}}],["你可以把",{"2":{"197":1}}],["你可以通过视频文件看到失败用例执行过程都发生了什么",{"2":{"193":1}}],["你可以使用",{"2":{"156":1}}],["你可以直接在系统中使用截图录屏进行尺量",{"2":{"148":1}}],["你可以任意命名",{"2":{"148":1}}],["你可以在这些目录里面去查看对应的测试报告",{"2":{"179":1}}],["你可以在配置文件中每一个配置项上面看到该配置项的使用说明",{"2":{"156":1}}],["你可以在实例化对象的时候显式的传入",{"2":{"149":1}}],["你可以在调用函数的时候",{"2":{"133":1}}],["你可以在",{"2":{"41":1,"178":1}}],["你这个重命名的操作关联了多个模块",{"2":{"300":1}}],["你所有的方法都可以直接写在应用库的业务层",{"2":{"266":1}}],["你想输出什么报告形式都行",{"2":{"242":1}}],["你想不到一个",{"2":{"242":1}}],["你再也不用为每个方法单独写输出日志的代码",{"2":{"242":1}}],["你不需要有额外的导入代码即可使用到所有的方法",{"2":{"181":1}}],["你仍然通过命令行参数进行传参",{"2":{"161":1,"255":1}}],["你们是不是闲的啊",{"2":{"136":1}}],["你只需要在应用库根目录下",{"2":{"234":1}}],["你只需要将你的图片路径传递给这个参数就行",{"2":{"133":1}}],["你只需要知道它就是中文识别的天花板",{"2":{"117":1}}],["你看",{"2":{"131":1,"152":1}}],["你会发现一切都是那么的简单",{"2":{"301":1}}],["你会发现",{"2":{"129":1}}],["感兴趣请查看源码",{"2":{"133":1}}],["感兴趣的可以点这里了解",{"2":{"117":1}}],["感谢王波总",{"2":{"41":1}}],["感谢桌面测试部",{"2":{"39":1}}],["感谢",{"2":{"20":1,"21":1,"22":1,"26":1,"28":1,"29":1,"30":1,"33":2}}],["感谢您参与本项目",{"2":{"0":1}}],["经过前面代码检查并修复之后",{"2":{"153":1}}],["经过大量的调研",{"2":{"117":1}}],["经过和业务专家多轮次讨论和反复验证观察",{"2":{"23":1}}],["传统跳过用例的方式是在用例脚本里面给用例添加装饰器",{"2":{"201":1}}],["传统的日志输出方式",{"2":{"189":1}}],["传统的",{"2":{"117":1,"140":1}}],["传入目标小图的文件名称",{"2":{"136":1}}],["传入目标图片路径",{"2":{"50":1}}],["传入不同的识别度的值",{"2":{"133":1}}],["传入多个识别目标逻辑判断错误的问题",{"2":{"34":1}}],["传入的标签超过",{"2":{"26":1}}],["传入",{"2":{"16":1,"50":1,"56":1}}],["背景介绍",{"0":{"274":1},"1":{"275":1,"276":1,"277":1}}],["背景",{"0":{"117":1,"140":1,"146":1,"189":1},"2":{"133":1,"134":1,"138":1}}],["z0",{"2":{"154":2}}],["za",{"2":{"154":2}}],["zero",{"2":{"110":1}}],["zh",{"2":{"74":2,"229":2}}],["输入的内容",{"2":{"183":1}}],["输入字符串",{"2":{"183":2}}],["输入youqu",{"2":{"98":1}}],["输出原始数据错误的问题",{"2":{"17":1}}],["百度首页搜索",{"2":{"98":1}}],["搜索框中输入关键词",{"2":{"97":1}}],["搜索框输入youqu",{"2":{"96":1}}],["点击某个元素",{"2":{"189":2,"192":1,"282":1,"283":1}}],["点击键盘上指定的按键",{"2":{"183":1}}],["点击坐标",{"2":{"183":1}}],["点击鼠标左键",{"2":{"183":1}}],["点击新建歌单按钮",{"2":{"148":1}}],["点击",{"2":{"148":1,"183":1}}],["点击元素",{"2":{"144":1}}],["点击相应的元素控件",{"2":{"141":1}}],["点击应用名称前面的三角形图标",{"2":{"141":1}}],["点击右键菜单之后再截取一张图",{"2":{"131":1}}],["点击搜索框",{"2":{"97":1,"98":1}}],["点击任务栏上的音乐图标",{"2":{"93":1}}],["点击任务栏上的文件管理器图标",{"2":{"83":1,"84":3,"85":1}}],["访问百度首页",{"2":{"97":1}}],["访问速度更快",{"2":{"41":1}}],["发送代码到测试机",{"2":{"161":1,"229":1,"255":1}}],["发送给",{"2":{"137":1}}],["发送",{"2":{"93":1}}],["发布了新版本",{"2":{"30":2}}],["继电器",{"2":{"272":1}}],["继承操作层的所有类",{"2":{"296":1}}],["继承核心层",{"2":{"294":1}}],["继承的类符合",{"2":{"265":1}}],["继承",{"2":{"174":1,"184":1}}],["继承底层",{"2":{"93":1}}],["继续再按",{"2":{"127":1}}],["继续尝试将一些功能模块拆分为独立构件",{"2":{"34":1}}],["显示协议",{"2":{"86":1,"240":1,"242":1}}],["显示为",{"2":{"57":1}}],["桌面的操作方法",{"2":{"283":1}}],["桌面公共方法类",{"2":{"266":1}}],["桌面公共方法基类",{"2":{"266":1}}],["桌面应用性能自动化测试",{"0":{"270":1},"1":{"271":1,"272":1}}],["桌面应用",{"2":{"241":1}}],["桌面应用大多是采用",{"2":{"140":1}}],["桌面",{"0":{"86":1},"1":{"87":1,"88":1,"89":1},"2":{"86":1}}],["判断当前架构是否为",{"2":{"203":1}}],["判断",{"2":{"83":1,"85":1}}],["判断操作系统的激活状态为激活",{"2":{"63":1,"65":1}}],["封装的方法整理成一个表",{"2":{"287":1}}],["封装",{"2":{"76":1}}],["封装用例步骤的方法",{"0":{"64":1,"74":1,"84":1,"97":1,"110":1}}],["自定义断言模块",{"2":{"280":1}}],["自定义断言",{"2":{"242":1}}],["自定义断言类",{"2":{"175":1}}],["自带多种断言语句",{"2":{"173":1}}],["自带网络接口模块",{"2":{"76":1}}],["自研图像识别技术",{"0":{"136":1}}],["自动安装指定应用版本",{"2":{"280":1}}],["自动安装镜像",{"2":{"280":1}}],["自动环境清理等等",{"2":{"260":1}}],["自动生成多种报告",{"2":{"242":1}}],["自动从pms爬取数据并同步本地csv文件",{"2":{"229":1}}],["自动同步标签到",{"0":{"211":1}}],["自动同步脚本",{"0":{"210":1}}],["自动同步到",{"2":{"36":1}}],["自动将函数说明打印为日志",{"2":{"191":3,"229":3}}],["自动输出日志",{"2":{"242":1}}],["自动输出日志的配置",{"2":{"191":1,"229":1}}],["自动输出的日志",{"2":{"192":1}}],["自动输入日志增加以",{"2":{"17":1}}],["自动的将函数说明作为日志打印出来",{"2":{"189":1}}],["自动化维护变得异常困难",{"2":{"277":1}}],["自动化的应用",{"0":{"276":1}}],["自动化相关的依赖",{"2":{"234":1}}],["自动化大多都是基于浏览器的",{"2":{"140":1}}],["自动化中是不可缺少的",{"2":{"132":1}}],["自动化用例脚本",{"2":{"199":1}}],["自动化用例",{"2":{"98":1}}],["自动化项目",{"2":{"86":1}}],["自动化测试平台作为前端界面系统",{"2":{"286":1}}],["自动化测试平台",{"0":{"286":1},"2":{"280":1}}],["自动化测试架构设计规划",{"0":{"273":1},"1":{"274":1,"275":1,"276":1,"277":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1}}],["自动化测试架构设计",{"2":{"261":1}}],["自动化测试对应的去跑这些关联的用例",{"2":{"194":1}}],["自动化测试工具",{"2":{"185":1}}],["自动化测试方案",{"2":{"103":1}}],["自动化测试方向也有非常多的技术突破",{"2":{"86":1}}],["自动化测试是一种通用的自动化测试类型",{"2":{"103":1}}],["自动化测试为基础",{"2":{"86":1}}],["自动化测试",{"0":{"86":1,"103":1},"1":{"87":1,"88":1,"89":1,"104":1,"105":1,"106":1},"2":{"185":1,"186":1,"241":2}}],["自动化测试基础框架",{"2":{"41":1,"260":1,"262":1}}],["自动化测试功能",{"2":{"16":1}}],["自动化测试功能和远程交互式控制功能",{"2":{"13":1}}],["自动化测试框架操作方法封装写法",{"2":{"189":1}}],["自动化测试框架在便捷性和稳定性方面迈出了重要的一步",{"2":{"13":1}}],["自动化测试框架迎来了一系列令人振奋的更新",{"2":{"13":1}}],["自动创建的",{"2":{"248":1}}],["自动创建",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1}}],["自动计算出",{"2":{"50":1}}],["备注信息",{"2":{"74":1}}],["管理负载均衡算法时",{"2":{"122":1}}],["管理权限管理员分组数组id",{"2":{"74":1}}],["管理部门范围",{"2":{"74":1}}],["管理员",{"2":{"75":1}}],["管理员照片",{"2":{"74":1}}],["管理员邮箱",{"2":{"74":1}}],["管理员手机号",{"2":{"74":1}}],["管理员姓名",{"2":{"74":1}}],["管理员账号",{"2":{"74":1}}],["管理员api",{"2":{"74":1}}],["角色权限",{"2":{"74":1}}],["关键词驱动支持",{"2":{"167":1}}],["关键词可以是用例对象中的任意字符",{"2":{"167":1,"229":1}}],["关于",{"2":{"131":1}}],["关联角色id",{"2":{"74":1}}],["关闭同步",{"2":{"210":1}}],["关闭终端输出捕获用例执行过程日志快照",{"2":{"56":1}}],["关闭录屏",{"2":{"41":1,"229":1}}],["密码问题",{"2":{"231":1,"247":1}}],["密码",{"2":{"74":1,"158":1,"252":1}}],["qdbus",{"2":{"175":1}}],["qt",{"2":{"140":3}}],["q=0",{"2":{"74":1}}],["quote",{"2":{"154":1}}],["quotes",{"2":{"154":1}}],["quot",{"2":{"16":4,"27":4,"30":2,"133":2,"200":2}}],["及各种网络弹窗",{"2":{"295":1}}],["及子目录无",{"2":{"175":1}}],["及大小",{"2":{"147":1,"148":1}}],["及其相关依赖存在问题",{"2":{"144":1}}],["及",{"2":{"74":1}}],["再逐个进行回填的接口请求",{"2":{"195":1}}],["再或者直接导入键鼠模块使用",{"2":{"181":1}}],["再次扫描就不会再报之前的问题",{"2":{"154":1}}],["再次执行",{"0":{"72":1,"101":1}}],["再进行",{"2":{"131":1}}],["再按",{"2":{"127":1}}],["再一个就是",{"2":{"40":1}}],["底层库用途说明文档编写",{"2":{"287":1}}],["底层核心模块包括",{"2":{"280":1}}],["底层功能库层",{"2":{"275":1}}],["底层src",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["底层基础能力的代码为上层业务服务",{"2":{"3":1}}],["编辑器推荐使用",{"2":{"300":1}}],["编辑器打开",{"0":{"62":1,"81":1,"102":1,"108":1}}],["编码规范",{"2":{"280":1}}],["编写定时自动维护本地",{"2":{"287":1}}],["编写爬虫脚本",{"2":{"287":1}}],["编写和维护用例时只需要自己应用下的方法和公共库即可",{"2":{"280":1}}],["编写和维护更高效",{"2":{"273":1}}],["编写方法时只需要导入一个包就可以使用到核心库提供的所有功能",{"2":{"242":1}}],["编写的",{"2":{"140":1}}],["编写用例时逻辑比较复杂",{"2":{"277":1}}],["编写用例",{"0":{"65":1,"75":1,"85":1,"98":1,"111":1}}],["即为公共方法库",{"2":{"283":1}}],["即应用的用例",{"2":{"275":1}}],["即它是对应用库中的用例生效的",{"2":{"267":1}}],["即使标记了skip",{"2":{"229":1}}],["即第一次用例执行失败会自动重跑",{"2":{"229":1}}],["即",{"2":{"193":1,"229":1}}],["即最后一个窗口",{"2":{"149":1}}],["即重试",{"2":{"133":1}}],["即在一定的时间内",{"2":{"133":1}}],["即可在终端激活当前虚拟环境",{"2":{"237":1}}],["即可实现条件判断跳过",{"2":{"203":1}}],["即可返回在当前屏幕中的中心坐标",{"2":{"136":1}}],["即可返回小图在大图中的中心坐标点",{"2":{"136":1}}],["即可轻松计算出菜单选项在屏幕中的坐标",{"2":{"129":1}}],["即可",{"2":{"119":1,"127":1,"133":1,"195":1,"221":1,"231":1,"265":1}}],["即可启动工具",{"2":{"64":1}}],["即任意一个匹配成功则通过",{"2":{"18":1}}],["其丰富的自定义配置项",{"2":{"242":1}}],["其使用简单且高效",{"2":{"242":1}}],["其在pms上的音乐用例库的url为",{"2":{"211":1,"229":1}}],["其根本问题就是标签分散在每一条用例的装饰器上",{"2":{"206":1}}],["其效果一定能惊讶到你",{"2":{"146":1}}],["其实",{"2":{"130":1}}],["其中功能测试设计思路",{"2":{"280":1}}],["其中有一张图片识别成功即返回结果",{"2":{"134":1,"175":1}}],["其中",{"2":{"64":1,"236":1}}],["其他人员也就可想而知",{"2":{"271":1}}],["其他的都不需要",{"2":{"234":1}}],["其他的一些配置也可以根据自己的一些需要进行配置",{"2":{"154":1}}],["其他方法类",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["其他应用的基于相对位移元素定位方案的配置文件",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["其他文字的干扰",{"2":{"53":1}}],["其他一些小小功能更新",{"2":{"41":1}}],["授权接口对象",{"2":{"64":1}}],["打开进行编辑查看",{"2":{"207":1}}],["打开",{"2":{"62":1,"81":1,"102":1,"108":1}}],["│\\t└──",{"2":{"165":1}}],["│\\t├──",{"2":{"165":1}}],["│",{"2":{"61":60,"70":60,"71":49,"80":60,"92":24,"99":60,"100":51,"107":60,"165":5,"177":14,"248":10,"262":68,"280":27,"292":15}}],["├──",{"2":{"61":21,"68":8,"70":21,"71":17,"78":8,"80":21,"88":8,"92":8,"99":21,"100":18,"105":8,"107":21,"114":8,"165":4,"177":12,"233":4,"234":2,"248":21,"262":41,"280":13,"292":18}}],["工程改造实施步骤",{"0":{"298":1},"1":{"299":1,"300":1,"301":1,"302":1,"303":1}}],["工程这部分代码即可",{"2":{"248":1}}],["工程遵循完整的",{"2":{"248":1}}],["工程中的资源",{"2":{"218":1}}],["工程的功能",{"2":{"218":1}}],["工程自有断言模块",{"2":{"174":1}}],["工程名称需要符合",{"2":{"248":1}}],["工程名称命名规范",{"2":{"248":1}}],["工程名称",{"2":{"158":1,"248":1,"252":1}}],["工程里面",{"2":{"133":1}}],["工程",{"0":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1},"1":{"62":1,"71":1,"72":1,"81":1,"100":1,"101":1,"102":1,"108":1},"2":{"61":2,"70":2,"80":2,"99":2,"107":2,"248":2}}],["工具查看",{"2":{"64":1,"84":1}}],["工具",{"2":{"55":1}}],["定位模块",{"2":{"280":1}}],["定位的方案写法",{"2":{"266":1}}],["定位的坐标配置文件",{"2":{"262":1,"292":1}}],["定位配置文件路径",{"2":{"149":1}}],["定制依赖",{"0":{"232":1},"1":{"233":1,"234":1}}],["定制",{"2":{"178":1}}],["定制报告",{"0":{"178":1}}],["定制修改allure报告logo",{"2":{"53":1}}],["定能碰撞出智慧的火花",{"2":{"60":1}}],["相关的模块是否也一起改名了",{"2":{"300":1}}],["相关环境就准备好了",{"2":{"101":1}}],["相互之间是独立的",{"2":{"266":1}}],["相互之间不影响",{"2":{"41":1}}],["相册的用例文件为",{"2":{"200":1}}],["相册切换图片类的测试场景",{"2":{"138":1}}],["相当于帧率为",{"2":{"134":1}}],["相似度",{"2":{"133":1}}],["相对项目根目录下",{"2":{"229":1}}],["相对移动到位置",{"2":{"183":1}}],["相对坐标",{"2":{"149":1}}],["相对坐标定位方案是是一种基于",{"2":{"146":1}}],["相对坐标定位",{"0":{"145":1},"1":{"146":1,"147":1,"148":1,"149":1}}],["相对于鼠标位置的距离",{"2":{"129":1}}],["相对位置",{"2":{"129":1,"183":1}}],["相对位移法",{"0":{"129":1}}],["相对位移元素定位方案的配置文件",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["相信通过大家的共同努力",{"2":{"60":1}}],["分层设计图",{"0":{"291":1}}],["分布式轮换执行的功能",{"2":{"285":1}}],["分布式轮换执行",{"2":{"285":1}}],["分布式执行",{"2":{"260":1}}],["分钟",{"2":{"273":1}}],["分钟降低至",{"2":{"273":1}}],["分割",{"2":{"213":1}}],["分别用",{"2":{"199":1,"284":1}}],["分别是",{"2":{"181":1}}],["分别按照机器的",{"2":{"179":1}}],["分别为",{"2":{"148":1}}],["分享和成长的平台",{"2":{"60":1}}],["分辨率检查功能支持多组分辨率",{"2":{"16":1}}],["致力于为广大自动化技术爱好者提供一个交流",{"2":{"60":1}}],["源代码",{"2":{"59":1}}],["兼容现有用例标签",{"2":{"280":1}}],["兼容性测试主要通过",{"2":{"280":1}}],["兼容性",{"2":{"199":1}}],["兼容",{"2":{"59":1,"86":1}}],["偶现异常",{"2":{"58":1}}],["列填入",{"2":{"203":1}}],["列填入函数名和参数",{"2":{"203":1}}],["列有的写了",{"2":{"57":1}}],["列没写表头",{"2":{"57":1}}],["忽略",{"2":{"56":1}}],["秒",{"2":{"56":1}}],["当",{"2":{"204":1}}],["当用例执行完之后",{"2":{"195":1}}],["当元素按钮位置相对于应用界面位置发生修改之后",{"2":{"146":1}}],["当前鼠标坐标",{"2":{"183":1}}],["当前子节点",{"2":{"144":2}}],["当前指定第几条",{"2":{"56":1}}],["当然你也可以直接通过",{"2":{"181":1}}],["当然你可以指定一个具体的目录或文件",{"2":{"152":1}}],["当然",{"2":{"41":2,"136":1,"266":1,"302":1}}],["总共执行",{"2":{"229":1}}],["总执行用例数为",{"2":{"229":1}}],["总结",{"2":{"185":1}}],["总数剔除",{"2":{"54":1}}],["总的来说",{"2":{"13":1}}],["更符合断言的使用习惯",{"2":{"296":1}}],["更好的发挥自动化测试的作用",{"2":{"278":1}}],["更重要的是这一切使用起来都非常简单",{"2":{"260":1}}],["更重要的是确保创建工程的规范性",{"2":{"248":1}}],["更重要的是",{"2":{"217":1}}],["更重要的是我们不想引入三方依赖",{"2":{"207":1}}],["更换成",{"2":{"54":1}}],["更新贡献者名单",{"2":{"18":1}}],["更新",{"2":{"11":1,"12":1}}],["依赖安装下载过程网络波动导致安装失败",{"2":{"239":1}}],["依赖安装的逻辑",{"2":{"47":1}}],["依赖关系就越复杂",{"2":{"239":1}}],["依赖项越多",{"2":{"239":1}}],["依赖最少化",{"2":{"239":1}}],["依赖治理的意义",{"2":{"239":1}}],["依赖治理思路",{"2":{"239":1}}],["依赖治理原则",{"2":{"239":1}}],["依赖治理",{"0":{"239":1}}],["依赖库",{"2":{"233":1}}],["依赖主控机的用例",{"2":{"199":1}}],["依赖外设的用例",{"2":{"199":1}}],["依赖",{"2":{"54":1,"137":1}}],["未来随着业务的变化可能需要增加各种各样的标签",{"2":{"285":1}}],["未来规划",{"0":{"269":1},"1":{"270":1,"271":1,"272":1}}],["未来有希望成为",{"2":{"12":1}}],["未指定版本则安装最新版",{"2":{"233":1}}],["未识别到",{"2":{"175":3}}],["未写入",{"2":{"53":1}}],["后期越容易出问题",{"2":{"239":1}}],["后面标签化管理章节会讲到",{"2":{"280":1}}],["后面第四章会讲到细节",{"2":{"267":1}}],["后面不加参数",{"2":{"246":1}}],["后面部分是生成的随机字符串",{"2":{"236":1}}],["后面一条执行开始时通过子线程对前一条用例的执行结果进行回填",{"2":{"229":1}}],["后面想再次回填就不生效了",{"2":{"197":1}}],["后面提到的一些命令行参数也都默认是在",{"2":{"156":1}}],["后无法执行用例的问题",{"2":{"53":1}}],["后续只能手动解决",{"2":{"300":1}}],["后续执行同理",{"2":{"285":1}}],["后续编写新增自动化用例时",{"2":{"284":1}}],["后续可以根据需要嫁接进来",{"2":{"280":1}}],["后续解除跳过的时候又需要找到这条脚本",{"2":{"277":1}}],["后续用例继续执行",{"2":{"229":1}}],["后续你打",{"2":{"204":1}}],["后续需要新增用例标签",{"2":{"200":1,"284":1}}],["后续就不会再此触发回填了",{"2":{"197":1}}],["后续手动回填方法",{"2":{"195":1}}],["后续手动将结果进行回填请求",{"2":{"195":1}}],["后续版本将不需要在系统中安装dogtail",{"2":{"59":1}}],["后续版本再考虑针对此接口做修改",{"2":{"40":1}}],["后续使用",{"2":{"53":1}}],["后续专注于本地执行功能开发",{"2":{"43":1}}],["后续均通过",{"2":{"41":1}}],["后续在",{"2":{"27":1}}],["后续默认不再使用",{"2":{"15":1}}],["后续将以",{"2":{"12":1}}],["ja",{"2":{"229":1}}],["javascript",{"2":{"185":2}}],["jinja2",{"2":{"192":1}}],["jenkins",{"2":{"53":1}}],["json三种形式的报告",{"2":{"177":1}}],["json报告",{"2":{"177":1}}],["json=data",{"2":{"74":2}}],["json",{"2":{"11":12,"12":2,"13":2,"15":1,"27":1,"53":1,"74":4,"177":4,"229":3}}],["断言库",{"2":{"280":1}}],["断言的图片资源目录",{"2":{"292":1}}],["断言的图片资源",{"2":{"262":1}}],["断言方法模块",{"2":{"262":1,"292":1}}],["断言方法",{"0":{"187":1}}],["断言方法类",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["断言关键字",{"2":{"175":2}}],["断言路径下是否存在以",{"2":{"175":1}}],["断言图片尺寸",{"2":{"175":1}}],["断言结果为假",{"2":{"175":1}}],["断言结果为真",{"2":{"175":1}}],["断言不相等",{"2":{"175":1}}],["断言不存在共享文件夹",{"2":{"175":1}}],["断言相等",{"2":{"175":1}}],["断言主题是否为",{"2":{"175":1}}],["断言主题",{"2":{"175":1}}],["断言共享目录中存在",{"2":{"175":1}}],["断言共享目录中不存在",{"2":{"175":1}}],["断言共享目录中是否存在",{"2":{"175":2}}],["断言存在共享文件夹",{"2":{"175":1}}],["断言应用窗口数量",{"2":{"175":3}}],["断言应用进程的数量",{"2":{"175":1}}],["断言应用进程状态",{"2":{"175":2}}],["断言应用进程是否存在",{"2":{"175":1}}],["断言实际窗口大小",{"2":{"175":1}}],["断言窗口大小与期望一致",{"2":{"175":1}}],["断言元素出现的个数",{"2":{"175":1}}],["断言元素不存在",{"2":{"175":1}}],["断言元素存在",{"2":{"175":1}}],["断言文案不存在",{"2":{"175":1}}],["断言文案存在",{"2":{"119":1,"175":1}}],["断言文件不存在",{"2":{"175":1}}],["断言文件存在",{"2":{"175":1}}],["断言",{"0":{"173":1},"1":{"174":1,"175":1},"2":{"83":1,"85":1,"175":2}}],["断言函数的调用也会自动打印日志",{"2":{"53":1}}],["断言音乐的删除弹窗中",{"2":{"53":1}}],["所属管理员分组id",{"2":{"74":1}}],["所有应用是整体发布",{"2":{"277":1}}],["所有应用库均放置在基础框架下的",{"2":{"264":1}}],["所有应用库配置对象都是继承框架的全局配置类的",{"2":{"228":1}}],["所有用例执行的超时时间",{"2":{"229":1}}],["所有用例执行完之后不做回填的接口请求",{"2":{"195":1}}],["所有用例执行完之后会在",{"2":{"161":1,"255":1}}],["所有条件判断跳过的函数写在此文件中",{"2":{"203":1}}],["所有",{"2":{"200":1}}],["所有匹配的位置的元组组成的列表",{"2":{"183":1}}],["所有功能的驱动执行都是通过",{"2":{"156":1}}],["所有标签以",{"2":{"141":1}}],["所有的编码风格都是趋于相同的",{"2":{"266":1}}],["所有的远程调用方法",{"2":{"219":1}}],["所有的方法",{"2":{"215":1}}],["所有的方法都在",{"2":{"64":1,"74":1,"84":1}}],["所有的报告相关的文件会统一存放在里面",{"2":{"177":1}}],["所有的用例都在",{"2":{"65":1,"75":1,"85":1,"98":1,"111":1}}],["所有音乐按钮",{"2":{"53":1}}],["所以你仍然需要手动看下各处是否修改到位",{"2":{"302":1}}],["所以你需要考虑是否有必要每条用例都录屏",{"2":{"193":1}}],["所以存在应用间方法交叉调用的问题",{"2":{"277":1}}],["所以需要处理这个问题",{"2":{"222":1}}],["所以",{"2":{"147":1}}],["所以逻辑也是一样的",{"2":{"140":1}}],["所以我这里是推荐加",{"2":{"41":1}}],["所以她那边的项目调用此定制接口会报",{"2":{"40":1}}],["所以本次",{"2":{"40":1}}],["​\\t",{"2":{"261":2,"275":1,"279":1,"291":1,"295":1}}],["​\\timage",{"2":{"53":1}}],["​\\t\\t后两种入参方式可以很方便在输入命令的过程中使用补全",{"2":{"47":1}}],["▀▀█",{"2":{"53":1}}],["▄",{"2":{"53":2}}],["▄█",{"2":{"53":2}}],["█",{"2":{"53":4}}],["██║▄▄",{"2":{"53":1}}],["██║",{"2":{"53":20}}],["██╔═══██╗",{"2":{"53":2}}],["██╔╝",{"2":{"53":1}}],["██████╗",{"2":{"53":2}}],["██╗",{"2":{"53":6}}],["╚══▀▀═╝",{"2":{"53":1}}],["╚═════╝",{"2":{"53":3}}],["╚═╝",{"2":{"53":1}}],["╚██████╔╝",{"2":{"53":4}}],["╚████╔╝",{"2":{"53":1}}],["╚██╔╝",{"2":{"53":1}}],["╚██╗",{"2":{"53":1}}],["最终的用例状态会被标记为",{"2":{"284":1}}],["最终的用例状态会被标签为",{"2":{"202":1}}],["最完美的方案",{"2":{"272":1}}],["最常用的方法类",{"2":{"266":1}}],["最大匹配次数",{"2":{"175":2}}],["最大匹配超时",{"2":{"175":2}}],["最大失败用例数量的占比",{"2":{"229":1}}],["最大失败率",{"2":{"158":1,"252":1}}],["最大失败次数",{"2":{"53":1}}],["最强代码检查",{"2":{"150":1}}],["最后按回车或者鼠标点",{"2":{"300":1}}],["最后进行自动化测试",{"2":{"276":2}}],["最后在断言的时候再将图片路径作为参数传入断言语句即可",{"2":{"138":1}}],["最后将识别结果返回给测试机",{"2":{"137":1}}],["最后再对这一堆图片逐个进行图像识别",{"2":{"134":1}}],["最后移除掉一些不相关的文件",{"2":{"71":1,"100":1}}],["最有名的一个开源项目",{"2":{"117":1}}],["最新版本的检查",{"2":{"33":1}}],["最新的",{"2":{"16":1,"98":1,"103":1}}],["\\tdef",{"2":{"297":1}}],["\\tpass",{"2":{"296":2}}],["\\tcls",{"2":{"133":1}}],["\\t\\t",{"2":{"119":1}}],["\\t",{"2":{"119":1,"297":1}}],["\\t200",{"2":{"53":1}}],["\\t49",{"2":{"53":1}}],["\\t11880s",{"2":{"53":1}}],["\\t1",{"2":{"53":1}}],["\\t99",{"2":{"53":1}}],["如执行哪个应用",{"2":{"286":1}}],["如功能测试",{"2":{"280":1}}],["如下图",{"2":{"261":1}}],["如下图所示",{"2":{"128":1,"129":1,"131":1}}],["如依赖关系错乱冲突导致安装失败",{"2":{"239":1}}],["如项目根目录绝对路径",{"2":{"226":1,"268":1}}],["如何使用",{"0":{"156":1}}],["如此实现时间效率最大化",{"2":{"229":1}}],["如此循环",{"2":{"195":1}}],["如此循环直到所有用例执行完",{"2":{"162":1,"256":1}}],["如此即可消除干扰",{"2":{"131":1}}],["如此",{"2":{"127":1}}],["如",{"2":{"53":1,"133":2,"218":1,"229":1,"273":1,"280":1,"282":1}}],["如果所有用例都调试通过了",{"2":{"303":1}}],["如果快捷键没反应",{"2":{"300":1}}],["如果没有被编辑器自动处理的路径问题",{"2":{"300":1}}],["如果没有开启",{"2":{"161":1,"255":1}}],["如果已经标记了跳过原因",{"2":{"284":1}}],["如果某个方法被",{"2":{"282":1,"283":1}}],["如果某条用例需要单独配置超时时间",{"2":{"229":1}}],["如果在局部配置里面配置了用例执行标签",{"2":{"280":1}}],["如果在大图的其中一个坐标点上匹配到了小图的所有rgb值",{"2":{"136":1}}],["如果在大图的",{"2":{"136":1}}],["如果确实需要引入三方库",{"2":{"239":1}}],["如果多个应用库都存在",{"2":{"233":1}}],["如果接口请求失败",{"2":{"229":1}}],["如果是远程执行",{"2":{"229":1}}],["如果是其他第三方的浏览器可以指定浏览器对应的路径",{"2":{"98":1,"229":1}}],["如果第",{"2":{"229":1}}],["如果一条用例的执行时间超时",{"2":{"229":1}}],["如果这里有值",{"2":{"229":1}}],["如果这条用例之前已经回填过了",{"2":{"197":1}}],["如果有对象实例化的",{"2":{"222":1}}],["如果有多个窗口",{"2":{"30":1}}],["如果$",{"2":{"213":1,"229":2}}],["如果应用库还需要其他",{"2":{"233":1}}],["如果应用库同样使用了系统安装的",{"2":{"59":1}}],["如果应用受到新需求影响需要跳过",{"2":{"202":1,"284":1}}],["如果比较复杂操作步骤",{"2":{"189":1}}],["如果还需要其他的操作方法",{"2":{"182":1}}],["如果远程机器没有搭建自动化测试环境",{"2":{"161":1,"255":1}}],["如果为yes",{"2":{"161":1,"229":1,"255":1}}],["如果password不传入",{"2":{"161":1,"255":1}}],["如果匹配了大图所有的坐标点",{"2":{"136":1}}],["如果匹配成功",{"2":{"133":1}}],["如果小图上的rgb值与对应大图位置的rgb都相等",{"2":{"136":1}}],["如果用常规的图像识别则有可能无法识别到",{"2":{"134":1,"175":1}}],["如果找不到",{"2":{"133":1}}],["如果识别不到",{"2":{"133":1}}],["如果你之前并没有这样的设计",{"2":{"302":1}}],["如果你原来本来就有一个函数专门用于组装路径的",{"2":{"302":1}}],["如果你是想对原来的工程进行改造",{"2":{"301":1}}],["如果你是新写项目",{"2":{"301":1}}],["如果你嫌麻烦",{"2":{"301":1}}],["如果你的应用本身是属于根本就不需要和其他应用交互的",{"2":{"266":1}}],["如果你的应用分了很多模块",{"2":{"211":1,"229":1}}],["如果你用到了十个功能模块",{"2":{"265":1}}],["如果你还没有遇到",{"2":{"180":1}}],["如果你不想通过配置文件",{"2":{"161":1,"255":1}}],["如果你不希望大图是屏幕的截图",{"2":{"133":1}}],["如果你想直接部署在本机上",{"2":{"235":1}}],["如果你想重新做回填",{"2":{"197":1}}],["如果你想执行这个",{"2":{"164":1}}],["如果你想指定不同的窗口",{"2":{"149":1}}],["如果你想每次截图存在一些间隔时间传入对应的时间间隔即可",{"2":{"134":1}}],["如果你发现使用常规的",{"2":{"146":1}}],["如果你在用例中需要调整识别度",{"2":{"133":1}}],["如果你移动鼠标到屏幕四边",{"2":{"129":1}}],["如果提示没有",{"2":{"64":1}}],["如果传入了",{"2":{"47":1}}],["如果",{"2":{"47":1,"133":1,"148":1,"246":1}}],["如果不给就是apps目录下所有的",{"2":{"208":1}}],["如果不存在",{"2":{"138":1,"210":1}}],["如果不传默认截取全屏识别",{"2":{"119":1,"175":2}}],["如果不传参",{"2":{"119":1}}],["如果不指定版本号默认是安装最新发布的",{"2":{"41":1}}],["如果不加",{"2":{"41":1}}],["如果本地执行版本不是最新的",{"2":{"33":1}}],["如果需要指定其他第三方的浏览器",{"2":{"16":1,"98":1,"103":1}}],["子命令创建子项目工程模板",{"2":{"53":1}}],["子项目工程名称可以为任意名称",{"2":{"34":1}}],["子项目需要时通过新增依赖机制进行安装",{"2":{"11":1}}],["创建",{"0":{"248":1}}],["创建项目",{"0":{"246":1}}],["创建文件",{"2":{"234":1}}],["创建管理员成功",{"2":{"75":1}}],["创建平台子管理员",{"2":{"74":1}}],["创建的app工程",{"2":{"61":1,"70":1,"71":1,"80":1,"92":1,"99":1,"100":1,"107":1}}],["创建一条在百度首页搜索",{"2":{"95":1}}],["创建一条通过任务栏打开文件管理器的测试用例",{"2":{"82":1}}],["创建一条完整的用例",{"0":{"63":1,"73":1,"82":1,"95":1,"109":1},"1":{"64":1,"65":1,"74":1,"75":1,"83":1,"84":1,"85":1,"96":1,"97":1,"98":1,"110":1,"111":1},"2":{"11":1}}],["创建一个项目",{"0":{"68":1,"78":1,"88":1,"105":1,"114":1},"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["创建一个",{"0":{"61":1,"70":1,"80":1,"99":1,"107":1},"1":{"62":1,"71":1,"72":1,"81":1,"100":1,"101":1,"102":1,"108":1},"2":{"61":1,"70":1,"80":1,"99":1,"107":1}}],["创建工程时存在工程名称时无法继续创建",{"2":{"52":1}}],["然后同步修改掉",{"2":{"300":1}}],["然后使用快捷键",{"2":{"300":1}}],["然后配合",{"2":{"280":1}}],["然后由执行器来执行相应的测试",{"2":{"280":1}}],["然后测试机安装最新的镜像",{"2":{"276":1}}],["然后才能使用该模块下的功能",{"2":{"265":1}}],["然后将这些基础能力通过",{"2":{"212":1}}],["然后",{"2":{"204":1}}],["然后在输入框中输入要重命名的名称",{"2":{"300":1}}],["然后在测试机上安装更新",{"2":{"276":1}}],["然后在浏览器访问",{"2":{"179":1}}],["然后在命令行",{"2":{"161":1,"255":1}}],["然后右键选择浏览器打开",{"2":{"179":1}}],["然后服务端就先拿着第",{"2":{"162":1,"256":1}}],["然后再通过子命令",{"2":{"156":1}}],["然后移动鼠标就就可以看到上图的参考线及数据",{"2":{"147":1}}],["然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小",{"2":{"147":1}}],["然后勾选",{"2":{"141":1}}],["然后这本身就是不确定的",{"2":{"131":1}}],["然后通过负载均衡技术将业务请求分发到",{"2":{"121":1}}],["然后通过",{"2":{"118":1}}],["然后作为稳定版本发布",{"2":{"52":1}}],["然后每次我就需要解释这个",{"2":{"26":1}}],["指定某台机器在指定镜像版本上执行用例",{"2":{"280":1}}],["指定某个目录执行",{"0":{"165":1}}],["指定安装某个版本",{"2":{"233":1}}],["指定报告生成的路径",{"2":{"229":1}}],["指定拖动的起始",{"2":{"183":2}}],["指定执行某一个用例",{"0":{"164":1}}],["指定用例执行次数",{"2":{"158":1,"229":1,"252":1}}],["指定浏览器可执行文件路径",{"2":{"98":1,"229":1}}],["指定浏览器启动的用户数据缓存目录",{"2":{"98":1,"229":1}}],["指定不同的端口",{"2":{"51":1}}],["指南",{"2":{"12":1,"14":1}}],["替换为",{"2":{"51":1,"58":1}}],["替换成",{"2":{"41":1}}],["扫描的代码风格问题",{"2":{"50":1}}],["公共库建设",{"0":{"283":1},"2":{"287":1}}],["公共库抽取",{"2":{"273":1}}],["公共库中的",{"2":{"49":1}}],["公共方法库抽离和方法文档整理",{"2":{"287":6}}],["公共方法库里面的编写形式",{"2":{"266":1}}],["公共方法库里面所封装的一些操作方法都是至少被",{"2":{"266":1}}],["公共方法库里面每个应用都是一个单独的",{"2":{"266":1}}],["公共方法库意义",{"2":{"266":1}}],["公共方法库",{"0":{"266":1},"2":{"260":2,"262":1,"280":1}}],["公共",{"2":{"226":1,"268":1,"283":1}}],["公网文档使用的是",{"2":{"41":1}}],["公网文档",{"2":{"41":1}}],["刷新源的日志在终端显示",{"2":{"47":1}}],["连接符号不可使用下划线和逗号",{"2":{"203":1}}],["连接服务器重试次数",{"2":{"175":2}}],["连接",{"2":{"47":1,"161":1,"203":1,"255":1,"280":1}}],["两对大括号中的内容",{"2":{"192":1}}],["两次点击的间隔",{"2":{"183":1}}],["两个功能接口",{"2":{"137":1}}],["两个情况的优先级是优先判断本地存在",{"2":{"40":1}}],["两张图唯一变化的就是右键菜单",{"2":{"131":1}}],["两种写法",{"2":{"47":1}}],["测试",{"2":{"286":1}}],["测试平台可能会涉及到的模块有",{"2":{"286":1}}],["测试同学可以根据自己的测试计划",{"2":{"280":1}}],["测试资源",{"2":{"280":1}}],["测试用例",{"2":{"280":1}}],["测试人员在本地编写代码",{"2":{"271":1}}],["测试数据",{"2":{"262":1,"292":1}}],["测试级别",{"2":{"229":1}}],["测试过程中立即显示报错",{"2":{"158":1,"229":1,"252":1}}],["测试单关联的用例",{"2":{"194":1}}],["测试单id为",{"2":{"229":1}}],["测试单id",{"2":{"158":1,"195":3,"252":1}}],["测试单驱动执行",{"0":{"170":1}}],["测试单驱动",{"2":{"10":1}}],["测试报告的默认语言",{"2":{"229":1}}],["测试报告的name",{"2":{"229":1}}],["测试报告的title",{"2":{"229":1}}],["测试报告",{"0":{"176":1},"1":{"177":1,"178":1,"179":1}}],["测试报告格式",{"2":{"158":1,"252":1}}],["测试报告查看",{"2":{"57":1}}],["测试机应用安装更新接口等",{"2":{"286":1}}],["测试机镜像安装接口",{"2":{"286":1}}],["测试机资源管理模块",{"2":{"286":1}}],["测试机",{"2":{"271":1}}],["测试机轮询次数",{"2":{"229":1}}],["测试机的密码",{"2":{"229":1}}],["测试机密码",{"2":{"161":1,"229":1,"255":1}}],["测试机截取当前屏幕图片以及模板图片",{"2":{"137":1}}],["测试机上不用安装",{"2":{"137":1}}],["测试机通过远程调用",{"2":{"118":1}}],["测试结果统计时",{"2":{"54":1}}],["测试套件驱动执行",{"0":{"171":1}}],["测试套件执行报错的的问题",{"2":{"45":1}}],["测试套id为",{"2":{"229":1}}],["测试套id",{"2":{"158":1,"252":1}}],["测试套执行或测试单执行时",{"2":{"54":1}}],["由",{"2":{"199":1}}],["由子项目在",{"2":{"43":1,"49":1}}],["由于测试机资源有限",{"2":{"285":1}}],["由于需求变更",{"2":{"205":1}}],["由于需要修改",{"2":{"59":1}}],["由于你的测试资源是不固定的",{"2":{"138":1}}],["由于右键菜单选项几乎都是文本",{"2":{"131":1}}],["由于内建了非常多的断言语句",{"2":{"85":1}}],["由于系统一些",{"2":{"49":1}}],["由于默认基于虚拟化环境部署方案",{"2":{"41":1}}],["由于将这个定制图像识别接口进行服务化兼容改造需要一定时间",{"2":{"40":1}}],["由于之前是预装到镜像里面的",{"2":{"40":1}}],["由于",{"2":{"11":1,"31":1}}],["由于窗管团队修改获取窗口信息的返回值",{"2":{"9":1}}],["移动的速度",{"2":{"183":1}}],["移动的倍数",{"2":{"149":4}}],["移动到的位置",{"2":{"183":6}}],["移动到某个位置点击双击",{"2":{"183":1}}],["移动到某个位置点击右键",{"2":{"183":1}}],["移动到某个位置点击",{"2":{"183":1}}],["移动到指定位置",{"2":{"183":1}}],["移动到",{"2":{"15":2}}],["移除了参数",{"2":{"50":1}}],["移除",{"2":{"43":1,"47":1,"50":1,"53":1,"58":1}}],["参考性能自动化工程完成工程化改造",{"2":{"273":1}}],["参考章节",{"2":{"186":1}}],["参考系",{"2":{"149":1}}],["参考系的选取标准",{"2":{"148":1}}],["参考",{"2":{"42":1,"299":1}}],["参数是什么",{"2":{"301":1}}],["参数说明",{"2":{"208":1}}],["参数加上",{"2":{"204":1}}],["参数为",{"2":{"203":1}}],["参数直接给你修复掉",{"2":{"152":1}}],["参数就是配置里面的",{"2":{"148":1}}],["参数介绍",{"2":{"133":1,"134":1}}],["参数可能出现与其他框架的工程依赖存在冲突",{"2":{"51":1}}],["参数",{"2":{"24":1,"133":1,"203":1}}],["参数不能对",{"2":{"20":1}}],["参数后面新增支持",{"2":{"47":1}}],["参数后",{"2":{"16":1}}],["每写一条都需要在对应的",{"2":{"284":1}}],["每日下载最新的",{"2":{"276":1}}],["每日下班之后会将各应用进行打包",{"2":{"276":1}}],["每日构建流水线",{"2":{"276":1}}],["每一列都是一个用例标签",{"2":{"200":1,"284":1}}],["每个应用内部会有一个单独的配置模块",{"2":{"280":1}}],["每个方法均对应一个元素的一个具体操作",{"2":{"275":1}}],["每个",{"2":{"266":1}}],["每个模块建立一个",{"2":{"200":1,"284":1}}],["每个操作步骤之前暂停的时间",{"2":{"149":1}}],["每个菜单选项就可以通过图像识别的方式进行元素定位",{"2":{"128":1}}],["每次执行时原",{"2":{"211":1}}],["每次操作会将",{"2":{"210":1,"211":1}}],["每次生成会被覆盖",{"2":{"175":1}}],["每次截取图片的间隔时间",{"2":{"134":1}}],["每次间隔1秒",{"2":{"133":1}}],["每次需要去量一下",{"2":{"129":1}}],["每次变更之后就需要进行大量图片资源的重新截图替换",{"2":{"128":1}}],["每次",{"2":{"122":1}}],["每次识别间隔时间",{"2":{"30":1}}],["每条用例仍然会生成json文件",{"2":{"229":1}}],["每条用例执行之后进行环境清理",{"2":{"229":1}}],["每条用例执行时日志输出当前进度",{"2":{"56":1}}],["每条用例都录屏",{"2":{"41":1,"229":1}}],[">按键",{"2":{"183":2}}],[">滑动滚轮",{"2":{"183":1}}],[">与期望尺寸",{"2":{"175":1}}],[">与实际值",{"2":{"175":4}}],[">不符",{"2":{"175":1}}],[">不为假",{"2":{"175":1}}],[">不为真",{"2":{"175":1}}],[">不相等",{"2":{"175":2}}],[">是否相等",{"2":{"175":2}}],[">主题",{"2":{"175":1}}],[">",{"2":{"41":1,"64":1,"143":1,"144":9,"149":29,"175":12,"183":6,"187":1,"229":1}}],[">=",{"2":{"41":1,"175":3,"193":1,"229":1}}],["之前这个配置项只能在",{"2":{"41":1}}],["之后拖动到目标位置即可",{"2":{"300":1}}],["之后添加使用",{"2":{"156":1}}],["之后",{"2":{"33":1,"41":1,"192":1,"196":1}}],["仍然强制执行",{"2":{"56":1}}],["仍然保留",{"2":{"41":1}}],["仍然可以通过源码获取",{"2":{"41":1}}],["内网文档",{"2":{"41":1}}],["内获取应用名称的逻辑错误的问题",{"2":{"6":1}}],["咱不能直接把",{"2":{"204":1}}],["咱们先初步排除掉一些明显不用的",{"2":{"185":1}}],["咱们",{"2":{"41":1}}],["咱也不知道为啥",{"2":{"26":1}}],["代表不跳过",{"2":{"203":1}}],["代表跳过",{"2":{"203":1}}],["代码中可以在不依赖三方库的情况下方便快速的解析它",{"2":{"280":1}}],["代码相互独立",{"2":{"273":1}}],["代码规范问题清零",{"2":{"273":1}}],["代码调试环境",{"2":{"272":1}}],["代码报错看不到报错信息",{"2":{"271":1}}],["代码补全",{"0":{"219":1}}],["代码格式化",{"0":{"153":1}}],["代码实现和维护上可能出现的分歧",{"2":{"273":1}}],["代码实现",{"2":{"136":1,"137":1}}],["代码实现请查看",{"2":{"131":1}}],["代码示例",{"2":{"131":1,"134":1,"138":1,"143":1,"147":2}}],["代码示意",{"2":{"119":1,"138":1}}],["代码检查是扫描代码中存在的问题",{"2":{"152":1}}],["代码检查",{"0":{"152":1},"2":{"20":1}}],["代理下就好了",{"2":{"41":1}}],["白嫖怪一顿狂喜~~",{"2":{"41":1}}],["了解系统的方方面面也有好处",{"2":{"266":1}}],["了解到其他应用的功能",{"2":{"266":1}}],["了",{"2":{"41":1,"153":1}}],["看到这里有些同学可能要问了",{"2":{"204":1}}],["看图相册在图片资源不一定固定",{"2":{"138":1}}],["看起来很和谐~",{"2":{"41":1}}],["看着烦人我都能接受",{"2":{"26":1}}],["就会终止测试",{"2":{"229":1}}],["就可以实现自动输出日志了",{"2":{"192":1}}],["就可以了",{"2":{"41":1}}],["就不能找到这只鸟了",{"2":{"138":1}}],["就获取了在服务端图像识别的结果",{"2":{"137":1}}],["就像有没有可能有一天国内无法使用",{"2":{"136":1}}],["就像录制视频一样",{"2":{"134":1}}],["就像气泡一样",{"2":{"134":1}}],["就需要进一步做数据处理",{"2":{"131":1}}],["就实现了对右键菜单的操作",{"2":{"127":1}}],["就是干",{"2":{"300":1}}],["就是当你写一个大型项目时",{"2":{"239":1}}],["就是你不知道预期是啥",{"2":{"138":1}}],["就是屏幕中出现多个和菜单选项文字相同的文字时",{"2":{"131":1}}],["就是右键菜单的选项位置不可能一直不变",{"2":{"127":1}}],["就是以桌面",{"2":{"86":1}}],["就是本地直接安装",{"2":{"40":1}}],["就是本地测试机不需要安装",{"2":{"40":1}}],["就好了",{"2":{"41":1,"159":1,"253":1}}],["只能执行其中一种测试类型",{"2":{"285":1}}],["只能说使用的场景还不够多",{"2":{"180":1}}],["只有一台机器",{"2":{"272":1}}],["只有想不到没有办不到",{"2":{"229":1}}],["只会安装最基础的依赖",{"2":{"234":1}}],["只会将",{"2":{"47":1}}],["只收集不执行用例",{"2":{"229":1}}],["只支持谷歌浏览器",{"2":{"185":1}}],["只支持",{"2":{"185":1}}],["只留下菜单界面",{"2":{"131":1}}],["只需要写一个导入",{"2":{"265":1}}],["只需要保存",{"2":{"248":1}}],["只需要在应用库根目录下保存一个",{"2":{"233":1}}],["只需要在出口文件加上类装饰器",{"2":{"192":1}}],["只需要给应用方法层的唯一出口类加一个装饰器",{"2":{"221":1}}],["只需要将对应的信息依次配置好就行了",{"2":{"211":1,"229":1}}],["只需要修改",{"2":{"195":1}}],["只需要根据",{"2":{"146":1}}],["只需要通过",{"2":{"119":1}}],["只需要把",{"2":{"41":1}}],["只返回第一个",{"2":{"119":1,"175":2}}],["只要标记了fixed的用例",{"2":{"229":1}}],["只要有1个机器上用例失败",{"2":{"196":1}}],["只要有接口请求能力就能做",{"2":{"76":1}}],["只要操作前后后变化的都可以",{"2":{"131":1}}],["只要是基于浏览器的项目都适用",{"2":{"103":1}}],["只不过之前是用于指定分辨率大小",{"2":{"41":1}}],["只是在",{"2":{"218":1}}],["只是需要增加一个参数",{"2":{"162":1,"256":1}}],["只是需要关注下环境变量的问题",{"2":{"41":1}}],["只是内部做了不同的事情",{"2":{"41":1}}],["可操作性和可维护性较高",{"2":{"280":1}}],["可灵活支撑不同的自动化运用场景",{"2":{"273":1}}],["可支持迭代期间独立新增",{"2":{"273":1}}],["可维护性差",{"2":{"206":1}}],["可自定义多个参数之间的连接符",{"2":{"203":1}}],["可能是编辑器的",{"2":{"302":1}}],["可能你只需要安装一些最最基础的依赖",{"2":{"234":1}}],["可能遇到的",{"0":{"197":1}}],["可能包含多条日志信息",{"2":{"189":1}}],["可能存在一些依赖报错",{"2":{"184":1}}],["可能会报错",{"2":{"59":1}}],["可能出现的程序报错的问题",{"2":{"57":1}}],["可用于本地用例驱动执行",{"2":{"155":1}}],["可用于定位断言",{"2":{"53":1}}],["可用于拉取",{"2":{"18":1}}],["可将python3",{"2":{"51":1}}],["可以配置自己的测试计划",{"2":{"286":1}}],["可以实现在全架构测试机上轮流执行用例",{"2":{"285":1}}],["可以实现不同系统版本",{"2":{"280":1}}],["可以实现多窗口的控制",{"2":{"265":1}}],["可以进行测试机管理",{"2":{"280":1}}],["可以根据需要进行灵活配置",{"2":{"280":1}}],["可以根据需要进行相应配置",{"2":{"280":1}}],["可以组合其中的标签而从驱动对应的自动化用例执行",{"2":{"280":1}}],["可以组合出任意的用例集合",{"2":{"229":1}}],["可以查看所有支持的命令行参数",{"2":{"252":1}}],["可以同时使用",{"2":{"234":1}}],["可以使用",{"2":{"234":1}}],["可以不传",{"2":{"213":1,"229":2}}],["可以直接在",{"2":{"179":1,"200":1,"284":1}}],["可以在用例中这样写",{"2":{"229":1}}],["可以在用例层优雅的调用远程方法",{"2":{"217":1}}],["可以在",{"2":{"154":1}}],["可以从",{"2":{"147":1}}],["可以展开应用的标签",{"2":{"141":1}}],["可以排除部分区域对识别结果的影响",{"2":{"133":1}}],["可以指定截取屏幕中的固定区域",{"2":{"133":1}}],["可以用于元素定位",{"2":{"119":1}}],["可以是空文件",{"2":{"92":1}}],["可以通过公共方法库里面的一些方法",{"2":{"266":1}}],["可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标",{"2":{"129":1}}],["可以通过",{"2":{"64":1,"84":1,"142":1}}],["可以给它个",{"2":{"41":1}}],["可以作为开发时的环境部署",{"2":{"41":1}}],["可以看出来和原来使用方法没有变化",{"2":{"41":1}}],["虚拟环境部署本机环境部署",{"2":{"247":1}}],["虚拟环境实际安装的位置是在",{"2":{"236":1}}],["虚拟环境解释器",{"0":{"236":1}}],["虚拟环境的工具",{"2":{"41":1}}],["虚拟环境的解释器版本没有动态获取系统中的",{"2":{"18":1}}],["虚拟化环境部署使用方法",{"2":{"41":1}}],["能支持多个标签的逻辑组合",{"2":{"285":1}}],["能做什么",{"0":{"241":1}}],["能不能基于框架执行时",{"2":{"189":1}}],["能满足对大部分的网络接口处理的需求",{"2":{"76":1}}],["能够完全管理常规的",{"2":{"41":1}}],["能自动分析统计每次提交中包含的用例和方法的增删改的数据",{"2":{"12":1}}],["值得一提的是",{"2":{"41":2}}],["还依赖较多设备",{"2":{"271":1}}],["还可以这样导入",{"2":{"227":1}}],["还搞什么确认修复干啥",{"2":{"204":1}}],["还是",{"2":{"184":1}}],["还是在",{"2":{"41":1}}],["还需要提供一个对象",{"2":{"98":1,"103":1}}],["还提供一个",{"2":{"16":1}}],["hk",{"2":{"183":3}}],["h=100",{"2":{"175":2}}],["hg",{"2":{"154":1}}],["h2",{"2":{"147":2}}],["huangmingqiang",{"2":{"144":1,"149":1,"183":1}}],["hub",{"2":{"54":1}}],["hiddenprints",{"2":{"183":2}}],["hightlight",{"2":{"141":1}}],["history",{"2":{"41":1}}],["hand",{"2":{"158":1,"195":1,"229":1,"252":1}}],["has",{"2":{"154":1}}],["hasattr",{"2":{"149":4}}],["hash",{"2":{"122":1}}],["hashlib",{"2":{"74":4}}],["have",{"2":{"98":1}}],["hook",{"2":{"262":1,"267":1}}],["hotkey",{"2":{"183":1}}],["hot",{"2":{"183":5}}],["home",{"2":{"98":1,"110":1,"229":1}}],["hostname",{"2":{"119":1}}],["host",{"2":{"74":4,"137":2,"229":2}}],["heard",{"2":{"229":1}}],["header",{"2":{"74":2}}],["headersp",{"2":{"74":2}}],["headers=headers",{"2":{"74":2}}],["headers=",{"2":{"74":1}}],["headers",{"2":{"74":15}}],["hebrew",{"2":{"229":1}}],["he",{"2":{"229":1}}],["help",{"2":{"156":2,"158":2,"161":2,"252":3,"255":2}}],["hexdigest",{"2":{"74":2}}],["height",{"2":{"53":1,"136":2,"138":2,"149":28,"183":4}}],["h",{"2":{"50":2,"129":2,"133":3,"137":2,"143":2,"144":2,"148":2,"149":30,"156":4,"158":1,"161":1,"175":20,"252":3,"255":1}}],["html",{"2":{"14":1,"177":3,"178":1,"179":5,"211":1,"229":3}}],["http",{"0":{"76":1},"1":{"77":1,"78":1,"79":1},"2":{"51":2,"75":1,"76":1,"97":1,"179":2,"241":1}}],["httperror",{"2":{"25":1}}],["http接口自动化测试",{"2":{"11":1}}],["https",{"2":{"2":1,"74":1,"211":1,"229":3}}],["会尽可能的自动解决移动导致的路径问题",{"2":{"300":1}}],["会包含一些本应用的测试资源的路径",{"2":{"280":1}}],["会引入非常非常多的依赖",{"2":{"239":1}}],["会进行重试",{"2":{"229":1}}],["会自动拷贝到远程并安装",{"2":{"229":1}}],["会自动加载",{"2":{"53":1}}],["会话超时",{"2":{"229":1}}],["会话超时时间",{"2":{"53":1,"226":1,"268":1}}],["会将整个项目下的相同地方都修改到",{"2":{"302":1}}],["会将所有远程测试机的测试报告都收集到",{"2":{"179":1}}],["会将图片的rgb值获取到",{"2":{"136":1}}],["会展示元素控件的",{"2":{"141":1}}],["会出现这样",{"2":{"127":2}}],["会出现下图",{"2":{"127":1}}],["会出现",{"2":{"41":1}}],["会打印更新提示信息",{"2":{"33":1}}],["加上类的关键词",{"2":{"295":1}}],["加上装饰器",{"2":{"192":1}}],["加架构名",{"2":{"203":1}}],["加入了",{"2":{"178":1}}],["加入了失败录屏",{"2":{"178":1}}],["加入了用例断言失败时的屏幕截图",{"2":{"178":1}}],["加",{"2":{"41":1}}],["推荐统一使用",{"2":{"203":1}}],["推荐指定版本号",{"2":{"41":1}}],["推荐使用",{"2":{"41":1,"62":1,"81":1,"102":1,"108":1}}],["推动自动化测试技术向前发展",{"2":{"13":1}}],["也就是在一次执行中",{"2":{"285":1}}],["也就是说如果您是部署自动化环境是用的",{"2":{"224":1}}],["也就是说流水线上我们是希望他继续跳过的",{"2":{"204":1}}],["也就是说同一条用例会在多台机器上同时执行",{"2":{"196":1}}],["也就是说",{"2":{"195":1}}],["也就是说我们需要写大量的日志代码",{"2":{"189":1}}],["也就是说通过命令行参数指定了对应的参数",{"2":{"156":1}}],["也就是说小图在大图中存在一个相似度",{"2":{"133":1}}],["也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向",{"2":{"129":1}}],["也就是说你得经常去维护菜单选项的步长",{"2":{"127":1}}],["也就是说从使用的角度是完全没有区别的",{"2":{"41":1}}],["也就是说后续可以使用",{"2":{"41":1}}],["也放在项目根目录",{"2":{"267":1}}],["也不做设备分辨率的检查",{"2":{"229":1}}],["也不会被执行",{"2":{"199":1}}],["也会执行",{"2":{"229":1}}],["也会正常执行",{"2":{"204":1}}],["也都挺好的",{"2":{"180":1}}],["也希望有志之士能一起优化此方案",{"2":{"136":1}}],["也有可能气泡出现的时间太短了",{"2":{"134":1}}],["也是全局配置对象",{"2":{"227":1}}],["也是极不稳定",{"2":{"138":1}}],["也是可以调用的",{"2":{"137":1}}],["也是可以的",{"2":{"41":1}}],["也是",{"2":{"117":1}}],["也可统计某两个commit之间或一段时间内用例和方法的修改数据",{"2":{"229":1}}],["也可以",{"2":{"245":1}}],["也可以使用配置文件选项",{"2":{"208":1}}],["也可以是多个操作的组合操作",{"2":{"275":1}}],["也可以是youqu特有的csv文件管理的标签",{"2":{"229":1}}],["也可以是自定义的数字代表用例序号",{"2":{"200":1}}],["也可以是传统的",{"2":{"168":1}}],["也可以用于文字断言",{"2":{"119":1}}],["也可以修改配置文件",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"231":1,"247":1}}],["也可传入子管理账号及密码调用接口操作",{"2":{"74":1}}],["也能使用",{"2":{"55":1}}],["也能管理到",{"2":{"41":1}}],["也拓展了其功能和适用范围",{"2":{"13":1}}],["刘郑等研发同事的大力支持",{"2":{"41":1}}],["架构设计",{"0":{"279":1}}],["架构设计思路",{"2":{"273":1}}],["架构工程化",{"2":{"273":1}}],["架构图",{"0":{"261":1},"2":{"261":1}}],["架构上安装并不能保证100",{"2":{"136":1}}],["架构师徐小东",{"2":{"41":1}}],["架构环境依赖的问题",{"2":{"40":1}}],["装机完之后自动开始执行配置的测试用例",{"2":{"280":1}}],["装机模块",{"2":{"280":1}}],["装饰器方法指定次数",{"2":{"53":1}}],["装进虚拟环境",{"2":{"40":1}}],["装载到虚拟环境方案中不太好处理",{"2":{"40":1}}],["改善历史",{"2":{"273":1}}],["改完还需要测试",{"2":{"40":1}}],["改为使用",{"2":{"10":1}}],["前端平台目前还没有太多详细的方案",{"2":{"286":1}}],["前面代码检查的时候报了一个问题",{"2":{"154":1}}],["前面我们已经把",{"2":{"40":1}}],["前",{"2":{"122":1}}],["前期测试一切看起来都很和谐",{"2":{"40":1}}],["而外层执行器没有指定执行标签",{"2":{"280":1}}],["而此路径可能不在环境变量",{"2":{"245":1}}],["而通过",{"2":{"201":1,"284":1}}],["而我们自动化人员大多使用",{"2":{"185":1}}],["而我们的测试机都在同一个网段",{"2":{"122":1}}],["而是所有远程机器执行的用例之和",{"2":{"162":1,"256":1}}],["而是通过请求",{"2":{"137":1}}],["而是你自定义传入的某个图片",{"2":{"133":1}}],["而",{"2":{"136":1}}],["而不同的方向上计算方法是不同的",{"2":{"129":1}}],["而不容易关注到首次包安装失败的问题",{"2":{"27":1}}],["而且不好维护",{"2":{"277":1}}],["而且它的作用域是当前目录及以下",{"2":{"267":1}}],["而且还支持动态控制用例批量执行的总时间",{"2":{"242":1}}],["而且我们在报告中还加入了失败录屏和失败截图的功能",{"2":{"242":1}}],["而且距离是通过像素",{"2":{"129":1}}],["而且使用方法非常简单",{"2":{"119":1}}],["而且在各架构上依赖包还不尽相同",{"2":{"40":1}}],["粗略数了下依赖有",{"2":{"40":1}}],["年多以来的观察",{"2":{"40":1}}],["基类",{"0":{"294":1}}],["基本就可以进行用例代码的调试了",{"2":{"303":1}}],["基本保持不变",{"2":{"280":1}}],["基本上你能用到的键鼠操作",{"2":{"181":1}}],["基础依赖仅安装最基础的几个包",{"2":{"234":1}}],["基础框架代码拉取",{"0":{"299":1}}],["基础框架中包含应用库",{"2":{"260":1}}],["基础框架是做为一个自动化测试的基础框架来设计的",{"2":{"260":1}}],["基础框架设计方案",{"0":{"257":1},"1":{"258":1,"259":1,"260":1,"261":1,"262":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1}}],["基础框架",{"2":{"147":1,"260":2}}],["基础框架移除此模块",{"2":{"33":1}}],["基线",{"2":{"199":1}}],["基于此",{"2":{"189":1}}],["基于元素按钮在应用中的相对位置",{"2":{"146":1}}],["基于以上两个原因",{"2":{"129":1}}],["基于",{"0":{"137":1},"2":{"40":1,"103":1,"122":1,"133":1,"148":1,"168":1,"185":1,"189":1}}],["原有自动化测试架构整体分为三层",{"2":{"275":1}}],["原有架构介绍",{"0":{"275":1}}],["原at框架架构图",{"2":{"275":1}}],["原则上可实现无限扩展",{"2":{"273":1}}],["原理实现",{"2":{"133":1,"134":1}}],["原理",{"2":{"131":1,"136":1,"137":1,"138":1}}],["原来的地址",{"2":{"51":1}}],["原因就是自动化项目里面各个应用的有比较多的耦合关系",{"2":{"277":1}}],["原因为",{"2":{"40":1}}],["原因是之前我这里本地没有",{"2":{"40":1}}],["原函数接口ocr",{"2":{"13":1,"124":1}}],["原函数接口使用方法不变以保持兼容性",{"2":{"13":1,"124":1}}],["kr",{"2":{"229":1}}],["klvv",{"2":{"203":2}}],["klvvw5821",{"2":{"39":1,"203":4}}],["kde",{"2":{"149":2,"175":1}}],["kwin",{"2":{"149":2,"175":1}}],["kw",{"2":{"97":2}}],["kwargs",{"2":{"94":2,"143":2,"144":7,"217":2,"265":6}}],["khtml",{"2":{"74":1}}],["keep",{"2":{"74":1}}],["key是本地csv文件的文件名称",{"2":{"211":1,"229":1}}],["keyup",{"2":{"183":1}}],["keydown",{"2":{"183":1}}],["keyerror",{"2":{"149":3}}],["keycombo",{"2":{"142":1}}],["keywords",{"2":{"97":3,"98":1,"158":4,"229":4,"252":3}}],["key",{"2":{"26":1,"74":1,"131":1,"144":3,"148":1,"175":1,"181":1,"182":3,"183":34,"203":16}}],["k",{"2":{"41":1,"51":1,"53":1,"74":2,"158":1,"161":2,"162":1,"164":2,"165":1,"167":1,"252":2,"255":1}}],["比如纯接口自动化的项目",{"2":{"234":1}}],["比如像这样",{"2":{"233":2}}],["比如要同步音乐的数据",{"2":{"211":1,"229":1}}],["比如是此文件中定义了的函数",{"2":{"203":1}}],["比如文件管理器叫",{"2":{"260":1}}],["比如文件管理器",{"2":{"200":1,"284":1}}],["比如文管右键菜单可以自定义",{"2":{"127":1}}],["比如用例里面如果断言的图片不同",{"2":{"184":1}}],["比如终端",{"2":{"183":1}}],["比如在注销登录界面",{"2":{"182":1}}],["比如截图录屏",{"2":{"146":1}}],["比如截取播放按钮",{"2":{"133":1}}],["比如音乐",{"2":{"146":1}}],["比如输入框",{"2":{"142":1}}],["比如说服务端也可以用",{"2":{"137":1}}],["比如气泡在1秒内消失",{"2":{"134":1,"175":1}}],["比如下面这种情况",{"2":{"131":1}}],["比如",{"2":{"39":1,"41":3,"47":1,"98":1,"127":1,"128":1,"129":1,"131":1,"132":1,"133":1,"134":1,"148":1,"161":1,"167":1,"181":1,"183":1,"184":1,"193":1,"203":4,"208":1,"211":1,"227":1,"229":6,"255":1,"266":1,"275":1,"283":1,"284":1}}],["扩充",{"2":{"39":1}}],["何权",{"2":{"39":1}}],["次执行成功",{"2":{"229":1}}],["次执行失败之后开始录屏",{"2":{"41":1,"229":1}}],["次调用识别的接口做识别",{"2":{"122":1}}],["次是将当前屏幕截图并发送到",{"2":{"122":1}}],["次",{"2":{"39":1,"127":2,"133":1,"193":1,"229":3}}],["识别所有匹配的图像",{"2":{"183":1}}],["识别到不应存在的文案",{"2":{"175":2}}],["识别率",{"2":{"134":1,"175":1}}],["识别右键菜单虽然已经很完美了",{"2":{"131":1}}],["识别我们在前面已经讲到",{"2":{"131":1}}],["识别",{"2":{"131":3}}],["识别业务实际是两次",{"2":{"122":1}}],["识别一个字符串或多个字符串",{"2":{"119":1,"175":2}}],["识别的服务",{"2":{"118":1}}],["识别工具",{"2":{"117":1}}],["识别新增支持传入目标图片路径进行文字识别",{"2":{"53":1}}],["识别自动重试机制",{"2":{"39":1}}],["识别模型准确率提升",{"2":{"34":1}}],["识别模型",{"2":{"13":1}}],["开源许可证",{"0":{"243":1}}],["开源了",{"2":{"41":1}}],["开启同步",{"2":{"210":1,"229":1}}],["开始的坐标的纵坐标",{"2":{"183":1}}],["开始的坐标的横坐标",{"2":{"183":1}}],["开始坐标",{"2":{"183":2}}],["开始",{"2":{"175":4}}],["开始构建应用",{"2":{"140":1}}],["开始匹配",{"2":{"136":1}}],["开发根据用例标签文件里面的用例标签执行对应用例的功能",{"2":{"285":1}}],["开发环境部署",{"0":{"235":1}}],["开发环境部署是可能影响到正式环境",{"2":{"38":1}}],["开发了自己的图像识别功能",{"2":{"132":1}}],["开头的目录",{"2":{"196":1,"197":1}}],["开头的",{"2":{"191":1,"229":1}}],["开头的限制",{"2":{"34":1}}],["开头",{"2":{"65":1,"75":1,"85":1,"98":1,"111":1,"203":1}}],["尝试人员都觉得难搞",{"2":{"271":1}}],["尝试合入一个有趣的功能",{"2":{"38":1}}],["尝试将一些功能模块拆分为独立构件",{"2":{"35":1}}],["采用异步的方式去进行数据回填",{"2":{"195":1}}],["采用",{"2":{"38":1,"122":1}}],["剥离文档中的图片资源",{"2":{"38":1}}],["技术方案",{"2":{"37":1,"220":1}}],["上面介绍",{"2":{"206":1}}],["上用例的标签",{"2":{"287":1}}],["上用例的跳过",{"2":{"204":1}}],["上用例等级",{"2":{"284":1}}],["上用例级别",{"2":{"199":1,"284":1}}],["上线对象",{"2":{"199":2}}],["上对应的用例",{"2":{"199":1}}],["上层用例完全不用关心机器是wayland",{"2":{"184":1}}],["上层用例不用管当前测试机执行环境",{"2":{"59":1}}],["上层用例不受影响",{"2":{"58":1}}],["上",{"2":{"183":1}}],["上图的菜单是在鼠标的左下方",{"2":{"129":1}}],["上传图片",{"2":{"119":1,"137":1}}],["上调用鼠标中键",{"2":{"46":1}}],["上关闭",{"2":{"41":1}}],["上的",{"2":{"41":1}}],["上跳过",{"2":{"39":2}}],["上获取用例相关标签的功能",{"2":{"36":1}}],["上个版本此问题没有完全修复",{"2":{"28":1}}],["或为空",{"2":{"284":1}}],["或子目录存在",{"2":{"175":1}}],["或看图",{"2":{"138":1}}],["或者你可以用一个",{"2":{"179":1}}],["或者有些父窗口不需要添加",{"2":{"141":1}}],["或者或者识别的那一刻",{"2":{"133":1}}],["或者",{"2":{"127":1,"203":1}}],["或者修改",{"2":{"41":1}}],["或",{"2":{"34":1,"39":1,"47":1,"156":2,"158":1,"161":1,"175":2,"182":1,"229":2,"252":2,"255":1}}],["960",{"2":{"149":3}}],["99",{"2":{"146":1}}],["90",{"2":{"133":1}}],["9",{"0":{"43":1},"2":{"34":1,"46":1,"74":1,"133":1,"136":1,"154":2,"192":2}}],["导包报错的问题",{"2":{"51":1}}],["导入路径",{"2":{"302":1}}],["导入全局配置对象",{"2":{"227":1}}],["导入使用",{"2":{"181":1}}],["导入的问题",{"2":{"40":1}}],["导入报错的问题",{"2":{"40":1}}],["导出的csv文件名称",{"2":{"208":1,"229":1}}],["导出csv文件",{"0":{"208":1}}],["导出",{"2":{"33":1,"208":1,"229":1}}],["导致相对距离改变",{"2":{"129":1}}],["导致程序中断的问题",{"2":{"58":1}}],["导致与",{"2":{"46":1}}],["导致子项目依赖报错",{"2":{"40":1}}],["导致",{"2":{"9":1,"31":1,"32":1}}],["暂时先回滚到",{"2":{"33":1}}],["检查分辨率",{"2":{"158":1,"252":1}}],["检查测试机分辨率",{"2":{"41":1,"229":1}}],["检测模型升级到",{"2":{"33":1,"34":1}}],["检索窗口",{"2":{"30":1}}],["禄烨",{"2":{"33":1}}],["模板匹配的效果",{"2":{"136":1}}],["模板图片路径",{"2":{"133":1}}],["模块划分",{"2":{"295":1}}],["模块方法类",{"2":{"292":4}}],["模块",{"2":{"280":1}}],["模块名称",{"2":{"167":1,"229":1}}],["模块对",{"2":{"123":1}}],["模块的问题",{"2":{"34":1}}],["模块的初始化",{"2":{"33":1}}],["模式执行用例",{"2":{"229":1}}],["模式新增参数",{"2":{"11":1}}],["模式下执行用例",{"2":{"59":1}}],["模式下",{"2":{"11":2}}],["独立发布",{"2":{"33":1}}],["产品库用例",{"2":{"32":1,"229":1}}],["解决方法也很简单",{"2":{"224":1}}],["解决方案是将代码中的",{"2":{"59":1}}],["解决在",{"2":{"47":1}}],["解决注销登录界面无法控制键鼠的问题",{"2":{"32":1}}],["解除所有交叉调用的方法",{"2":{"273":1}}],["解除跳过时将装饰器代码删掉",{"2":{"201":1,"284":1}}],["解除子项目的工程名称以",{"2":{"34":1}}],["解除",{"2":{"27":1}}],["yyy",{"2":{"252":1}}],["yy",{"2":{"196":1}}],["yoffset=int",{"2":{"183":2}}],["you",{"2":{"27":1,"211":1}}],["youqu==2",{"2":{"41":2}}],["youqu",{"0":{"1":1,"2":1,"3":1,"60":1,"123":1,"240":1,"241":1,"242":1},"1":{"241":1,"242":1,"243":1},"2":{"2":1,"9":1,"11":2,"12":6,"13":3,"15":1,"16":1,"18":1,"22":3,"25":1,"26":1,"33":2,"34":1,"40":2,"41":11,"47":3,"49":2,"51":4,"52":1,"66":1,"67":2,"69":1,"76":2,"77":2,"79":1,"86":3,"87":2,"89":1,"95":1,"98":3,"103":2,"104":2,"106":1,"113":2,"115":1,"123":1,"124":1,"132":2,"150":1,"155":1,"156":2,"157":1,"158":2,"159":1,"160":1,"161":4,"162":1,"168":1,"173":1,"174":1,"180":1,"181":1,"184":1,"185":1,"187":1,"189":2,"211":1,"212":1,"213":1,"220":1,"222":1,"229":3,"235":1,"236":3,"237":1,"238":1,"240":1,"243":1,"245":4,"246":4,"247":1,"248":1,"251":1,"252":2,"254":1,"255":4,"256":1}}],["y=int",{"2":{"183":1}}],["y=",{"2":{"183":6}}],["y=100",{"2":{"175":2}}],["y=0",{"2":{"175":4}}],["y=none",{"2":{"149":2,"183":5}}],["yes表示所有测试机并行跑",{"2":{"229":1}}],["yes",{"2":{"158":3,"161":1,"195":1,"204":3,"210":2,"223":2,"229":8,"252":3,"255":1}}],["y2",{"2":{"147":3}}],["y1",{"2":{"147":4}}],["yaml",{"2":{"54":1}}],["y",{"2":{"50":2,"53":1,"129":1,"133":5,"136":2,"137":3,"138":2,"143":4,"144":8,"148":2,"149":161,"161":1,"175":38,"183":56,"255":1}}],["ydotool=true",{"2":{"182":1}}],["ydotool",{"2":{"32":1,"182":1,"183":8}}],["集成测试",{"2":{"273":1,"280":1}}],["集成了自研的",{"2":{"220":1}}],["集成",{"2":{"32":1}}],["是很有代表性的",{"2":{"290":1}}],["是测试执行的入口",{"2":{"280":1}}],["是对应用提交集成的版本进行测试",{"2":{"276":1}}],["是对研发每日提交的代码进行测试",{"2":{"276":1}}],["是你的",{"2":{"248":1}}],["是你根据对应的元素按钮命名",{"2":{"148":1}}],["是统信公司开源的一个用于",{"2":{"240":1}}],["是什么",{"0":{"240":1},"1":{"241":1,"242":1,"243":1}}],["是不冲突的",{"2":{"234":1}}],["是不是",{"2":{"184":1}}],["是根据全局超时配置和用例单独超时配置自动计算的",{"2":{"229":1}}],["是无法使用此技术方案的",{"2":{"224":1}}],["是在最新的代码上提交的",{"2":{"204":1}}],["是类装饰器",{"2":{"192":1}}],["是否失败录屏",{"2":{"226":1,"268":1}}],["是否分模块维护",{"2":{"200":1,"284":1}}],["是否相同",{"2":{"175":3}}],["是否递归查找",{"2":{"175":2}}],["是否返回匹配到的多个目标",{"2":{"133":2,"137":1}}],["是说在",{"2":{"154":1}}],["是固定写法",{"2":{"148":1}}],["是该元素按钮的相对与参考系的",{"2":{"148":1}}],["是配置该元素的参考系",{"2":{"148":1}}],["是按钮",{"2":{"147":2}}],["是我们自研的一个使用简单",{"2":{"146":1}}],["是应用对象使用child",{"2":{"142":1}}],["是因为开发人员在添加标签的时候没有添加",{"2":{"141":1}}],["是一种名称空间的设计",{"2":{"154":1}}],["是一种协议",{"2":{"137":1}}],["是一个前端系统",{"2":{"280":1}}],["是一个为应用程序间通信的消息总线系统",{"2":{"66":1}}],["是一个相对平衡识别准确性和用例稳定性的值",{"2":{"23":1}}],["是框架提供的常规图像识别函数接口",{"2":{"133":1}}],["是小图的绝对路径",{"2":{"133":1}}],["是鼠标事件",{"2":{"131":1}}],["是个比较麻烦的事情",{"2":{"128":1}}],["是",{"2":{"98":1,"213":1,"227":1,"267":1}}],["是由于特殊机型下",{"2":{"31":1}}],["失败自动录屏和截图",{"2":{"260":1}}],["失败亦为失败",{"2":{"229":1}}],["失败用例重跑次数",{"2":{"193":1,"229":1}}],["失败重跑用例重跑之前延迟",{"2":{"56":1}}],["失败重跑次数",{"2":{"53":1,"158":1,"226":1,"252":1,"268":1}}],["失败录屏从第几次开始录制视频",{"2":{"193":1}}],["失败录屏从第几次失败开始录制视频",{"2":{"41":1,"158":1,"229":1,"252":1}}],["失败录屏",{"0":{"193":1}}],["失败录屏进程阻塞的问题",{"2":{"31":1}}],["失败数",{"2":{"12":2}}],["华为w525",{"2":{"31":1}}],["华为机型安装键鼠工具时依赖不兼容的问题",{"2":{"47":1}}],["华为机型",{"2":{"21":1}}],["反向同步标签到",{"2":{"31":1}}],["图形图像应用代码解耦",{"2":{"287":1}}],["图上没有提供你想要的元素数据",{"2":{"148":1}}],["图上的按钮",{"2":{"148":1}}],["图标",{"2":{"147":1}}],["图标到任务栏",{"2":{"93":1}}],["图像断言需要用到的图片资源",{"2":{"218":1}}],["图像的路径",{"2":{"183":1}}],["图像定位",{"2":{"146":1}}],["图像识别模块",{"2":{"280":1}}],["图像识别元素定位要用的图片",{"2":{"262":1,"292":1}}],["图像识别端口",{"2":{"229":1}}],["图像识别匹配度",{"2":{"229":1}}],["图像识别重试每次间隔等待时间",{"2":{"229":1}}],["图像识别重试次数",{"2":{"133":1,"229":1}}],["图像识别的最大次数",{"2":{"229":1}}],["图像识别的总超时",{"2":{"229":1}}],["图像识别的结果是",{"2":{"138":1}}],["图像识别的的匹配度或者说相似度",{"2":{"133":1}}],["图像识别目标文件的存放路径",{"2":{"133":1,"137":1}}],["图像识别在",{"2":{"132":1}}],["图像识别方法所需要的资源",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["图像识别新增指定目标图片",{"2":{"50":1}}],["图像识别新增指定区域识别",{"2":{"50":1}}],["图像识别",{"0":{"132":1},"1":{"133":1,"134":1,"135":1,"136":1,"137":1,"138":1},"2":{"30":1,"133":1,"137":1,"242":1}}],["图片中颜色大于50",{"2":{"175":1}}],["图片中仅包含一个菜单选项",{"2":{"128":1}}],["图片路径",{"2":{"138":1,"175":2}}],["图片的名称以用例的名称命名",{"2":{"133":1}}],["图片的名称以实际的元素名称命名",{"2":{"133":1}}],["图片入参支持多种图片格式",{"2":{"11":1,"12":1}}],["类似",{"2":{"267":1}}],["类方法",{"2":{"190":1,"192":1}}],["类里面一个函数只包含一个操作或多次调用的一系列可合并的操作",{"2":{"189":1}}],["类",{"2":{"93":1,"190":1,"282":1,"283":1}}],["类名以",{"2":{"282":1}}],["类名",{"2":{"71":1,"100":1,"167":1,"229":1,"300":1}}],["类型时",{"2":{"30":1}}],["类自动化",{"2":{"17":1}}],["版",{"2":{"29":1}}],["版本将修复期间出现的",{"2":{"52":1}}],["版本运行一段时间",{"2":{"52":1}}],["版本适配持续集成流水线且新增了较多新特性",{"2":{"52":1}}],["版本为",{"2":{"46":1}}],["版本升级到",{"2":{"46":1}}],["版本",{"2":{"41":2}}],["版本我们大胆的将图像识别的默认功能修改为面向服务的方式",{"2":{"40":1}}],["版本指定",{"2":{"29":1}}],["版本不匹配",{"2":{"29":1}}],["版本过高与",{"2":{"29":1}}],["版本问题",{"2":{"28":1}}],["版本的问题",{"2":{"18":1}}],["版本上线",{"2":{"16":1}}],["版本更新记录",{"0":{"4":1},"1":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1}}],["缓存",{"2":{"29":1}}],["玉婷",{"2":{"28":1,"29":1}}],["里面把该写的都写好",{"2":{"301":1}}],["里面可实现",{"2":{"300":1}}],["里面可以看到系统中已启动的应用",{"2":{"141":1}}],["里面填入镜像的下载地址",{"2":{"280":1}}],["里面为空即可",{"2":{"280":1}}],["里面写入应用包名",{"2":{"280":1}}],["里面写入需要安装的三方依赖",{"2":{"233":2}}],["里面进行配置",{"2":{"280":1}}],["里面进行维护",{"2":{"49":1}}],["里面执行",{"2":{"271":1}}],["里面只需要唯一继承",{"2":{"265":1}}],["里面我们设计成这样",{"2":{"265":1}}],["里面主要包含的是用例",{"2":{"260":1}}],["里面不需要写任何内容",{"2":{"234":1}}],["里面保存了所有远程测试机的测试结果",{"2":{"196":1}}],["里面配置测试机",{"2":{"280":1}}],["里面配置为",{"2":{"280":2}}],["里面配置以下参数",{"2":{"195":1}}],["里面配置关注",{"2":{"193":1}}],["里面找到",{"2":{"179":1}}],["里面支持配置对执行的一些参数进行配置",{"2":{"159":1,"253":1}}],["里面点击进入应用的标签",{"2":{"141":1}}],["里面需要定义",{"2":{"84":1}}],["里面",{"2":{"54":1,"213":1,"283":1}}],["里面增加指定",{"2":{"46":1}}],["里面通过配置文件定位桌面文件的方法",{"2":{"46":1}}],["里面定义登陆接口",{"2":{"74":1}}],["里面定义接口对象",{"2":{"64":1}}],["里面定义",{"2":{"43":1}}],["里面包含了基础框架所有的代码",{"2":{"41":1}}],["里面查看有哪些版本",{"2":{"41":1}}],["里面优化了标签化管理章节的描述",{"2":{"37":1}}],["里面细化了远程执行章节的描述",{"2":{"37":1}}],["里面报错",{"2":{"27":1}}],["里面的路径配置进行资源路径的拼接",{"2":{"302":1}}],["里面的参数",{"2":{"193":1}}],["里面的配置",{"2":{"41":2}}],["里面的",{"2":{"27":1,"69":1,"79":1,"89":1,"106":1,"115":1,"133":1,"231":1,"247":1}}],["里面的导入全部设置别名",{"2":{"26":1}}],["容易出现某些包安装失败",{"2":{"27":1}}],["因地制宜",{"2":{"272":1}}],["因为编辑器会自动给我们找到关联的地方",{"2":{"300":1}}],["因为代码编辑器调试代码只能通过入口文件执行",{"2":{"271":1}}],["因为大家都应该参照公共库里面的一些写法来写自己应用库里面的一些方法类",{"2":{"266":1}}],["因为大图中可能存在多个相同的小图",{"2":{"133":1}}],["因为重启类场景需要注册自启服务以及对用例执行过程的处理",{"2":{"223":1}}],["因为有些情况下需要用到",{"2":{"218":1}}],["因为在用例收集阶段可以指定到具体的应用库",{"2":{"195":1,"211":1}}],["因为理论上用例的执行时间是大于数据回填的接口请求时间的",{"2":{"195":1}}],["因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因",{"2":{"193":1}}],["因为你写用例层肯定是会导入方法层出口类的",{"2":{"181":1}}],["因为你得明确知道菜单在左边还是右边",{"2":{"131":1}}],["因为",{"2":{"179":1,"184":1,"222":1}}],["因为此类场景不仅仅在右键存在",{"2":{"131":1}}],["因为用法上更加简洁",{"2":{"76":1}}],["因为用固定的源替换之后",{"2":{"27":1}}],["因此将",{"2":{"283":1}}],["因此将修改后的源码放入到核心库里面",{"2":{"59":1}}],["因此您需要添加环境变量",{"2":{"245":1}}],["因此你不用担心脚本执行导致你的数据丢失",{"2":{"211":1}}],["因此应该配置为",{"2":{"211":1,"229":1}}],["因此用例的录屏能让我们看到用例在执行过程",{"2":{"193":1}}],["因此会导致负载不均衡",{"2":{"122":1}}],["因此我们选取文件管理器作为应用库改造的实验应用",{"2":{"290":1}}],["因此我们将它放到项目根目录",{"2":{"267":1}}],["因此我们大胆的设想",{"2":{"189":1}}],["因此我们形象的称之为",{"2":{"134":1}}],["因此我们需要进行解耦",{"2":{"277":1}}],["因此我们需要一种等待机制",{"2":{"133":1}}],["因此我们需要将",{"2":{"121":1}}],["因此我们增加了一个系统命令",{"2":{"41":1}}],["因此它可以使用",{"2":{"98":1}}],["因此",{"2":{"86":1,"118":1,"154":1,"196":1,"204":1}}],["因此方法里面不用写日志的代码",{"2":{"84":1}}],["因此在方法基类",{"2":{"84":1}}],["因此在底层将这部分日志输出屏蔽掉",{"2":{"26":1}}],["因此需要将文档部署到公网",{"2":{"41":1}}],["因此先把",{"2":{"40":1}}],["因此没有装载到虚拟环境里面",{"2":{"40":1}}],["因此暂留",{"2":{"15":1}}],["机器信息有",{"2":{"213":1}}],["机器密码不对时报错",{"2":{"14":1}}],["机制",{"2":{"27":1}}],["vue",{"2":{"286":1}}],["virtualenvs",{"2":{"236":1}}],["view",{"2":{"229":1,"292":4}}],["vscode",{"2":{"154":1}}],["venv",{"2":{"154":2}}],["verify=false",{"2":{"74":2}}],["version",{"2":{"27":1,"154":1,"203":6}}],["val",{"2":{"183":1}}],["value是对应pms上的模块id",{"2":{"211":1,"229":1}}],["valueerror",{"2":{"149":3,"175":6,"265":1}}],["values",{"2":{"119":1,"136":1,"175":3}}],["value",{"2":{"64":1,"148":1,"175":2}}],["variable",{"2":{"154":1}}],["variables",{"2":{"154":1}}],["variety",{"2":{"154":1}}],["v",{"2":{"74":2,"183":1}}],["v23",{"2":{"54":1}}],["v3",{"2":{"33":1}}],["v4",{"2":{"13":2,"33":1,"34":1,"74":1}}],["个及以上的外部应用调用",{"2":{"283":1}}],["个外部应用调用",{"2":{"282":1}}],["个应用都用到的",{"2":{"266":1}}],["个理由",{"0":{"242":1}}],["个参数",{"2":{"193":1}}],["个问题",{"2":{"123":1}}],["个执行最慢的用例列表",{"2":{"56":1}}],["个小点要注意",{"2":{"41":1}}],["个",{"2":{"26":1,"40":1,"131":1}}],["不然你可能会花上一天的时间来解决重命名的问题",{"2":{"300":1}}],["不然我为什么不用文管的重命名功能呢",{"2":{"300":1}}],["不做其他事情",{"2":{"296":1}}],["不关心元素的定位和操作",{"2":{"275":1}}],["不插串口线",{"2":{"271":1}}],["不好定位问题",{"2":{"271":1}}],["不好做时",{"2":{"146":1}}],["不能适应自动化测试在多场景下的应用",{"2":{"277":1}}],["不能在编辑器中直接执行单个用例脚本",{"2":{"271":1}}],["不能接受的是经常会导致大家在分析用例失败原因的时候将矛头指向它",{"2":{"26":1}}],["不要以",{"2":{"246":1}}],["不仅支持单条用例超时控制",{"2":{"242":1}}],["不会在每条用例执行完之后生成json结果文件",{"2":{"229":1}}],["不会受到字体",{"2":{"131":1}}],["不会受到菜单选项顺序改变的影响",{"2":{"131":1}}],["不跳过用例",{"2":{"229":1}}],["不建议在组合步骤中间插入一个reboot",{"2":{"222":1}}],["不管配置文件是否配置",{"2":{"210":1}}],["不管send",{"2":{"161":1,"229":1,"255":1}}],["不适合马上放到流水线去跑",{"2":{"204":1}}],["不适用于界面不固定的应用",{"2":{"146":1}}],["不打印构造函数和魔法函数的功能说明",{"2":{"191":1,"229":1}}],["不熟悉",{"2":{"185":1}}],["不存在以",{"2":{"175":1}}],["不相同",{"2":{"175":4}}],["不符",{"2":{"175":1}}],["不含report目录",{"2":{"161":1,"229":1,"255":1}}],["不需要",{"2":{"154":1}}],["不妨考虑使用这种",{"2":{"146":1}}],["不同测试类型的用例执行",{"2":{"285":1}}],["不同测试类型的配置都在同一个配置文件里面",{"2":{"280":1}}],["不同应用版本环境上都可以进行自动化的",{"2":{"280":1}}],["不同的定位方案调用不同的定位工具对象",{"2":{"295":1}}],["不同的维度来挑选要执行的用例",{"2":{"277":1}}],["不同的at项目在同一台机器上部署环境时依赖版本冲突的问题",{"2":{"41":1}}],["不同版本的系统壁纸不同",{"2":{"138":1}}],["不依赖",{"0":{"135":1},"1":{"136":1,"137":1}}],["不停的截取这段时间内的大图",{"2":{"134":1}}],["不容易捕捉到",{"2":{"134":1}}],["不用担心",{"2":{"301":1}}],["不用安装",{"2":{"136":1}}],["不用保存大量的图片",{"2":{"131":1}}],["不用再单独处理远程执行的参数逻辑",{"2":{"43":1}}],["不想步长那么只管",{"2":{"129":1}}],["不生效的问题",{"2":{"56":1}}],["不输出异常日志的问题",{"2":{"49":1}}],["不传入",{"2":{"47":1}}],["不兼容",{"2":{"46":1}}],["不过没关系",{"2":{"41":1}}],["不加",{"2":{"41":1,"245":2}}],["不在系统",{"2":{"41":1}}],["不应该把含有业务相关的代码提交到框架底层",{"2":{"3":1}}],["但可能出现",{"2":{"245":1}}],["但可能会出现文档速度慢的问题",{"2":{"41":1}}],["但这样做有一个很严重的问题",{"2":{"239":1}}],["但框架不会进行数据回填",{"2":{"229":1}}],["但我们仍然实现了",{"2":{"219":1}}],["但仍然想要跳过用例",{"2":{"204":1}}],["但不能立即删除跳过原因",{"2":{"204":1}}],["但基本的使用该有的都有",{"2":{"185":1}}],["但基础框架不需要",{"2":{"40":1}}],["但问题是没有一种方案是通用的",{"2":{"180":1}}],["但远程机器执行的用例不同",{"2":{"162":1,"256":1}}],["但没有被使用",{"2":{"154":1}}],["但实际获取的窗口为",{"2":{"149":1}}],["但最好有具体含义",{"2":{"148":1}}],["但最终还是没能解决",{"2":{"130":1}}],["但在识别效率上还没有达到",{"2":{"136":1}}],["但其实安装包有点大",{"2":{"118":1}}],["但大多数同学喜欢用三方模块",{"2":{"76":1}}],["但写了",{"2":{"57":1}}],["但终端没有错误日志输出的问题",{"2":{"54":1}}],["但有些接口的项目不需要这个检查",{"2":{"41":1}}],["但是又是相同名称的重命名",{"2":{"302":1}}],["但是没有串口线",{"2":{"272":1}}],["但是没注意到之前给海燕姐那边项目单独定制做了个图像识别接口",{"2":{"40":1}}],["但是对测试人员本地编写代码安装环境很不友好",{"2":{"271":1}}],["但是由于它的特殊性",{"2":{"267":1}}],["但是我们想让事情变得简单",{"2":{"265":1}}],["但是方法类同样会进行实例化",{"2":{"222":1}}],["但是此时",{"2":{"204":1}}],["但是执行结果可能不一致",{"2":{"196":1}}],["但是填了可以提高用例的执行速度",{"2":{"195":1,"211":1}}],["但是你不能直接通过浏览器打开",{"2":{"179":1}}],["但是几乎所有的命令行参数都对应提供了配置文件配置项",{"2":{"156":1}}],["但是这样的区分太宽泛了",{"2":{"277":1}}],["但是这是我特意这样写的",{"2":{"154":1}}],["但是这里仍然存在两个严重的问题",{"2":{"129":1}}],["但是位置是固定的",{"2":{"142":1}}],["但是在一些情况下仍然存在一点问题",{"2":{"131":1}}],["但是在属性的",{"2":{"130":1}}],["但是需要保存大量的图片",{"2":{"128":1}}],["但是",{"2":{"127":1,"277":1}}],["但是它对于中文的识别非常差",{"2":{"117":1}}],["但是都有个问题",{"2":{"41":1}}],["但本次时间比较紧",{"2":{"40":1}}],["但",{"2":{"26":1,"31":1,"210":1}}],["但考虑到有些同学仍然有使用",{"2":{"15":1}}],["执行入口提供给测试平台的接口包括",{"2":{"286":1}}],["执行入口能随意通过用例标签指定要执行的用例",{"2":{"285":1}}],["执行入口加载相应的用例集并控制执行",{"2":{"280":1}}],["执行一个或多个应用的用例",{"2":{"280":1}}],["执行一下",{"2":{"224":1}}],["执行器",{"2":{"262":1}}],["执行所需环境",{"2":{"247":1}}],["执行",{"2":{"233":1,"280":1}}],["执行包含用例标签的用例",{"2":{"229":1}}],["执行包含关键词的用例",{"2":{"167":1,"229":1}}],["执行结束之后在",{"2":{"196":1}}],["执行完之后会在",{"2":{"193":1}}],["执行完之后所有测试机的测试结果会返回给服务端",{"2":{"161":1,"255":1}}],["执行的应用名称",{"2":{"229":1}}],["执行的时候会自动输出",{"2":{"192":1}}],["执行的业务线",{"2":{"158":1,"252":1}}],["执行某个app工程的所有用例",{"0":{"166":1}}],["执行前确保远程机器已经开启了",{"2":{"161":1,"255":1}}],["执行相同的测试用例",{"2":{"161":1,"229":1,"255":1}}],["执行环境要对编码人员更加友好",{"2":{"272":1}}],["执行环境",{"0":{"224":1},"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["执行开始时打印",{"2":{"53":1}}],["执行用例的范围",{"2":{"286":1}}],["执行用例的标签配置等等",{"2":{"280":1}}],["执行用例默认读取到",{"2":{"193":1}}],["执行用例",{"2":{"51":1}}],["执行时间",{"2":{"286":1}}],["执行时间会越来越长",{"2":{"285":1}}],["执行时日志级别",{"2":{"226":1,"268":1}}],["执行时会在根目录下动态生成",{"2":{"177":1}}],["执行时",{"2":{"41":1}}],["执行会报错",{"2":{"26":1}}],["执行管理器",{"0":{"155":1,"250":1},"1":{"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1},"2":{"12":1,"68":1,"78":1,"88":1,"105":1,"114":1}}],["有没有网络无所谓",{"2":{"272":1}}],["有没有可能有一天国内无法使用",{"2":{"136":1}}],["有网络",{"2":{"272":1}}],["有两台机器",{"2":{"272":2}}],["有趣",{"2":{"240":1}}],["有必要自己实现一个图像识别的功能吗",{"2":{"136":1}}],["有",{"2":{"136":1}}],["有同学可能会发现",{"2":{"197":1}}],["有同学肯定要问",{"2":{"180":1}}],["有同学要问了",{"2":{"136":1}}],["有同学说干嘛不通过属性定位呢",{"2":{"130":1}}],["有可能图像识别的时候气泡已经消失了",{"2":{"134":1}}],["有可能存在识别的那一刻页面也没有跳转出来",{"2":{"133":1}}],["有时候页面跳转有延时",{"2":{"133":1}}],["有的没写",{"2":{"57":1}}],["有些骚操作编辑器是无法自动处理的",{"2":{"300":1}}],["有些地方可能不支持ctrl+v粘贴",{"2":{"183":1}}],["有些机器可能",{"2":{"41":1}}],["有些镜像没有",{"2":{"26":1}}],["有志",{"2":{"20":1,"21":1,"26":1,"30":2,"33":1}}],["英文数字字符等使用",{"2":{"26":1}}],["~$",{"2":{"47":2,"141":1}}],["~",{"2":{"25":1,"84":1,"111":1,"133":1,"175":2,"229":1,"296":1}}],["孙翠",{"2":{"25":1,"39":1}}],["佳斌",{"2":{"25":1}}],["本项目是一个自动化测试的基础框架",{"2":{"260":1}}],["本身无法提供代码补全",{"2":{"219":1}}],["本机同步解析",{"2":{"272":1}}],["本机执行",{"2":{"272":2}}],["本机执行方案",{"2":{"272":1}}],["本机执行时回填",{"0":{"195":1}}],["本机",{"2":{"226":1,"268":1}}],["本机部署的功能仍然保留",{"2":{"41":1}}],["本地插件模块",{"2":{"262":1}}],["本地插件",{"2":{"262":1,"292":1}}],["本地文件测试套",{"2":{"229":1}}],["本地用例文件驱动执行",{"0":{"172":1}}],["本地执行子命令为",{"2":{"157":1}}],["本地执行",{"0":{"157":1,"251":1},"1":{"158":1,"159":1,"252":1,"253":1},"2":{"179":1}}],["本地再次调用报属性找不到的问题",{"2":{"16":1}}],["本章节主要讲基于",{"2":{"131":1}}],["本次设计主要集中在后端这部分架构的设计上",{"2":{"286":1}}],["本次我们解决了这个问题",{"2":{"41":1}}],["本次彻底解决",{"2":{"28":1}}],["本次功能更新离不开多个部门领导和同事们的协助",{"2":{"25":1}}],["堪称完美",{"2":{"25":1}}],["至此基于",{"2":{"25":1}}],["默认配置文件",{"2":{"262":1}}],["默认的项目名称为",{"2":{"246":1}}],["默认采用虚拟化部署",{"2":{"236":1}}],["默认在所有测试完成之后输出报错信息",{"2":{"229":1}}],["默认失败重跑的次数是",{"2":{"193":1}}],["默认",{"2":{"183":1}}],["默认值为",{"2":{"175":1}}],["默认值设置为",{"2":{"23":1}}],["默认使用虚拟环境执行",{"2":{"224":1}}],["默认使用",{"2":{"150":1}}],["默认使用系统自带的浏览器进行测试",{"2":{"98":1,"103":1}}],["默认参考点",{"2":{"149":2}}],["默认不间隔",{"2":{"134":1,"175":1}}],["默认不传参",{"2":{"133":1}}],["默认image",{"2":{"133":1}}],["默认情况下同时生成",{"2":{"177":1}}],["默认情况下是一刻不停的截图",{"2":{"134":1}}],["默认情况下",{"2":{"133":2}}],["默认大图是截取屏幕",{"2":{"133":1,"137":1}}],["默认为空",{"2":{"229":1}}],["默认为",{"2":{"119":1,"142":1,"149":1,"175":2}}],["默认开启",{"2":{"58":1}}],["默认备份至",{"2":{"56":1}}],["默认语言",{"2":{"53":1}}],["默认取sett",{"2":{"161":1,"255":1}}],["默认取",{"2":{"47":1,"122":1}}],["默认重试1次",{"2":{"50":1}}],["默认重试",{"2":{"39":1}}],["默认最大递归深度的问题",{"2":{"26":1}}],["默认环境中移除此模块",{"2":{"11":1}}],["泽铭",{"2":{"22":1,"25":1,"39":1}}],["换了调用逻辑",{"2":{"22":1}}],["global",{"2":{"262":1}}],["globalconfig",{"2":{"25":1,"34":3,"41":2,"69":1,"79":1,"89":1,"98":1,"106":1,"115":1,"119":2,"133":4,"137":2,"144":5,"149":11,"156":2,"159":1,"161":1,"175":11,"183":5,"184":2,"193":2,"195":1,"203":7,"213":1,"227":5,"228":3,"231":1,"247":1,"253":1,"255":1,"262":2,"280":3}}],["g",{"2":{"229":2}}],["gpl",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1,"243":1}}],["gti",{"2":{"229":1}}],["gt",{"2":{"142":3}}],["grab",{"2":{"175":1}}],["graph",{"2":{"136":4}}],["grep",{"2":{"144":1}}],["group",{"2":{"74":8,"144":1}}],["goto",{"2":{"97":2,"98":3,"229":2}}],["genericpredicate",{"2":{"144":2}}],["generate",{"2":{"75":2}}],["gecko",{"2":{"74":1}}],["getmembers",{"2":{"190":1}}],["getattr",{"2":{"149":4}}],["getallwindowstateslist",{"2":{"22":1,"25":1,"149":4}}],["getwindowinformation",{"2":{"149":4}}],["get",{"2":{"50":1,"64":2,"65":1,"74":7,"134":1,"147":2,"149":27,"175":29,"183":2,"203":1,"265":3,"295":1,"296":1}}],["gzip",{"2":{"74":1}}],["git仓库的分支",{"2":{"229":1}}],["git仓库的密码",{"2":{"229":1}}],["git仓库的用户名",{"2":{"229":1}}],["git仓库的地址",{"2":{"229":1}}],["git子命令用于拉取子项目仓库代码",{"2":{"229":1}}],["gitmodules",{"2":{"57":1}}],["gitignore",{"2":{"19":1}}],["gitlab",{"2":{"17":1}}],["git",{"2":{"5":1,"7":1,"11":4,"18":2,"41":1,"53":1,"154":2,"229":4,"248":1}}],["github",{"2":{"2":1,"41":2}}],["调试和编写用例",{"0":{"303":1}}],["调试模式",{"2":{"158":1,"252":1}}],["调起的文管对话框实际为",{"2":{"283":1}}],["调用其他应用的方法库",{"2":{"280":1}}],["调用上述方法会报错",{"2":{"182":1}}],["调用所有的断言语句",{"2":{"174":1}}],["调用方法时",{"2":{"192":1}}],["调用方法",{"2":{"148":1}}],["调用相关方法失败~",{"2":{"144":1}}],["调用",{"2":{"85":1,"215":1,"216":1}}],["调用的函数增加了",{"2":{"53":1}}],["调用函数同时传入可变参数和默认参数",{"2":{"13":1}}],["调整工程目录",{"0":{"300":1}}],["调整",{"2":{"22":1}}],["布局",{"2":{"22":1}}],["切换图片之后再次识别这张图片",{"2":{"138":1}}],["切换",{"2":{"22":1}}],["多种报告输出",{"2":{"260":1}}],["多种元素定位方案",{"2":{"242":1}}],["多机器分布式异步负载均衡执行也是用本地作为服务端控制远程机器执行",{"2":{"162":1,"256":1}}],["多机器分布式异步负载均衡执行",{"0":{"162":1}}],["多机器分布式异步执行就是由本地",{"2":{"161":1,"255":1}}],["多机器分布式异步执行",{"0":{"161":1}}],["多的不说了",{"2":{"117":1}}],["多样的元素定位方案",{"2":{"86":1}}],["多个应用之间用",{"2":{"280":1}}],["多个应用都要用到的一些操作方法",{"2":{"260":1}}],["多个分辨率检查用英文逗号连接",{"2":{"229":1}}],["多个机器之间用斜线分割",{"2":{"213":1,"229":2}}],["多个机器信息用",{"2":{"213":1}}],["多个机器用",{"2":{"47":1,"161":1,"255":1}}],["多个参数用",{"2":{"203":1}}],["多个参数以逗号隔开",{"2":{"191":3,"229":3}}],["多个架构之间使用",{"2":{"203":1}}],["多个以",{"2":{"21":1}}],["多条件跳过用例功能",{"2":{"21":1}}],["阻塞问题",{"2":{"20":1}}],["获取被装饰的类下所有函数",{"2":{"190":1}}],["获取当前鼠标位置",{"2":{"183":1}}],["获取屏幕分辨率",{"2":{"183":1}}],["获取屏幕大小",{"2":{"183":1}}],["获取活动应用窗口id",{"2":{"149":1}}],["获取窗口下边界中心的坐标",{"2":{"149":2}}],["获取窗口右边界中心坐标",{"2":{"149":2}}],["获取窗口上边界中心坐标",{"2":{"149":2}}],["获取窗口左边界中心坐标",{"2":{"149":1}}],["获取窗口左上角坐标错误",{"2":{"149":1}}],["获取窗口左上角坐标",{"2":{"149":1}}],["获取窗口的中心点坐标",{"2":{"149":1}}],["获取窗口的大小",{"2":{"149":1}}],["获取窗口的位置及大小",{"2":{"149":1}}],["获取窗口大小错误",{"2":{"149":2}}],["获取窗口大小",{"2":{"149":2}}],["获取配置",{"2":{"147":1}}],["获取应用的所有窗口编号",{"2":{"149":1}}],["获取应用所有窗口数量",{"2":{"149":1}}],["获取应用窗口的信息",{"2":{"147":1}}],["获取应用对象的时候",{"2":{"142":1}}],["获取应用对象",{"2":{"142":1}}],["获取app元素的对象",{"2":{"143":1,"144":1}}],["获取到当前的显示服务器",{"2":{"184":1}}],["获取到应用窗口在当前屏幕中的位置",{"2":{"147":1}}],["获取到这个元素下面所有的元素列表",{"2":{"142":1}}],["获取到相应元素的对象",{"2":{"142":1}}],["获取元素按钮相对与应用窗口边界的位置及大小",{"2":{"147":1}}],["获取元素中心坐标",{"2":{"144":1}}],["获取元素右上角的坐标",{"2":{"144":1}}],["获取元素的左上角坐标及长宽",{"2":{"149":1}}],["获取元素的中心坐标",{"2":{"149":1}}],["获取元素的中心位置",{"2":{"143":1,"144":1}}],["获取元素的大小",{"2":{"144":1}}],["获取元素",{"2":{"144":2}}],["获取元素左上角的坐标",{"2":{"144":1}}],["获取元素对象列表",{"2":{"142":1}}],["获取元素对象",{"2":{"142":2,"144":1}}],["获取元素控件的标签名称",{"2":{"141":1}}],["获取管理员登陆",{"2":{"74":1}}],["获取激活状态",{"2":{"64":1}}],["获取控件左上角坐标及长宽",{"2":{"53":1}}],["获取以外",{"2":{"41":1}}],["获取的窗口名称为空",{"2":{"27":1}}],["获取不到有效信息会有一些",{"2":{"26":1}}],["获取",{"2":{"20":1}}],["获取数据",{"2":{"16":1}}],["标定操作方法",{"2":{"295":1}}],["标题栏方法类",{"2":{"295":1}}],["标题栏",{"2":{"295":1}}],["标记所有已实现的用例标签",{"2":{"284":1}}],["标准库",{"2":{"137":1}}],["标准库difflib",{"2":{"17":1}}],["标识文件",{"0":{"92":1}}],["标签支持扩展",{"2":{"284":1}}],["标签和资源都是相互独立的",{"2":{"280":1}}],["标签化执行驱动程序编写",{"2":{"287":1}}],["标签化执行",{"2":{"260":1}}],["标签化管理的驱动执行逻辑功能实现",{"2":{"285":1}}],["标签化管理",{"0":{"198":1},"1":{"199":1,"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1}}],["标签化管理支持判断系统版本跳过用例",{"2":{"27":1}}],["标签可以是传统的pytest标签",{"2":{"229":1}}],["标签自动同步",{"0":{"209":1},"1":{"210":1,"211":1}}],["标签的用例",{"2":{"208":1,"229":1}}],["标签记录为",{"2":{"203":2}}],["标签说明",{"0":{"199":1}}],["标签驱动支持",{"2":{"168":1}}],["标签",{"2":{"34":1,"57":1,"168":1,"262":1}}],["标签生效的问题",{"2":{"20":1}}],["español",{"2":{"229":1}}],["es",{"2":{"229":1}}],["esc",{"2":{"149":1}}],["eg",{"2":{"229":1}}],["eggs",{"2":{"154":1}}],["ec",{"2":{"208":1}}],["echo",{"2":{"183":1,"203":2,"222":1}}],["easy",{"2":{"184":1}}],["each",{"2":{"136":1}}],["e9",{"2":{"154":1}}],["e712",{"2":{"154":1}}],["e711",{"2":{"154":1}}],["e731",{"2":{"154":1}}],["e722",{"2":{"154":1}}],["e721",{"2":{"154":1}}],["e7",{"2":{"154":1}}],["e402",{"2":{"154":1}}],["e4",{"2":{"154":1}}],["eval",{"2":{"149":2}}],["evalx",{"2":{"144":4}}],["effect",{"2":{"154":1}}],["ef",{"2":{"144":1}}],["e",{"2":{"133":2,"161":3,"229":2,"255":3}}],["eles",{"2":{"144":3}}],["ele",{"2":{"144":5}}],["elementexpressionerror",{"2":{"175":2}}],["elements",{"2":{"144":6,"175":1,"192":5}}],["elementnotfound",{"2":{"144":5,"175":2}}],["element",{"2":{"84":2,"93":1,"133":2,"142":2,"143":7,"144":58,"175":5,"192":2,"215":9,"295":1}}],["elif",{"2":{"119":1,"144":1,"149":10,"175":4}}],["else",{"2":{"119":2,"133":1,"144":10,"149":24,"175":25,"183":14,"184":1,"265":1}}],["email",{"2":{"74":3}}],["email=none",{"2":{"74":1}}],["examples",{"2":{"154":1}}],["export",{"2":{"208":1,"229":2}}],["exp",{"2":{"175":2}}],["expanduser",{"2":{"175":4}}],["expr=",{"2":{"144":1,"175":2}}],["expr",{"2":{"144":27,"175":15}}],["expect",{"2":{"75":3,"98":2,"175":38,"187":1}}],["extents",{"2":{"143":1,"144":1}}],["excel",{"2":{"207":1,"280":1}}],["exception",{"2":{"133":1,"144":2,"149":5,"175":11}}],["exceptions",{"2":{"74":1}}],["except",{"2":{"74":1,"133":1,"137":1,"144":5,"149":6,"175":9,"222":1}}],["exclude",{"2":{"154":2}}],["exc",{"2":{"137":2,"149":15,"175":12,"183":3}}],["executable",{"2":{"98":1,"229":1}}],["exit",{"2":{"53":2,"158":1,"161":1,"183":1,"252":1,"255":1}}],["exists",{"2":{"175":4,"296":3}}],["exist",{"2":{"18":1,"24":1,"34":1,"53":2,"111":1,"119":2,"175":10,"184":2,"222":1}}],["equal",{"2":{"65":1,"175":2}}],["etc",{"2":{"27":1}}],["error",{"2":{"21":1,"27":1,"144":1,"177":1,"191":1,"229":1}}],["english",{"2":{"229":1}}],["en",{"2":{"229":1}}],["enabled",{"2":{"154":2}}],["enable",{"2":{"154":3,"161":1,"255":1}}],["endwith=endwith",{"2":{"175":1}}],["endwith",{"2":{"175":5}}],["ending",{"2":{"154":2}}],["endswith",{"2":{"144":2,"191":1,"229":1}}],["end",{"2":{"144":2,"175":42,"183":6,"229":1}}],["enddate",{"2":{"12":1}}],["enter",{"2":{"127":2,"182":1,"183":4}}],["encoding",{"2":{"74":1}}],["encode",{"2":{"74":2}}],["environ",{"2":{"183":1}}],["environmenterror",{"2":{"137":1,"144":1}}],["env",{"0":{"72":1,"101":1,"230":1},"1":{"231":1,"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1},"2":{"12":1,"15":3,"16":1,"17":1,"18":1,"27":2,"29":1,"38":2,"41":2,"42":1,"43":2,"45":1,"46":1,"47":3,"50":2,"53":4,"54":2,"57":1,"68":1,"69":2,"72":1,"78":1,"79":2,"88":1,"89":2,"101":1,"105":1,"106":2,"114":1,"115":2,"118":1,"144":1,"149":1,"161":1,"175":1,"183":1,"184":1,"203":1,"224":2,"229":1,"231":3,"233":2,"234":1,"235":1,"247":3,"255":1}}],["azərbaycanca",{"2":{"229":1}}],["az",{"2":{"229":1}}],["awk",{"2":{"203":2}}],["aarch64",{"2":{"203":7,"242":1}}],["amount",{"2":{"175":1,"183":5}}],["amp",{"2":{"21":2,"150":1,"203":7}}],["absolute",{"2":{"149":2}}],["abspath",{"2":{"119":4,"133":5,"137":3,"175":14}}],["abspath=",{"2":{"133":1}}],["abspath=picture",{"2":{"133":1,"175":2}}],["abspath=pic",{"2":{"119":1,"175":2}}],["abspath=none",{"2":{"119":2,"133":1,"175":2}}],["abspath=deepinmusicwidget",{"2":{"53":1}}],["add",{"2":{"148":1,"222":1}}],["admin123",{"2":{"213":1,"229":2}}],["adminapi",{"2":{"74":2,"75":1}}],["admin",{"2":{"74":21,"75":3}}],["arch",{"2":{"203":1,"228":1}}],["arrch64",{"2":{"203":1}}],["arguments",{"2":{"144":1,"252":1}}],["args",{"2":{"119":3,"143":2,"144":7,"175":10,"183":10,"203":14}}],["are",{"2":{"136":2,"154":1}}],["asan",{"2":{"280":1}}],["async",{"2":{"158":1,"170":1,"171":1,"195":2,"229":1,"252":1}}],["assume",{"2":{"154":1}}],["assertoptionerror",{"2":{"175":4}}],["assertionerror",{"2":{"119":2,"175":30}}],["assertcommon",{"2":{"24":1,"174":2,"175":1}}],["assert",{"2":{"18":1,"24":1,"34":1,"53":4,"61":2,"65":2,"70":2,"71":2,"75":2,"80":2,"85":3,"92":1,"98":4,"99":2,"100":2,"107":2,"111":2,"119":2,"133":1,"174":5,"175":25,"184":2,"187":1,"191":1,"222":1,"229":1,"248":2,"262":2,"280":1,"292":2,"296":7}}],["as",{"2":{"133":1,"137":3,"149":5,"154":1,"175":7,"183":1}}],["airtest",{"2":{"132":1}}],["an",{"2":{"154":1}}],["and",{"2":{"119":1,"136":3,"144":2,"149":13,"154":2,"158":1,"161":1,"167":2,"168":1,"175":6,"183":7,"229":1,"252":1,"255":1,"300":1}}],["any",{"2":{"18":1,"175":3}}],["actions",{"2":{"141":1}}],["action",{"2":{"131":4}}],["actual",{"2":{"75":2,"175":10}}],["accept",{"2":{"74":3}}],["agent",{"2":{"74":1}}],["album",{"2":{"200":2,"208":3,"280":4}}],["alt",{"2":{"183":1,"216":2,"217":2,"218":1}}],["also",{"2":{"136":1}}],["all",{"2":{"154":3,"175":6,"183":1,"229":1}}],["allow",{"2":{"119":1,"137":2,"154":2}}],["allure报告备份",{"2":{"177":1}}],["allure报告",{"2":{"177":1}}],["allure",{"2":{"45":1,"53":1,"56":2,"177":3,"178":1,"179":6,"192":2,"229":3}}],["alive",{"2":{"74":1}}],["apiresponseassertions",{"2":{"187":1}}],["apiresponse",{"2":{"187":1}}],["api",{"2":{"71":5,"74":10,"75":7,"199":1}}],["app工程",{"2":{"248":1}}],["app工程配置对象",{"0":{"228":1}}],["app工程的名称",{"2":{"218":1}}],["appropriate",{"2":{"154":1}}],["append",{"2":{"144":1}}],["appname",{"2":{"93":3}}],["appname=",{"2":{"16":1,"218":1}}],["applewebkit",{"2":{"74":1}}],["applicationstarterror",{"2":{"144":2,"149":6,"222":1}}],["applications",{"2":{"93":1}}],["application",{"2":{"20":1,"74":2,"142":2,"143":1,"144":1}}],["app",{"0":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1},"1":{"62":1,"71":1,"72":1,"81":1,"100":1,"101":1,"102":1,"108":1},"2":{"34":2,"35":1,"47":3,"53":1,"61":6,"64":1,"65":4,"70":6,"71":3,"75":2,"80":6,"84":4,"85":6,"92":1,"94":2,"97":1,"98":4,"99":6,"100":3,"107":6,"111":4,"142":3,"143":2,"144":6,"147":4,"149":61,"158":5,"165":1,"166":1,"174":5,"175":18,"195":3,"211":1,"218":3,"229":4,"248":7,"252":3,"265":9,"266":3,"294":3,"297":5}}],["apps",{"0":{"264":1},"2":{"18":1,"34":1,"41":1,"47":3,"49":2,"53":1,"56":1,"61":1,"64":1,"65":3,"68":1,"70":1,"71":1,"74":2,"75":3,"78":1,"80":1,"84":1,"85":3,"88":1,"92":1,"94":2,"97":1,"98":3,"99":1,"100":1,"105":1,"107":1,"111":3,"114":1,"158":2,"166":1,"167":1,"170":1,"171":1,"172":3,"174":1,"175":2,"181":1,"195":1,"196":1,"208":2,"229":3,"248":3,"252":2,"255":1,"260":2,"262":1,"264":1,"267":1,"280":1,"295":1,"296":3,"297":6,"299":1}}],["attr",{"2":{"84":2,"85":1,"93":2,"94":1,"144":7,"175":3,"215":3,"222":1,"266":1,"282":1,"283":1,"295":2}}],["at",{"0":{"257":1,"288":1},"1":{"258":1,"259":1,"260":1,"261":1,"262":1,"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"289":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1},"2":{"55":1,"133":1,"136":1,"141":1,"147":1,"204":2,"248":1,"260":2,"264":1,"273":7,"276":2,"280":2,"289":1}}],["autostart",{"2":{"158":2,"223":2,"229":1,"252":2}}],["auto",{"2":{"154":2,"158":1,"195":2,"229":2,"252":1}}],["automatically",{"2":{"154":1}}],["autotool",{"2":{"42":1,"180":1}}],["autotest",{"2":{"34":3,"41":2,"47":4,"49":2,"53":1,"61":2,"64":1,"65":3,"70":2,"71":1,"74":2,"75":3,"80":2,"84":1,"85":3,"92":1,"94":2,"97":1,"98":3,"99":2,"100":1,"107":2,"111":3,"158":4,"161":2,"162":1,"166":1,"167":1,"170":1,"171":1,"172":4,"174":1,"175":2,"177":2,"181":1,"195":1,"196":1,"208":2,"218":1,"229":3,"248":4,"252":3,"255":1,"260":2,"262":2,"295":1,"296":2,"297":5,"299":1,"301":1}}],["author",{"2":{"144":1,"149":1,"183":1}}],["authorizationstate",{"2":{"64":1}}],["authorization",{"2":{"64":1,"65":3}}],["auotest",{"2":{"53":1}}],["a",{"2":{"34":3,"47":3,"51":1,"53":1,"154":4,"158":1,"161":2,"162":1,"166":1,"170":1,"171":1,"183":2,"195":1,"196":1,"203":2,"208":3,"252":2,"255":2,"256":1}}],["环境也无法部署",{"2":{"271":1}}],["环境不好搭建",{"2":{"271":1}}],["环境问题",{"2":{"271":1}}],["环境以提供",{"2":{"212":1}}],["环境影响或评估不再适用于自动化测试时",{"2":{"205":1}}],["环境依赖这块后面会单独详细讲",{"2":{"136":1}}],["环境部署简单",{"2":{"240":1}}],["环境部署",{"0":{"230":1},"1":{"231":1,"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1},"2":{"68":1,"78":1,"88":1,"105":1,"114":1,"271":1}}],["环境执行",{"2":{"55":1}}],["环境安装",{"2":{"272":1}}],["环境安装难度",{"2":{"185":1}}],["环境安装移除",{"2":{"53":1}}],["环境安装失败的问题",{"2":{"47":1}}],["环境变量指向错误",{"2":{"51":1}}],["环境变量缺失问题",{"2":{"18":1}}],["环境目录下",{"2":{"41":1}}],["环境下能顺畅运行",{"2":{"242":1}}],["环境下使用命令行参数会更加方便",{"2":{"158":1,"252":1}}],["环境下安装无法读取密码的问题",{"2":{"54":1}}],["环境下多个工程存在",{"2":{"51":1}}],["环境下运行提示",{"2":{"49":1}}],["环境下",{"2":{"18":1,"47":1,"53":1}}],["x4",{"2":{"255":1}}],["x3",{"2":{"255":1}}],["x3c",{"2":{"27":1,"100":1,"144":3,"149":3,"175":24,"183":10,"248":1}}],["xoffset=int",{"2":{"183":2}}],["xy",{"2":{"175":6}}],["x=int",{"2":{"183":1}}],["x=",{"2":{"183":6}}],["x=100",{"2":{"175":2}}],["x=0",{"2":{"175":4}}],["x=none",{"2":{"149":2,"183":5}}],["xwininfo",{"2":{"147":2,"149":1,"184":1}}],["x26",{"2":{"203":8}}],["x2",{"2":{"147":3}}],["x1",{"2":{"147":4}}],["x11",{"2":{"25":1,"39":1,"74":1,"149":7,"175":1,"183":1,"184":5,"203":1,"240":1,"242":1}}],["x86",{"2":{"74":1,"192":1,"242":1}}],["xsrf",{"2":{"74":2}}],["xml报告",{"2":{"177":1}}],["xmlrpc",{"2":{"119":1,"137":4}}],["xml",{"2":{"56":1,"177":3,"229":3}}],["x",{"2":{"50":2,"53":1,"74":1,"119":2,"129":1,"133":5,"136":2,"137":7,"138":2,"143":4,"144":8,"148":2,"149":152,"175":42,"183":61,"192":2}}],["xx",{"2":{"47":6,"144":1,"161":6,"162":2,"196":1,"255":2}}],["xxx的用例不跳过",{"2":{"229":1}}],["xxxwidget",{"2":{"189":1}}],["xxxx",{"2":{"170":1,"171":1,"195":1,"196":1,"295":1}}],["xxx",{"2":{"12":1,"16":2,"47":2,"49":1,"53":2,"57":1,"98":3,"144":4,"158":3,"161":4,"162":2,"164":5,"170":1,"171":1,"174":1,"175":1,"184":2,"189":1,"191":3,"192":1,"195":1,"196":2,"197":2,"199":4,"200":2,"202":1,"204":5,"215":5,"216":1,"218":1,"229":6,"233":2,"234":1,"252":1,"255":2,"262":1,"266":1,"282":1,"283":1,"284":1,"292":2,"295":2,"296":2,"297":5,"299":1}}],["xdg",{"2":{"39":1,"203":3}}],["xdotool",{"2":{"30":1,"147":2,"149":5,"180":1,"183":4,"184":1}}],["xauth",{"2":{"26":1}}],["xauthorty",{"2":{"25":1}}],["xauthority",{"2":{"18":1,"26":1,"42":1}}],["xlib",{"2":{"21":1,"26":1}}],["中期任务计划",{"2":{"287":1}}],["中配版",{"2":{"272":1}}],["中文",{"2":{"229":1}}],["中文按现有",{"2":{"26":1}}],["中同时填入后",{"2":{"204":1}}],["中横线",{"2":{"203":1}}],["中键",{"2":{"183":2}}],["中编写用例所在路径",{"2":{"172":1}}],["中编写方法",{"2":{"84":1}}],["中心坐标",{"2":{"147":1}}],["中心",{"2":{"144":1}}],["中有些地方是空白的或者是",{"2":{"141":1}}],["中后",{"2":{"141":1}}],["中鼠标选中元素标签的时候",{"2":{"141":1}}],["中也是从最顶层的",{"2":{"140":1}}],["中去做匹配",{"2":{"133":1}}],["中加入它",{"2":{"118":1}}],["中间层主要服务于用例层",{"2":{"275":1}}],["中间层",{"2":{"275":2}}],["中间操作",{"2":{"53":2}}],["中间的失败结果被后续用例更新为成功的问题",{"2":{"31":1}}],["中安装",{"2":{"45":1}}],["中的类",{"2":{"283":1}}],["中的标签全部删掉就可以了",{"2":{"204":1}}],["中的标签同步到",{"2":{"34":1}}],["中的任意一个",{"2":{"175":1}}],["中的",{"2":{"34":1}}],["中英文场景检测模型准确率提升",{"2":{"34":1}}],["中某个",{"2":{"27":1}}],["中",{"2":{"18":1,"47":1,"183":2,"245":1}}],["条",{"2":{"273":2}}],["条件判断组合",{"2":{"203":1}}],["条件判断跳过",{"0":{"203":1}}],["条件跳过的功能函数",{"2":{"39":1}}],["条件跳过逻辑",{"2":{"12":1}}],["条用例给远程",{"2":{"162":2,"256":2}}],["条用例",{"2":{"162":1,"256":1}}],["条示例用例和一个方法",{"2":{"18":1}}],["初步断言主题失败",{"2":{"175":1}}],["初步适配欧拉系统",{"2":{"16":1}}],["初始化工程中的错误",{"2":{"19":1}}],["初始化工程新增",{"2":{"19":1}}],["初始化应用新增",{"2":{"18":1}}],["做一个简单",{"2":{"258":1}}],["做网络接口",{"2":{"76":1}}],["做",{"2":{"17":1}}],["时会将多个",{"2":{"233":1}}],["时会一并将其安装",{"2":{"233":1}}],["时的深度",{"2":{"229":1}}],["时的日志输出",{"2":{"50":1}}],["时间字符串",{"2":{"226":1,"268":1}}],["时",{"2":{"17":1,"27":1,"30":1,"34":1,"41":1,"234":1,"245":1}}],["以上几个步骤做完",{"2":{"303":1}}],["以上例子为用例执行时",{"2":{"203":1}}],["以实现应用库高效的编写",{"2":{"289":1}}],["以应用为维度划分",{"2":{"280":2}}],["以便进行一些开发调试",{"2":{"237":1}}],["以便后续各组件重命名之后仍能保持接口一致性和兼容性",{"2":{"26":1}}],["以此激活虚拟环境即可",{"2":{"224":1}}],["以此确保在截取的一堆图片中",{"2":{"134":1}}],["以处理人工删除了用例脚本文件",{"2":{"210":1}}],["以",{"2":{"200":1}}],["以绝对优势获胜",{"2":{"185":1}}],["以及分布式执行的一些策略配置项等等",{"2":{"226":1,"268":1}}],["以及汇总的结果",{"2":{"196":1}}],["以及此时图像对比的模板图片",{"2":{"178":1}}],["以及用例自定义的",{"2":{"50":1}}],["以子命令",{"2":{"156":1}}],["以下操作均在",{"2":{"300":1}}],["以下流水线指的是每日构建的流水线",{"2":{"204":1}}],["以下涉及到的参数配置都是在配置文件里面进行配置",{"2":{"195":1}}],["以下为",{"2":{"158":1,"161":1,"255":1}}],["以下我将整个屏幕的截图称为",{"2":{"133":1}}],["以下配置项默认值为系统自带的浏览器的配置",{"2":{"98":1,"229":1}}],["以右键菜单来讲解此方案",{"2":{"125":1}}],["以域管服务端平台创建子管理员为例",{"2":{"73":1}}],["以解决远程开发时无法同步文件的问题",{"2":{"26":1}}],["以确保程序能正常运行",{"2":{"26":1}}],["以适应应用不同的迭代周期",{"2":{"277":1}}],["以适应",{"2":{"17":1}}],["以保持统一的断言语句风格",{"2":{"16":1,"187":1}}],["名称空间下直接导入",{"2":{"154":1}}],["名称",{"2":{"17":1}}],["结构举例",{"2":{"280":1}}],["结果返回接口",{"2":{"286":1}}],["结果展示模块",{"2":{"286":1}}],["结果展示输出等",{"2":{"280":1}}],["结果成功",{"2":{"229":1}}],["结果的文件",{"2":{"175":1}}],["结果",{"2":{"175":3}}],["结果以",{"2":{"13":1}}],["结束日期",{"2":{"229":1}}],["结束",{"2":{"47":1,"175":4}}],["结尾",{"2":{"30":1,"65":1,"75":1,"85":1,"98":1,"111":1,"282":2}}],["结尾的文件",{"2":{"175":1}}],["结尾的",{"2":{"17":1,"191":1,"229":1}}],["增加用例标签",{"2":{"280":1}}],["增加执行过程中立即显示错误的功能",{"2":{"57":1}}],["增加执行前显示执行的python文件数量",{"2":{"34":1}}],["增加函数",{"2":{"53":1}}],["增加开始执行时打印一些执行参数",{"2":{"53":1}}],["增加了用例执行过程中对",{"2":{"57":1}}],["增加了在线文档的显示宽度",{"2":{"34":1}}],["增加了",{"2":{"33":1}}],["增加了识别的总耗时",{"2":{"30":1}}],["增加了留言模块",{"2":{"22":1}}],["增加清理",{"2":{"29":1}}],["增加",{"2":{"17":1,"21":1,"39":1,"57":1}}],["同一个应用的用例分散到不同架构的测试机上执行",{"2":{"285":1}}],["同样匹配小图里面所有的坐标点",{"2":{"136":1}}],["同步pms数据到本地csv文件",{"2":{"211":1,"229":1}}],["同步到",{"2":{"34":1}}],["同步标签到",{"2":{"16":1,"52":1}}],["同时可以标记区域",{"2":{"295":1}}],["同时由于",{"2":{"280":1}}],["同时在用例标签化管理",{"2":{"260":1}}],["同时在流水线上将",{"2":{"204":1}}],["同时新建好工程模板目录和模板文件",{"2":{"248":1}}],["同时完美兼容",{"2":{"240":1}}],["同时也在修复一些用例",{"2":{"204":1}}],["同时标记了skip",{"2":{"204":1}}],["同时我们应该充分考虑后期的可维护性",{"2":{"200":1,"284":1}}],["同时推出了",{"2":{"41":1}}],["同时启用",{"2":{"13":1}}],["同时",{"2":{"13":1,"300":1}}],["方便在用例里面使用",{"2":{"296":1}}],["方便在输入命令的过程中使用补全",{"2":{"158":1}}],["方便使用断言语句",{"2":{"296":1}}],["方便应用库使用",{"2":{"258":1}}],["方便统一拉取代码",{"2":{"57":1}}],["方案设计",{"0":{"278":1,"290":1},"1":{"279":1,"280":1,"291":1,"292":1},"2":{"300":1}}],["方案",{"0":{"272":1},"2":{"117":1}}],["方案大多采用谷歌",{"2":{"117":1}}],["方案使用场景较少",{"2":{"11":1}}],["方法和用例中都会涉及到导入路径的修改",{"2":{"302":1}}],["方法内所要用到不同定位方法的写法修改",{"2":{"301":1}}],["方法的统一出口",{"2":{"292":1}}],["方法的使用说明",{"2":{"185":1}}],["方法调用逻辑得到简化",{"2":{"273":1}}],["方法库",{"2":{"262":1,"280":1}}],["方法库里面",{"2":{"192":1}}],["方法及一些测试资源",{"2":{"260":1}}],["方法可以不用在方法层定义了",{"2":{"217":1}}],["方法只能有一个入参",{"2":{"203":1}}],["方法必须有返回结果并且为布尔值",{"2":{"203":1}}],["方法名必须以",{"2":{"203":1}}],["方法二",{"2":{"195":1}}],["方法一",{"2":{"195":1}}],["方法加入了此功能",{"2":{"182":1}}],["方法明细",{"0":{"144":1,"149":1,"175":1,"183":1}}],["方法编写规范",{"2":{"203":1}}],["方法编写",{"0":{"93":1},"2":{"295":1}}],["方法主文件",{"2":{"74":1}}],["方法主文件里面",{"2":{"64":1,"97":1,"110":1}}],["方法唯一出口类",{"2":{"61":1,"70":1,"71":1,"80":1,"99":1,"100":1,"107":1,"248":1}}],["方法基类",{"2":{"61":1,"64":1,"70":1,"71":1,"74":1,"80":1,"97":1,"99":1,"100":1,"107":1,"248":1,"265":1,"280":1,"292":1,"294":1,"297":1}}],["方法层所有的函数",{"2":{"192":1}}],["方法层",{"2":{"61":1,"70":1,"71":1,"80":1,"99":1,"100":1,"107":1,"248":1}}],["方法将不再维护",{"2":{"49":1}}],["方法",{"2":{"24":1,"142":2,"190":1,"280":1,"292":1}}],["方法没有返回值",{"2":{"16":1}}],["tb",{"2":{"183":1}}],["tbody",{"2":{"98":1}}],["t",{"2":{"154":1,"158":1,"161":2,"162":1,"168":1,"169":1,"208":3,"216":2,"217":2,"218":1,"252":2,"255":1}}],["typing",{"2":{"144":1,"175":1}}],["typewrite",{"2":{"183":1}}],["type=",{"2":{"183":1}}],["typetext",{"2":{"142":1}}],["type",{"2":{"39":1,"74":1,"183":4,"203":3}}],["tpl",{"2":{"137":2}}],["this",{"2":{"154":3,"158":1,"161":1,"252":1,"255":1}}],["than",{"2":{"154":1}}],["theme",{"2":{"175":1,"229":1}}],["the",{"2":{"136":11,"144":1,"154":5,"183":1}}],["threadxmlrpcserver",{"2":{"119":2,"137":2}}],["threadingmixin",{"2":{"119":2,"137":2}}],["tuple",{"2":{"119":1,"143":1,"144":4,"149":21,"175":2,"183":4,"192":1}}],["tag",{"2":{"204":3,"262":1,"280":1,"292":1}}],["tags",{"2":{"158":4,"200":1,"229":5,"252":3,"280":4}}],["task",{"2":{"158":2,"170":1,"195":4,"196":1,"229":1,"252":2}}],["tabs",{"2":{"154":1}}],["table",{"2":{"98":1}}],["take",{"2":{"136":2}}],["target",{"2":{"119":2,"154":1}}],["tripleclick",{"2":{"183":1}}],["triple",{"2":{"183":1}}],["trigger",{"2":{"158":1,"195":3,"229":1,"252":1}}],["trailing",{"2":{"154":2}}],["trace",{"2":{"144":3,"190":2}}],["transfer",{"2":{"16":1,"218":1}}],["tr",{"2":{"98":1}}],["tree",{"2":{"74":3,"141":3,"142":2,"144":5}}],["tree=",{"2":{"74":1}}],["true",{"2":{"74":1,"85":1,"144":1,"175":5,"183":1,"203":6}}],["try",{"2":{"74":1,"133":1,"137":1,"144":5,"149":6,"175":5,"222":1}}],["touch",{"2":{"234":1}}],["tox",{"2":{"154":1}}],["too",{"2":{"144":2}}],["to",{"2":{"93":2,"98":1,"131":1,"144":2,"149":1,"154":1,"183":13,"210":1,"229":1}}],["token=",{"2":{"74":1}}],["token",{"2":{"74":9}}],["tomlignore",{"2":{"154":1}}],["toml",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1,"154":2}}],["top",{"2":{"54":2,"148":3,"149":17,"158":2,"229":2,"252":2}}],["tmpdir",{"2":{"229":2}}],["tmp",{"2":{"53":1,"74":2,"119":1,"229":2}}],["terminal",{"2":{"216":3,"217":2,"218":2}}],["technology",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["templateelementfound",{"2":{"175":4}}],["templateelementnotfound",{"2":{"133":1,"175":6}}],["template",{"2":{"137":4}}],["temporary",{"2":{"53":4,"138":1,"175":2}}],["tesseract",{"2":{"117":1}}],["testddefilemanager",{"2":{"297":1}}],["testfilemanager",{"2":{"296":1}}],["testtask",{"2":{"229":1}}],["testsuite",{"2":{"229":1}}],["testmusic",{"2":{"167":1,"172":2,"222":1,"229":1}}],["testmycase005",{"2":{"111":1}}],["testmycase003",{"2":{"94":1,"217":1}}],["testmycase004",{"2":{"65":1}}],["testmycase",{"2":{"85":1,"98":1,"174":1}}],["testcase",{"2":{"164":1,"229":1}}],["testudcpapi",{"2":{"75":1}}],["test",{"2":{"53":3,"61":2,"65":4,"70":2,"71":2,"75":4,"80":2,"85":4,"92":2,"94":3,"98":6,"99":2,"100":2,"107":2,"111":4,"119":1,"164":5,"165":2,"167":2,"172":7,"174":1,"177":1,"200":2,"217":1,"222":1,"229":5,"248":2,"292":1,"296":1,"297":1}}],["text",{"2":{"74":1,"98":1}}],["teardown",{"2":{"57":1,"75":1}}],["txtapps",{"2":{"172":1}}],["txt",{"2":{"43":1,"53":1,"172":2,"175":4,"229":1,"233":7}}],["tip",{"2":{"280":1,"286":1,"295":1}}],["titlewidget",{"2":{"221":1,"222":1,"295":2,"296":1,"297":3}}],["title",{"2":{"32":1,"53":1,"178":1,"229":1,"292":2,"295":1,"297":2}}],["time",{"2":{"133":1,"134":3,"136":1,"149":1,"175":5,"183":4,"229":2}}],["timeout时间内重试间隔",{"2":{"229":1}}],["timeout=60",{"2":{"183":1}}],["timeout=timeout",{"2":{"175":4}}],["timeout=5",{"2":{"93":1}}],["timeout",{"2":{"32":1,"50":3,"56":2,"158":2,"175":6,"229":4,"252":2}}],["timestr",{"2":{"11":3}}],["返回最新创建的窗口编号",{"2":{"149":1}}],["返回图片路径",{"2":{"138":1}}],["返回图片中识别到的所有字符串",{"2":{"119":1}}],["返回匹配到的多个目标",{"2":{"133":1}}],["返回小图在大图中的坐标",{"2":{"133":1}}],["返回",{"2":{"131":1,"203":2}}],["返回识别到的所有数据",{"2":{"119":1,"175":2}}],["返回识别的原生数据",{"2":{"119":1}}],["返回的",{"2":{"98":1}}],["返回值为",{"2":{"16":1}}],["返回坐标",{"2":{"13":1,"124":1,"133":1}}],["信息文件",{"2":{"158":1,"252":1}}],["信息",{"2":{"16":1,"74":1}}],["信息获取",{"2":{"7":1}}],["浏览器进行测试",{"2":{"16":1,"98":1,"103":1}}],["它被多个地方都使用到了",{"2":{"300":1}}],["它提供接口给自动化测试平台",{"2":{"280":1}}],["它提供了自动化测试所要用的基础功能",{"2":{"260":1}}],["它会根据配置里面的配置项",{"2":{"280":1}}],["它都提供了完善的解决方案",{"2":{"260":1}}],["它不需要",{"2":{"234":1}}],["它保存了远程测试机的信息列表",{"2":{"213":1}}],["它们都有自己存在的问题或者说不适用的场景",{"2":{"180":1}}],["它继承了",{"2":{"174":1}}],["它同样支持本地执行的所有参数",{"2":{"161":1,"255":1}}],["它是一个执行器入口",{"2":{"250":1}}],["它是一个开源的基于深度学习的",{"2":{"117":1}}],["它是全局的入口文件",{"2":{"156":1}}],["它可以方便的用于界面元素的定位和断言",{"2":{"132":1}}],["它基于标准库",{"2":{"76":1}}],["它使用最新的chromium浏览器进行测试",{"2":{"98":1,"229":1}}],["它使用",{"2":{"16":1,"98":1,"103":1}}],["它默认使用系统自带的浏览器进行测试",{"2":{"16":1,"98":1,"229":1}}],["重启步骤最好是一个简单的reboot操作",{"2":{"222":1}}],["重启步骤前面的步骤",{"2":{"222":1}}],["重启之后继续执行",{"2":{"222":1}}],["重启之后虽然重启步骤前面的步骤函数不会执行",{"2":{"222":1}}],["重启之后如何让用例能继续重启前的步骤继续执行",{"2":{"220":1}}],["重启类场景",{"0":{"220":1},"1":{"221":1,"222":1,"223":1,"224":1}}],["重启类场景开启letmego执行方案",{"2":{"158":1,"252":1}}],["重要",{"2":{"203":1}}],["重试间隔时间",{"2":{"175":2}}],["重复去识别",{"2":{"133":1}}],["重跑失败之后才会关闭文件选择框",{"2":{"59":1}}],["重新设计了测试报告主题",{"2":{"50":1}}],["重新构建了文档",{"2":{"22":1}}],["重新整理了章节结构和排版",{"2":{"16":1}}],["重写了",{"2":{"16":1}}],["重点对统计",{"2":{"12":1}}],["添加跳过用例的代码",{"2":{"277":1}}],["添加",{"2":{"15":1,"100":1}}],["目标",{"0":{"258":1,"289":1},"2":{"273":1}}],["目标字符",{"2":{"119":1,"175":2}}],["目录删掉",{"2":{"197":1}}],["目录结构调整",{"2":{"287":1}}],["目录结构",{"0":{"177":1,"262":1,"292":1},"2":{"300":1}}],["目录",{"2":{"41":1,"53":1,"56":1,"175":2,"177":1,"229":1}}],["目录权限",{"2":{"26":1}}],["目录下的",{"2":{"267":1}}],["目录下的文件名称",{"2":{"71":1,"100":1}}],["目录下为自动化测试的底层核心组件",{"2":{"265":1}}],["目录下可以存在任意多个",{"2":{"248":1}}],["目录下所有应用的用例",{"2":{"229":1}}],["目录下所有用例",{"2":{"165":1}}],["目录下会创建一个子项目工程",{"2":{"248":1}}],["目录下会有",{"2":{"196":1,"197":1}}],["目录下会生成一堆文本文件",{"2":{"179":1}}],["目录下保存失败用例的录屏和断言的那个时间点的截屏",{"2":{"193":1}}],["目录下给你生成了",{"2":{"179":1}}],["目录下回收各个测试机执行的测试报告",{"2":{"161":1,"255":1}}],["目录下新建一个",{"2":{"283":1}}],["目录下新建",{"2":{"94":1}}],["目录下进行",{"2":{"56":1}}],["目录下子项目存在",{"2":{"53":1}}],["目录下",{"2":{"15":2,"18":1,"33":1,"41":1,"47":1,"56":1,"64":1,"65":1,"74":1,"75":1,"84":1,"85":1,"98":1,"111":1,"133":2,"156":1,"161":1,"179":1,"200":1,"210":1,"211":2,"236":1,"255":1,"264":1,"299":1}}],["目前需要跳过的用例都需要在对应的用例脚本里面",{"2":{"277":1}}],["目前自动化用例执行时",{"2":{"277":1}}],["目前的策略是全用例覆盖全架构",{"2":{"276":1}}],["目前的方案中",{"2":{"183":1}}],["目前配置了一些通用的命令行执行参数",{"2":{"267":1}}],["目前支持",{"2":{"229":1}}],["目前支持三种参数传入方式",{"2":{"47":1}}],["目前仅对",{"2":{"182":1}}],["目前已经启用了更先进的",{"2":{"15":1}}],["目前我们欢迎以下方面的贡献",{"2":{"0":1}}],["章节",{"2":{"14":1,"299":1}}],["远程多机器分布式异步负载均衡执行",{"0":{"256":1}}],["远程多机器分布式异步执行",{"0":{"255":1}}],["远程测试机",{"2":{"252":1}}],["远程过程调用等方式提供功能",{"2":{"239":1}}],["远程机器执行的用例相同",{"2":{"160":1,"254":1}}],["远程机器的user",{"2":{"47":1,"161":1,"255":1}}],["远程用例驱动执行",{"2":{"155":1}}],["远程交互式控制标识文件",{"2":{"92":1}}],["远程交互式控制可以在用例步骤中实现对远程机器的交互式控制",{"2":{"90":1}}],["远程交互式控制",{"0":{"90":1,"212":1},"1":{"91":1,"92":1,"93":1,"94":1,"213":1,"214":1,"215":1,"216":1,"217":1,"218":1,"219":1},"2":{"242":1}}],["远程交互式控制等等",{"2":{"86":1}}],["远程执行等的功能",{"2":{"250":1}}],["远程执行任何用例集的用例",{"2":{"242":1}}],["远程执行测试机",{"2":{"229":1}}],["远程执行的数据回填需要等所有测试机执行结束之后",{"2":{"196":1}}],["远程执行需要控制多台测试机同时执行用例",{"2":{"196":1}}],["远程执行结束之后",{"2":{"179":1}}],["远程执行同样通过配置文件",{"2":{"161":1,"255":1}}],["远程执行就是用本地作为服务端控制远程机器执行",{"2":{"160":1,"254":1}}],["远程执行",{"0":{"160":1,"254":1},"1":{"161":1,"162":1,"255":1,"256":1},"2":{"179":1}}],["远程执行时回填",{"0":{"196":1}}],["远程执行时",{"2":{"47":1,"49":1}}],["远程执行新增从命令行传入测试机信息",{"2":{"47":1}}],["远程执行自动适用",{"2":{"43":1}}],["远程路径错误的问题",{"2":{"16":1}}],["远程调用的稳定性和兼容性等问题",{"2":{"13":1}}],["远端无法解析默认参数的问题",{"2":{"13":1}}],["f6",{"2":{"300":1}}],["français",{"2":{"229":1}}],["frame",{"2":{"226":1,"260":1,"268":1}}],["fr",{"2":{"229":1}}],["from",{"2":{"59":1,"64":1,"65":3,"74":3,"75":3,"84":4,"85":4,"93":1,"94":2,"98":4,"110":2,"111":3,"119":2,"137":3,"144":16,"149":15,"174":3,"175":22,"181":1,"183":9,"192":2,"203":1,"215":1,"229":1,"265":5,"296":1,"297":2}}],["f8cab367",{"2":{"177":1}}],["f841",{"2":{"154":1}}],["ffb324f3",{"2":{"177":1}}],["ffmpeg",{"2":{"31":2}}],["f541",{"2":{"154":1}}],["f507",{"2":{"154":1}}],["f403",{"2":{"154":1}}],["f401",{"2":{"154":2}}],["flake8",{"2":{"154":1}}],["flag=false",{"2":{"93":1,"149":6,"175":2}}],["float",{"2":{"133":3,"134":3,"137":1,"149":4,"175":13,"183":1}}],["folder",{"2":{"175":12}}],["focus",{"2":{"149":1}}],["font",{"2":{"119":1}}],["formats",{"2":{"158":2,"252":2}}],["format`",{"2":{"154":1}}],["formatting",{"2":{"154":2}}],["format",{"2":{"153":1,"154":2,"229":1}}],["form",{"2":{"141":1}}],["forever",{"2":{"119":1,"137":1}}],["for",{"2":{"74":1,"133":2,"136":2,"144":2,"147":2,"149":11,"154":3,"175":5,"183":7,"203":4,"300":1}}],["finish",{"2":{"158":1,"195":3,"196":1,"229":1,"252":1}}],["findimage",{"2":{"265":2}}],["findall",{"2":{"149":7}}],["findchildren",{"2":{"144":2}}],["find",{"2":{"133":2,"144":8,"175":7,"192":4,"262":1,"265":1,"282":1,"295":1}}],["first=return",{"2":{"119":1,"175":2}}],["first=false",{"2":{"119":2,"175":2}}],["first",{"2":{"119":2,"175":4,"222":1}}],["filter",{"2":{"119":1,"131":2,"175":2}}],["fill",{"2":{"97":1}}],["files",{"2":{"175":5}}],["filesize",{"2":{"110":2,"111":2}}],["file=none",{"2":{"175":2}}],["filectl",{"2":{"175":3}}],["filecopyrighttext",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["filepath",{"2":{"111":3}}],["filename",{"2":{"110":2,"175":16}}],["file",{"2":{"84":2,"85":2,"110":1,"111":2,"119":2,"137":1,"149":1,"158":5,"175":19,"208":1,"229":3,"252":5,"260":1,"262":1,"265":2,"292":1,"294":2,"295":1,"296":9,"297":8,"301":1}}],["fixed",{"2":{"199":2,"204":3,"205":1,"229":1}}],["fixed不生效",{"2":{"158":1,"229":1,"252":1}}],["fix`",{"2":{"154":1}}],["fixable",{"2":{"152":1,"154":1}}],["fixture",{"2":{"16":3,"61":1,"70":1,"80":1,"99":1,"107":1,"248":1,"267":1}}],["fix",{"2":{"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":2,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":2,"58":1,"59":1,"152":2,"154":1}}],["future",{"2":{"154":1}}],["func",{"2":{"190":1,"199":2}}],["function",{"2":{"119":2,"137":2,"280":3}}],["funnylog",{"0":{"188":1},"1":{"189":1,"190":1,"191":1,"192":1},"2":{"45":1}}],["full",{"2":{"74":1}}],["fullname=self",{"2":{"75":1}}],["fullname",{"2":{"74":3}}],["feet",{"2":{"64":3}}],["f",{"2":{"45":1,"74":2,"93":1,"110":1,"111":1,"119":4,"137":1,"144":13,"147":2,"149":44,"154":1,"158":1,"172":1,"175":56,"183":25,"192":1,"203":2,"252":1,"296":1}}],["failsafe",{"2":{"183":1}}],["fail",{"2":{"158":2,"229":3,"252":2}}],["failed",{"2":{"41":6,"158":2,"193":5,"229":5,"252":2}}],["false",{"2":{"74":1,"119":4,"133":2,"137":1,"138":1,"144":7,"154":2,"175":13,"183":5,"203":6}}],["favicon",{"2":{"13":1}}],["系统部相关编码规范要求",{"2":{"273":1}}],["系统主题",{"2":{"229":1}}],["系统架构",{"2":{"226":1,"268":1}}],["系统版本不跳过",{"2":{"203":1}}],["系统版本跳过",{"2":{"203":1}}],["系统信息",{"2":{"178":1}}],["系统应用软件包",{"2":{"149":1}}],["系统适配",{"2":{"13":1}}],["系统完成了适配",{"2":{"13":1}}],["确保",{"2":{"242":1}}],["确保了框架的稳定性和可靠性",{"2":{"13":1}}],["确认勾选",{"2":{"300":1}}],["确认修复",{"0":{"204":1},"2":{"57":2,"199":2,"204":6,"205":1}}],["确认",{"2":{"53":2}}],["确定",{"2":{"13":3,"124":5}}],["新建歌单+",{"2":{"148":3}}],["新图片的路径",{"2":{"131":1}}],["新方案不同的项目会动态生成自己的虚拟环境",{"2":{"41":1}}],["新的文档地址",{"2":{"41":1}}],["新的驱动方式",{"2":{"41":1}}],["新的驱动命令",{"2":{"41":1}}],["新的at虚拟化环境部署方案",{"2":{"41":1}}],["新的基础框架代码获取方式及新的初始化工程命令",{"2":{"41":1}}],["新的函数接口ocrx",{"2":{"13":1,"124":1}}],["新增依赖",{"0":{"233":1},"2":{"234":1}}],["新增一列标签名为",{"2":{"204":1}}],["新增pms数据回填功能",{"2":{"57":1}}],["新增收集阶段报错",{"2":{"56":1}}],["新增终端输出显示",{"2":{"56":1}}],["新增终端输出用例执行结束之后所有失败用例的列表",{"2":{"56":1}}],["新增执行进度显示",{"2":{"56":1}}],["新增测试结果表情显示",{"2":{"54":1}}],["新增测试套执行",{"2":{"54":1}}],["新增环境安装",{"2":{"54":1}}],["新增图像断言成功输出匹配度",{"2":{"54":1}}],["新增裁剪依赖的方案",{"2":{"53":1}}],["新增安装子项目",{"2":{"53":1}}],["新增指定用例执行次数",{"2":{"53":1}}],["新增指定用例重复执行次数",{"2":{"53":1}}],["新增气泡类图像识别方案",{"2":{"50":1}}],["新增系统命令",{"2":{"49":1}}],["新增失败录屏从第几次失败开始录制视频的命令行参数",{"2":{"41":1}}],["新增关闭分辨率检测的参数值",{"2":{"41":1}}],["新增自动从",{"2":{"36":1}}],["新增用例脚本",{"2":{"36":1}}],["新增用例驱动方式章节",{"2":{"12":1}}],["新增导入全局配置对象",{"2":{"34":1}}],["新增贡献者名单及贡献规则文档",{"2":{"25":1}}],["新增定制依赖功能支持应用库定义",{"2":{"20":1}}],["新增子命令",{"2":{"18":1}}],["新增命令行入参或配置文件传入远程机器的",{"2":{"16":1}}],["新增远程控制功能",{"2":{"16":1}}],["新增尝鲜版",{"2":{"16":1}}],["新增支持链式调用函数接口",{"2":{"13":1}}],["新增了生成的",{"2":{"13":1}}],["新增的链式调用函数接口使操作更加直观和便捷",{"2":{"13":1}}],["新增",{"2":{"10":1,"12":1,"18":1,"24":1,"50":1,"53":2,"54":1,"56":1,"57":1,"59":1}}],["新增在所有属性中查找同名节点的功能",{"2":{"5":1}}],["进来",{"2":{"265":1}}],["进入项目根目录",{"2":{"247":1}}],["进程期望结果",{"2":{"175":1}}],["进一步优化了",{"2":{"42":1}}],["进一步提高识别稳定性和准确性",{"2":{"13":1}}],["进行目录调整",{"2":{"300":1}}],["进行测试",{"2":{"280":1}}],["进行测试用例范围选择",{"2":{"280":1}}],["进行用例的加载和执行",{"2":{"280":1}}],["进行用例相关配置",{"2":{"161":1,"255":1}}],["进行自动装机",{"2":{"280":1}}],["进行",{"2":{"276":1}}],["进行分割",{"2":{"203":1}}],["进行的",{"2":{"156":1}}],["进行配置",{"2":{"154":1}}],["进行元素定位",{"2":{"140":1}}],["进行了封装",{"2":{"132":1}}],["进行选择菜单选择",{"2":{"127":1}}],["进行识别",{"2":{"119":1}}],["进行日志分段",{"2":{"57":1}}],["进行断言",{"2":{"53":1,"296":1}}],["进行安装",{"2":{"41":2}}],["进行包的发布",{"2":{"41":1}}],["进行开发适配并兼容新老接口",{"2":{"25":1}}],["进行适配",{"2":{"9":1}}],["使用鼠标选中并按住",{"2":{"300":1}}],["使用一段时间后会痛恨",{"2":{"271":1}}],["使用一定的算法即可计算出元素按钮在当前屏幕中的位置",{"2":{"147":1}}],["使用所有",{"2":{"265":1}}],["使用标准库",{"2":{"239":1}}],["使用时需要为每一个用例添加标签装饰器",{"2":{"206":1}}],["使用全局配置里面的常量进行逻辑编写即可",{"2":{"184":1}}],["使用正则获取窗口的位置及大小",{"2":{"147":1}}],["使用的是",{"2":{"142":1}}],["使用的默认密码是",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"231":1,"247":1}}],["使用说明",{"0":{"119":1}}],["使用方法二",{"2":{"208":1,"210":1,"211":1}}],["使用方法一",{"2":{"208":1,"210":1,"211":1}}],["使用方法很简单",{"2":{"192":1,"221":1}}],["使用方法和前面一样",{"2":{"162":1,"256":1}}],["使用方法和过去一样",{"2":{"41":1}}],["使用方法",{"0":{"148":1,"192":1,"221":1},"2":{"49":1,"193":1,"195":2,"196":1}}],["使用它可以初始化工程",{"2":{"41":1}}],["使用窗管最新提供的二进制接口",{"2":{"39":1}}],["使用更方便更符合语义",{"2":{"13":1,"124":1}}],["使用",{"0":{"141":1},"2":{"13":1,"30":2,"41":1,"61":1,"70":1,"80":1,"99":1,"107":1,"109":1,"110":1,"111":1,"131":1,"147":1,"160":1,"183":1,"193":1,"203":3,"246":1,"248":1,"252":1,"254":1,"280":2}}],["包括类和方法的命名",{"2":{"301":1}}],["包括实例方法",{"2":{"192":1}}],["包括高分屏",{"2":{"146":1}}],["包括报告生成时的错误处理",{"2":{"13":1}}],["包未指定版本时",{"2":{"45":1}}],["包形式发布的",{"2":{"41":2}}],["包的大小才",{"2":{"41":1}}],["包含以下几个方面",{"2":{"229":1}}],["包含静态方法",{"2":{"190":1}}],["包含一个区域",{"2":{"175":2}}],["包含气泡从出现到消失",{"2":{"134":1}}],["包含",{"2":{"71":1,"100":1}}],["包含了以下配置文件",{"2":{"226":1,"268":1}}],["包含了",{"2":{"53":1}}],["包含等关键字控制需要打印的函数日志",{"2":{"47":1}}],["包含多个用例",{"2":{"31":1}}],["包含每条",{"2":{"11":1}}],["包安装失败后替换源",{"2":{"27":1}}],["包",{"2":{"20":1,"41":2,"233":1,"276":1}}],["在修改路径时",{"2":{"302":1}}],["在编辑器里面选中文件",{"2":{"300":1}}],["在编辑模式下",{"2":{"148":1}}],["在系统所有应用中",{"2":{"290":1}}],["在哪台机器上执行",{"2":{"286":1}}],["在每个应用目录下新建",{"2":{"284":1}}],["在每日构建和持续集成流程落地使用",{"2":{"273":1}}],["在类中重写此方法",{"2":{"282":1,"283":1}}],["在跳过用例较多的情况下",{"2":{"277":1}}],["在新需求快速变化的过程中",{"2":{"277":1}}],["在自动化测试项目初期",{"2":{"277":1}}],["在各验收节点进行自动化验收",{"2":{"276":1}}],["在文件中写一个",{"2":{"282":1,"283":1}}],["在文件选择框点击音乐目录",{"2":{"266":1}}],["在文档方便确实没有老牌的",{"2":{"185":1}}],["在你的远程",{"2":{"248":1}}],["在写一些功能时",{"2":{"239":1}}],["在项目根目录下有一个",{"2":{"250":1}}],["在项目根目录下输入",{"2":{"238":1}}],["在项目目录路径下存在文件",{"2":{"203":1}}],["在框架根目录下命令行输入",{"2":{"237":1}}],["在开发过程中有可能需要在终端激活虚拟环境",{"2":{"237":1}}],["在开发过程中",{"2":{"235":1}}],["在开发调试时也会记录执行过程的问题",{"2":{"36":1}}],["在执行",{"2":{"233":1}}],["在pms上查看测试单链接",{"2":{"229":1}}],["在pms上查看用例",{"2":{"229":1}}],["在调用的时候",{"2":{"218":1}}],["在调用时",{"2":{"143":1}}],["在远程测试机上部署一个完整的",{"2":{"212":1}}],["在远程服务器上部署",{"2":{"137":1}}],["在命令行执行",{"2":{"211":1}}],["在命令行这样运行",{"2":{"161":1,"255":1}}],["在report目录下会自动生成",{"2":{"208":1}}],["在日常跳过用例的过程中",{"2":{"204":1}}],["在csv文件中",{"2":{"203":2}}],["在子项目目录下新建",{"2":{"200":1}}],["在子项目根目录下写",{"2":{"53":1}}],["在进行数据回填",{"2":{"196":1}}],["在报告中更能一目了然的看到用例执行步骤",{"2":{"192":1}}],["在屏幕中相似度大于",{"2":{"192":2}}],["在屏幕中区寻找小图",{"2":{"133":1}}],["在应用库根目录下保存一个",{"2":{"233":1}}],["在应用库",{"2":{"192":1}}],["在应用库方法层这样写",{"2":{"148":1}}],["在此基础上",{"2":{"248":1}}],["在此装饰器中我们能动态的捕获所调用函数的功能说明",{"2":{"190":1}}],["在此时间内会不断的进行截图操作",{"2":{"134":1}}],["在菜单中的位置数",{"2":{"183":3}}],["在坐标",{"2":{"183":1}}],["在区域内进行识别",{"2":{"175":2}}],["在data",{"2":{"175":1}}],["在配置文件",{"2":{"159":1,"253":1}}],["在一些",{"2":{"158":1,"252":1}}],["在一段时间内截图多张图片进行识别",{"2":{"134":1,"175":1}}],["在一段时间内",{"2":{"134":1}}],["在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明",{"2":{"156":1}}],["在上面配置文件中",{"2":{"154":1}}],["在根目录下",{"2":{"154":1}}],["在扫描日志最后可以看到一个",{"2":{"152":1}}],["在获取到元素之后",{"2":{"142":1}}],["在工具下方",{"2":{"141":1}}],["在切换图片之后再用这张小图在当前屏幕中进行图像识别",{"2":{"138":1}}],["在切换图片之前截图保存并返回图片的路径",{"2":{"138":1}}],["在测试机上可以通过",{"2":{"137":1}}],["在测试过程中需要获取的坐标是相对于整个屏幕的坐标",{"2":{"133":1}}],["在其他国产",{"2":{"136":1}}],["在某些情况下",{"2":{"234":1}}],["在某些情况下无法生成测试报告的问题",{"2":{"41":1}}],["在某些场景下你可能需要全部获取到所有匹配到的坐标",{"2":{"133":1}}],["在元素识别的过程中",{"2":{"133":1}}],["在游戏等特定领域也有不错的效果",{"2":{"132":1}}],["在点击右键菜单之前截一张图",{"2":{"131":1}}],["在需求迭代的过程中",{"2":{"127":1}}],["在右键菜单呼出来之后",{"2":{"127":1}}],["在浏览器访问百度首页",{"2":{"96":1,"98":1}}],["在用例层修改用例中类的导入路径",{"2":{"283":1}}],["在用例脚本中添加关键字需要人工一条条的改",{"2":{"277":1}}],["在用例执行过程中控制远程机器执行复杂的",{"2":{"212":1}}],["在用例执行的过程中",{"2":{"195":1}}],["在用例收集阶段会以第一个",{"2":{"203":1}}],["在用例里面只需要通过方法层的类对象直接调用即可",{"2":{"181":1}}],["在用例中使用断言",{"2":{"119":1}}],["在用例",{"2":{"94":1}}],["在用例步骤中操作远程机器",{"2":{"16":1}}],["在方法层新建",{"2":{"93":1}}],["在桌面壁纸切换",{"2":{"138":1}}],["在桌面点击右键菜单之后",{"2":{"127":1}}],["在桌面",{"2":{"86":1}}],["在出口类",{"2":{"84":1}}],["在终端输入",{"2":{"64":1,"84":1,"141":1}}],["在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题",{"2":{"60":1}}],["在没有安装",{"2":{"55":1}}],["在传入",{"2":{"53":1}}],["在服务端通过调用",{"2":{"212":1}}],["在服务端",{"2":{"49":1}}],["在不添加环境变量的情况下",{"2":{"41":1}}],["在识别某些文本情况下出现不能识别的问题",{"2":{"33":1}}],["在环境部署阶段进行",{"2":{"33":1}}],["在迭代窗口",{"2":{"30":1}}],["在原始代码中",{"2":{"30":1}}],["在",{"2":{"27":1,"54":1,"123":1,"136":1,"140":1,"141":3,"147":2,"149":1,"179":1,"184":2,"193":1,"195":1,"197":1,"201":1,"203":2,"211":1,"213":1,"243":1,"265":2,"271":1,"280":6,"284":1,"301":1}}],["在线文档地址修改为域名",{"2":{"51":1}}],["在线文档",{"2":{"16":1}}],["在线文档增加团队页",{"2":{"15":1}}],["在问题修复方面",{"2":{"13":1}}],["在功能创新方面",{"2":{"13":1}}],["社区做好准备",{"2":{"13":1}}],["为什么使用csv格式",{"2":{"280":1}}],["为什么基于",{"0":{"122":1}}],["为解决以上问题",{"2":{"278":1}}],["为将来适配更多的",{"2":{"273":1}}],["为空",{"2":{"229":1}}],["为空表示执行",{"2":{"229":1}}],["为空的问题",{"2":{"32":1}}],["为互斥关系",{"2":{"175":4}}],["为断言主题准确性",{"2":{"175":1}}],["为你想要执行的用例集",{"2":{"162":1,"256":1}}],["为应用左上角相对于屏幕左上角",{"2":{"147":1}}],["为web",{"2":{"98":1,"229":1}}],["为属性名称",{"2":{"84":1}}],["为自动化测试框架的发展和演进贡献力量",{"2":{"60":1}}],["为自动化测试提供了更加丰富和灵活的手段",{"2":{"13":1}}],["为了突显本文的重点",{"2":{"261":1}}],["为了方便查看元素控件对应的位置",{"2":{"141":1}}],["为了方便描述后面经常提到的",{"2":{"156":1}}],["为了方便描述",{"2":{"133":1}}],["为了实现识别图像的目的",{"2":{"136":1}}],["为了能稳定的识别气泡类场景",{"2":{"134":1}}],["为了能简单平滑的迁移到",{"2":{"40":1}}],["为了解决上面",{"2":{"123":1}}],["为了解决以下问题",{"2":{"41":1}}],["为",{"2":{"34":1,"175":1}}],["为一个脚本",{"2":{"15":1}}],["为后续开源到",{"2":{"13":1}}],["为测试数据的分析和解读提供了更多维度",{"2":{"13":1}}],["服务打开",{"2":{"179":1}}],["服务的方式提供出来",{"2":{"212":1}}],["服务的方式进行图像识别",{"2":{"137":1}}],["服务的方式使用它",{"2":{"118":1}}],["服务实现图像识别",{"0":{"137":1}}],["服务集群进行负载均衡",{"2":{"123":1}}],["服务集群化部署",{"2":{"13":1}}],["服务集群化部署和模型",{"2":{"13":1}}],["服务器对测试机进行装机",{"2":{"280":1}}],["服务器",{"2":{"122":1,"137":1}}],["服务器上",{"2":{"121":1}}],["服务器链接重试",{"2":{"50":1}}],["服务做分布式集群化部署",{"2":{"121":1}}],["服务端收集到测试结果",{"2":{"196":1}}],["服务端想要执行",{"2":{"162":1,"256":1}}],["服务端会根据收集到的测试用例自动分配给各个测试机执行",{"2":{"229":1}}],["服务端会根据收集到的测试用例自",{"2":{"161":1,"255":1}}],["服务端拿到两张图片进行图像识别",{"2":{"137":1}}],["服务端",{"2":{"137":1,"271":1,"272":2}}],["服务端参考插件",{"2":{"120":1}}],["服务端代码示意",{"2":{"119":1,"137":1}}],["服务将功能提供出来",{"2":{"118":1}}],["服务在自动化测试子项目中被广泛使用",{"2":{"121":1}}],["服务在其他机器上部署",{"2":{"118":1}}],["服务在并发时可能出现无法返回结果的问题",{"2":{"52":1}}],["服务高并发稳定性",{"2":{"52":1}}],["服务",{"2":{"51":1,"137":1,"161":1,"255":1}}],["服务性能优化",{"2":{"13":1}}],["服务不响应的问题",{"2":{"10":1}}],["这部分工作主要解决你之前几个步骤遗漏的问题",{"2":{"303":1}}],["这部分基本可以复制文管的代码",{"2":{"301":1}}],["这时候你可能你的代码中可能会有一些报错",{"2":{"301":1}}],["这不废话吗",{"2":{"300":1}}],["这两个选项",{"2":{"300":1}}],["这两个参数也可以同时使用",{"2":{"229":1}}],["这条用例会被停止",{"2":{"229":1}}],["这点如果了解方案实现原理很容易理解",{"2":{"222":1}}],["这一列标签删掉不就好了",{"2":{"204":1}}],["这一系列的更新标志着",{"2":{"13":1}}],["这是最重要的一个部分",{"2":{"260":1}}],["这是因为不加",{"2":{"245":1}}],["这是因为为了应对前面提到的多种数据回填的方式",{"2":{"197":1}}],["这是一个全局统一配置",{"2":{"229":1}}],["这是一个预设值",{"2":{"134":1}}],["这是一种不推荐但能用的方法",{"2":{"148":1}}],["这就是",{"2":{"204":1}}],["这就是我们参考django",{"2":{"192":1}}],["这就是负载均衡执行",{"2":{"162":1,"256":1}}],["这就要说到本章的主题",{"2":{"131":1}}],["这也不是个问题",{"2":{"154":1}}],["这四个数据可以通过",{"2":{"148":1}}],["这么问的话",{"2":{"136":1}}],["这类用例相对特殊",{"2":{"222":1}}],["这类场景在用例执行过程中进行图像识别时就可能存在不稳定性",{"2":{"134":1}}],["这类自动化测试也比较简单",{"2":{"112":1}}],["这明显是错误的",{"2":{"122":1}}],["这会让整个自动化环境变得非常臃肿",{"2":{"118":1}}],["这并不符合我们对框架依赖治理的理解",{"2":{"118":1}}],["这样从最初的设计来讲确实能够减少重复代码的编写",{"2":{"277":1}}],["这样使得从公司的角度去看所有应用的自动化测试项目都是统一的",{"2":{"266":1}}],["这样即使是各个应用库都独立维护",{"2":{"266":1}}],["这样做可以减少整体代码量",{"2":{"266":1}}],["这样执行",{"2":{"234":1}}],["这样可以获取到",{"2":{"227":1}}],["这样可以查看到子命令支持的各项参数及参数使用说明",{"2":{"156":1}}],["这样可以查看它支持的子命令",{"2":{"156":1}}],["这样的写法就和本地方法的调用写法是一样的",{"2":{"217":1}}],["这样才能将pms与本地csv文件建立联系",{"2":{"211":1,"229":1}}],["这样你本地调试用例的时候这条已修复的用例是会执行的",{"2":{"204":1}}],["这样这条用例即使同时标记了",{"2":{"204":1}}],["这样这条用例脚本在",{"2":{"184":1}}],["这样运行是从配置文件去读取相关配置",{"2":{"161":1,"255":1}}],["这样在子项目就可以使用到所有的全局配置",{"2":{"228":1}}],["这样在日志输出的时候就能把调用函数时参数的值输出出来",{"2":{"192":1}}],["这样在",{"2":{"141":1,"248":1}}],["这样在当前图片中",{"2":{"138":1}}],["这样是为了方便管理和维护",{"2":{"133":1}}],["这样维护起来可以说非常复杂",{"2":{"129":1}}],["这样我们只需要在服务端部署好",{"2":{"118":1}}],["这样我们就完成了一条简单的",{"2":{"98":1}}],["这样",{"2":{"101":1,"128":1,"137":1,"138":1}}],["这样所有的断言语句都是通过",{"2":{"85":1}}],["这样就可以重新做数据回填了",{"2":{"197":1}}],["这样就能获取到此元素的中心坐标",{"2":{"143":1}}],["这样就不会有干扰了",{"2":{"131":1}}],["这样就完成了一个简单的命令行自动化用例编写",{"2":{"111":1}}],["这样就完成了一个简单的用例编写",{"2":{"85":1}}],["这样就完成了一个简单的",{"2":{"65":1,"75":1}}],["这样就会在当前目录下生成一个",{"2":{"41":1}}],["这个方法存在被外部应用调用的情况",{"2":{"282":1}}],["这个方法适用于有些标签没有添加",{"2":{"142":1}}],["这个命令",{"2":{"235":1}}],["这个标签的背景",{"2":{"204":1}}],["这个参数可填可不填",{"2":{"195":1,"211":1}}],["这个参数一直都有的",{"2":{"41":1}}],["这个就是标签名称",{"2":{"141":1}}],["这个函数",{"2":{"136":1}}],["这个函数提供了隐式等待的功能",{"2":{"133":1}}],["这个版本中",{"2":{"12":1}}],["这里介绍以前的at框架情况以及存在的一些问题",{"2":{"274":1}}],["这里贴一下整体的架构图",{"2":{"261":1}}],["这里主要介绍写用例的时候注意事项",{"2":{"222":1}}],["这里就矛盾了",{"2":{"204":1}}],["这里就不多介绍",{"2":{"41":1}}],["这里给各位看官稍微解释一下",{"2":{"204":1}}],["这里都包含了",{"2":{"181":1}}],["这里以音乐举例",{"2":{"41":1}}],["这里有",{"2":{"41":1}}],["这里特别感谢",{"2":{"25":1}}],["这种方案的时间效率最高的",{"2":{"195":1}}],["这种方式安装的环境不会有",{"2":{"235":1}}],["这种方式需要修改用例代码",{"2":{"201":1,"284":1}}],["这种方式不用担心菜单选项的顺序或位置",{"2":{"128":1}}],["这种方式有个很烦人的问题",{"2":{"127":1}}],["这种全新的元素定位方案有它的适用条件",{"2":{"146":1}}],["这种在实际业务中是不影响的",{"2":{"141":1}}],["这种写法和之前的写法效果是一样的",{"2":{"34":1}}],["这种情况会导致错误",{"2":{"30":1}}],["这些是",{"2":{"179":1}}],["这些问题值得思考",{"2":{"136":1}}],["这些工具实际上也是用的",{"2":{"132":1}}],["这些修复进一步提升了用户体验",{"2":{"13":1}}],["这些更新不仅提升了框架的性能和稳定性",{"2":{"13":1}}],["近期任务计划",{"2":{"287":1}}],["近期",{"2":{"13":1}}],["报错重复注册的问题",{"2":{"51":1}}],["报错",{"2":{"27":1}}],["报错超过",{"2":{"26":1}}],["报错的问题",{"2":{"12":1,"15":1,"32":1,"55":1}}],["报告",{"2":{"178":1}}],["报告默认语言为中文",{"2":{"178":1}}],["报告进行了一系列的定制",{"2":{"178":1}}],["报告生成路径异常的问题",{"2":{"56":1}}],["报告备份功能",{"2":{"56":1}}],["报告中",{"2":{"192":1}}],["报告中直接看录制的视频",{"2":{"178":1}}],["报告中定位问题除了日志",{"2":{"53":1}}],["报告中用例总数为包含跳过用例数量",{"2":{"14":1}}],["报告新增显示当前目录",{"2":{"20":1}}],["报告增加",{"2":{"15":1}}],["报告失败数量没有剔除跳过数量的问题",{"2":{"13":1}}],["报告计算逻辑",{"2":{"12":1}}],["报告内容进行了重新规划",{"2":{"12":1}}],["报告的路径",{"2":{"12":1}}],["报告功能优化",{"2":{"11":1}}],["将你之前写的每个方案进行对应的修改",{"2":{"301":1}}],["将应用库代码拉到基础框架下",{"2":{"299":1}}],["将自动化基础框架的功能拉到本地",{"2":{"299":1}}],["将文管业务层进行",{"2":{"291":1}}],["将所有的功能模块都进入到",{"2":{"265":1}}],["将功能进行服务化封装部署",{"2":{"239":1}}],["将测试结果数据回填到pms",{"2":{"229":1}}],["将要执行的用例写入指定的",{"2":{"229":1}}],["将以上信息配置好之后",{"2":{"211":1}}],["将py文件的case",{"2":{"210":1,"229":1}}],["将跳过用例操作也整合进入用例标签",{"2":{"201":1,"284":1}}],["将小图与大图的rgb值进行匹配",{"2":{"136":1}}],["将截图的小图",{"2":{"133":1}}],["将相同的部分给消除掉",{"2":{"131":1}}],["将两种图做前后对比提取可以得到这样的图",{"2":{"131":1}}],["将其他相同的地方都屏蔽掉",{"2":{"131":1}}],["将方法层大目录",{"2":{"71":1,"100":1}}],["将不在使用",{"2":{"51":1}}],["将上述路径添加到环境变量之后也是可以用的",{"2":{"41":1}}],["将有趣的文档系统迁移到",{"2":{"38":1}}],["将",{"2":{"23":1,"26":1,"34":1,"47":1,"52":1}}],["将生成的",{"2":{"15":1}}],["将项目根目录下",{"2":{"15":2}}],["将删除虚拟环境的命令修改为",{"2":{"12":1}}],["将在下一个版本开发并发布",{"2":{"12":1}}],["提高兼容性测试效率",{"2":{"280":1}}],["提高代码利用率",{"2":{"273":1}}],["提高架构专业性",{"2":{"273":1}}],["提取不同的部分生成一张新的图片",{"2":{"131":1}}],["提供通用的接口能力",{"2":{"280":1}}],["提供所有自动化测试所需要的底层功能",{"2":{"258":1}}],["提供更友好化的错误提示",{"2":{"242":1}}],["提供用例标签化管理",{"2":{"242":1}}],["提供统一的接口",{"2":{"242":1}}],["提供的一个全局对象",{"2":{"213":1}}],["提供的一些参数选项",{"2":{"161":1,"255":1}}],["提供的一些常用的参数选项",{"2":{"158":1}}],["提供了本地执行",{"2":{"250":1}}],["提供了丰富的配置和命令行参数",{"2":{"155":1}}],["提供了对",{"2":{"66":1}}],["提供一个全局默认的对象",{"2":{"98":1,"103":1}}],["提供配置项可以指定浏览器对应的路径",{"2":{"16":1,"98":1,"103":1}}],["提升",{"2":{"52":1}}],["提示",{"2":{"274":1}}],["提示不是问题",{"2":{"26":1}}],["提示找不到",{"2":{"12":1}}],["提交地址",{"2":{"2":1}}],["提交",{"0":{"2":1}}],["跳过的原因统一标记为",{"2":{"284":1}}],["跳过的原因统一标签开头为",{"2":{"202":1}}],["跳过的原因标签为",{"2":{"203":1}}],["跳过用例标签化",{"2":{"284":1}}],["跳过用例的标签",{"2":{"204":1}}],["跳过用例",{"0":{"201":1},"1":{"202":1,"203":1}}],["跳过用例数",{"2":{"12":1}}],["跳过原因",{"2":{"199":2,"201":1,"202":1,"203":3,"204":3,"205":1,"284":3}}],["跳过数",{"2":{"12":1}}],["+|",{"2":{"154":1}}],["+=",{"2":{"144":1}}],["+",{"2":{"12":1,"49":1,"74":4,"119":1,"133":1,"143":2,"144":4,"147":6,"149":40,"154":2,"175":12,"272":1,"286":1,"300":1,"302":2}}],["=========",{"2":{"222":1}}],["==========",{"2":{"222":3}}],["================",{"2":{"191":1,"229":1}}],["==============================================",{"2":{"191":1,"229":1}}],["===================================",{"2":{"98":1,"213":1,"229":9}}],["===============================",{"2":{"98":1,"213":1,"229":9}}],["=============",{"2":{"191":1,"229":1}}],["==",{"2":{"119":1,"137":1,"144":7,"149":2,"175":9,"183":1,"203":5,"215":1,"216":1,"218":1}}],["=",{"2":{"12":2,"41":4,"53":2,"64":4,"65":2,"74":29,"75":4,"84":2,"85":1,"93":1,"94":2,"98":3,"110":2,"111":3,"119":9,"131":1,"133":13,"134":4,"136":2,"137":11,"142":3,"143":6,"144":41,"147":5,"148":3,"149":140,"154":17,"175":85,"183":23,"191":4,"192":1,"193":5,"195":18,"203":5,"208":1,"210":1,"211":6,"213":1,"215":1,"216":1,"217":2,"218":1,"222":2,"228":1,"229":87,"265":8,"266":2,"294":2,"297":3}}],["用这个功能就是想把关联到的都修改",{"2":{"300":1}}],["用下划线连接是",{"2":{"280":1}}],["用户",{"2":{"286":1}}],["用户执行命令",{"2":{"246":1}}],["用户名",{"2":{"158":1,"252":1}}],["用两对大括号把函数的参数括起来",{"2":{"192":1}}],["用中括号括起来就行",{"2":{"148":1}}],["用于管理模块内的用例标签",{"2":{"284":1}}],["用于给每条用例打标签",{"2":{"280":1}}],["用于图像识别坐标",{"2":{"229":1}}],["用于其他操作",{"2":{"216":1}}],["用于自动同步",{"2":{"211":1}}],["用于自动输出方法的日志",{"2":{"84":1}}],["用于保存用例标签",{"2":{"200":1,"284":1}}],["用于标记已经废弃的用例",{"2":{"199":1}}],["用于标记用例的修复状态",{"2":{"199":1}}],["用于标记所有子项目",{"2":{"57":1}}],["用于控制用例是否执行",{"2":{"199":1}}],["用于控制重复识别的次数",{"2":{"133":1}}],["用于干扰较大时提升ocr识别精准度",{"2":{"175":2}}],["用于用例断言的图片资源放到",{"2":{"133":1}}],["用于放置app工程",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["用于记录了用例的执行结果和回填情况",{"2":{"197":1}}],["用于记录历史发布版本的更新内容",{"2":{"59":1}}],["用于记录系统资源占用情况",{"2":{"54":1}}],["用于只跑上次失败用例的功能",{"2":{"56":1}}],["用于动态的截取元素的图片",{"2":{"53":1}}],["用于静态代码扫描",{"2":{"49":1}}],["用于获取桌面所有窗口的信息",{"2":{"25":1}}],["用起来很稳定",{"2":{"40":1}}],["用",{"2":{"27":1}}],["用例代码调用逻辑举例",{"2":{"297":1}}],["用例逻辑上更清楚",{"2":{"296":1}}],["用例里面本来也应该被关联修改",{"2":{"301":1}}],["用例里面直接继承",{"2":{"296":1}}],["用例里面来判断用哪个",{"2":{"131":1}}],["用例也不会被执行",{"2":{"284":1}}],["用例来源",{"2":{"284":3}}],["用例来源等等",{"2":{"277":1}}],["用例可以添加对应的标签",{"2":{"284":1}}],["用例解耦",{"0":{"282":1}}],["用例触发执行控制",{"2":{"280":1}}],["用例层",{"2":{"275":2}}],["用例层可能需要对这部分用例做逻辑判断",{"2":{"184":1}}],["用例实现标签化管理",{"2":{"273":1}}],["用例超时控制",{"2":{"242":1}}],["用例超时时间",{"2":{"53":1}}],["用例名称默认存在第一列",{"2":{"229":1}}],["用例注意事项",{"0":{"222":1}}],["用例模块的对应关系",{"2":{"211":1}}],["用例需要用到的资源",{"2":{"262":1,"292":1}}],["用例需要废弃",{"2":{"205":1}}],["用例需要添加的标签有",{"2":{"199":1}}],["用例id",{"2":{"204":1,"205":1,"284":2}}],["用例id兼容用例库id和产品库id",{"2":{"54":1}}],["用例标签文件",{"2":{"292":1}}],["用例标签目录",{"2":{"292":1}}],["用例标签分类评估",{"2":{"287":1}}],["用例标签的驱动方式必须能支持标签的扩展",{"2":{"285":1}}],["用例标签",{"2":{"280":1}}],["用例标签化管理",{"0":{"284":1},"2":{"242":1}}],["用例标签化管理和执行",{"2":{"240":1}}],["用例标签数据至本地",{"2":{"211":1}}],["用例标签可以无序",{"2":{"200":1}}],["用例标签管理文件",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["用例脚本的",{"2":{"200":1}}],["用例类型和用例来源",{"2":{"284":1}}],["用例类型",{"2":{"199":2,"229":1,"284":2}}],["用例级别",{"2":{"199":2,"229":1,"284":2}}],["用例库",{"2":{"199":1,"229":1}}],["用例失败重跑的次数不能小于失败录屏次数",{"2":{"193":1}}],["用例失败录屏",{"2":{"86":1}}],["用例兼容",{"2":{"184":1}}],["用例驱动方式",{"0":{"163":1},"1":{"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1}}],["用例的类型",{"2":{"277":1}}],["用例的前置和后置要写在同一个用例文件里面",{"2":{"222":1}}],["用例的标签",{"2":{"158":1,"252":1}}],["用例的关键词",{"2":{"158":1,"252":1}}],["用例操作动态的",{"2":{"138":1}}],["用例继承了用例基类",{"2":{"98":1}}],["用例步骤过程中控制远程机器",{"2":{"242":1}}],["用例步骤中与其他机器进行交互",{"2":{"213":1,"229":1}}],["用例步骤",{"0":{"83":1,"96":1}}],["用例编写",{"0":{"94":1},"2":{"65":1,"75":1}}],["用例",{"2":{"65":1,"75":1,"85":1,"98":1,"111":1,"210":1,"262":1,"273":1,"280":1,"292":1}}],["用例文件以",{"2":{"65":1,"75":1,"85":1,"98":1,"111":1}}],["用例执行接口",{"2":{"286":1}}],["用例执行控制模块",{"2":{"286":1}}],["用例执行",{"0":{"285":1}}],["用例执行模块",{"2":{"280":1}}],["用例执行的范围不够精准",{"2":{"277":1}}],["用例执行都使用",{"2":{"235":1}}],["用例执行完后生成的测试报告格式",{"2":{"229":1}}],["用例执行完之后回填",{"2":{"195":1}}],["用例执行时判断",{"2":{"202":1,"284":1}}],["用例执行时配置",{"2":{"195":1}}],["用例执行过程中进行图像识别时",{"2":{"133":1}}],["用例执行过程中输出执行进度百分比",{"2":{"29":1}}],["用例执行所需要的资源",{"2":{"61":1,"70":1,"71":1,"80":1,"99":1,"100":1,"107":1,"248":1}}],["用例示例",{"2":{"61":2,"70":2,"80":2,"99":2,"107":2,"248":2}}],["用例基类用于继承断言模块",{"2":{"85":1}}],["用例基类",{"2":{"61":1,"65":2,"70":1,"75":2,"80":1,"85":1,"98":1,"99":1,"107":1,"111":2,"174":2,"248":1}}],["用例断言所需要的资源",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["用例目录",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["用例收集时仅在",{"2":{"56":1}}],["用例顺序被调整的问题",{"2":{"53":1}}],["用例中通过",{"2":{"174":1}}],["用例中通过框架提供的",{"2":{"16":1}}],["用例中使用方法",{"0":{"174":1}}],["用例中的图像识别会通过远程服务接口进行图像识别和结果获取",{"2":{"40":1}}],["用例管理系统存在缺陷",{"2":{"31":1}}],["用例在收集阶段报错",{"2":{"19":1}}],["用例结果以",{"2":{"15":1}}],["用例维度统计数据",{"2":{"15":1}}],["用例总数",{"2":{"12":2,"56":1}}],["用以集中说明",{"2":{"12":1}}],["用以控制拉取",{"2":{"11":1}}],["和前面配置项client",{"2":{"229":1}}],["和前面配置项password一样",{"2":{"213":1,"229":1}}],["和端口进行",{"2":{"137":1}}],["和当前版本",{"2":{"53":1}}],["和命令行参数",{"2":{"34":1}}],["和",{"2":{"12":1,"15":1,"20":1,"47":1,"53":1,"56":1,"137":1,"147":1,"181":1,"184":1,"192":1,"204":3,"229":2,"234":1,"242":1,"271":1,"300":1}}],["mk",{"2":{"295":1}}],["m",{"2":{"179":1}}],["mp4",{"2":{"177":1}}],["mccabe",{"2":{"154":1}}],["ms",{"2":{"134":1}}],["msg=",{"2":{"75":1}}],["msg",{"2":{"7":1}}],["multiplier",{"2":{"149":16}}],["multiple=multiple",{"2":{"133":1,"175":2,"192":1}}],["multiple=true",{"2":{"133":1}}],["multiple=false",{"2":{"133":1,"192":1}}],["multiple",{"2":{"133":5,"137":3,"175":2,"192":1}}],["musicwidget",{"2":{"282":1}}],["music",{"2":{"34":2,"41":2,"47":3,"49":2,"51":1,"53":4,"93":2,"94":1,"133":1,"142":1,"148":2,"158":3,"161":2,"162":1,"167":4,"172":9,"177":3,"181":2,"211":4,"222":18,"229":8,"252":2,"255":1,"262":1,"266":1,"280":1,"282":1}}],["movie",{"2":{"280":1}}],["moveto",{"2":{"183":1}}],["move",{"2":{"131":1,"144":1,"183":16}}],["moverel",{"2":{"38":1,"183":1}}],["mode",{"2":{"175":6,"222":2}}],["modules",{"2":{"154":1}}],["modulenotfounderror",{"2":{"144":1,"175":1}}],["mouseup",{"2":{"183":1}}],["mousedown",{"2":{"183":1}}],["mousedownup=true",{"2":{"183":2}}],["mousemove",{"2":{"183":2}}],["mousekey",{"2":{"131":5,"144":2,"175":3,"181":3,"182":2,"183":1}}],["mouse",{"2":{"131":1,"144":3,"175":1,"181":1,"182":1,"183":6}}],["mozilla",{"2":{"74":1}}],["mypy",{"2":{"154":1}}],["myappwidget",{"2":{"84":3,"85":2}}],["myappassert",{"2":{"65":2,"75":2,"85":2,"98":2,"111":2,"174":5}}],["mycase",{"2":{"61":3,"65":3,"70":3,"71":3,"75":2,"80":3,"85":3,"92":2,"94":3,"98":3,"99":3,"100":3,"107":3,"111":3,"165":2,"174":1,"217":1,"248":3}}],["my",{"2":{"61":4,"64":1,"65":4,"68":1,"69":2,"70":4,"71":4,"72":1,"75":2,"78":1,"79":2,"80":4,"84":4,"85":5,"88":1,"89":2,"92":2,"94":3,"97":1,"98":4,"99":4,"100":4,"101":1,"105":1,"106":2,"107":4,"111":4,"114":1,"115":2,"165":1,"166":1,"170":1,"171":1,"174":5,"195":1,"196":1,"217":1,"218":1,"231":1,"246":1,"247":2}}],["menu",{"2":{"183":2}}],["methods",{"2":{"144":1}}],["method",{"2":{"75":1}}],["meant",{"2":{"27":1}}],["message=str",{"2":{"183":1}}],["message",{"2":{"26":1,"158":1,"161":1,"183":11,"252":1,"255":1}}],["mixin",{"2":{"265":1}}],["mips64",{"2":{"203":2}}],["middleclick",{"2":{"183":1}}],["middle",{"2":{"144":1,"183":2}}],["minorversion",{"2":{"27":1,"203":1}}],["mikigo",{"2":{"12":6,"13":6,"14":4,"15":8,"16":10,"17":5,"18":2,"19":3,"20":5,"21":1,"22":2,"23":1,"24":2,"26":3,"27":1,"29":2,"30":1,"31":3,"32":3,"33":3,"34":12,"35":3,"36":4,"37":3,"38":5,"39":2,"40":3,"41":3,"42":2,"43":3,"44":1,"45":2,"46":4,"47":9,"48":1,"49":6,"50":9,"51":5,"52":5,"53":18,"54":12,"55":2,"56":12,"57":11,"58":4,"59":5,"84":1,"141":1,"144":1,"149":1,"183":1,"213":1,"229":2}}],["make",{"2":{"295":1}}],["master",{"2":{"213":1,"229":1}}],["map",{"2":{"192":1}}],["magic",{"2":{"154":2}}],["many",{"2":{"144":3}}],["manager",{"2":{"84":2,"85":2,"119":1,"149":1,"175":1,"260":1,"262":1,"265":2,"292":1,"294":2,"295":1,"296":3,"297":8,"301":1}}],["manage",{"0":{"155":1},"1":{"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1},"2":{"18":1,"33":1,"34":2,"41":4,"47":2,"50":1,"51":1,"53":3,"56":1,"61":1,"68":1,"70":1,"78":1,"80":1,"88":1,"99":1,"105":1,"107":1,"114":1,"155":1,"156":4,"157":1,"158":2,"159":2,"160":1,"161":4,"162":1,"164":2,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"193":1,"195":3,"196":1,"204":1,"208":2,"210":2,"211":2,"213":1,"223":1,"235":1,"248":1,"250":1,"251":1,"252":2,"253":1,"254":1,"255":4,"256":1,"262":1,"280":1}}],["max",{"2":{"134":2,"158":2,"175":8,"229":4,"252":2}}],["matching",{"2":{"136":5}}],["match",{"2":{"133":11,"136":4,"137":6,"144":1,"175":12,"229":4}}],["matchtemplate",{"2":{"133":1}}],["mainwindow",{"2":{"140":1}}],["main",{"2":{"119":1,"137":1,"203":1,"215":1,"216":1,"218":1}}],["markdown",{"2":{"154":1}}],["mark",{"2":{"53":1,"168":1,"201":1,"206":1,"221":2,"222":1,"229":2}}],["maybe",{"2":{"27":1}}],["macos",{"2":{"12":1}}],["md",{"2":{"15":1,"57":1,"59":1}}],["文管界面分为四个区域",{"2":{"295":1}}],["文管代码解耦",{"2":{"287":1}}],["文管方法库出口",{"2":{"192":2}}],["文本输入",{"2":{"142":1}}],["文件右键菜单",{"2":{"300":1}}],["文件或目录",{"2":{"300":1}}],["文件脚本",{"2":{"287":1}}],["文件实际是以都好分隔的文本文件",{"2":{"280":1}}],["文件维护用例与标签的对应关系",{"2":{"280":1}}],["文件操作模块",{"2":{"280":1}}],["文件只会用来写",{"2":{"267":2}}],["文件命名规范",{"2":{"248":1}}],["文件原来能干这么多事情",{"2":{"242":1}}],["文件可能存在相同的依赖被指定安装不同版本等等兼容性问题",{"2":{"233":1}}],["文件一并加载",{"2":{"233":1}}],["文件是不需要人工去修改的",{"2":{"226":1}}],["文件会自动备份在",{"2":{"211":1}}],["文件会直接创建一个并写入用例脚本的",{"2":{"210":1}}],["文件先备份到",{"2":{"210":1,"211":1}}],["文件几乎是唯一能满足所有的要求的文件格式",{"2":{"207":1}}],["文件进行集中管理",{"2":{"206":1}}],["文件覆盖历史",{"2":{"204":1}}],["文件跳过原因一栏中填写为",{"2":{"203":1}}],["文件来管理跳过用例则会方便很多",{"2":{"201":1,"284":1}}],["文件里面跳过原因列是否存在跳过标记",{"2":{"284":1}}],["文件里面跳过原因列是否存在跳过标签",{"2":{"202":1}}],["文件里面标记此条用例的标签",{"2":{"284":1}}],["文件里面分不同的",{"2":{"280":1}}],["文件里面分不同的类",{"2":{"280":1}}],["文件里面是该应用的方法类",{"2":{"266":1}}],["文件里面对应的",{"2":{"210":1}}],["文件里面添加对应的列即可",{"2":{"200":1,"284":1}}],["文件里面写了一个导入",{"2":{"154":1}}],["文件太多了也是一个很糟糕的事情",{"2":{"200":1,"284":1}}],["文件建议放在一个",{"2":{"200":1}}],["文件去掉首字符串",{"2":{"200":1}}],["文件后缀",{"2":{"175":1}}],["文件夹",{"2":{"175":4}}],["文件存在",{"2":{"175":2}}],["文件全路径",{"2":{"175":1}}],["文件全路径或目录",{"2":{"175":1}}],["文件名与",{"2":{"211":1}}],["文件名就应为",{"2":{"200":1}}],["文件名",{"2":{"175":2,"282":1}}],["文件名称可以自定义",{"2":{"208":1}}],["文件名称",{"2":{"12":1,"167":1}}],["文件标签关联管理",{"2":{"155":1}}],["文件管理的标签",{"2":{"168":1}}],["文件管理",{"2":{"155":1}}],["文件管理器从业务复杂度和用例量来讲",{"2":{"290":1}}],["文件管理器",{"2":{"84":3,"291":1}}],["文件管理器已经启动",{"2":{"83":1,"85":1}}],["文件中多余的",{"2":{"210":1}}],["文件中查找是否有同名函数",{"2":{"203":1}}],["文件中新增一列为",{"2":{"201":1,"284":1}}],["文件中所有的用例",{"2":{"164":1}}],["文件中没有配置",{"2":{"149":1}}],["文件中",{"2":{"57":1,"156":1}}],["文件中可以使用此方法进行条件跳过",{"2":{"27":1}}],["文件时配置的字段名",{"2":{"229":1}}],["文件时",{"2":{"53":1}}],["文件不支持用例库的问题",{"2":{"52":1}}],["文件不存在",{"2":{"25":1,"175":2}}],["文件功能",{"2":{"36":1}}],["文件的增删改查操作模块等",{"2":{"275":1}}],["文件的",{"2":{"210":1}}],["文件的字段格式已经适配了",{"2":{"208":1}}],["文件的设计来实现了对历史",{"2":{"204":1}}],["文件的文件名",{"2":{"200":1}}],["文件的问题",{"2":{"34":1,"42":1}}],["文件的名称一样",{"2":{"33":1}}],["文件写入为",{"2":{"34":1}}],["文件找不到",{"2":{"27":1}}],["文件",{"0":{"210":1},"2":{"19":1,"26":1,"36":1,"48":1,"53":1,"57":1,"59":1,"175":2,"179":3,"200":2,"206":1,"210":1,"211":1,"229":1,"233":3,"266":1,"280":1,"282":1,"283":1,"284":2}}],["文件对比时",{"2":{"17":1}}],["文件用例列表不完整的问题",{"2":{"16":1}}],["文档目录",{"2":{"262":1}}],["文档里面已经有详细描述了",{"2":{"261":1}}],["文档工程迁移到单独的仓库",{"2":{"52":1}}],["文档内容一样",{"2":{"41":1}}],["文档内容及排版",{"2":{"35":1}}],["文档界面ui调整",{"2":{"14":1}}],["文档新增",{"2":{"14":1}}],["文档更新",{"2":{"11":1,"12":1}}],["文档",{"0":{"1":1},"2":{"120":1,"185":1,"264":1}}],["对照",{"2":{"284":1}}],["对用例实现标签化管理",{"2":{"280":1}}],["对断言进行了二次封装",{"2":{"242":1}}],["对比指标",{"2":{"185":1}}],["对比下文件前后",{"2":{"152":1}}],["对比动作前后两张图片",{"2":{"131":1}}],["对元素的操作",{"2":{"142":1}}],["对应",{"2":{"199":1,"284":3}}],["对应应用里面的父窗口和子窗口",{"2":{"141":1}}],["对应的所有小图的rgb值不相等",{"2":{"136":1}}],["对于我们需求理解",{"2":{"266":1}}],["对于重启类场景的用例需要解决的核心问题是",{"2":{"220":1}}],["对于用例规模比较大的应用",{"2":{"200":1,"284":1}}],["对于一些文案的场景非常适用",{"2":{"119":1}}],["对于任何形式的贡献我们都欢迎",{"2":{"0":1}}],["对操作系统的接口测试通常指的是对",{"2":{"66":1}}],["对",{"2":{"37":2,"185":1}}],["对多个文档模块及文档内容进行了修改",{"2":{"22":1}}],["对象组合",{"2":{"265":1}}],["对象能获取到所有可获取的配置项的值",{"2":{"227":1}}],["对象包含了",{"2":{"215":1}}],["对象",{"2":{"16":3,"98":1}}],["对生成的",{"2":{"12":1}}],["drf",{"2":{"286":1}}],["draw",{"2":{"183":1}}],["dragrel",{"2":{"183":1}}],["dragto",{"2":{"183":1}}],["drag",{"2":{"183":7}}],["dmidecode",{"2":{"203":4}}],["dfmassert",{"2":{"296":4}}],["dfmwidget",{"2":{"192":2,"296":3,"297":3}}],["dfm",{"2":{"192":7,"262":1,"292":2,"296":2,"297":5}}],["dynamic",{"2":{"154":1}}],["duration=1",{"2":{"183":1}}],["duration=duration",{"2":{"183":3}}],["duration=0",{"2":{"183":4}}],["duration",{"2":{"183":7}}],["duringfail",{"2":{"158":1,"252":1}}],["during",{"2":{"50":1,"134":1,"175":2,"229":1}}],["dummy",{"2":{"154":1}}],["d+",{"2":{"149":6}}],["dd",{"2":{"109":1,"110":3,"111":2}}],["ddedesktoppublicwidget",{"2":{"266":1,"283":1}}],["ddedesktoppublicbasewidget",{"2":{"266":2}}],["ddedockpublicwidget",{"2":{"222":1}}],["dde",{"2":{"46":1,"84":8,"85":3,"93":3,"149":2,"175":1,"260":1,"262":7,"265":2,"266":3,"283":2,"292":1,"294":2,"295":1,"296":3,"297":8,"301":1}}],["dict",{"2":{"119":2,"144":1,"149":4,"175":6}}],["direnv",{"2":{"154":1}}],["direct",{"2":{"183":3}}],["directories",{"2":{"154":1}}],["direction",{"2":{"147":2,"148":2,"149":19}}],["dirname",{"2":{"119":1,"137":1}}],["dir",{"2":{"98":1,"119":1,"137":1,"226":1,"229":3,"266":1,"268":1}}],["display",{"2":{"183":1,"203":1}}],["displayconnectionerror",{"2":{"21":1}}],["dist",{"2":{"154":1}}],["disabled",{"2":{"154":1}}],["disable=ungrouped",{"2":{"183":1}}],["disable=eval",{"2":{"149":2}}],["disable=too",{"2":{"144":1}}],["disable=c0114",{"2":{"144":1}}],["disable",{"2":{"74":1}}],["d",{"2":{"64":3,"154":1,"235":1,"247":1}}],["dbuswidget",{"2":{"64":1,"65":2}}],["dbusutils",{"2":{"64":3,"66":1}}],["dbus",{"0":{"66":1},"1":{"67":1,"68":1,"69":1},"2":{"49":2,"64":5,"65":2,"66":3,"93":1,"149":3,"241":1,"275":1,"280":1}}],["doesn",{"2":{"154":1}}],["dom",{"2":{"130":1,"140":2}}],["domain",{"2":{"74":4}}],["downloads",{"2":{"229":1}}],["down",{"2":{"127":3,"183":6}}],["doubleclick",{"2":{"142":1,"183":1}}],["double",{"2":{"124":1,"131":1,"144":2,"154":2,"183":3,"295":1}}],["dogutils",{"2":{"215":1}}],["dog",{"2":{"84":2,"143":1,"265":1,"295":2,"297":3}}],["dogtails",{"2":{"262":1,"265":1}}],["dogtailutils",{"2":{"143":1,"144":1,"175":4}}],["dogtail",{"2":{"20":1,"55":1,"59":5,"140":2,"142":2,"143":1,"144":9,"175":1,"265":3}}],["doctests",{"2":{"154":1}}],["doc",{"2":{"110":1,"111":1,"190":1}}],["docker",{"2":{"271":2}}],["dock的信息",{"2":{"84":1}}],["dock",{"2":{"84":5,"85":1,"93":6,"94":1,"222":1,"262":3}}],["docstring",{"2":{"154":2}}],["docstrings",{"2":{"154":2}}],["docs",{"2":{"35":1,"37":2,"262":1}}],["date",{"2":{"98":1,"229":3}}],["data",{"2":{"74":2,"119":1,"136":3,"137":1}}],["daemon",{"2":{"93":3,"175":1}}],["dagtail",{"2":{"24":1}}],["darklii",{"2":{"12":1,"16":1,"18":2}}],["deutsch",{"2":{"229":1}}],["de",{"2":{"229":1}}],["demo可以看",{"2":{"220":1}}],["delay",{"2":{"183":6}}],["delay=1",{"2":{"183":1}}],["delete",{"2":{"75":1}}],["detect",{"2":{"154":1}}],["detail",{"2":{"11":3}}],["degree",{"2":{"136":2}}],["dest=com",{"2":{"93":1}}],["desc=self",{"2":{"265":1,"266":1,"294":1,"297":1}}],["description",{"2":{"143":3,"144":3}}],["description=none",{"2":{"143":1,"144":1}}],["desc",{"2":{"84":1,"265":7,"266":2,"294":2,"297":3}}],["desktop",{"2":{"46":1,"93":1,"110":1,"111":1,"133":1,"175":2,"262":3,"266":3,"283":2,"296":4}}],["department",{"2":{"74":4}}],["depends",{"2":{"59":2,"144":5,"183":3}}],["depth",{"2":{"11":1,"229":2}}],["default",{"2":{"119":1,"149":12,"154":3}}],["default=false",{"2":{"119":1}}],["deflate",{"2":{"74":1}}],["def",{"2":{"53":1,"64":2,"65":1,"74":5,"75":2,"84":2,"85":1,"93":2,"94":1,"97":4,"98":3,"110":1,"111":1,"119":4,"136":4,"137":2,"143":3,"144":17,"149":28,"164":2,"174":1,"175":23,"183":36,"187":1,"189":1,"192":2,"203":7,"215":2,"216":2,"217":2,"218":1,"222":2,"229":3,"265":2,"266":3,"282":2,"283":2,"294":1,"295":1,"296":2,"297":5}}],["deepinmusicwidget",{"2":{"53":4,"181":3,"221":1,"222":4}}],["deepin",{"2":{"34":2,"41":2,"47":3,"49":2,"51":1,"53":3,"54":1,"64":3,"93":5,"94":1,"142":1,"158":3,"161":2,"162":1,"167":2,"172":4,"177":2,"181":2,"208":3,"211":1,"229":5,"248":6,"252":3,"255":1,"262":1,"280":4,"299":1}}],["debug",{"2":{"57":1,"93":1,"144":10,"149":29,"158":2,"175":2,"177":1,"183":22,"191":1,"229":4,"252":2}}],["deb",{"2":{"20":1,"27":1,"41":2,"47":1,"158":2,"229":1,"233":3,"252":2,"276":1}}],["devnull",{"2":{"183":1}}],["dev",{"2":{"15":1,"16":1,"28":1,"29":2,"38":1,"41":1,"47":1,"110":1,"224":1}}],["nl",{"2":{"229":1}}],["nederlands",{"2":{"229":1}}],["net",{"2":{"175":2}}],["network",{"2":{"175":10,"229":2}}],["next",{"2":{"144":3}}],["new",{"2":{"5":1,"7":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"29":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"41":1,"47":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1}}],["np",{"2":{"137":1}}],["nginx",{"0":{"122":1},"2":{"122":3}}],["nz",{"2":{"98":1}}],["nubmer=nubmer",{"2":{"297":2}}],["nubmer=",{"2":{"297":2}}],["num",{"2":{"175":7}}],["numbers",{"2":{"175":1}}],["number=number",{"2":{"265":1,"294":1,"297":1}}],["number=max",{"2":{"175":2}}],["number=match",{"2":{"175":2}}],["number=",{"2":{"144":1,"265":1,"294":1,"297":1}}],["number",{"2":{"54":1,"133":7,"144":2,"147":1,"149":9,"175":19,"183":11,"229":4,"265":9,"297":3}}],["numpy",{"2":{"44":1,"137":1}}],["null",{"2":{"34":2}}],["name=self",{"2":{"265":1,"266":1,"294":1,"297":1}}],["name=spur",{"2":{"74":2}}],["name=app",{"2":{"175":1}}],["name=none",{"2":{"136":1,"143":1,"144":1}}],["name=name",{"2":{"74":1}}],["name",{"2":{"34":1,"35":1,"39":2,"47":2,"53":1,"64":3,"74":2,"75":4,"84":1,"85":1,"119":2,"137":1,"141":1,"142":3,"143":3,"144":17,"147":3,"149":49,"158":2,"191":3,"195":3,"203":12,"211":2,"215":1,"216":1,"218":1,"229":8,"252":2,"265":8,"266":2,"294":2,"296":2,"297":4}}],["native",{"2":{"16":1,"98":4,"103":1,"229":3}}],["n",{"0":{"242":1},"2":{"30":2,"147":1,"149":4,"161":1,"175":3,"203":2,"255":1}}],["no表示测试机分布式执行",{"2":{"229":1}}],["nox",{"2":{"154":1}}],["nosetreferencepoint",{"2":{"149":3}}],["nosectionerror",{"2":{"149":3}}],["noskip",{"2":{"20":1,"158":1,"229":1,"252":1}}],["node=none",{"2":{"144":1}}],["node",{"2":{"144":16,"154":1}}],["no",{"2":{"41":3,"144":3,"161":1,"162":1,"210":1,"229":10,"255":1,"256":1}}],["none=true",{"2":{"119":1,"137":2}}],["none",{"2":{"15":1,"16":1,"119":2,"133":8,"134":2,"137":3,"144":4,"149":7,"175":66,"265":2}}],["not逻辑组合",{"2":{"158":2,"252":2}}],["not",{"2":{"12":1,"34":1,"119":1,"133":1,"144":4,"149":2,"167":1,"168":1,"175":40,"203":10,"229":1}}],["此层在框架中提供一些通用的接口能力",{"2":{"275":1}}],["此目录名称前面部分是你的代码根目录的名称",{"2":{"236":1}}],["此功能默认会将",{"2":{"210":1}}],["此功能目前还处于内部灰度阶段",{"2":{"12":1}}],["此配置文件需要维护大量的标签数据",{"2":{"207":1}}],["此配置文件用于标签化管理方案实现条件判断跳过的配置项",{"2":{"203":1}}],["此时编辑器可能会提示你",{"2":{"300":1}}],["此时",{"2":{"200":1}}],["此时要定位到菜单中的",{"2":{"131":1}}],["此用例标签不会被添加",{"2":{"199":1}}],["此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用",{"2":{"146":1}}],["此函数用于在操作之前截图一张临时图片",{"2":{"138":1}}],["此方案时间效率比较低",{"2":{"195":1}}],["此方案用到的场景不多",{"2":{"182":1}}],["此方案在框架内没有引入任何三方依赖完全采用标准库实现",{"2":{"119":1}}],["此方法直接返回坐标",{"2":{"119":1}}],["此接口底层没有兼容服务化",{"2":{"40":1}}],["此外",{"2":{"12":1}}],["b2ae5ab1d3a5",{"2":{"177":1}}],["be",{"2":{"154":1}}],["blocks",{"2":{"154":1}}],["black",{"2":{"153":1,"154":5}}],["bzr",{"2":{"154":1}}],["b",{"2":{"149":48}}],["bdata",{"2":{"136":2}}],["big",{"2":{"133":1,"136":1}}],["binary",{"2":{"137":3}}],["bin",{"2":{"41":1,"84":1,"98":1,"144":1,"149":1,"175":1,"183":1,"203":1,"229":1,"245":2,"265":1,"266":1,"294":1,"297":1}}],["bbox=screen",{"2":{"133":1}}],["bbox",{"2":{"133":6,"137":2,"175":30}}],["boundary",{"2":{"149":6}}],["bottom",{"2":{"148":2,"149":20}}],["bool",{"2":{"133":2,"137":1,"144":1,"175":5,"183":3,"184":1}}],["box",{"2":{"97":1,"98":1}}],["bs=",{"2":{"110":1}}],["brazil",{"2":{"229":1}}],["branch",{"2":{"11":1,"229":1}}],["br",{"2":{"229":1}}],["browse",{"2":{"211":1,"229":1}}],["browser",{"2":{"98":6,"141":1,"229":2}}],["break",{"2":{"149":2}}],["baidu",{"2":{"97":5,"98":6,"229":2}}],["backspace",{"2":{"183":2}}],["back",{"2":{"56":1,"177":1,"210":1,"211":1}}],["basic",{"2":{"260":1}}],["basicenv",{"2":{"234":3}}],["bash",{"2":{"49":1,"64":1,"69":2,"72":1,"79":2,"89":2,"101":1,"106":2,"115":2,"224":1,"231":2,"233":1,"235":1,"247":3}}],["baseline",{"2":{"199":1}}],["based",{"2":{"149":1}}],["basepage",{"2":{"97":4}}],["baseapi",{"2":{"74":4}}],["basecase",{"2":{"65":4,"75":4,"85":4,"94":2,"98":4,"111":4,"174":3,"217":1,"222":1,"296":3,"297":2}}],["basewidget",{"2":{"64":4,"84":5,"265":1,"294":1,"295":2,"297":7,"301":2}}],["base",{"0":{"294":1},"2":{"15":1,"61":2,"64":2,"65":3,"70":2,"71":2,"74":9,"75":2,"80":2,"84":3,"85":2,"92":1,"94":1,"97":2,"98":2,"99":2,"100":2,"107":2,"111":3,"165":1,"174":1,"226":1,"248":2,"262":1,"265":1,"268":1,"280":1,"292":1}}],["btn",{"2":{"53":3,"84":3,"93":1,"133":2,"147":2,"148":3,"149":68,"222":2,"266":1,"295":1}}],["but",{"2":{"154":1}}],["button=cls",{"2":{"183":2}}],["button=1",{"2":{"142":2,"144":1,"183":2}}],["buttoncenter",{"2":{"149":1,"175":2,"265":2}}],["button",{"2":{"53":1,"142":1,"144":5,"147":1,"149":124,"175":1,"183":6,"262":1,"265":2}}],["buck",{"2":{"154":1}}],["build",{"2":{"154":2,"158":2,"161":1,"229":1,"252":2,"255":1}}],["bug",{"2":{"12":1,"31":1,"51":1,"52":1,"199":3,"302":1}}],["by",{"2":{"12":1,"15":1,"16":1,"18":5,"19":2,"20":2,"74":3,"75":2,"84":2,"85":1,"93":2,"94":1,"110":1,"111":1,"133":3,"136":3,"137":6,"144":7,"148":1,"149":10,"154":3,"175":3,"215":3,"222":7,"266":2,"282":1,"283":1,"295":5,"297":4}}],["功能测试",{"2":{"285":1}}],["功能测试用例",{"2":{"280":1}}],["功能模块相对独立",{"2":{"275":1}}],["功能强大的自动化测试框架",{"2":{"258":1}}],["功能强大的执行管理器",{"2":{"242":1}}],["功能进行了增强",{"2":{"123":1}}],["功能进行了优化和",{"2":{"12":1}}],["功能做了服务化",{"2":{"40":1}}],["功能的一些信息输出",{"2":{"38":1}}],["功能",{"2":{"12":1,"31":1,"133":1,"199":1}}],["功能增加显示明细数据",{"2":{"5":1}}],["希望欧拉系统上使用到",{"2":{"12":1}}],["的配置比较灵活",{"2":{"280":1}}],["的配置均不生效",{"2":{"229":1}}],["的内容",{"2":{"267":1}}],["的名称空间",{"2":{"265":1}}],["的公共方法",{"2":{"262":2}}],["的普通文件",{"2":{"234":1}}],["的表达式",{"2":{"229":1}}],["的所有用例",{"2":{"229":1}}],["的所有方法",{"2":{"98":1}}],["的别名",{"2":{"227":1}}],["的对象实例化默认会检测应用是否启动",{"2":{"222":1}}],["的基础上增加了发送",{"2":{"218":1}}],["的要求",{"2":{"208":1}}],["的钩子函数",{"2":{"206":1}}],["的时候",{"2":{"204":1}}],["的全量用例",{"2":{"204":1}}],["的模板语法设计出的日志模板语法",{"2":{"192":1}}],["的模板匹配",{"2":{"133":1}}],["的方式",{"2":{"190":1,"192":1}}],["的方式持续在欧拉社区进行代码更新",{"2":{"12":1}}],["的日志系统",{"2":{"189":1}}],["的想法",{"2":{"189":1}}],["的键鼠操作模块主要有两个",{"2":{"181":1}}],["的报告都是基于在线的服务",{"2":{"179":1}}],["的执行管理器",{"2":{"155":1}}],["的文件",{"2":{"154":1}}],["的文字",{"2":{"53":1}}],["的距离",{"2":{"148":1}}],["的中心坐标为",{"2":{"147":1}}],["的左上角相对于应用窗口左上角",{"2":{"147":1}}],["的位置为",{"2":{"147":1}}],["的位置",{"2":{"147":1}}],["的元素定位采用这种",{"2":{"146":1}}],["的元素定位方案的数据源是应用库中的",{"2":{"148":1}}],["的元素定位方案",{"2":{"146":1,"242":1}}],["的元素定位方案在",{"2":{"25":1,"39":1}}],["的大致流程",{"2":{"276":2}}],["的大小",{"2":{"144":1,"147":1}}],["的大力支持",{"2":{"39":1}}],["的形式展示",{"2":{"141":1}}],["的项目介绍可以猛戳这里",{"2":{"140":1}}],["的环境",{"2":{"137":1}}],["的图像识别方案",{"0":{"135":1},"1":{"136":1,"137":1}}],["的图像识别功能几乎满足了你的所有要求",{"2":{"132":1}}],["的图像识别功能兼容两种情况",{"2":{"40":1}}],["的图标即返回其在大图中的坐标",{"2":{"133":1}}],["的坐标",{"2":{"131":1,"147":1,"192":2}}],["的步长为",{"2":{"127":1}}],["的解决方案",{"0":{"123":1}}],["的前",{"2":{"122":1}}],["的负载均衡方案不能满足业务需求",{"0":{"122":1}}],["的调用逻辑",{"2":{"118":1}}],["的专用断言语句",{"2":{"98":1}}],["的用例中标记了",{"2":{"208":1}}],["的用例",{"2":{"95":1,"204":1}}],["的用例数量",{"2":{"20":1}}],["的情况下",{"2":{"55":1}}],["的数量",{"2":{"54":1}}],["的目录发送到测试机",{"2":{"47":1}}],["的值",{"2":{"47":1,"50":1}}],["的参数直接传给远程机器的",{"2":{"43":1}}],["的三方源",{"2":{"42":1,"43":1}}],["的在线文档是部署在公司内网的",{"2":{"41":1}}],["的初始化工程命令",{"2":{"41":1}}],["的机器",{"2":{"40":1}}],["的",{"0":{"242":1},"2":{"31":1,"98":1,"122":1,"153":1,"191":1,"229":1,"267":1,"282":1,"283":1}}],["的正式域名为",{"2":{"22":1}}],["的断言语句",{"2":{"16":1}}],["的需求",{"2":{"15":1}}],["的另一个亮点",{"2":{"12":1}}],["的同学们能给我们反馈使用情况",{"2":{"12":1}}],["的问题",{"2":{"7":1,"12":1,"13":1,"38":2,"49":1,"53":1,"57":1,"271":1}}],["ohtm7l7g",{"2":{"236":2}}],["option",{"2":{"280":1}}],["opt",{"2":{"154":1}}],["operate",{"2":{"149":1}}],["open",{"2":{"137":2,"183":1,"222":1}}],["opencv服务端地址",{"2":{"229":1}}],["opencv",{"0":{"135":1},"1":{"136":1,"137":1},"2":{"40":4,"132":2,"133":4,"136":7,"137":10,"229":7}}],["openeuler",{"2":{"12":1,"13":3}}],["org",{"2":{"149":2,"175":1}}],["or",{"2":{"133":1,"144":1,"154":1,"158":2,"167":1,"168":2,"169":3,"175":3,"183":1,"203":1,"229":2,"252":2,"265":2,"280":2}}],["original",{"2":{"183":2}}],["origin",{"2":{"74":1}}],["out",{"2":{"93":1,"149":6,"154":2,"175":2,"183":7,"229":1}}],["onlyvisible",{"2":{"147":1,"149":4}}],["only",{"2":{"144":1,"149":1,"154":1,"175":1,"183":1,"203":1}}],["on",{"2":{"84":2,"85":1,"93":1,"94":1,"136":2,"149":1,"183":3}}],["obj就是应用的对象",{"2":{"142":1}}],["object",{"2":{"64":3,"149":3}}],["obj",{"2":{"64":2,"142":2,"143":2,"144":10}}],["other",{"2":{"49":1,"61":2,"70":2,"80":2,"99":2,"107":2,"248":2,"280":1}}],["oserror",{"2":{"137":1}}],["os",{"2":{"27":1,"175":12,"183":4,"203":8,"222":1}}],["offset",{"2":{"149":20}}],["of=",{"2":{"110":1}}],["of",{"2":{"15":1,"136":3,"154":3,"183":5}}],["ocr端口",{"2":{"229":1}}],["ocr服务端地址",{"2":{"229":1}}],["ocrutils",{"2":{"175":1}}],["ocr识别以外",{"2":{"242":1}}],["ocr识别的最大次数",{"2":{"229":1}}],["ocr识别的总超时",{"2":{"229":1}}],["ocr识别",{"0":{"116":1},"1":{"117":1,"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1}}],["ocrx",{"2":{"13":2,"124":4}}],["ocr",{"2":{"10":1,"13":10,"18":1,"30":1,"33":1,"34":2,"39":1,"40":1,"50":1,"52":2,"53":2,"117":3,"118":1,"119":13,"121":3,"122":1,"123":2,"124":8,"131":6,"175":10,"229":8,"280":1}}],["scan",{"2":{"229":1}}],["scroll为传入滚轮数",{"2":{"183":1}}],["scroll",{"2":{"183":6}}],["screenshotfullscreen",{"2":{"175":1}}],["screenshot",{"2":{"175":1}}],["screen",{"2":{"119":4,"133":8,"134":3,"136":2,"137":8,"175":13,"183":2,"229":2}}],["sys",{"2":{"183":5,"203":1,"226":1,"228":1,"229":1,"268":1}}],["systemctl",{"2":{"161":2,"255":2}}],["system",{"2":{"64":1,"183":1,"203":4,"222":1}}],["smoke",{"2":{"165":3,"168":1,"229":1,"280":1,"284":1}}],["small",{"2":{"136":12}}],["snippets",{"2":{"154":1}}],["sniff",{"0":{"141":1},"2":{"25":1,"34":1,"55":1,"84":3,"141":5,"142":1}}],["svn",{"2":{"154":1}}],["s",{"2":{"149":8,"161":1,"203":6,"222":1,"255":1}}],["some",{"2":{"248":6,"252":1}}],["somke",{"2":{"229":1}}],["so",{"2":{"184":1}}],["sort",{"2":{"149":2}}],["software",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["socketserver",{"2":{"119":1,"137":1}}],["sdata",{"2":{"136":2}}],["singer",{"2":{"222":2}}],["site",{"2":{"154":1}}],["sikuli",{"2":{"132":1}}],["simplexmlrpcserver",{"2":{"119":2,"137":2}}],["similarity=similarity",{"2":{"119":1,"175":2}}],["similarity=0",{"2":{"119":2,"175":2}}],["similarity",{"2":{"119":1,"175":2}}],["size=",{"2":{"175":1}}],["sizes",{"2":{"149":12}}],["size",{"2":{"53":3,"144":6,"149":3,"175":6,"183":2}}],["slave",{"2":{"213":4,"229":4}}],["slaves对象提供远程机器信息",{"0":{"213":1}}],["slaves",{"2":{"16":1,"94":2,"213":3,"217":2,"229":1,"252":2}}],["sleep",{"2":{"85":2,"133":1,"149":7,"175":5,"183":15}}],["stdout",{"2":{"183":6}}],["style",{"2":{"154":2}}],["strftime",{"2":{"226":1,"268":1}}],["str",{"2":{"133":3,"134":1,"137":2,"149":13,"175":6,"183":4,"199":1,"203":7}}],["strings",{"2":{"119":2,"154":1,"300":1}}],["string",{"2":{"75":2,"93":1,"142":1}}],["strip",{"2":{"74":1,"147":1,"149":7,"175":1}}],["str2",{"2":{"74":2}}],["staticmethod",{"2":{"136":3,"144":1,"175":20,"187":1,"222":1}}],["status=200",{"2":{"75":1}}],["status=status",{"2":{"75":1}}],["status",{"2":{"74":4,"75":1,"85":1,"175":2}}],["state",{"2":{"64":1,"65":3}}],["startswith",{"2":{"144":3,"191":1,"229":1}}],["start",{"2":{"144":1,"175":44,"183":12,"216":3,"217":2,"218":2,"229":1}}],["start=true",{"2":{"144":1}}],["startproject",{"2":{"38":1,"41":3,"68":1,"78":1,"88":1,"105":1,"114":1,"245":2,"246":3}}],["startapp",{"2":{"18":1,"19":2,"52":1,"53":2,"61":2,"70":2,"80":2,"99":2,"107":2,"248":2}}],["step",{"2":{"53":1,"192":1}}],["same",{"2":{"154":1}}],["safari",{"2":{"74":1}}],["save",{"2":{"53":4,"138":1,"175":3}}],["saifeilee",{"2":{"18":1}}],["space",{"2":{"154":1}}],["spaces",{"2":{"154":1}}],["spdx",{"2":{"144":2,"149":2,"175":2,"183":2,"203":2}}],["spi",{"2":{"141":1}}],["spur",{"2":{"74":4}}],["sphinx",{"2":{"52":1}}],["split",{"2":{"30":1,"74":4,"119":1,"147":2,"149":7,"175":2,"203":6}}],["sec",{"2":{"199":1}}],["section",{"2":{"148":3}}],["several",{"2":{"136":1}}],["serve",{"2":{"119":1,"137":1}}],["serverproxy",{"2":{"137":2}}],["server",{"2":{"74":4,"75":1,"119":5,"137":12,"179":1,"203":1,"229":4}}],["service",{"2":{"119":1,"137":1}}],["searchcutoffcount",{"2":{"144":1}}],["searcherror",{"2":{"144":7}}],["search",{"2":{"97":1,"98":1,"144":2,"147":1,"149":4,"300":2}}],["send2task",{"2":{"195":1}}],["send",{"2":{"93":3,"158":1,"161":1,"170":1,"171":1,"195":5,"196":1,"229":3,"252":1,"255":1}}],["selenium",{"2":{"185":5}}],["selected",{"2":{"136":1}}],["select",{"2":{"74":4,"154":1,"183":3}}],["self",{"2":{"53":5,"64":3,"65":2,"74":27,"75":9,"84":4,"85":3,"93":5,"94":1,"97":7,"98":3,"110":2,"111":2,"119":2,"143":10,"144":52,"147":3,"148":4,"149":99,"164":2,"174":3,"183":4,"184":2,"189":1,"192":1,"215":4,"216":4,"217":3,"218":2,"222":2,"265":5,"266":6,"282":1,"283":1,"294":2,"295":5,"296":5,"297":13}}],["setattr",{"2":{"190":1}}],["set",{"2":{"74":2,"136":1,"154":1}}],["setup",{"2":{"53":1,"57":1}}],["setting",{"0":{"225":1,"268":1},"1":{"226":1,"227":1,"228":1,"229":1},"2":{"15":1,"27":2,"34":2,"41":2,"47":1,"56":1,"68":1,"69":1,"78":1,"79":1,"88":1,"89":1,"98":1,"105":1,"106":1,"110":1,"114":1,"115":1,"133":1,"144":1,"149":1,"152":1,"153":1,"154":2,"156":2,"159":1,"161":1,"175":1,"183":1,"184":1,"203":2,"213":1,"226":1,"227":2,"228":1,"231":1,"247":1,"253":1,"255":1,"262":1}}],["sessionbus",{"2":{"149":1}}],["sessiontimeout",{"2":{"50":1}}],["session",{"2":{"50":1,"56":1,"93":1,"122":1}}],["ssh",{"2":{"49":1,"161":3,"255":3}}],["sw64",{"2":{"242":1}}],["sw",{"2":{"40":2}}],["skiped",{"2":{"202":1,"284":1}}],["skip",{"2":{"19":1,"20":1,"54":1,"154":1,"199":2,"201":1,"202":2,"203":8,"204":6,"205":1,"229":1,"284":2}}],["skipif",{"2":{"12":1,"20":2,"27":2,"39":4,"203":31}}],["submenu",{"2":{"183":1}}],["subset",{"2":{"154":1}}],["suit",{"2":{"171":1}}],["suite",{"2":{"158":2,"172":2,"229":1,"252":2}}],["supported",{"2":{"154":1}}],["super",{"2":{"97":1}}],["sudo",{"2":{"16":1,"41":5,"161":2,"203":4,"222":1,"245":4,"255":2}}],["summarize",{"2":{"11":4}}],["shift",{"2":{"183":3,"300":1,"302":1}}],["shehllyouqu",{"2":{"165":1}}],["shell命令",{"2":{"294":1}}],["shelloptional",{"2":{"252":1}}],["shellexport",{"2":{"245":1}}],["shell>>",{"2":{"192":1}}],["shell$",{"2":{"156":2,"157":1,"158":1,"159":1,"160":1,"161":4,"162":1,"231":1,"235":2,"237":1,"238":1,"245":1,"246":1,"247":3,"248":1,"251":1,"252":2,"254":1,"255":4,"256":1}}],["shellruff",{"2":{"152":2,"153":1}}],["shellbig",{"2":{"136":1}}],["shellbash",{"2":{"41":1}}],["shellsmall",{"2":{"136":1}}],["shellsudo",{"2":{"67":1,"77":1,"87":1,"104":1,"113":1}}],["shelltouch",{"2":{"100":1}}],["shellmikigo",{"2":{"84":1,"141":1}}],["shellmy",{"2":{"61":1,"68":1,"70":1,"78":1,"80":1,"88":1,"99":1,"105":1,"107":1,"114":1,"248":1}}],["shellautotest",{"2":{"71":1,"92":1,"100":1,"165":1,"233":2,"234":1,"292":1}}],["shellcd",{"2":{"69":1,"72":1,"79":1,"89":1,"101":1,"106":1,"115":1,"179":1}}],["shell用例收集数量",{"2":{"53":1}}],["shell~$",{"2":{"47":1}}],["shellpyyaml==6",{"2":{"233":1}}],["shellpython3",{"2":{"41":1,"47":1,"53":1,"204":1}}],["shellpip3",{"2":{"151":1,"245":1}}],["shellpdocr",{"2":{"45":1}}],["shellyouqu",{"2":{"34":1,"41":2,"51":1,"61":1,"68":1,"70":1,"78":1,"80":1,"88":1,"99":1,"105":1,"107":1,"114":1,"164":2,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"195":3,"196":1,"208":2,"210":1,"211":1,"213":1,"223":1,"262":1}}],["shell",{"2":{"12":1,"53":1,"177":1,"237":1,"273":1,"280":1}}],["show",{"2":{"158":1,"161":1,"252":1,"255":1}}],["shortcut",{"2":{"149":3,"181":4,"191":1,"229":1}}],["share",{"2":{"93":1,"175":12,"236":1}}],["sha512",{"2":{"74":2}}],["shyouqu",{"2":{"41":2,"210":1}}],["shsudo",{"2":{"41":1}}],["sh",{"0":{"72":1,"101":1,"230":1},"1":{"231":1,"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1},"2":{"12":1,"15":4,"16":1,"17":1,"18":1,"27":2,"29":1,"38":2,"41":2,"42":1,"43":2,"45":1,"46":1,"47":3,"49":2,"50":2,"53":4,"54":2,"57":1,"68":1,"69":2,"72":1,"78":1,"79":2,"88":1,"89":2,"101":1,"105":1,"106":2,"114":1,"115":2,"118":1,"184":1,"224":2,"231":3,"233":2,"234":1,"235":1,"247":3}}],["src",{"0":{"265":1},"2":{"12":1,"13":1,"15":1,"26":1,"34":1,"56":1,"59":2,"64":1,"68":1,"78":1,"84":5,"85":1,"88":1,"93":1,"97":1,"98":1,"105":1,"110":3,"114":1,"119":1,"124":1,"131":2,"143":1,"144":10,"147":1,"149":7,"174":2,"175":13,"181":7,"182":1,"183":7,"187":1,"192":2,"215":1,"216":1,"260":2,"262":1,"265":11,"266":4,"267":1,"294":6,"297":2}}],["cd",{"2":{"247":1}}],["cdn",{"2":{"38":1}}],["cfg",{"2":{"203":1}}],["cts",{"2":{"199":1}}],["ctrl",{"2":{"49":1,"181":3,"183":3,"216":2,"217":2,"218":1,"302":1}}],["cypress",{"2":{"185":2}}],["c0103",{"2":{"144":1}}],["c++",{"2":{"137":1}}],["create",{"2":{"74":1,"75":1,"110":1,"111":1}}],["cn",{"2":{"74":1}}],["csrf",{"2":{"74":5}}],["csv文件里面标记了",{"2":{"229":1}}],["csv文件里面标记了skip跳过的用例不生效",{"2":{"158":1,"252":1}}],["csv文件名称为music",{"2":{"211":1,"229":1}}],["csv文件格式",{"0":{"207":1}}],["csvctl",{"2":{"33":1,"208":2,"210":3,"229":1}}],["csv",{"0":{"210":1,"211":1},"2":{"16":1,"21":1,"27":1,"31":1,"34":3,"36":1,"52":1,"53":1,"57":1,"61":1,"70":1,"71":1,"80":1,"99":1,"100":1,"107":1,"155":2,"168":1,"200":9,"201":2,"202":1,"203":1,"204":2,"206":2,"207":1,"208":5,"210":6,"211":7,"229":8,"242":1,"248":1,"280":5,"284":9,"287":2,"292":1}}],["curl",{"2":{"53":1}}],["currently",{"2":{"154":1}}],["current",{"2":{"48":1,"68":1,"78":1,"88":1,"105":1,"114":1,"119":1,"137":1,"183":6}}],["custom",{"2":{"45":1,"144":2,"149":3,"175":5}}],["c",{"2":{"47":2,"49":1,"161":3,"162":1,"181":3,"183":10,"196":1,"255":2}}],["cv2",{"2":{"137":1}}],["cv",{"2":{"40":2,"133":1,"137":1}}],["cpu",{"2":{"39":3,"136":1,"203":7}}],["camera",{"2":{"280":1}}],["call",{"2":{"57":1}}],["case\\t",{"2":{"233":2,"234":1}}],["cases",{"2":{"229":1,"280":3}}],["caselib",{"2":{"211":1,"229":3}}],["case",{"2":{"33":1,"41":6,"53":1,"61":3,"65":5,"70":3,"71":3,"75":4,"80":3,"85":4,"92":2,"94":4,"98":4,"99":3,"100":3,"107":3,"111":5,"133":1,"158":5,"165":2,"167":1,"172":4,"174":2,"193":5,"208":3,"217":1,"229":13,"248":3,"252":5,"262":3,"292":2,"296":1,"297":1}}],["cache",{"2":{"27":1,"119":3,"154":3,"175":8,"229":1}}],["cicd",{"2":{"41":1,"199":3,"208":4}}],["ci",{"2":{"27":1,"47":1,"51":1,"53":2,"54":1,"55":1,"56":1,"158":1,"242":1,"252":1,"273":1,"276":1,"285":1}}],["chinese",{"2":{"183":3}}],["childrenlimit",{"2":{"144":1}}],["children",{"2":{"142":1,"144":5}}],["child",{"2":{"142":1,"143":1,"144":1}}],["ch",{"2":{"119":2,"175":2,"183":2}}],["chrome",{"2":{"74":1}}],["chromium",{"2":{"16":1,"98":1,"103":1}}],["checkpoints",{"2":{"154":1}}],["check",{"2":{"27":1,"74":1,"136":1,"144":2,"152":2,"183":3,"273":1}}],["clear",{"2":{"183":1}}],["clean",{"2":{"158":1,"229":3,"252":1}}],["close",{"2":{"137":2,"183":1}}],["clone",{"2":{"41":1,"229":1}}],["cls",{"2":{"133":1,"134":1,"136":1,"175":3,"183":64,"192":2}}],["cli",{"2":{"191":1,"229":1}}],["clients",{"2":{"161":3,"229":1,"255":3}}],["client",{"2":{"47":1,"119":1,"137":3,"161":3,"229":5,"255":3}}],["click",{"2":{"13":1,"84":4,"85":1,"93":2,"94":1,"97":2,"98":1,"124":3,"131":3,"142":1,"144":12,"148":2,"181":3,"183":18,"189":1,"192":1,"215":5,"222":4,"266":3,"282":1,"283":1,"295":5,"297":4}}],["classname",{"2":{"147":1,"149":4}}],["classmethod",{"2":{"136":1,"175":3,"183":33,"192":1}}],["class",{"2":{"17":1,"64":2,"65":2,"74":2,"75":2,"84":2,"85":2,"93":1,"94":1,"97":2,"98":2,"110":1,"111":2,"119":1,"137":1,"143":1,"144":1,"149":1,"164":1,"174":2,"175":1,"183":2,"187":1,"191":3,"192":2,"215":1,"216":1,"221":1,"222":2,"228":1,"229":3,"265":2,"266":2,"294":1,"295":1,"296":3,"297":4}}],["cmdtrl",{"2":{"262":1}}],["cmdwidget",{"2":{"110":1,"111":2}}],["cmd",{"2":{"16":1,"93":3,"110":4,"111":4,"144":1,"147":2,"149":12,"175":2,"183":3,"222":1}}],["cmdctl",{"2":{"16":1,"144":3,"147":2,"149":8,"175":6,"183":5,"265":3}}],["center",{"2":{"12":1,"13":1,"24":1,"30":1,"53":1,"124":1,"143":2,"144":4,"147":1,"148":2,"149":31,"175":1,"262":1,"265":2,"266":1,"295":1}}],["ccrazypeter",{"2":{"11":1,"12":1}}],["col",{"2":{"199":1}}],["color",{"2":{"175":6}}],["coffeescript",{"2":{"158":1,"161":1,"255":1}}],["core",{"2":{"277":1,"280":1,"284":2}}],["coredump",{"2":{"58":1}}],["corner",{"2":{"144":4}}],["co",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["coding",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["code是否为yes都会发送代码到测试机",{"2":{"161":1,"229":1,"255":1}}],["codes",{"2":{"154":1}}],["code=0",{"2":{"75":1}}],["code",{"2":{"15":1,"74":1,"154":6,"161":1,"229":1,"255":1}}],["coordinates",{"2":{"136":2}}],["cookie0",{"2":{"74":2}}],["cookie",{"2":{"74":8}}],["count=1",{"2":{"110":1}}],["count",{"2":{"51":1,"53":2,"175":2}}],["contain",{"2":{"191":1,"229":1}}],["container",{"2":{"177":2}}],["content=content",{"2":{"75":1}}],["content",{"2":{"74":4,"75":1}}],["control",{"2":{"61":1,"70":1,"71":1,"80":1,"99":1,"100":1,"107":1,"248":1}}],["connection",{"2":{"74":1}}],["conftest",{"0":{"267":1},"2":{"61":1,"68":1,"70":1,"71":1,"78":1,"80":1,"88":1,"99":1,"100":1,"105":1,"107":1,"114":1,"248":1,"262":2,"267":4,"292":1}}],["configparser",{"2":{"147":1,"149":5}}],["config",{"2":{"61":2,"70":2,"71":2,"74":5,"80":2,"98":2,"99":2,"100":2,"107":2,"144":6,"147":1,"149":13,"175":3,"184":1,"192":1,"213":1,"228":3,"229":10,"248":2,"262":3,"268":1,"280":1,"292":2,"302":1}}],["conf",{"0":{"225":1},"1":{"226":1,"227":1,"228":1,"229":1},"2":{"34":1,"110":2,"147":3,"149":13,"184":4,"227":3}}],["conduct",{"2":{"15":1}}],["copy",{"2":{"10":1,"183":1}}],["complexity",{"2":{"154":1}}],["compile",{"2":{"149":2}}],["comparing",{"2":{"136":1}}],["combovalue",{"2":{"144":1}}],["combostring",{"2":{"142":1}}],["com>",{"2":{"144":2,"149":2,"183":2}}],["comments",{"2":{"300":1}}],["common",{"2":{"174":1}}],["commonly",{"2":{"154":1}}],["comma",{"2":{"154":1}}],["commas",{"2":{"154":1}}],["command",{"2":{"27":1,"93":1,"149":6,"175":2}}],["commit",{"2":{"5":1,"7":2,"12":3,"17":2}}],["com",{"2":{"2":1,"22":1,"51":2,"54":2,"64":3,"93":2,"97":1,"98":2,"211":1,"229":5}}],["并在",{"2":{"280":1}}],["并通过",{"2":{"206":1}}],["并将测试数据和测试资源整合进来",{"2":{"280":1}}],["并将截取的右侧作为参数传递给该函数",{"2":{"203":1}}],["并将其部署为",{"2":{"137":1}}],["并将其转换为",{"2":{"30":1}}],["并对外提供唯一的接口",{"2":{"258":1}}],["并对测试结果做处理",{"2":{"196":1}}],["并对其进行定位操作",{"2":{"140":1}}],["并没有再补充其对应的命令行参数",{"2":{"156":1}}],["并且有串口线",{"2":{"272":1}}],["并且传递",{"2":{"265":1}}],["并且将执行的结果回填的测试用例的状态里面",{"2":{"194":1}}],["并且所有调用的方法会以",{"2":{"192":1}}],["并且迅速爱上他",{"2":{"146":1}}],["并且帮助我们改进",{"0":{"0":1},"1":{"1":1,"2":1,"3":1}}],["并返回编号最大的窗口id",{"2":{"149":1}}],["并返回用于鼠标和键盘操作的坐标",{"2":{"149":1}}],["并返回图片路径",{"2":{"138":1}}],["并返回新图片的路径",{"2":{"131":1}}],["并返回其在图片中的坐标",{"2":{"119":1}}],["并指定虚拟解释器",{"2":{"62":1,"81":1,"102":1,"108":1}}],["并提供可调用的配置对象config",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["并生成大量模板代码",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1}}],["并详细列出各个阶段的耗时",{"2":{"56":1}}],["并优化了进度获取的算法",{"2":{"54":1}}],["并优化了日志的排版",{"2":{"54":1}}],["并兼容不带文件后缀名入参方式",{"2":{"11":1,"12":1}}],["支持标签的逻辑组合",{"2":{"280":1}}],["支持标签反向同步",{"2":{"34":1}}],["支持多元化元素定位和断言",{"2":{"240":1}}],["支持多种数据回填模式",{"2":{"57":1}}],["支持同时生成",{"2":{"229":1}}],["支持自动同步脚本",{"2":{"210":1}}],["支持类名包含",{"2":{"191":1,"229":1}}],["支持类名以",{"2":{"191":2,"229":2}}],["支持and",{"2":{"158":2,"252":2}}],["支持指定屏幕区域截图并返回图片存放的本地路径",{"2":{"53":1}}],["支持使用系统命令",{"2":{"51":1}}],["支持动态传入参数",{"2":{"50":1}}],["支持动态传入重试次数",{"2":{"39":1}}],["支持通过位置参数传入文件路径",{"2":{"49":1}}],["支持不同",{"2":{"39":1}}],["支持统计分析仓库新增修复的用例或方法数量",{"2":{"18":1}}],["支持链式调用函数接口",{"2":{"124":1}}],["支持链式调用",{"2":{"13":1,"124":1}}],["支持",{"2":{"12":1,"39":1}}],["支持的驱动方式",{"2":{"12":1}}],["支持windows和macos",{"2":{"11":1}}],["支持将测试结果回传给测试平台",{"2":{"11":1}}],["插件生成的报告源数据",{"2":{"179":1}}],["插件库",{"2":{"61":1,"68":1,"70":1,"78":1,"80":1,"88":1,"99":1,"105":1,"107":1,"114":1,"248":1}}],["插件中实现了此功能",{"2":{"27":1}}],["插件",{"2":{"11":2,"12":1}}],["l4",{"2":{"199":1,"284":1}}],["l3",{"2":{"199":1,"284":1}}],["l2",{"2":{"199":1,"284":1}}],["l1",{"2":{"168":2,"199":2,"229":3,"284":2}}],["level",{"2":{"158":2,"191":1,"229":1,"252":2}}],["length",{"2":{"154":3}}],["len",{"2":{"149":2,"175":9,"183":2}}],["leftviewwidget",{"2":{"295":1,"296":1}}],["left",{"2":{"144":3,"148":3,"149":20,"292":2}}],["letmego",{"2":{"11":1,"36":1,"37":1,"220":2,"221":3,"222":2}}],["ltd",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["lastest",{"2":{"149":1}}],["lastfailed",{"2":{"56":1,"158":1,"252":1}}],["large",{"2":{"136":2}}],["lambda",{"2":{"119":1,"175":2,"192":1}}],["lang",{"2":{"119":3,"175":2}}],["lang=lang",{"2":{"119":1,"175":2}}],["lang=",{"2":{"119":2,"175":2}}],["language",{"2":{"74":1,"229":1}}],["loongarch64",{"2":{"242":1}}],["lower",{"2":{"175":1,"183":2}}],["load",{"2":{"136":3}}],["loads",{"2":{"74":1}}],["location",{"2":{"147":1,"148":2,"149":17,"158":2,"183":6,"252":2}}],["locateallonscreen",{"2":{"183":1}}],["locate",{"2":{"133":3,"183":1}}],["locatorassertions",{"2":{"187":1}}],["locator",{"2":{"97":2,"98":4,"187":4}}],["locals",{"2":{"144":1}}],["local",{"2":{"41":1,"236":1,"245":2}}],["lo",{"2":{"64":2}}],["log=true",{"2":{"183":1}}],["log=false",{"2":{"93":1,"149":6,"175":2,"183":5}}],["logdebugtofile",{"2":{"144":1}}],["logdebugtostdout",{"2":{"144":2}}],["logger",{"2":{"84":2,"144":12,"149":24,"175":18,"183":23,"189":1,"192":1}}],["logging",{"2":{"58":1}}],["login",{"2":{"74":8}}],["loguru",{"2":{"58":2}}],["log",{"2":{"54":1,"84":3,"158":2,"175":2,"177":2,"183":1,"190":1,"191":2,"192":5,"229":2,"252":2}}],["logs",{"2":{"54":1,"177":1}}],["logo",{"2":{"53":1,"178":1}}],["limit",{"2":{"154":1}}],["literal",{"2":{"154":1}}],["litaoa",{"2":{"144":1,"149":1,"183":1}}],["litao",{"2":{"144":1,"149":1,"183":1}}],["library",{"2":{"149":4}}],["libkf5waylandclient5",{"2":{"29":2}}],["libkf5wayland",{"2":{"28":1,"29":2}}],["lint",{"2":{"154":1}}],["line",{"2":{"154":5,"158":2,"183":1,"252":2}}],["link",{"2":{"93":2,"211":2,"229":1}}],["linux",{"0":{"66":1,"86":1},"1":{"67":1,"68":1,"69":1,"87":1,"88":1,"89":1},"2":{"74":1,"86":1,"112":1,"140":1,"240":1,"241":2}}],["linuxdeepin",{"2":{"2":1,"38":1}}],["like",{"2":{"74":1,"154":4}}],["license",{"2":{"64":5,"144":1,"149":1,"175":1,"183":1,"203":1}}],["list类型",{"2":{"74":1}}],["list",{"2":{"53":1,"133":2,"136":1,"137":1,"142":2,"144":2,"147":2,"148":1,"149":14,"175":6,"208":3,"229":3}}],["仓库中",{"2":{"248":1}}],["仓库代码到",{"2":{"18":1}}],["仓库代码",{"2":{"11":1}}],["仓库提交代码",{"0":{"3":1}}],["u9fff",{"2":{"183":1}}],["u4e00",{"2":{"183":1}}],["u",{"2":{"158":1,"170":1,"171":1,"195":1,"196":1,"211":1,"252":1}}],["ut00xxxx",{"2":{"211":1}}],["ut001234",{"2":{"170":1,"171":1,"195":1,"196":1,"229":1}}],["utf",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["utils",{"2":{"15":1,"50":1,"53":1,"64":1,"123":1,"143":1,"175":3,"192":1}}],["upper",{"2":{"144":4}}],["up",{"2":{"127":1,"183":5}}],["usages",{"2":{"282":1}}],["use",{"2":{"154":1}}],["used",{"2":{"149":2,"154":1}}],["user=",{"2":{"215":1,"216":1,"218":1}}],["usershare",{"2":{"175":2}}],["username=self",{"2":{"75":1}}],["username",{"2":{"74":6,"110":1,"226":1,"268":1}}],["user",{"2":{"11":1,"16":1,"74":1,"98":1,"158":3,"195":3,"211":1,"213":5,"229":13,"252":3}}],["usr",{"2":{"84":1,"93":1,"98":1,"144":1,"149":1,"175":1,"183":1,"203":1,"229":1,"265":1,"266":1,"294":1,"297":1}}],["udcpapi",{"2":{"75":4}}],["udcp",{"2":{"74":4,"75":4}}],["underscore",{"2":{"154":1}}],["unused",{"2":{"154":1}}],["unfixable",{"2":{"154":1}}],["unlike",{"2":{"154":1}}],["union",{"2":{"144":2,"175":3,"187":2}}],["uniontech",{"2":{"22":1,"51":2,"54":1,"144":3,"149":3,"175":1,"183":3,"203":1,"211":1,"229":3}}],["unknown",{"2":{"27":1}}],["uos",{"2":{"25":1,"47":6,"53":1,"54":1,"55":1,"56":1,"161":6,"162":2,"192":1,"196":2,"255":4}}],["uim",{"2":{"74":1}}],["ui自动化测试提供一个fixture对象",{"2":{"98":1,"229":1}}],["ui自动化测试提供一个",{"2":{"16":1}}],["ui",{"0":{"86":1,"103":1},"1":{"87":1,"88":1,"89":1,"104":1,"105":1,"106":1},"2":{"13":1,"16":1,"17":1,"22":1,"25":1,"39":1,"53":2,"61":1,"70":1,"80":1,"86":3,"98":3,"99":1,"100":2,"101":1,"103":2,"107":1,"128":1,"131":1,"132":1,"140":1,"146":2,"147":3,"148":8,"149":1,"178":1,"185":1,"186":1,"212":2,"222":5,"229":1,"234":1,"241":2,"242":1,"248":1,"262":4,"265":1,"266":2,"275":1,"280":1,"292":2,"295":4,"297":7}}],["urllib",{"2":{"76":1}}],["urllib3",{"2":{"74":2}}],["url",{"2":{"11":1,"74":7,"226":1,"229":1,"268":1,"280":1}}],["$nf",{"2":{"203":2}}],["$根节点",{"2":{"144":2}}],["$home",{"2":{"26":1,"41":1,"236":1,"245":2}}],["$",{"2":{"11":5,"69":1,"79":1,"89":1,"106":1,"115":1,"144":4,"154":1,"161":1,"175":1,"213":12,"229":24,"231":1,"247":1,"255":1}}],["pl",{"2":{"229":1}}],["plus",{"0":{"218":1},"2":{"218":2}}],["plc",{"2":{"211":1}}],["platform",{"2":{"203":11}}],["planned",{"2":{"154":1}}],["play",{"2":{"133":2}}],["playwright",{"2":{"16":2,"98":2,"103":2,"185":7}}],["plain",{"2":{"74":1}}],["ppl",{"2":{"199":2}}],["perf",{"2":{"199":1}}],["pexpect",{"2":{"40":1}}],["ps",{"2":{"144":1}}],["pxe",{"2":{"276":1,"280":3,"286":1}}],["px",{"2":{"129":1,"175":2}}],["png",{"2":{"119":2,"133":3,"175":6,"192":2,"229":1,"262":1}}],["po",{"2":{"248":1,"291":1}}],["polski",{"2":{"229":1}}],["pop",{"2":{"292":2}}],["popwidget",{"2":{"221":1,"222":1,"295":1,"296":1}}],["popen",{"2":{"119":1,"175":1,"183":1,"203":2}}],["position",{"2":{"144":8,"147":1,"149":38,"183":4}}],["post",{"2":{"74":2}}],["points",{"2":{"136":3}}],["point",{"2":{"136":2,"142":1,"144":1,"149":12}}],["port",{"2":{"119":2,"229":2}}],["pc",{"2":{"84":1,"141":1}}],["pwd",{"2":{"75":2}}],["photo",{"2":{"74":3}}],["photo=none",{"2":{"74":1}}],["phone",{"2":{"74":3}}],["phone=none",{"2":{"74":1}}],["pic",{"2":{"53":4,"61":1,"70":1,"80":1,"99":1,"107":1,"119":7,"133":1,"136":6,"149":5,"175":19,"192":1,"248":1,"262":1,"292":1}}],["picture",{"2":{"53":5,"119":6,"133":7,"137":2,"138":1,"175":20}}],["pip3",{"2":{"41":2,"67":1,"77":1,"87":1,"104":1,"113":1,"245":1}}],["pip",{"2":{"29":1,"41":3}}],["p2c",{"2":{"33":1,"210":1,"211":2}}],["puppeteer",{"2":{"185":2}}],["put",{"2":{"119":3,"137":6}}],["pubilic",{"2":{"46":1}}],["public",{"0":{"266":1},"2":{"26":1,"33":2,"46":1,"56":1,"144":1,"260":2,"262":5,"266":1,"280":1,"283":5,"296":1}}],["pull",{"2":{"1":1}}],["p",{"2":{"17":1,"69":2,"79":2,"89":2,"106":2,"115":2,"158":1,"161":1,"170":1,"171":1,"195":1,"196":1,"211":1,"231":2,"247":2,"252":1,"255":1}}],["pms回填的重试次数",{"2":{"229":1}}],["pms配置使用",{"2":{"229":1}}],["pms测试套的id",{"2":{"229":1}}],["pms测试套执行",{"2":{"229":1}}],["pms相关配置",{"2":{"229":1}}],["pms2csv",{"2":{"211":1}}],["pms的密码",{"2":{"211":1,"229":1}}],["pms的用户名",{"2":{"211":1,"229":1}}],["pms用例id",{"2":{"199":2}}],["pmsctl",{"2":{"195":1,"211":4,"229":2}}],["pms密码",{"2":{"195":3}}],["pms账号",{"2":{"195":3}}],["pms数据回填",{"0":{"194":1},"1":{"195":1,"196":1,"197":1},"2":{"229":1}}],["pms",{"0":{"211":1},"2":{"15":1,"16":1,"31":2,"32":2,"34":2,"36":1,"52":1,"54":1,"155":1,"158":13,"170":1,"171":1,"195":9,"196":2,"197":2,"199":2,"211":7,"229":10,"252":13,"284":3,"287":1}}],["primary",{"2":{"183":3}}],["print",{"2":{"93":1,"119":1,"203":3,"297":6}}],["printscreen",{"2":{"34":1}}],["prefixed",{"2":{"154":1}}],["predicate",{"2":{"144":3}}],["pre",{"2":{"136":3}}],["press",{"2":{"26":1,"182":2,"183":17}}],["prc",{"2":{"122":1}}],["product",{"2":{"203":4}}],["proportion",{"2":{"175":3}}],["properties",{"2":{"64":1}}],["property",{"2":{"64":1}}],["provided",{"2":{"154":1,"175":10}}],["proxy",{"2":{"149":2}}],["process",{"2":{"85":1,"175":4}}],["project$",{"2":{"84":1}}],["project",{"2":{"61":1,"68":2,"69":1,"70":1,"71":1,"72":1,"78":2,"79":1,"80":1,"88":2,"89":1,"92":1,"99":1,"100":1,"101":1,"105":2,"106":1,"107":1,"114":2,"115":1,"158":2,"246":1,"247":1,"248":1,"252":2}}],["pr",{"2":{"12":1,"16":1,"18":3,"182":1}}],["parallel",{"2":{"161":3,"162":2,"229":1,"255":3,"256":2}}],["param",{"2":{"74":11,"119":2,"131":1,"133":9,"134":5,"137":5,"138":4,"143":1,"144":10,"149":49,"175":60,"183":58,"192":2,"265":2}}],["pants",{"2":{"154":1}}],["package",{"2":{"149":1,"262":2}}],["packages",{"2":{"74":1,"154":1}}],["pause=pause",{"2":{"175":4}}],["pause",{"2":{"134":4,"149":6,"175":9,"183":1,"229":2}}],["paddle",{"2":{"119":3}}],["paddlepaddle",{"2":{"117":1}}],["paddleocr目前支持的多语言语种可以通过修改lang参数进行切换",{"2":{"119":1}}],["paddleocr",{"2":{"117":1,"119":2}}],["pass",{"2":{"53":1,"119":2,"137":1,"175":6,"184":2,"222":1,"228":1,"266":1,"297":1}}],["password一样",{"2":{"229":1}}],["password2",{"2":{"213":1}}],["password1",{"2":{"213":2}}],["password的值",{"2":{"161":1,"255":1}}],["password=self",{"2":{"75":1}}],["password=spur",{"2":{"74":2}}],["password=",{"2":{"74":1,"215":1,"216":1,"218":1}}],["password=password",{"2":{"74":1}}],["password",{"2":{"11":1,"16":1,"47":3,"69":2,"74":14,"79":2,"89":2,"106":2,"115":2,"158":3,"161":4,"170":1,"171":1,"195":4,"196":1,"203":2,"211":2,"213":3,"227":2,"229":10,"231":2,"247":2,"252":3,"255":4}}],["pattern",{"2":{"149":5,"280":1}}],["path=$path",{"2":{"245":1}}],["path=none",{"2":{"136":1}}],["path=",{"2":{"74":1,"175":1}}],["path",{"2":{"41":1,"53":4,"64":3,"98":1,"119":1,"133":4,"134":2,"137":7,"147":1,"149":11,"158":2,"175":18,"183":3,"192":1,"229":5,"245":1,"252":2}}],["patch",{"2":{"12":1}}],["pageassertions",{"2":{"187":1}}],["pages",{"2":{"41":1}}],["page",{"2":{"16":2,"17":1,"97":7,"98":12,"100":5,"103":2,"187":1,"229":7}}],["pdocr",{"2":{"11":2,"30":1,"120":1,"123":1}}],["pyaudio",{"2":{"233":1}}],["pyautogui",{"2":{"46":1,"180":2,"183":38,"184":1}}],["py文件名称",{"2":{"229":1}}],["pyfrom",{"2":{"227":2}}],["pyflakes",{"2":{"154":1}}],["pyid2csv",{"2":{"210":1}}],["pyscreenshot",{"2":{"175":2}}],["py37",{"2":{"154":1}}],["pypackages",{"2":{"154":1}}],["pypinyin",{"2":{"50":1}}],["pypi",{"2":{"41":2,"44":1,"245":1}}],["pyenv",{"2":{"154":1}}],["pyconf",{"2":{"227":1}}],["pycodestyle",{"2":{"154":2}}],["pycharm",{"2":{"62":1,"81":1,"102":1,"108":1,"179":1,"300":3}}],["pycreeze",{"2":{"46":2}}],["py新增参数",{"2":{"56":1}}],["pytype",{"2":{"154":1}}],["pytest",{"2":{"53":1,"61":1,"68":3,"70":1,"78":3,"80":1,"88":3,"99":1,"105":3,"107":1,"114":3,"154":1,"168":2,"201":1,"206":2,"229":2,"248":1,"262":4,"267":2,"292":1}}],["pythonby",{"2":{"295":1}}],["pythonimport",{"2":{"221":1}}],["pythonif",{"2":{"184":1}}],["pythondfmwidget",{"2":{"192":1}}],["pythondef",{"2":{"53":2,"131":1,"133":2,"134":1,"138":1,"148":1}}],["pythonclick",{"2":{"295":1}}],["pythonclass",{"2":{"84":1,"136":1,"174":1,"189":1,"215":1,"216":1,"217":2,"218":1,"282":1,"283":1,"296":1,"297":1}}],["pythonconfig",{"2":{"228":1}}],["pythonconf",{"2":{"147":1}}],["pythonapp",{"2":{"147":1}}],["pythonelement",{"2":{"142":8}}],["pythonself",{"2":{"98":1,"143":1,"295":1}}],["python最强代码扫描工具",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["python3",{"2":{"41":1,"47":2,"53":1,"144":1,"149":1,"161":1,"175":1,"179":1,"183":1,"203":1,"233":1,"235":2,"255":1}}],["python",{"2":{"17":1,"18":2,"20":1,"26":1,"27":1,"41":4,"42":1,"43":1,"45":1,"51":1,"53":3,"64":1,"65":2,"74":2,"75":2,"84":2,"85":2,"93":1,"94":1,"98":2,"110":1,"111":2,"119":2,"137":2,"143":1,"144":1,"149":1,"150":1,"154":1,"164":1,"174":2,"175":1,"183":1,"185":2,"187":1,"192":2,"203":1,"215":1,"222":2,"233":2,"248":1,"265":1,"280":1,"282":1,"283":1}}],["pythonfrom",{"2":{"13":1,"34":2,"64":1,"97":2,"119":2,"124":1,"131":1,"137":2,"142":1,"181":3,"182":1,"184":1,"216":1,"228":1,"265":1,"266":1,"294":1,"295":1,"296":3,"297":4}}],["pyyaml",{"2":{"43":1}}],["pylint",{"2":{"15":3,"49":4,"50":1,"144":2,"149":2,"183":1,"273":1}}],["py",{"0":{"155":1,"267":1,"294":1},"1":{"156":1,"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1},"2":{"11":1,"13":1,"15":1,"18":1,"26":1,"27":2,"31":1,"33":2,"34":2,"36":1,"41":4,"47":2,"49":1,"50":2,"51":1,"53":4,"54":1,"55":1,"56":1,"61":13,"64":3,"65":4,"68":2,"70":13,"71":11,"74":4,"75":4,"78":2,"80":13,"84":4,"85":4,"88":2,"92":4,"93":2,"94":2,"97":2,"98":4,"99":13,"100":11,"105":2,"107":13,"110":2,"111":4,"114":2,"131":1,"143":1,"147":1,"154":1,"155":1,"156":4,"157":1,"158":2,"159":2,"160":1,"161":4,"162":1,"164":4,"165":5,"166":1,"167":3,"168":1,"169":1,"170":1,"171":1,"172":5,"174":3,"187":1,"192":2,"193":1,"195":3,"196":1,"200":2,"203":2,"204":1,"208":2,"210":4,"211":2,"213":1,"215":1,"223":1,"226":2,"229":2,"235":1,"248":13,"250":1,"251":1,"252":2,"253":1,"254":1,"255":4,"256":1,"262":20,"265":2,"266":3,"267":4,"268":1,"280":2,"282":1,"283":1,"292":11,"300":1,"302":1}}],["rdog",{"0":{"215":1},"2":{"215":4}}],["rgx",{"2":{"154":1}}],["rgb",{"2":{"136":3}}],["r",{"2":{"144":1,"149":6,"215":2,"216":2,"218":2,"302":1}}],["round",{"2":{"175":1}}],["root",{"2":{"142":2,"143":1,"144":5,"213":3,"215":1,"216":1,"218":1,"246":1}}],["role",{"2":{"74":1}}],["roleids",{"2":{"74":2}}],["roleids=",{"2":{"74":1}}],["rb",{"2":{"137":8}}],["rightviewwidget",{"2":{"295":1,"296":1,"297":3}}],["rightclick",{"2":{"183":1}}],["right",{"2":{"124":1,"131":1,"144":3,"148":2,"149":29,"183":4,"292":2,"295":1,"297":2}}],["rctl",{"0":{"216":1,"217":1,"218":1},"1":{"217":1},"2":{"93":1,"216":3,"218":3}}],["rar",{"2":{"175":1}}],["rather",{"2":{"154":1}}],["rate=rate",{"2":{"175":2}}],["rate=0",{"2":{"136":1,"192":1}}],["rate",{"2":{"23":1,"24":2,"25":1,"133":9,"134":2,"136":2,"137":3,"175":7,"192":1,"229":1}}],["range",{"2":{"133":1,"134":2,"149":2,"183":3}}],["randomly",{"2":{"136":2}}],["random",{"2":{"75":2,"136":4}}],["raise",{"2":{"119":2,"133":2,"137":1,"144":6,"149":13,"175":41,"265":1}}],["ru",{"2":{"229":1}}],["rules",{"2":{"154":1}}],["ruff",{"0":{"150":1},"1":{"151":1,"152":1,"153":1,"154":1},"2":{"15":1,"20":1,"68":2,"78":2,"88":2,"105":2,"114":2,"150":1,"151":1,"153":1,"154":5}}],["ruff代码检查",{"2":{"14":1}}],["run",{"2":{"11":1,"16":1,"34":2,"41":4,"43":1,"47":3,"51":1,"53":1,"93":1,"110":1,"144":1,"147":2,"149":6,"156":2,"157":2,"158":2,"159":1,"164":2,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"175":2,"183":3,"195":2,"204":1,"213":1,"223":1,"229":2,"235":1,"251":1,"252":2}}],["rm",{"2":{"12":2,"238":1}}],["references",{"2":{"300":1}}],["refactor",{"2":{"300":3}}],["rename",{"2":{"300":1}}],["reboot",{"2":{"222":5}}],["reverse",{"2":{"183":1}}],["reversed",{"2":{"183":1}}],["relative",{"2":{"183":1}}],["rel",{"2":{"183":13}}],["release",{"2":{"41":1,"59":1}}],["really",{"2":{"175":3}}],["real",{"2":{"175":5}}],["read",{"2":{"119":1,"137":2,"147":1,"149":4,"175":1,"203":2}}],["readme",{"2":{"57":1,"61":3,"70":3,"71":2,"80":3,"92":1,"99":3,"100":2,"107":3,"248":3}}],["rewrite",{"2":{"154":1}}],["recovery",{"2":{"222":1}}],["record",{"2":{"41":6,"158":2,"177":1,"193":6,"229":5,"252":2}}],["recur",{"2":{"144":3}}],["recursive=false",{"2":{"144":1,"175":2}}],["recursive=true",{"2":{"144":1}}],["recursive=recursive",{"2":{"144":1}}],["recursive",{"2":{"144":1,"175":4}}],["re",{"2":{"144":2,"149":15}}],["register",{"2":{"119":2,"137":2}}],["repeat",{"2":{"158":2,"183":1,"229":1,"252":2}}],["replace",{"2":{"144":1,"203":2}}],["reply",{"2":{"93":1}}],["report",{"2":{"11":8,"54":1,"158":2,"161":2,"177":2,"179":4,"193":1,"196":1,"197":2,"210":1,"211":2,"229":17,"252":2,"255":2}}],["removed",{"2":{"199":2,"205":2}}],["remotewidget",{"2":{"93":1,"94":2,"215":3,"216":3,"217":2,"218":2}}],["remotectl",{"2":{"93":1,"215":1,"216":1}}],["remote",{"0":{"215":1,"216":1,"218":1},"1":{"217":1},"2":{"11":5,"41":1,"43":1,"47":4,"49":1,"92":1,"93":6,"94":3,"160":2,"161":5,"162":1,"196":1,"215":6,"216":5,"217":3,"218":3,"229":2,"254":2,"255":5,"256":1}}],["remark",{"2":{"74":3}}],["remark=none",{"2":{"74":1}}],["ret",{"2":{"74":6}}],["returned",{"2":{"136":1}}],["return",{"2":{"64":2,"74":5,"119":7,"131":1,"133":2,"137":1,"138":1,"143":4,"144":25,"147":1,"149":61,"175":9,"183":37,"187":1,"192":2,"203":11}}],["retry=network",{"2":{"175":4}}],["retry=false",{"2":{"143":1,"144":1}}],["retry",{"2":{"27":1,"149":5,"175":10,"229":3}}],["requestdock",{"2":{"93":1}}],["requestx",{"2":{"76":1}}],["requests",{"2":{"1":1,"74":5,"76":1,"233":1}}],["requirement",{"2":{"43":1,"53":1,"233":7}}],["rerun",{"2":{"41":2,"158":2,"193":2,"229":4,"252":2}}],["res这个目录下生成一张临时的图",{"2":{"175":1}}],["restart",{"2":{"161":1,"255":1}}],["restructuredtext",{"2":{"154":1}}],["respect",{"2":{"154":1}}],["response",{"2":{"75":1}}],["res",{"2":{"61":3,"70":3,"71":2,"80":3,"92":1,"99":3,"100":2,"107":3,"119":8,"133":2,"175":21,"192":1,"248":3,"262":5,"280":1,"292":3}}],["resolution",{"2":{"41":4,"158":2,"175":9,"229":1,"252":2}}],["result",{"2":{"27":1,"53":1,"144":7,"149":7,"175":4,"177":1}}],["rpc服务器链接失败",{"2":{"137":1}}],["rpc服务端部署",{"0":{"120":1}}],["rpc",{"0":{"137":1},"2":{"10":1,"11":2,"30":1,"45":1,"51":1,"118":5,"120":1,"122":2,"123":1,"137":6,"212":2,"219":1}}],["修改为失败之后会关闭文件选择框",{"2":{"59":1}}],["修改为",{"2":{"59":1,"71":1,"100":1}}],["修改失败用例回溯日志为详细级别",{"2":{"54":1}}],["修改工程名称为",{"2":{"52":1}}],["修改",{"0":{"71":1,"100":1},"2":{"10":1,"12":1,"14":1,"26":1,"48":1}}],["修复的这些用例可能还不稳定",{"2":{"204":1}}],["修复后的这些用例在本地调试的时候我们不希望继续跳过",{"2":{"204":1}}],["修复持续集成流水线中没有安装",{"2":{"55":1}}],["修复自动生成",{"2":{"53":1}}],["修复单独运行方法时无日志输出的",{"2":{"51":1}}],["修复youqu",{"2":{"49":1}}],["修复运行时程序退出",{"2":{"49":1}}],["修复1060",{"2":{"47":1}}],["修复子项目",{"2":{"40":1}}],["修复子项目单独需要三方包",{"2":{"40":1}}],["修复了第一次失败不会关闭文件选择框的问题",{"2":{"58":1}}],["修复了三方库",{"2":{"58":1}}],["修复了用例收集阶段报错看不到详细信息的问题",{"2":{"57":1}}],["修复了部分机器上",{"2":{"57":1}}],["修复了同一应用内多个",{"2":{"57":1}}],["修复了在没有指定应用名称执行时",{"2":{"56":1}}],["修复了执行进度未计算跳过用例的问题",{"2":{"54":1}}],["修复了一些",{"2":{"50":1}}],["修复了wayland下偶现找不到",{"2":{"42":1}}],["修复了特殊场景下",{"2":{"38":1}}],["修复了远程执行传入",{"2":{"35":1}}],["修复了",{"2":{"34":1,"36":1,"38":2,"44":1,"52":1,"54":1,"56":1,"57":2}}],["修复了键盘",{"2":{"34":1}}],["修复了不同的",{"2":{"33":1}}],["修复无法导出",{"2":{"34":1}}],["修复无法连续多次调用对远程终端的键鼠操作",{"2":{"15":1}}],["修复反向同步标签",{"2":{"32":1}}],["修复更新太耗时",{"2":{"31":1}}],["修复某些机型下",{"2":{"31":1}}],["修复同一个用例",{"2":{"31":1}}],["修复在低版本系统上安装的",{"2":{"28":1,"29":1}}],["修复用例收集阶段报错",{"2":{"54":1}}],["修复用例收集数量为",{"2":{"27":1}}],["修复用例在",{"2":{"53":1}}],["修复用例失败截图添加到测试报告时报错的问题",{"2":{"8":1}}],["修复通过标签批量执行时",{"2":{"26":1}}],["修复偶现测试报告生成阶段报错",{"2":{"25":1}}],["修复域管环境下",{"2":{"17":1}}],["修复基于",{"2":{"17":1}}],["修复从",{"2":{"16":1,"34":1}}],["修复实例化远程类时",{"2":{"16":1}}],["修复使用远程执行命令时",{"2":{"16":1}}],["修复生成测试报告阶段",{"2":{"14":1}}],["修复远程执行数据回填过程中报",{"2":{"25":1}}],["修复远程调用报错后",{"2":{"16":1}}],["修复远程调用返回",{"2":{"15":1}}],["修复远程调用时",{"2":{"13":1}}],["修复远程交互控制测试机注销后",{"2":{"10":1}}],["修复内网文档不能加载",{"2":{"13":1}}],["修复统计用例和方法数量功能在子项目为",{"2":{"17":1}}],["修复统计",{"2":{"12":2}}],["修复服务器系统获取显示协议错误的问题",{"2":{"11":1}}],["修复测试单驱动执行报错的问题",{"2":{"11":1}}],["修复测试单驱动收集用例数量为",{"2":{"7":1}}],["修复",{"2":{"6":1,"7":1,"12":2,"13":1,"16":1,"18":2,"19":2,"20":2,"21":1,"24":1,"25":2,"27":2,"32":1,"33":1,"34":1,"40":1,"41":1,"42":1,"45":1,"46":2,"47":1,"49":1,"51":2,"52":2,"53":1,"54":1}}],["范围识别",{"2":{"10":1}}],["3个remote远程对象",{"0":{"214":1},"1":{"215":1,"216":1,"217":1,"218":1}}],["3s",{"2":{"183":1}}],["3>right",{"2":{"144":1}}],["36",{"2":{"74":2}}],["3小时18分0秒",{"2":{"53":1}}],["300",{"2":{"183":1,"229":2}}],["30",{"0":{"52":1},"2":{"134":2,"273":1}}],["30+",{"2":{"40":1}}],["31",{"0":{"38":1}}],["37",{"2":{"20":1,"175":3}}],["3840x1080",{"2":{"229":1}}],["38",{"2":{"20":1}}],["3",{"0":{"10":1,"16":1,"26":1,"27":1,"28":1,"29":1,"30":2,"31":1,"32":1,"33":1,"35":1,"42":1,"49":1,"54":1,"129":1,"254":1,"255":1,"256":1,"262":1,"266":1,"277":1,"284":1,"296":1,"301":1},"1":{"255":1,"256":1},"2":{"16":1,"41":1,"45":1,"122":2,"127":2,"133":1,"136":1,"142":1,"144":3,"149":3,"154":1,"183":7,"195":1,"222":1,"229":2,"271":1,"282":1,"284":5,"285":1,"287":1,"291":1,"301":4}}],["下划线",{"2":{"248":1}}],["下发布",{"2":{"243":1}}],["下线cd",{"2":{"229":1}}],["下同",{"2":{"195":1,"211":1}}],["下都可以跑",{"2":{"184":1}}],["下有些应用的界面显示和功能本身存在一些差异",{"2":{"184":1}}],["下执行时会安装自研的键鼠操作服务",{"2":{"184":1}}],["下兼容适配",{"2":{"184":1}}],["下的键鼠操作方法无法使用",{"2":{"184":1}}],["下自动化主要问题是",{"2":{"184":1}}],["下面的远程执行功能同样支持",{"2":{"158":1}}],["下面介绍两个常用的用例执行的功能",{"2":{"156":1}}],["下个迭代可能就是",{"2":{"127":1}}],["下使用",{"2":{"57":1}}],["下获取窗口信息的方法",{"2":{"39":1}}],["下获取窗口信息功能模块中环境变量的问题",{"2":{"38":1}}],["下系统监视器使用",{"2":{"27":1}}],["下输入的方法区分中英文",{"2":{"26":1}}],["下",{"2":{"25":1,"47":1,"175":1,"183":1,"245":1}}],["下表现一致",{"2":{"25":1}}],["下表现和",{"2":{"25":1}}],["下窗管团队提供了新的接口",{"2":{"25":1}}],["下窗管返回的应用名称错误的问题",{"2":{"7":1}}],["下窗管返回的",{"2":{"6":1}}],["下报错",{"2":{"21":1}}],["下中文写入剪贴版问题",{"2":{"10":1}}],["下相对位移定位方案报错",{"2":{"9":1}}],["495",{"2":{"229":2}}],["47",{"2":{"192":1}}],["48",{"2":{"192":1}}],["4eea",{"2":{"177":1}}],["4103",{"2":{"74":1}}],["44aa",{"2":{"177":1}}],["44",{"2":{"19":1}}],["43",{"2":{"19":1}}],["400",{"2":{"149":1,"175":3}}],["40",{"2":{"18":1,"175":6,"273":1}}],["46",{"2":{"18":1}}],["4",{"0":{"9":1,"15":1,"20":1,"21":1,"22":2,"23":1,"24":1,"25":1,"29":1,"34":1,"48":1,"53":1,"130":1,"267":1,"285":1,"297":1,"302":1},"2":{"34":1,"41":1,"52":2,"126":1,"127":1,"133":1,"136":1,"154":1,"183":4,"271":1,"284":1,"285":3,"287":9,"302":2}}],["1>left",{"2":{"144":1}}],["1s",{"2":{"136":1}}],["1m",{"2":{"110":1,"111":1}}],["180",{"2":{"148":1}}],["18",{"0":{"40":1},"2":{"27":1}}],["168",{"2":{"213":4,"218":1,"229":2}}],["16",{"0":{"34":1,"41":1,"47":1,"57":1},"2":{"27":1,"273":1}}],["13",{"0":{"27":1,"36":1},"2":{"47":6,"161":6,"162":2,"196":2,"229":4,"255":4,"287":1}}],["175",{"2":{"229":1}}],["17",{"2":{"26":1,"30":1,"192":1,"287":1}}],["127",{"2":{"179":1}}],["120",{"2":{"175":1}}],["12",{"0":{"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"52":1,"53":1,"59":1},"2":{"229":1,"273":1,"287":3}}],["196",{"2":{"215":1,"216":1}}],["192",{"2":{"213":4,"215":1,"216":1,"218":1,"229":2}}],["1920",{"2":{"149":3,"175":2}}],["1920x1080",{"2":{"41":3,"229":2}}],["19",{"0":{"22":1,"56":1},"2":{"27":1}}],["1060",{"2":{"203":2}}],["1081333",{"2":{"177":1}}],["1080x1920",{"2":{"229":1}}],["1080",{"2":{"149":3}}],["100",{"2":{"154":1,"175":1,"229":4}}],["10000",{"2":{"134":1}}],["1000",{"2":{"26":1,"144":1}}],["1070",{"2":{"21":1,"22":1,"25":1}}],["10",{"0":{"14":1,"33":1,"34":1,"42":1,"54":1},"2":{"47":6,"51":2,"56":1,"136":1,"161":6,"162":3,"177":2,"196":2,"229":5,"255":4,"256":1,"287":1}}],["14",{"0":{"13":1,"18":1,"31":1,"53":1}}],["1",{"0":{"12":1,"18":1,"24":1,"32":1,"36":1,"38":1,"39":1,"40":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":2,"52":1,"53":2,"54":2,"55":2,"56":3,"57":2,"58":1,"59":2,"127":1,"136":1,"158":1,"161":1,"202":1,"233":1,"250":1,"252":1,"255":1,"260":1,"264":1,"275":1,"279":1,"282":1,"291":1,"294":1,"299":1},"2":{"40":1,"41":6,"45":5,"46":2,"47":2,"52":5,"56":1,"61":1,"65":1,"69":1,"70":1,"74":5,"75":1,"79":1,"80":1,"89":1,"98":1,"99":1,"106":1,"107":1,"110":1,"111":1,"115":1,"119":1,"122":1,"127":1,"133":4,"134":1,"136":4,"142":2,"144":8,"149":36,"161":1,"162":2,"164":2,"175":10,"179":1,"183":20,"193":5,"195":1,"213":5,"215":2,"216":2,"218":2,"222":2,"226":1,"229":19,"231":1,"247":1,"248":1,"255":1,"256":2,"265":2,"268":1,"271":2,"272":1,"282":5,"283":1,"284":1,"285":1,"286":1,"287":1,"294":1,"297":3,"299":3,"300":1,"301":1,"302":1}}],["1111",{"2":{"74":1}}],["116",{"2":{"74":1}}],["11",{"0":{"8":1,"30":1,"31":1,"32":1},"2":{"30":2,"177":3,"213":1,"229":2,"287":7}}],["15时14分09秒",{"2":{"177":1}}],["15",{"0":{"5":1,"6":1,"26":1,"35":1}}],["500",{"2":{"229":1}}],["50",{"2":{"229":1}}],["540",{"2":{"149":3}}],["5s",{"2":{"136":1}}],["537",{"2":{"74":2}}],["53",{"2":{"46":1,"211":1}}],["59",{"2":{"27":1}}],["55",{"2":{"18":2,"229":1}}],["51",{"2":{"18":1}}],["5",{"0":{"8":1,"14":2,"15":1,"16":1,"17":1,"18":1,"19":1,"21":1,"28":1,"38":1,"47":1,"268":1,"286":1,"303":1},"2":{"41":1,"74":1,"127":1,"133":1,"136":1,"162":1,"175":1,"229":3,"256":1,"286":2,"287":15}}],["0s",{"2":{"53":1}}],["005",{"2":{"111":2}}],["003",{"2":{"94":4,"172":1,"217":2}}],["003307",{"2":{"11":1}}],["004",{"2":{"65":3,"75":2,"111":1,"172":1}}],["002",{"2":{"61":1,"70":1,"71":1,"80":1,"92":1,"99":1,"100":1,"107":1,"165":1,"172":1,"248":1,"297":1}}],["001",{"2":{"51":1,"53":1,"61":1,"70":1,"71":1,"75":1,"80":1,"85":3,"92":1,"98":5,"99":1,"100":1,"107":1,"133":1,"164":5,"165":1,"167":2,"172":2,"174":2,"192":2,"203":1,"229":5,"248":1,"284":2,"292":1,"296":1}}],["09",{"0":{"35":1,"36":1,"37":1,"44":1,"55":1,"56":1,"57":1},"2":{"177":1}}],["01",{"0":{"21":1,"22":1,"51":1}}],["021",{"2":{"119":1}}],["02",{"0":{"20":1,"48":1,"49":1,"50":1},"2":{"192":1}}],["03分20秒",{"2":{"53":1}}],["03",{"0":{"17":1,"18":1,"19":1},"2":{"134":1,"183":3}}],["04",{"0":{"16":1,"19":1,"28":1,"29":1}}],["08",{"0":{"15":1,"32":1,"38":1,"39":1,"40":1,"41":1,"45":1,"50":1,"58":1,"59":1}}],["06",{"0":{"8":1,"9":1,"10":1,"43":1,"44":1,"45":1,"46":1,"51":1}}],["0",{"0":{"13":1,"19":1,"25":1,"33":1,"37":1,"40":1,"41":2,"42":1,"52":1,"57":1,"58":1,"59":1},"2":{"7":1,"16":1,"23":2,"27":1,"40":1,"41":6,"45":1,"46":3,"52":1,"74":3,"93":1,"94":1,"119":1,"133":1,"134":1,"136":9,"142":1,"144":4,"147":4,"149":22,"175":7,"179":2,"183":10,"192":1,"193":1,"203":3,"217":1,"229":3,"233":1,"243":1}}],["05",{"0":{"7":1,"11":1,"12":1,"13":1,"14":1,"15":1,"37":1,"47":1}}],["07",{"0":{"5":1,"6":1,"7":1,"9":1,"10":1,"42":1,"46":1}}],["icon",{"2":{"222":2}}],["ignore",{"2":{"154":2,"222":1,"229":1}}],["ignored",{"2":{"154":1}}],["iso",{"2":{"276":1}}],["isinstance",{"2":{"119":2,"144":1,"149":10,"175":5,"265":1}}],["is",{"2":{"119":3,"133":1,"136":1,"149":10,"154":4,"175":34,"183":3,"184":4,"265":2}}],["issues",{"0":{"2":1},"2":{"2":2,"15":1,"18":2,"19":2,"20":2,"25":6,"26":1,"27":4,"182":1}}],["i",{"2":{"119":1,"144":6,"147":2,"149":14}}],["ifixed",{"2":{"158":1,"204":3,"229":1,"252":1}}],["if=",{"2":{"110":1}}],["if",{"2":{"74":1,"119":6,"133":2,"137":1,"144":20,"147":1,"149":43,"175":68,"183":19,"184":2,"203":5,"215":1,"216":1,"218":1,"265":3}}],["items",{"2":{"74":1,"119":1,"141":1,"175":2}}],["it",{"2":{"54":1,"154":1}}],["id同步到csv文件",{"2":{"210":1,"229":1}}],["id4",{"2":{"169":1}}],["id3",{"2":{"169":1}}],["id2",{"2":{"169":1}}],["id1",{"2":{"169":1}}],["idea",{"2":{"154":1}}],["identifier",{"2":{"144":1,"149":1,"175":1,"183":1,"203":1}}],["ids",{"2":{"74":4}}],["ids=none",{"2":{"74":1}}],["id=1",{"2":{"74":1}}],["id",{"0":{"210":1},"2":{"30":2,"36":1,"65":1,"74":3,"75":1,"85":1,"98":1,"111":1,"147":8,"149":35,"158":4,"170":1,"171":1,"195":4,"196":1,"199":4,"200":1,"210":6,"229":3,"252":4,"284":1}}],["ing",{"2":{"161":1,"255":1}}],["indent",{"2":{"154":3}}],["indexerror",{"2":{"144":2,"149":2}}],["index",{"2":{"144":6,"177":1,"179":2}}],["index=0",{"2":{"144":3}}],["in",{"2":{"74":1,"119":1,"133":2,"136":2,"144":2,"147":2,"148":1,"149":15,"154":3,"175":8,"183":7,"203":4,"222":5,"295":1,"296":3,"300":1}}],["inspect",{"2":{"190":1}}],["insert",{"2":{"183":1}}],["insecurerequestwarning",{"2":{"74":2}}],["install",{"2":{"41":1,"67":1,"77":1,"87":1,"104":1,"113":1,"151":1,"245":2}}],["interval=interval",{"2":{"183":5}}],["interval=0",{"2":{"183":4}}],["interval",{"2":{"183":5}}],["inter",{"2":{"144":3}}],["interrupt=false",{"2":{"93":1,"149":6,"175":2}}],["interface",{"2":{"64":3,"149":1}}],["int32",{"2":{"93":1}}],["int",{"2":{"30":1,"133":6,"134":3,"137":1,"138":4,"144":2,"147":2,"149":47,"175":18,"183":7,"265":1}}],["input",{"2":{"26":1,"97":1,"98":1,"183":1}}],["iniapp",{"2":{"211":1}}],["inipms",{"2":{"195":3}}],["ini中client",{"2":{"161":1,"255":1}}],["ini配置文件",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["ini里面的配置",{"2":{"61":1,"70":1,"80":1,"99":1,"107":1,"248":1}}],["init",{"2":{"26":1,"61":3,"70":3,"71":3,"74":1,"80":3,"92":1,"97":2,"99":3,"100":3,"107":3,"143":1,"144":1,"149":1,"154":1,"165":1,"248":3,"262":6,"265":5,"266":2,"292":1,"294":2,"297":6}}],["ini",{"2":{"25":1,"34":1,"41":4,"47":1,"61":3,"68":1,"69":1,"70":3,"71":1,"78":1,"79":1,"80":3,"88":1,"89":1,"98":2,"99":3,"100":1,"105":1,"106":1,"107":3,"114":1,"115":1,"133":1,"147":1,"148":2,"156":2,"159":1,"161":1,"191":1,"193":3,"195":1,"208":2,"210":1,"211":1,"213":2,"226":2,"227":1,"229":1,"231":1,"247":1,"248":3,"253":1,"255":1,"262":6,"267":1,"268":1,"280":1,"292":2}}],["info",{"2":{"6":1,"27":1,"57":2,"64":2,"84":1,"149":51,"158":2,"175":17,"189":1,"191":2,"192":1,"229":1,"252":2}}],["img",{"2":{"295":1}}],["imports",{"2":{"183":1}}],["import",{"2":{"13":1,"34":2,"59":2,"64":2,"65":3,"74":8,"75":3,"84":4,"85":4,"93":1,"94":2,"97":2,"98":4,"110":2,"111":3,"119":4,"124":1,"131":1,"137":6,"142":1,"144":13,"149":12,"174":3,"175":18,"181":4,"182":1,"183":11,"184":1,"192":2,"203":2,"215":1,"216":1,"222":1,"227":2,"228":1,"265":6,"266":1,"294":1,"295":1,"296":4,"297":6}}],["imagergb",{"2":{"136":1}}],["imageutils",{"2":{"175":8}}],["imageutil",{"2":{"50":1}}],["image",{"2":{"12":1,"23":1,"24":2,"25":1,"30":1,"50":1,"53":3,"119":3,"131":2,"133":13,"134":2,"136":7,"137":14,"175":8,"183":3,"184":2,"192":4,"222":1,"229":4,"262":1,"265":1}}],["ip=",{"2":{"215":1,"216":1,"218":1}}],["ipynb",{"2":{"154":1}}],["ip",{"2":{"11":2,"16":1,"47":1,"51":1,"119":2,"122":3,"137":1,"161":1,"178":1,"179":1,"213":5,"226":1,"229":10,"255":1,"268":1,"280":2}}],["w5821",{"2":{"203":2}}],["wh",{"2":{"175":4}}],["when",{"2":{"154":4}}],["w=100",{"2":{"175":2}}],["wwininfo",{"2":{"149":11}}],["www",{"2":{"97":1,"98":2,"229":2}}],["w和h来定位元素在屏幕中的位置",{"2":{"149":1}}],["w2",{"2":{"147":2}}],["w",{"2":{"50":2,"129":2,"133":3,"137":2,"143":2,"144":2,"148":2,"149":38,"175":20,"183":1}}],["wininfo",{"2":{"149":4}}],["windowwidget",{"2":{"221":1,"222":1}}],["windowactivate",{"2":{"149":1}}],["windowmove",{"2":{"149":1}}],["windows",{"2":{"12":1,"136":1,"149":6,"175":1}}],["window",{"2":{"6":1,"27":1,"149":221,"175":2}}],["with",{"2":{"136":1,"154":1,"183":1}}],["width",{"2":{"53":1,"136":2,"138":2,"149":28,"154":1,"183":4}}],["widget",{"0":{"294":1},"2":{"46":1,"49":1,"61":4,"64":6,"65":4,"70":4,"71":3,"80":4,"84":7,"85":1,"93":2,"94":2,"99":4,"100":3,"107":4,"110":2,"111":2,"133":5,"175":37,"181":2,"191":1,"192":3,"215":1,"229":1,"248":4,"262":6,"265":2,"266":1,"280":5,"282":5,"283":3,"292":7,"295":1,"296":2,"297":5}}],["walk",{"2":{"175":2}}],["wait",{"2":{"133":1,"229":1}}],["warnings",{"2":{"74":1,"154":1}}],["warning",{"2":{"26":2}}],["wayland上",{"2":{"183":1}}],["waylandwindowinfo",{"2":{"27":1,"149":7}}],["wayland",{"0":{"184":1},"2":{"6":1,"7":1,"9":1,"10":1,"18":1,"21":1,"25":3,"26":1,"27":1,"38":2,"39":2,"42":1,"46":1,"47":1,"57":1,"59":1,"86":1,"149":3,"180":1,"183":6,"184":10,"203":3,"240":1,"242":1}}],["web文件中不用写任何东西",{"2":{"100":1}}],["webassert",{"2":{"98":2,"174":1,"187":1}}],["webui",{"0":{"185":1},"1":{"186":1,"187":1},"2":{"97":3,"98":1,"100":3,"174":1,"185":1,"187":1}}],["web",{"0":{"103":1},"1":{"104":1,"105":1,"106":1},"2":{"13":1,"16":2,"17":1,"74":1,"98":3,"100":2,"101":1,"103":2,"185":1,"186":1,"229":1,"241":1}}],["wl",{"2":{"10":1,"183":1}}],["71f6",{"2":{"177":1}}],["7",{"0":{"6":1,"26":1,"45":1},"2":{"154":1,"229":1,"287":7}}],["81",{"2":{"211":3,"229":2}}],["8000",{"2":{"179":1}}],["8a6f",{"2":{"177":1}}],["8810",{"2":{"177":1}}],["8889",{"2":{"137":1,"229":1}}],["8890",{"2":{"119":1,"229":1}}],["83",{"2":{"74":1}}],["8",{"0":{"5":1,"44":1},"2":{"23":2,"27":1,"47":6,"51":1,"144":1,"149":1,"161":6,"162":2,"175":1,"183":1,"196":2,"203":1,"213":1,"229":8,"255":4,"287":1}}],["66",{"2":{"229":1}}],["600",{"2":{"149":1}}],["600+",{"2":{"41":1}}],["679537",{"2":{"53":3,"177":1,"199":2,"202":1,"204":1,"205":1,"222":2}}],["62",{"2":{"16":1}}],["64",{"2":{"15":1,"74":1,"192":1,"242":1}}],["68",{"2":{"12":1,"27":1}}],["6",{"0":{"5":1,"6":1,"7":2,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"20":1,"27":1,"46":1},"2":{"119":2,"175":3,"192":1,"287":6}}],["2d7e77ce1718",{"2":{"177":1}}],["2>middle",{"2":{"144":1}}],["28",{"0":{"54":1},"2":{"46":1,"192":1,"287":2}}],["25",{"2":{"25":1,"287":1}}],["23",{"2":{"25":1,"287":2}}],["22",{"0":{"25":1,"30":1,"39":1,"58":1},"2":{"25":1,"30":1,"287":2}}],["20747",{"2":{"229":2}}],["20221109134736",{"2":{"177":2}}],["20221108114823",{"2":{"177":1}}],["2022",{"0":{"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1},"2":{"177":3,"287":34}}],["2023",{"0":{"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1},"2":{"30":2,"144":1,"149":1,"175":1,"183":1,"203":1}}],["2024",{"0":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1}}],["20",{"0":{"21":1},"2":{"27":1,"136":1,"287":4}}],["268",{"2":{"148":1}}],["26",{"0":{"20":1,"24":1,"43":1},"2":{"25":1,"287":1}}],["27",{"0":{"17":1,"23":1,"33":1,"48":1,"49":1},"2":{"287":1}}],["248",{"2":{"175":3}}],["24",{"0":{"16":1},"2":{"25":1}}],["2199",{"2":{"177":1}}],["215",{"2":{"51":1}}],["21",{"0":{"12":1,"55":1},"2":{"25":1,"148":2,"287":1}}],["29",{"0":{"11":1},"2":{"46":1}}],["2",{"0":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":2,"12":1,"13":1,"14":1,"15":1,"16":1,"17":2,"18":1,"19":1,"20":1,"21":1,"22":1,"23":2,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":2,"32":1,"33":1,"34":2,"35":2,"36":2,"37":2,"38":1,"39":2,"40":1,"41":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":2,"51":1,"52":1,"55":1,"58":1,"128":1,"137":1,"159":1,"162":1,"203":1,"234":1,"251":1,"252":1,"253":2,"256":1,"261":1,"265":1,"276":1,"280":1,"283":1,"292":1,"295":1,"300":1},"1":{"252":1,"253":1},"2":{"18":1,"34":1,"39":1,"40":1,"41":6,"45":2,"47":1,"52":1,"53":2,"61":1,"70":1,"74":1,"80":1,"85":1,"99":1,"107":1,"122":1,"123":1,"127":1,"129":1,"131":1,"133":1,"134":1,"136":2,"142":1,"143":2,"144":5,"147":2,"149":22,"162":2,"164":1,"175":2,"177":1,"183":6,"193":1,"195":1,"203":1,"213":2,"222":1,"226":1,"229":6,"243":1,"248":1,"256":2,"266":1,"268":1,"271":2,"272":1,"282":1,"283":4,"284":1,"285":1,"286":1,"287":1,"299":1,"300":3,"301":1,"302":1}}],["向量的纵坐标",{"2":{"183":1}}],["向量的横坐标",{"2":{"183":1}}],["向元素对象输入字符串",{"2":{"142":1}}],["向",{"0":{"2":1,"3":1},"2":{"183":1}}],["欢迎任何微如错别字",{"2":{"1":1}}],["帮助改进",{"0":{"1":1}}],["贡献",{"0":{"0":1},"1":{"1":1,"2":1,"3":1}}]],"serializationVersion":2}';export{t as default}; diff --git a/assets/chunks/@localSearchIndexroot.C_5et46b.js b/assets/chunks/@localSearchIndexroot.C_5et46b.js new file mode 100644 index 00000000..efc7d9d3 --- /dev/null +++ b/assets/chunks/@localSearchIndexroot.C_5et46b.js @@ -0,0 +1 @@ +const t='{"documentCount":305,"nextId":305,"documentIds":{"0":"/youqu/CONTRIBUTING.html#贡献-并且帮助我们改进","1":"/youqu/CONTRIBUTING.html#帮助改进-youqu-文档","2":"/youqu/CONTRIBUTING.html#向-youqu-提交-issues","3":"/youqu/CONTRIBUTING.html#向-youqu-仓库提交代码","4":"/youqu/RELEASE.html#版本更新记录","5":"/youqu/RELEASE.html#_2-6-9-2024-08-05","6":"/youqu/RELEASE.html#_2-6-8-2024-07-15","7":"/youqu/RELEASE.html#_2-6-7-2024-07-15","8":"/youqu/RELEASE.html#_2-6-6-2024-07-05","9":"/youqu/RELEASE.html#_2-6-5-2024-06-11","10":"/youqu/RELEASE.html#_2-6-4-2024-06-07","11":"/youqu/RELEASE.html#_2-6-3-2024-06-07","12":"/youqu/RELEASE.html#_2-6-2-2024-05-29","13":"/youqu/RELEASE.html#_2-6-1-2024-05-21","14":"/youqu/RELEASE.html#_2-6-0-2024-05-14","15":"/youqu/RELEASE.html#_2-5-5-2024-05-10","16":"/youqu/RELEASE.html#_2-5-4-2024-05-08","17":"/youqu/RELEASE.html#_2-5-3-2024-04-24","18":"/youqu/RELEASE.html#_2-5-2-2024-03-27","19":"/youqu/RELEASE.html#_2-5-1-2024-03-14","20":"/youqu/RELEASE.html#_2-5-0-2024-03-04","21":"/youqu/RELEASE.html#_2-4-6-2024-02-26","22":"/youqu/RELEASE.html#_2-4-5-2024-01-20","23":"/youqu/RELEASE.html#_2-4-4-2024-01-19","24":"/youqu/RELEASE.html#_2-4-2-2023-12-27","25":"/youqu/RELEASE.html#_2-4-1-2023-12-26","26":"/youqu/RELEASE.html#_2-4-0-2023-12-22","27":"/youqu/RELEASE.html#_2-3-7-2023-12-15","28":"/youqu/RELEASE.html#_2-3-6-2023-12-13","29":"/youqu/RELEASE.html#_2-3-5-2023-12-04","30":"/youqu/RELEASE.html#_2-3-4-2023-12-04","31":"/youqu/RELEASE.html#_2-3-3-2023-11-22","32":"/youqu/RELEASE.html#_2-3-2-2023-11-14","33":"/youqu/RELEASE.html#_2-3-1-2023-11-08","34":"/youqu/RELEASE.html#_2-3-0-2023-10-27","35":"/youqu/RELEASE.html#_2-2-4-2023-10-16","36":"/youqu/RELEASE.html#_2-2-3-2023-09-15","37":"/youqu/RELEASE.html#_2-2-1-2023-09-13","38":"/youqu/RELEASE.html#_2-2-0-2023-09-05","39":"/youqu/RELEASE.html#_2-1-5-2023-08-31","40":"/youqu/RELEASE.html#_2-1-2-2023-08-22","41":"/youqu/RELEASE.html#_2-1-0-2023-08-18","42":"/youqu/RELEASE.html#_2-0-0-2023-08-16","43":"/youqu/RELEASE.html#_1-3-0-2023-07-10","44":"/youqu/RELEASE.html#_1-2-9-2023-06-26","45":"/youqu/RELEASE.html#_1-2-8-2023-06-09","46":"/youqu/RELEASE.html#_1-2-7-2023-06-08","47":"/youqu/RELEASE.html#_1-2-6-2023-06-07","48":"/youqu/RELEASE.html#_1-2-5-2023-05-16","49":"/youqu/RELEASE.html#_1-2-4-2023-02-27","50":"/youqu/RELEASE.html#_1-2-3-2023-02-27","51":"/youqu/RELEASE.html#_1-2-2-2023-02-08","52":"/youqu/RELEASE.html#_1-2-1-2023-01-06","53":"/youqu/RELEASE.html#_1-2-0-2022-12-30","54":"/youqu/RELEASE.html#_1-1-4-2022-12-14","55":"/youqu/RELEASE.html#_1-1-3-2022-10-28","56":"/youqu/RELEASE.html#_1-1-2-2022-09-21","57":"/youqu/RELEASE.html#_1-1-1-2022-09-19","58":"/youqu/RELEASE.html#_1-1-0-2022-09-16","59":"/youqu/RELEASE.html#_1-0-2-2022-08-22","60":"/youqu/RELEASE.html#_1-0-1-2022-08-12","61":"/youqu/SIG.html#youqu-官方兴趣小组","62":"/youqu/实践/DBus接口自动化测试/创建APP工程.html#创建一个-app-工程","63":"/youqu/实践/DBus接口自动化测试/创建APP工程.html#编辑器打开","64":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#创建一条完整的用例","65":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#封装用例步骤的方法","66":"/youqu/实践/DBus接口自动化测试/创建一条完整的用例.html#编写用例","67":"/youqu/实践/DBus接口自动化测试/初始化项目.html#linux-dbus-接口自动化测试","68":"/youqu/实践/DBus接口自动化测试/初始化项目.html#安装","69":"/youqu/实践/DBus接口自动化测试/初始化项目.html#创建一个项目","70":"/youqu/实践/DBus接口自动化测试/初始化项目.html#部署环境","71":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#创建一个-app-工程","72":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#修改","73":"/youqu/实践/HTTP接口自动化测试/创建APP工程.html#再次执行-env-sh","74":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#创建一条完整的用例","75":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#封装用例步骤的方法","76":"/youqu/实践/HTTP接口自动化测试/创建一条完整的用例.html#编写用例","77":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#http-接口自动化测试","78":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#安装","79":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#创建一个项目","80":"/youqu/实践/HTTP接口自动化测试/初始化项目.html#部署环境","81":"/youqu/实践/Linux桌面UI自动化测试/创建APP工程.html#创建一个-app-工程","82":"/youqu/实践/Linux桌面UI自动化测试/创建APP工程.html#编辑器打开","83":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#创建一条完整的用例","84":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#用例步骤","85":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#封装用例步骤的方法","86":"/youqu/实践/Linux桌面UI自动化测试/创建一条完整的用例.html#编写用例","87":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#linux-桌面-ui-自动化测试","88":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#安装","89":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#创建一个项目","90":"/youqu/实践/Linux桌面UI自动化测试/初始化项目.html#部署环境","91":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#远程交互式控制","92":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#逻辑示意图","93":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#标识文件","94":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#方法编写","95":"/youqu/实践/Linux桌面UI自动化测试/远程交互式控制.html#用例编写","96":"/youqu/实践/WebUI自动化测试/创建APP工程.html#创建一个-app-工程","97":"/youqu/实践/WebUI自动化测试/创建APP工程.html#修改","98":"/youqu/实践/WebUI自动化测试/创建APP工程.html#再次执行-env-sh","99":"/youqu/实践/WebUI自动化测试/创建APP工程.html#编辑器打开","100":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#创建一条完整的用例","101":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#用例步骤","102":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#封装用例步骤的方法","103":"/youqu/实践/WebUI自动化测试/创建一条完整的用例.html#编写用例","104":"/youqu/实践/WebUI自动化测试/初始化项目.html#web-ui-自动化测试","105":"/youqu/实践/WebUI自动化测试/初始化项目.html#安装","106":"/youqu/实践/WebUI自动化测试/初始化项目.html#创建一个项目","107":"/youqu/实践/WebUI自动化测试/初始化项目.html#部署环境","108":"/youqu/实践/命令行自动化测试/创建APP工程.html#创建一个-app-工程","109":"/youqu/实践/命令行自动化测试/创建APP工程.html#编辑器打开","110":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#创建一条完整的用例","111":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#封装用例步骤的方法","112":"/youqu/实践/命令行自动化测试/创建一条完整的用例.html#编写用例","113":"/youqu/实践/命令行自动化测试/初始化项目.html#命令行自动化测试","114":"/youqu/实践/命令行自动化测试/初始化项目.html#安装","115":"/youqu/实践/命令行自动化测试/初始化项目.html#创建一个项目","116":"/youqu/实践/命令行自动化测试/初始化项目.html#部署环境","117":"/youqu/指南/元素定位/OCR识别.html#ocr识别","118":"/youqu/指南/元素定位/OCR识别.html#背景","119":"/youqu/指南/元素定位/OCR识别.html#实现原理","120":"/youqu/指南/元素定位/OCR识别.html#使用说明","121":"/youqu/指南/元素定位/OCR识别.html#rpc服务端部署","122":"/youqu/指南/元素定位/OCR识别.html#负载均衡","123":"/youqu/指南/元素定位/OCR识别.html#为什么基于-nginx-的负载均衡方案不能满足业务需求","124":"/youqu/指南/元素定位/OCR识别.html#youqu-的解决方案","125":"/youqu/指南/元素定位/OCR识别.html#链式调用","126":"/youqu/指南/元素定位/去干扰识别.html#去干扰识别","127":"/youqu/指南/元素定位/去干扰识别.html#现有右键菜单定位的方案及问题","128":"/youqu/指南/元素定位/去干扰识别.html#_1-步长操作法","129":"/youqu/指南/元素定位/去干扰识别.html#_2-常规图像识别法","130":"/youqu/指南/元素定位/去干扰识别.html#_3-相对位移法","131":"/youqu/指南/元素定位/去干扰识别.html#_4-属性定位","132":"/youqu/指南/元素定位/去干扰识别.html#去干扰识别-1","133":"/youqu/指南/元素定位/图像识别.html#图像识别","134":"/youqu/指南/元素定位/图像识别.html#常规识别","135":"/youqu/指南/元素定位/图像识别.html#气泡识别","136":"/youqu/指南/元素定位/图像识别.html#不依赖-opencv-的图像识别方案","137":"/youqu/指南/元素定位/图像识别.html#_1-自研图像识别技术","138":"/youqu/指南/元素定位/图像识别.html#_2-基于-rpc-服务实现图像识别","139":"/youqu/指南/元素定位/图像识别.html#动态图像识别","140":"/youqu/指南/元素定位/属性定位.html#属性定位","141":"/youqu/指南/元素定位/属性定位.html#背景","142":"/youqu/指南/元素定位/属性定位.html#sniff-嗅探器-使用","143":"/youqu/指南/元素定位/属性定位.html#元素操作","144":"/youqu/指南/元素定位/属性定位.html#框架封装","145":"/youqu/指南/元素定位/属性定位.html#方法明细","146":"/youqu/指南/元素定位/相对坐标定位.html#相对坐标定位","147":"/youqu/指南/元素定位/相对坐标定位.html#背景","148":"/youqu/指南/元素定位/相对坐标定位.html#实现原理","149":"/youqu/指南/元素定位/相对坐标定位.html#使用方法","150":"/youqu/指南/元素定位/相对坐标定位.html#方法明细","151":"/youqu/指南/框架必备/Ruff代码检查.html#ruff","152":"/youqu/指南/框架必备/Ruff代码检查.html#安装","153":"/youqu/指南/框架必备/Ruff代码检查.html#代码检查","154":"/youqu/指南/框架必备/Ruff代码检查.html#代码格式化","155":"/youqu/指南/框架必备/Ruff代码检查.html#配置","156":"/youqu/指南/框架必备/执行管理器.html#执行管理器-manage-py","157":"/youqu/指南/框架必备/执行管理器.html#如何使用","158":"/youqu/指南/框架必备/执行管理器.html#本地执行","159":"/youqu/指南/框架必备/执行管理器.html#_1-命令行参数","160":"/youqu/指南/框架必备/执行管理器.html#_2-配置文件","161":"/youqu/指南/框架必备/执行管理器.html#远程执行","162":"/youqu/指南/框架必备/执行管理器.html#_1-多机器分布式异步执行","163":"/youqu/指南/框架必备/执行管理器.html#_2-多机器分布式异步负载均衡执行","164":"/youqu/指南/框架必备/执行管理器.html#用例驱动方式","165":"/youqu/指南/框架必备/执行管理器.html#指定执行某一个用例","166":"/youqu/指南/框架必备/执行管理器.html#指定某个目录执行","167":"/youqu/指南/框架必备/执行管理器.html#执行某个app工程的所有用例","168":"/youqu/指南/框架必备/执行管理器.html#根据关键词执行","169":"/youqu/指南/框架必备/执行管理器.html#根据标签执行","170":"/youqu/指南/框架必备/执行管理器.html#批量用例id驱动执行","171":"/youqu/指南/框架必备/执行管理器.html#测试单驱动执行","172":"/youqu/指南/框架必备/执行管理器.html#测试套件驱动执行","173":"/youqu/指南/框架必备/执行管理器.html#本地用例文件驱动执行","174":"/youqu/指南/框架必备/断言.html#断言","175":"/youqu/指南/框架必备/断言.html#用例中使用方法","176":"/youqu/指南/框架必备/断言.html#方法明细","177":"/youqu/指南/框架必备/测试报告.html#测试报告","178":"/youqu/指南/框架必备/测试报告.html#目录结构","179":"/youqu/指南/框架必备/测试报告.html#定制报告","180":"/youqu/指南/框架必备/测试报告.html#查看报告","181":"/youqu/指南/框架必备/键鼠操作.html#键鼠操作","182":"/youqu/指南/框架必备/键鼠操作.html#常规键鼠操作","183":"/youqu/指南/框架必备/键鼠操作.html#特殊场景键鼠操作","184":"/youqu/指南/框架必备/键鼠操作.html#方法明细","185":"/youqu/指南/特色功能/Wayland适配.html#wayland-适配","186":"/youqu/指南/特色功能/WebUI.html#webui","187":"/youqu/指南/特色功能/WebUI.html#实践方法","188":"/youqu/指南/特色功能/WebUI.html#断言方法","189":"/youqu/指南/特色功能/全自动日志.html#全自动日志——funnylog","190":"/youqu/指南/特色功能/全自动日志.html#背景","191":"/youqu/指南/特色功能/全自动日志.html#实现原理","192":"/youqu/指南/特色功能/全自动日志.html#日志配置","193":"/youqu/指南/特色功能/全自动日志.html#使用方法","194":"/youqu/指南/特色功能/失败录屏.html#失败录屏","195":"/youqu/指南/特色功能/数据回填.html#pms数据回填","196":"/youqu/指南/特色功能/数据回填.html#本机执行时回填","197":"/youqu/指南/特色功能/数据回填.html#远程执行时回填","198":"/youqu/指南/特色功能/数据回填.html#可能遇到的-问题","199":"/youqu/指南/特色功能/标签化管理.html#标签化管理","200":"/youqu/指南/特色功能/标签化管理.html#标签说明","201":"/youqu/指南/特色功能/标签化管理.html#操作步骤","202":"/youqu/指南/特色功能/标签化管理.html#跳过用例","203":"/youqu/指南/特色功能/标签化管理.html#_1-固定跳过","204":"/youqu/指南/特色功能/标签化管理.html#_2-条件判断跳过","205":"/youqu/指南/特色功能/标签化管理.html#确认修复","206":"/youqu/指南/特色功能/标签化管理.html#废弃用例","207":"/youqu/指南/特色功能/标签化管理.html#设计思路","208":"/youqu/指南/特色功能/标签化管理.html#csv文件格式","209":"/youqu/指南/特色功能/标签导出.html#导出csv文件","210":"/youqu/指南/特色功能/标签自动同步.html#标签自动同步","211":"/youqu/指南/特色功能/标签自动同步.html#自动同步脚本-id-到-csv-文件","212":"/youqu/指南/特色功能/标签自动同步.html#从-pms-自动同步标签到-csv","213":"/youqu/指南/特色功能/远程交互式控制.html#远程交互式控制","214":"/youqu/指南/特色功能/远程交互式控制.html#slaves对象提供远程机器信息","215":"/youqu/指南/特色功能/远程交互式控制.html#_3个remote远程对象","216":"/youqu/指南/特色功能/远程交互式控制.html#remote-rdog","217":"/youqu/指南/特色功能/远程交互式控制.html#remote-rctl","218":"/youqu/指南/特色功能/远程交互式控制.html#跨过-rctl-直接调用","219":"/youqu/指南/特色功能/远程交互式控制.html#remote-rctl-plus","220":"/youqu/指南/特色功能/远程交互式控制.html#代码补全","221":"/youqu/指南/特色功能/重启类场景.html#重启类场景","222":"/youqu/指南/特色功能/重启类场景.html#使用方法","223":"/youqu/指南/特色功能/重启类场景.html#用例注意事项","224":"/youqu/指南/特色功能/重启类场景.html#驱动执行","225":"/youqu/指南/特色功能/重启类场景.html#执行环境","226":"/youqu/指南/环境/全局配置.html#全局配置-setting-conf","227":"/youqu/指南/环境/全局配置.html#配置文件","228":"/youqu/指南/环境/全局配置.html#配置对象获取","229":"/youqu/指南/环境/全局配置.html#app工程配置对象","230":"/youqu/指南/环境/全局配置.html#全局配置项明细","231":"/youqu/指南/环境/环境部署.html#环境部署-env-sh","232":"/youqu/指南/环境/环境部署.html#安装","233":"/youqu/指南/环境/环境部署.html#定制依赖","234":"/youqu/指南/环境/环境部署.html#_1-新增依赖","235":"/youqu/指南/环境/环境部署.html#_2-裁剪依赖","236":"/youqu/指南/环境/环境部署.html#开发环境部署","237":"/youqu/指南/环境/环境部署.html#虚拟环境解释器","238":"/youqu/指南/环境/环境部署.html#激活虚拟环境","239":"/youqu/指南/环境/环境部署.html#删除虚拟环境","240":"/youqu/指南/环境/环境部署.html#依赖治理","241":"/youqu/指南/简介/YouQu是什么.html#youqu-是什么","242":"/youqu/指南/简介/YouQu是什么.html#youqu-能做什么","243":"/youqu/指南/简介/YouQu是什么.html#爱上-youqu-的-n-个理由","244":"/youqu/指南/简介/YouQu是什么.html#开源许可证","245":"/youqu/指南/简介/快速开始.html#快速开始","246":"/youqu/指南/简介/快速开始.html#安装","247":"/youqu/指南/简介/快速开始.html#创建项目","248":"/youqu/指南/简介/快速开始.html#安装依赖","249":"/youqu/指南/简介/快速开始.html#创建-app-工程","250":"/youqu/指南/简介/快速开始.html#运行","251":"/youqu/指南/简介/快速开始.html#_1-执行管理器","252":"/youqu/指南/简介/快速开始.html#_2-本地执行","253":"/youqu/指南/简介/快速开始.html#_2-1-命令行参数","254":"/youqu/指南/简介/快速开始.html#_2-2-配置文件","255":"/youqu/指南/简介/快速开始.html#_3-远程执行","256":"/youqu/指南/简介/快速开始.html#_3-1-远程多机器分布式异步执行","257":"/youqu/指南/简介/快速开始.html#_3-2-远程多机器分布式异步负载均衡执行","258":"/youqu/规划/未来规划.html#未来规划","259":"/youqu/规划/未来规划.html#💡-桌面应用性能自动化测试","260":"/youqu/规划/未来规划.html#需优化解决的性能自动化问题","261":"/youqu/规划/未来规划.html#方案","262":"/youqu/规划/框架设计/AT基础框架设计方案.html#at-基础框架设计方案","263":"/youqu/规划/框架设计/AT基础框架设计方案.html#一、目标","264":"/youqu/规划/框架设计/AT基础框架设计方案.html#二、设计方案","265":"/youqu/规划/框架设计/AT基础框架设计方案.html#_1、统一概念","266":"/youqu/规划/框架设计/AT基础框架设计方案.html#_2、架构图","267":"/youqu/规划/框架设计/AT基础框架设计方案.html#_3、目录结构","268":"/youqu/规划/框架设计/AT基础框架设计方案.html#三、详细方案","269":"/youqu/规划/框架设计/AT基础框架设计方案.html#_1、应用库-apps","270":"/youqu/规划/框架设计/AT基础框架设计方案.html#_2、核心库-src","271":"/youqu/规划/框架设计/AT基础框架设计方案.html#_3、公共方法库-public","272":"/youqu/规划/框架设计/AT基础框架设计方案.html#_4、conftest-py","273":"/youqu/规划/框架设计/AT基础框架设计方案.html#_5、setting","274":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#自动化测试架构设计规划","275":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#一、背景介绍","276":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、原有架构介绍","277":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、自动化的应用","278":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_3、存在的问题","279":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#二、方案设计","280":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、架构设计","281":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、设计思路","282":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#三、详细方案","283":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_1、用例解耦","284":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_2、公共库建设","285":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_3、用例标签化管理","286":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_4、用例执行","287":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#_5、自动化测试平台","288":"/youqu/规划/框架设计/自动化测试架构设计v1.0.html#四、实施计划","289":"/youqu/规划/框架设计/AT应用库设计方案.html#at-应用库设计方案","290":"/youqu/规划/框架设计/AT应用库设计方案.html#一、目标","291":"/youqu/规划/框架设计/AT应用库设计方案.html#二、方案设计","292":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、分层设计图","293":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、目录结构","294":"/youqu/规划/框架设计/AT应用库设计方案.html#三、详细方案","295":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、基类-base-widget-py","296":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、操作层","297":"/youqu/规划/框架设计/AT应用库设计方案.html#_3、应用层","298":"/youqu/规划/框架设计/AT应用库设计方案.html#_4、逻辑举例","299":"/youqu/规划/框架设计/AT应用库设计方案.html#四、工程改造实施步骤","300":"/youqu/规划/框架设计/AT应用库设计方案.html#_1、基础框架代码拉取","301":"/youqu/规划/框架设计/AT应用库设计方案.html#_2、调整工程目录","302":"/youqu/规划/框架设计/AT应用库设计方案.html#_3、实现核心库接口","303":"/youqu/规划/框架设计/AT应用库设计方案.html#_4、路径处理","304":"/youqu/规划/框架设计/AT应用库设计方案.html#_5、调试和编写用例"},"fieldIds":{"title":0,"titles":1,"text":2},"fieldLength":{"0":[2,1,4],"1":[3,2,5],"2":[4,2,9],"3":[3,2,3],"4":[1,1,1],"5":[7,1,19],"6":[7,1,7],"7":[7,1,9],"8":[6,1,16],"9":[7,1,4],"10":[7,1,9],"11":[7,1,20],"12":[6,1,56],"13":[7,1,84],"14":[7,1,80],"15":[6,1,17],"16":[7,1,51],"17":[7,1,81],"18":[6,1,34],"19":[7,1,48],"20":[7,1,18],"21":[7,1,34],"22":[7,1,20],"23":[6,1,24],"24":[6,1,13],"25":[7,1,21],"26":[7,1,50],"27":[7,1,56],"28":[7,1,69],"29":[7,1,11],"30":[7,1,23],"31":[6,1,37],"32":[6,1,30],"33":[7,1,20],"34":[7,1,39],"35":[6,1,76],"36":[6,1,14],"37":[6,1,20],"38":[6,1,13],"39":[7,1,27],"40":[6,1,38],"41":[7,1,61],"42":[6,1,203],"43":[7,1,19],"44":[7,1,25],"45":[7,1,9],"46":[7,1,22],"47":[7,1,31],"48":[7,1,82],"49":[7,1,7],"50":[7,1,45],"51":[6,1,50],"52":[6,1,45],"53":[7,1,33],"54":[6,1,169],"55":[6,1,51],"56":[6,1,19],"57":[5,1,52],"58":[6,1,53],"59":[7,1,18],"60":[6,1,31],"61":[2,1,7],"62":[3,1,64],"63":[1,3,5],"64":[1,1,2],"65":[1,1,60],"66":[1,1,42],"67":[3,1,9],"68":[1,3,7],"69":[1,3,33],"70":[1,3,24],"71":[3,1,64],"72":[1,3,41],"73":[3,3,7],"74":[1,1,2],"75":[1,1,198],"76":[1,1,70],"77":[2,1,16],"78":[1,2,7],"79":[1,2,33],"80":[1,2,24],"81":[3,1,64],"82":[1,3,5],"83":[1,1,2],"84":[1,1,5],"85":[1,1,64],"86":[1,1,61],"87":[4,1,20],"88":[1,4,7],"89":[1,4,33],"90":[1,4,24],"91":[1,1,2],"92":[1,1,1],"93":[1,1,25],"94":[1,1,63],"95":[1,1,35],"96":[3,1,64],"97":[1,3,50],"98":[3,3,11],"99":[1,3,5],"100":[1,1,4],"101":[1,1,3],"102":[1,1,38],"103":[1,1,111],"104":[3,1,22],"105":[1,3,7],"106":[1,3,33],"107":[1,3,24],"108":[3,1,64],"109":[1,3,5],"110":[1,1,4],"111":[1,1,39],"112":[1,1,50],"113":[1,1,6],"114":[1,1,7],"115":[1,1,33],"116":[1,1,24],"117":[1,1,1],"118":[1,1,18],"119":[1,1,24],"120":[1,1,159],"121":[1,1,5],"122":[1,1,9],"123":[3,2,33],"124":[2,2,15],"125":[1,1,20],"126":[1,1,2],"127":[1,1,5],"128":[2,2,39],"129":[2,2,16],"130":[2,2,41],"131":[2,2,11],"132":[1,1,81],"133":[1,1,21],"134":[1,1,202],"135":[1,1,72],"136":[3,1,1],"137":[2,4,150],"138":[4,4,141],"139":[1,1,53],"140":[1,1,1],"141":[1,1,27],"142":[3,1,45],"143":[1,1,66],"144":[1,1,49],"145":[1,1,250],"146":[1,1,1],"147":[1,1,33],"148":[1,1,95],"149":[1,1,70],"150":[1,1,306],"151":[1,1,8],"152":[1,1,4],"153":[1,1,15],"154":[1,1,15],"155":[1,1,212],"156":[3,1,14],"157":[1,3,43],"158":[1,3,7],"159":[2,4,152],"160":[2,4,15],"161":[1,3,10],"162":[2,4,112],"163":[2,4,42],"164":[1,3,1],"165":[1,4,19],"166":[1,4,23],"167":[1,4,10],"168":[1,4,28],"169":[1,4,23],"170":[1,4,11],"171":[1,4,20],"172":[1,4,20],"173":[1,4,21],"174":[1,1,4],"175":[1,1,37],"176":[1,1,439],"177":[1,1,1],"178":[1,1,57],"179":[1,1,22],"180":[1,1,41],"181":[1,1,16],"182":[1,1,36],"183":[1,1,25],"184":[1,1,347],"185":[2,1,61],"186":[1,1,50],"187":[1,1,5],"188":[1,1,24],"189":[2,1,1],"190":[1,2,39],"191":[1,2,24],"192":[1,2,34],"193":[1,2,100],"194":[1,1,42],"195":[1,1,4],"196":[1,1,85],"197":[1,1,45],"198":[3,1,18],"199":[1,1,1],"200":[1,1,66],"201":[1,1,42],"202":[1,1,14],"203":[2,2,18],"204":[2,2,162],"205":[1,1,82],"206":[1,1,21],"207":[1,1,18],"208":[1,1,8],"209":[1,1,39],"210":[1,1,1],"211":[5,1,46],"212":[4,1,79],"213":[1,1,13],"214":[1,1,53],"215":[1,1,1],"216":[2,2,39],"217":[2,2,35],"218":[3,4,27],"219":[3,2,43],"220":[1,1,8],"221":[1,1,11],"222":[1,1,13],"223":[1,1,72],"224":[1,1,9],"225":[1,1,11],"226":[3,1,1],"227":[1,3,38],"228":[1,3,24],"229":[1,3,16],"230":[1,3,491],"231":[3,1,1],"232":[1,3,23],"233":[1,3,1],"234":[2,4,36],"235":[2,4,31],"236":[1,3,17],"237":[1,3,14],"238":[1,3,8],"239":[1,3,5],"240":[1,3,28],"241":[3,1,16],"242":[3,3,16],"243":[5,3,63],"244":[1,3,7],"245":[1,1,1],"246":[1,1,28],"247":[1,1,16],"248":[1,1,29],"249":[3,1,92],"250":[1,1,1],"251":[2,2,7],"252":[2,2,6],"253":[3,4,153],"254":[2,4,12],"255":[2,2,10],"256":[3,4,115],"257":[3,4,31],"258":[1,1,1],"259":[2,1,1],"260":[1,3,35],"261":[1,3,31],"262":[2,1,1],"263":[2,2,11],"264":[2,2,1],"265":[2,4,45],"266":[2,4,11],"267":[2,4,71],"268":[2,2,1],"269":[4,4,9],"270":[4,4,89],"271":[4,4,70],"272":[3,4,29],"273":[2,4,35],"274":[1,1,60],"275":[2,1,3],"276":[2,3,32],"277":[2,3,27],"278":[2,3,45],"279":[2,1,5],"280":[2,3,3],"281":[2,3,191],"282":[2,1,1],"283":[2,3,40],"284":[2,3,43],"285":[2,3,77],"286":[2,3,31],"287":[2,3,37],"288":[2,1,54],"289":[2,1,1],"290":[2,2,5],"291":[2,2,7],"292":[2,4,11],"293":[2,4,49],"294":[2,2,1],"295":[6,4,33],"296":[2,4,66],"297":[2,4,49],"298":[2,4,56],"299":[2,2,1],"300":[2,4,14],"301":[2,4,65],"302":[2,4,35],"303":[2,4,34],"304":[2,4,6]},"averageFieldLength":[2.5213114754098376,1.8229508196721316,40.00327868852457],"storedFields":{"0":{"title":"贡献,并且帮助我们改进","titles":[]},"1":{"title":"帮助改进 YouQu 文档","titles":["贡献,并且帮助我们改进"]},"2":{"title":"向 YouQu 提交 Issues","titles":["贡献,并且帮助我们改进"]},"3":{"title":"向 YouQu 仓库提交代码","titles":["贡献,并且帮助我们改进"]},"4":{"title":"版本更新记录","titles":[]},"5":{"title":"2.6.9(2024/08/05)","titles":["版本更新记录"]},"6":{"title":"2.6.8(2024/07/15)","titles":["版本更新记录"]},"7":{"title":"2.6.7(2024/07/15)","titles":["版本更新记录"]},"8":{"title":"2.6.6(2024/07/05)","titles":["版本更新记录"]},"9":{"title":"2.6.5(2024/06/11)","titles":["版本更新记录"]},"10":{"title":"2.6.4(2024/06/07)","titles":["版本更新记录"]},"11":{"title":"2.6.3(2024/06/07)","titles":["版本更新记录"]},"12":{"title":"2.6.2(2024/05/29)","titles":["版本更新记录"]},"13":{"title":"2.6.1(2024/05/21)","titles":["版本更新记录"]},"14":{"title":"2.6.0(2024/05/14)","titles":["版本更新记录"]},"15":{"title":"2.5.5(2024/05/10)","titles":["版本更新记录"]},"16":{"title":"2.5.4(2024/05/08)","titles":["版本更新记录"]},"17":{"title":"2.5.3(2024/04/24)","titles":["版本更新记录"]},"18":{"title":"2.5.2(2024/03/27)","titles":["版本更新记录"]},"19":{"title":"2.5.1(2024/03/14)","titles":["版本更新记录"]},"20":{"title":"2.5.0(2024/03/04)","titles":["版本更新记录"]},"21":{"title":"2.4.6(2024/02/26)","titles":["版本更新记录"]},"22":{"title":"2.4.5(2024/01/20)","titles":["版本更新记录"]},"23":{"title":"2.4.4(2024/01/19)","titles":["版本更新记录"]},"24":{"title":"2.4.2(2023/12/27)","titles":["版本更新记录"]},"25":{"title":"2.4.1(2023/12/26)","titles":["版本更新记录"]},"26":{"title":"2.4.0(2023/12/22)","titles":["版本更新记录"]},"27":{"title":"2.3.7(2023/12/15)","titles":["版本更新记录"]},"28":{"title":"2.3.6(2023/12/13)","titles":["版本更新记录"]},"29":{"title":"2.3.5(2023/12/04)","titles":["版本更新记录"]},"30":{"title":"2.3.4(2023/12/04)","titles":["版本更新记录"]},"31":{"title":"2.3.3(2023/11/22)","titles":["版本更新记录"]},"32":{"title":"2.3.2(2023/11/14)","titles":["版本更新记录"]},"33":{"title":"2.3.1(2023/11/08)","titles":["版本更新记录"]},"34":{"title":"2.3.0(2023/10/27)","titles":["版本更新记录"]},"35":{"title":"2.2.4(2023/10/16)","titles":["版本更新记录"]},"36":{"title":"2.2.3(2023/09/15)","titles":["版本更新记录"]},"37":{"title":"2.2.1(2023/09/13)","titles":["版本更新记录"]},"38":{"title":"2.2.0(2023/09/05)","titles":["版本更新记录"]},"39":{"title":"2.1.5(2023/08/31)","titles":["版本更新记录"]},"40":{"title":"2.1.2(2023/08/22)","titles":["版本更新记录"]},"41":{"title":"2.1.0(2023/08/18)","titles":["版本更新记录"]},"42":{"title":"2.0.0(2023/08/16)","titles":["版本更新记录"]},"43":{"title":"1.3.0(2023/07/10)","titles":["版本更新记录"]},"44":{"title":"1.2.9(2023/06/26)","titles":["版本更新记录"]},"45":{"title":"1.2.8(2023/06/09)","titles":["版本更新记录"]},"46":{"title":"1.2.7(2023/06/08)","titles":["版本更新记录"]},"47":{"title":"1.2.6(2023/06/07)","titles":["版本更新记录"]},"48":{"title":"1.2.5(2023/05/16)","titles":["版本更新记录"]},"49":{"title":"1.2.4(2023/02/27)","titles":["版本更新记录"]},"50":{"title":"1.2.3(2023/02/27)","titles":["版本更新记录"]},"51":{"title":"1.2.2(2023/02/08)","titles":["版本更新记录"]},"52":{"title":"1.2.1(2023/01/06)","titles":["版本更新记录"]},"53":{"title":"1.2.0(2022/12/30)","titles":["版本更新记录"]},"54":{"title":"1.1.4(2022/12/14)","titles":["版本更新记录"]},"55":{"title":"1.1.3(2022/10/28)","titles":["版本更新记录"]},"56":{"title":"1.1.2(2022/09/21)","titles":["版本更新记录"]},"57":{"title":"1.1.1(2022/09/19)","titles":["版本更新记录"]},"58":{"title":"1.1.0(2022/09/16)","titles":["版本更新记录"]},"59":{"title":"1.0.2(2022/08/22)","titles":["版本更新记录"]},"60":{"title":"1.0.1(2022/08/12)","titles":["版本更新记录"]},"61":{"title":"YouQu 官方兴趣小组","titles":[]},"62":{"title":"创建一个 APP 工程","titles":[]},"63":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"64":{"title":"创建一条完整的用例","titles":[]},"65":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"66":{"title":"编写用例","titles":["创建一条完整的用例"]},"67":{"title":"Linux DBus 接口自动化测试","titles":[]},"68":{"title":"安装","titles":["Linux DBus 接口自动化测试"]},"69":{"title":"创建一个项目","titles":["Linux DBus 接口自动化测试"]},"70":{"title":"部署环境","titles":["Linux DBus 接口自动化测试"]},"71":{"title":"创建一个 APP 工程","titles":[]},"72":{"title":"修改","titles":["创建一个 APP 工程"]},"73":{"title":"再次执行 env.sh","titles":["创建一个 APP 工程"]},"74":{"title":"创建一条完整的用例","titles":[]},"75":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"76":{"title":"编写用例","titles":["创建一条完整的用例"]},"77":{"title":"HTTP 接口自动化测试","titles":[]},"78":{"title":"安装","titles":["HTTP 接口自动化测试"]},"79":{"title":"创建一个项目","titles":["HTTP 接口自动化测试"]},"80":{"title":"部署环境","titles":["HTTP 接口自动化测试"]},"81":{"title":"创建一个 APP 工程","titles":[]},"82":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"83":{"title":"创建一条完整的用例","titles":[]},"84":{"title":"用例步骤","titles":["创建一条完整的用例"]},"85":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"86":{"title":"编写用例","titles":["创建一条完整的用例"]},"87":{"title":"Linux 桌面 UI 自动化测试","titles":[]},"88":{"title":"安装","titles":["Linux 桌面 UI 自动化测试"]},"89":{"title":"创建一个项目","titles":["Linux 桌面 UI 自动化测试"]},"90":{"title":"部署环境","titles":["Linux 桌面 UI 自动化测试"]},"91":{"title":"远程交互式控制","titles":[]},"92":{"title":"逻辑示意图","titles":["远程交互式控制"]},"93":{"title":"标识文件","titles":["远程交互式控制"]},"94":{"title":"方法编写","titles":["远程交互式控制"]},"95":{"title":"用例编写","titles":["远程交互式控制"]},"96":{"title":"创建一个 APP 工程","titles":[]},"97":{"title":"修改","titles":["创建一个 APP 工程"]},"98":{"title":"再次执行 env.sh","titles":["创建一个 APP 工程"]},"99":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"100":{"title":"创建一条完整的用例","titles":[]},"101":{"title":"用例步骤","titles":["创建一条完整的用例"]},"102":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"103":{"title":"编写用例","titles":["创建一条完整的用例"]},"104":{"title":"Web UI 自动化测试","titles":[]},"105":{"title":"安装","titles":["Web UI 自动化测试"]},"106":{"title":"创建一个项目","titles":["Web UI 自动化测试"]},"107":{"title":"部署环境","titles":["Web UI 自动化测试"]},"108":{"title":"创建一个 APP 工程","titles":[]},"109":{"title":"编辑器打开","titles":["创建一个 APP 工程"]},"110":{"title":"创建一条完整的用例","titles":[]},"111":{"title":"封装用例步骤的方法","titles":["创建一条完整的用例"]},"112":{"title":"编写用例","titles":["创建一条完整的用例"]},"113":{"title":"命令行自动化测试","titles":[]},"114":{"title":"安装","titles":["命令行自动化测试"]},"115":{"title":"创建一个项目","titles":["命令行自动化测试"]},"116":{"title":"部署环境","titles":["命令行自动化测试"]},"117":{"title":"OCR识别","titles":[]},"118":{"title":"背景","titles":["OCR识别"]},"119":{"title":"实现原理","titles":["OCR识别"]},"120":{"title":"使用说明","titles":["OCR识别"]},"121":{"title":"RPC服务端部署","titles":["OCR识别"]},"122":{"title":"负载均衡","titles":["OCR识别"]},"123":{"title":"为什么基于 Nginx 的负载均衡方案不能满足业务需求","titles":["OCR识别","负载均衡"]},"124":{"title":"YouQu 的解决方案","titles":["OCR识别","负载均衡"]},"125":{"title":"链式调用","titles":["OCR识别"]},"126":{"title":"去干扰识别","titles":[]},"127":{"title":"现有右键菜单定位的方案及问题","titles":["去干扰识别"]},"128":{"title":"1. 步长操作法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"129":{"title":"2. 常规图像识别法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"130":{"title":"3. 相对位移法","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"131":{"title":"4. 属性定位","titles":["去干扰识别","现有右键菜单定位的方案及问题"]},"132":{"title":"去干扰识别","titles":["去干扰识别"]},"133":{"title":"图像识别","titles":[]},"134":{"title":"常规识别","titles":["图像识别"]},"135":{"title":"气泡识别","titles":["图像识别"]},"136":{"title":"不依赖 OpenCV 的图像识别方案","titles":["图像识别"]},"137":{"title":"1. 自研图像识别技术","titles":["图像识别","不依赖 OpenCV 的图像识别方案"]},"138":{"title":"2. 基于 RPC 服务实现图像识别","titles":["图像识别","不依赖 OpenCV 的图像识别方案"]},"139":{"title":"动态图像识别","titles":["图像识别"]},"140":{"title":"属性定位","titles":[]},"141":{"title":"背景","titles":["属性定位"]},"142":{"title":"sniff(嗅探器)使用","titles":["属性定位"]},"143":{"title":"元素操作","titles":["属性定位"]},"144":{"title":"框架封装","titles":["属性定位"]},"145":{"title":"方法明细","titles":["属性定位"]},"146":{"title":"相对坐标定位","titles":[]},"147":{"title":"背景","titles":["相对坐标定位"]},"148":{"title":"实现原理","titles":["相对坐标定位"]},"149":{"title":"使用方法","titles":["相对坐标定位"]},"150":{"title":"方法明细","titles":["相对坐标定位"]},"151":{"title":"Ruff","titles":[]},"152":{"title":"安装","titles":["Ruff"]},"153":{"title":"代码检查","titles":["Ruff"]},"154":{"title":"代码格式化","titles":["Ruff"]},"155":{"title":"配置","titles":["Ruff"]},"156":{"title":"执行管理器 - manage.py","titles":[]},"157":{"title":"如何使用","titles":["执行管理器 - manage.py"]},"158":{"title":"本地执行","titles":["执行管理器 - manage.py"]},"159":{"title":"1. 命令行参数","titles":["执行管理器 - manage.py","本地执行"]},"160":{"title":"2. 配置文件","titles":["执行管理器 - manage.py","本地执行"]},"161":{"title":"远程执行","titles":["执行管理器 - manage.py"]},"162":{"title":"1. 多机器分布式异步执行","titles":["执行管理器 - manage.py","远程执行"]},"163":{"title":"2. 多机器分布式异步负载均衡执行","titles":["执行管理器 - manage.py","远程执行"]},"164":{"title":"用例驱动方式","titles":["执行管理器 - manage.py"]},"165":{"title":"指定执行某一个用例","titles":["执行管理器 - manage.py","用例驱动方式"]},"166":{"title":"指定某个目录执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"167":{"title":"执行某个APP工程的所有用例","titles":["执行管理器 - manage.py","用例驱动方式"]},"168":{"title":"根据关键词执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"169":{"title":"根据标签执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"170":{"title":"批量用例ID驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"171":{"title":"测试单驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"172":{"title":"测试套件驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"173":{"title":"本地用例文件驱动执行","titles":["执行管理器 - manage.py","用例驱动方式"]},"174":{"title":"断言","titles":[]},"175":{"title":"用例中使用方法","titles":["断言"]},"176":{"title":"方法明细","titles":["断言"]},"177":{"title":"测试报告","titles":[]},"178":{"title":"目录结构","titles":["测试报告"]},"179":{"title":"定制报告","titles":["测试报告"]},"180":{"title":"查看报告","titles":["测试报告"]},"181":{"title":"键鼠操作","titles":[]},"182":{"title":"常规键鼠操作","titles":["键鼠操作"]},"183":{"title":"特殊场景键鼠操作","titles":["键鼠操作"]},"184":{"title":"方法明细","titles":["键鼠操作"]},"185":{"title":"Wayland 适配","titles":[]},"186":{"title":"WebUI","titles":[]},"187":{"title":"实践方法","titles":["WebUI"]},"188":{"title":"断言方法","titles":["WebUI"]},"189":{"title":"全自动日志——funnylog","titles":[]},"190":{"title":"背景","titles":["全自动日志——funnylog"]},"191":{"title":"实现原理","titles":["全自动日志——funnylog"]},"192":{"title":"日志配置","titles":["全自动日志——funnylog"]},"193":{"title":"使用方法","titles":["全自动日志——funnylog"]},"194":{"title":"失败录屏","titles":[]},"195":{"title":"PMS数据回填","titles":[]},"196":{"title":"本机执行时回填","titles":["PMS数据回填"]},"197":{"title":"远程执行时回填","titles":["PMS数据回填"]},"198":{"title":"可能遇到的“问题”","titles":["PMS数据回填"]},"199":{"title":"标签化管理","titles":[]},"200":{"title":"标签说明","titles":["标签化管理"]},"201":{"title":"操作步骤","titles":["标签化管理"]},"202":{"title":"跳过用例","titles":["标签化管理"]},"203":{"title":"1. 固定跳过","titles":["标签化管理","跳过用例"]},"204":{"title":"2. 条件判断跳过","titles":["标签化管理","跳过用例"]},"205":{"title":"确认修复","titles":["标签化管理"]},"206":{"title":"废弃用例","titles":["标签化管理"]},"207":{"title":"设计思路","titles":["标签化管理"]},"208":{"title":"CSV文件格式","titles":["标签化管理"]},"209":{"title":"导出CSV文件","titles":[]},"210":{"title":"标签自动同步","titles":[]},"211":{"title":"自动同步脚本 ID 到 CSV 文件","titles":["标签自动同步"]},"212":{"title":"从 PMS 自动同步标签到 CSV","titles":["标签自动同步"]},"213":{"title":"远程交互式控制","titles":[]},"214":{"title":"slaves对象提供远程机器信息","titles":["远程交互式控制"]},"215":{"title":"3个Remote远程对象","titles":["远程交互式控制"]},"216":{"title":"Remote.rdog","titles":["远程交互式控制","3个Remote远程对象"]},"217":{"title":"Remote.rctl","titles":["远程交互式控制","3个Remote远程对象"]},"218":{"title":"跨过 rctl 直接调用","titles":["远程交互式控制","3个Remote远程对象","Remote.rctl"]},"219":{"title":"Remote.rctl_plus","titles":["远程交互式控制","3个Remote远程对象"]},"220":{"title":"代码补全","titles":["远程交互式控制"]},"221":{"title":"重启类场景","titles":[]},"222":{"title":"使用方法","titles":["重启类场景"]},"223":{"title":"用例注意事项","titles":["重启类场景"]},"224":{"title":"驱动执行","titles":["重启类场景"]},"225":{"title":"执行环境","titles":["重启类场景"]},"226":{"title":"全局配置 - setting.conf","titles":[]},"227":{"title":"配置文件","titles":["全局配置 - setting.conf"]},"228":{"title":"配置对象获取","titles":["全局配置 - setting.conf"]},"229":{"title":"APP工程配置对象","titles":["全局配置 - setting.conf"]},"230":{"title":"全局配置项明细","titles":["全局配置 - setting.conf"]},"231":{"title":"环境部署 - env.sh","titles":[]},"232":{"title":"安装","titles":["环境部署 - env.sh"]},"233":{"title":"定制依赖","titles":["环境部署 - env.sh"]},"234":{"title":"1. 新增依赖","titles":["环境部署 - env.sh","定制依赖"]},"235":{"title":"2. 裁剪依赖","titles":["环境部署 - env.sh","定制依赖"]},"236":{"title":"开发环境部署","titles":["环境部署 - env.sh"]},"237":{"title":"虚拟环境解释器","titles":["环境部署 - env.sh"]},"238":{"title":"激活虚拟环境","titles":["环境部署 - env.sh"]},"239":{"title":"删除虚拟环境","titles":["环境部署 - env.sh"]},"240":{"title":"依赖治理","titles":["环境部署 - env.sh"]},"241":{"title":"YouQu 是什么?","titles":[]},"242":{"title":"YouQu 能做什么?","titles":["YouQu 是什么?"]},"243":{"title":"爱上 YouQu 的 N 个理由","titles":["YouQu 是什么?"]},"244":{"title":"开源许可证","titles":["YouQu 是什么?"]},"245":{"title":"快速开始","titles":[]},"246":{"title":"安装","titles":["快速开始"]},"247":{"title":"创建项目","titles":["快速开始"]},"248":{"title":"安装依赖","titles":["快速开始"]},"249":{"title":"创建 APP 工程","titles":["快速开始"]},"250":{"title":"运行","titles":["快速开始"]},"251":{"title":"1. 执行管理器","titles":["快速开始","运行"]},"252":{"title":"2. 本地执行","titles":["快速开始","运行"]},"253":{"title":"2.1. 命令行参数","titles":["快速开始","运行","2. 本地执行"]},"254":{"title":"2.2. 配置文件","titles":["快速开始","运行","2. 本地执行"]},"255":{"title":"3. 远程执行","titles":["快速开始","运行"]},"256":{"title":"3.1. 远程多机器分布式异步执行","titles":["快速开始","运行","3. 远程执行"]},"257":{"title":"3.2. 远程多机器分布式异步负载均衡执行","titles":["快速开始","运行","3. 远程执行"]},"258":{"title":"未来规划","titles":[]},"259":{"title":"💡 桌面应用性能自动化测试","titles":["未来规划"]},"260":{"title":"需优化解决的性能自动化问题","titles":["未来规划","💡 桌面应用性能自动化测试"]},"261":{"title":"方案","titles":["未来规划","💡 桌面应用性能自动化测试"]},"262":{"title":"AT 基础框架设计方案","titles":[]},"263":{"title":"一、目标","titles":["AT 基础框架设计方案"]},"264":{"title":"二、设计方案","titles":["AT 基础框架设计方案"]},"265":{"title":"1、统一概念","titles":["AT 基础框架设计方案","二、设计方案"]},"266":{"title":"2、架构图","titles":["AT 基础框架设计方案","二、设计方案"]},"267":{"title":"3、目录结构","titles":["AT 基础框架设计方案","二、设计方案"]},"268":{"title":"三、详细方案","titles":["AT 基础框架设计方案"]},"269":{"title":"1、应用库(apps)","titles":["AT 基础框架设计方案","三、详细方案"]},"270":{"title":"2、核心库(src)","titles":["AT 基础框架设计方案","三、详细方案"]},"271":{"title":"3、公共方法库(public)","titles":["AT 基础框架设计方案","三、详细方案"]},"272":{"title":"4、conftest.py","titles":["AT 基础框架设计方案","三、详细方案"]},"273":{"title":"5、setting","titles":["AT 基础框架设计方案","三、详细方案"]},"274":{"title":"自动化测试架构设计规划","titles":[]},"275":{"title":"一、背景介绍","titles":["自动化测试架构设计规划"]},"276":{"title":"1、原有架构介绍","titles":["自动化测试架构设计规划","一、背景介绍"]},"277":{"title":"2、自动化的应用","titles":["自动化测试架构设计规划","一、背景介绍"]},"278":{"title":"3、存在的问题","titles":["自动化测试架构设计规划","一、背景介绍"]},"279":{"title":"二、方案设计","titles":["自动化测试架构设计规划"]},"280":{"title":"1、架构设计","titles":["自动化测试架构设计规划","二、方案设计"]},"281":{"title":"2、设计思路","titles":["自动化测试架构设计规划","二、方案设计"]},"282":{"title":"三、详细方案","titles":["自动化测试架构设计规划"]},"283":{"title":"1、用例解耦","titles":["自动化测试架构设计规划","三、详细方案"]},"284":{"title":"2、公共库建设","titles":["自动化测试架构设计规划","三、详细方案"]},"285":{"title":"3、用例标签化管理","titles":["自动化测试架构设计规划","三、详细方案"]},"286":{"title":"4、用例执行","titles":["自动化测试架构设计规划","三、详细方案"]},"287":{"title":"5、自动化测试平台","titles":["自动化测试架构设计规划","三、详细方案"]},"288":{"title":"四、实施计划","titles":["自动化测试架构设计规划"]},"289":{"title":"AT 应用库设计方案","titles":[]},"290":{"title":"一、目标","titles":["AT 应用库设计方案"]},"291":{"title":"二、方案设计","titles":["AT 应用库设计方案"]},"292":{"title":"1、分层设计图","titles":["AT 应用库设计方案","二、方案设计"]},"293":{"title":"2、目录结构","titles":["AT 应用库设计方案","二、方案设计"]},"294":{"title":"三、详细方案","titles":["AT 应用库设计方案"]},"295":{"title":"1、基类(base_widget.py)","titles":["AT 应用库设计方案","三、详细方案"]},"296":{"title":"2、操作层","titles":["AT 应用库设计方案","三、详细方案"]},"297":{"title":"3、应用层","titles":["AT 应用库设计方案","三、详细方案"]},"298":{"title":"4、逻辑举例","titles":["AT 应用库设计方案","三、详细方案"]},"299":{"title":"四、工程改造实施步骤","titles":["AT 应用库设计方案"]},"300":{"title":"1、基础框架代码拉取","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"301":{"title":"2、调整工程目录","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"302":{"title":"3、实现核心库接口","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"303":{"title":"4、路径处理","titles":["AT 应用库设计方案","四、工程改造实施步骤"]},"304":{"title":"5、调试和编写用例","titles":["AT 应用库设计方案","四、工程改造实施步骤"]}},"dirtCount":0,"index":[["资源路径",{"2":{"303":1}}],["吧",{"2":{"303":1}}],["想清楚这个方法是干什么的",{"2":{"302":1}}],["别想了",{"2":{"301":1}}],["尽可能",{"2":{"301":1}}],["尽量使用编辑器进行相应的调整",{"2":{"301":1}}],["尽量使用标准库或系统预装库来实现功能",{"2":{"240":1}}],["逻辑举例",{"0":{"298":1}}],["逻辑示意图",{"0":{"92":1}}],["避免方法重名",{"2":{"296":1}}],["界面元素直接与元素名称相同",{"2":{"296":1}}],["界面ui也进行了优化调整",{"2":{"17":1}}],["保险箱弹窗",{"2":{"296":1}}],["保存临时图片的路径",{"2":{"230":1}}],["保存临时图片",{"2":{"139":1}}],["弹窗",{"2":{"296":1}}],["抽取操作层的一些基础方法",{"2":{"295":1}}],["抽取其中重要功能模块",{"2":{"266":1}}],["层划分",{"2":{"292":1}}],["难度也是最大的",{"2":{"291":1}}],["难以集中维护",{"2":{"207":1}}],["落地运行",{"2":{"288":1}}],["静态扫描问题清零",{"2":{"288":1}}],["静态方法",{"2":{"193":1}}],["爬取",{"2":{"288":1}}],["爬虫的性能",{"2":{"58":1}}],["音视频应用代码解耦",{"2":{"288":1}}],["音乐的操作方法类",{"2":{"283":1}}],["音乐用例",{"2":{"223":1}}],["音乐业务层",{"2":{"222":1}}],["音乐",{"2":{"94":1,"271":1}}],["计划结束时间",{"2":{"288":2}}],["计划开始时间",{"2":{"288":2}}],["计算元素按钮坐标",{"2":{"148":1}}],["计算收集用例数量剔除",{"2":{"21":1}}],["计算的汇总数据",{"2":{"12":1}}],["阶段目标",{"2":{"288":2}}],["阶段报错后",{"2":{"54":1}}],["四",{"0":{"288":1,"299":1},"1":{"300":1,"301":1,"302":1,"303":1,"304":1}}],["研发同学等",{"2":{"287":1}}],["研发经理郑幼戈",{"2":{"42":1}}],["镜像下载接口",{"2":{"287":1}}],["镜像版本及下载地址",{"2":{"287":1}}],["镜像版本等",{"2":{"179":1}}],["镜像安装模块等",{"2":{"287":1}}],["又能在资源有限的情况下覆盖了所有的架构",{"2":{"286":1}}],["既能保证执行了所有的用例",{"2":{"286":1}}],["缩短执行总时间",{"2":{"286":1}}],["属于公共方法的则调用",{"2":{"284":1}}],["属性树",{"2":{"141":1}}],["属性定位模块",{"2":{"281":1}}],["属性定位",{"0":{"131":1,"140":1},"1":{"141":1,"142":1,"143":1,"144":1,"145":1},"2":{"147":1}}],["漏洞扫描",{"2":{"286":1}}],["漏洞扫描用例都可以单独触发",{"2":{"281":1}}],["漏洞扫描用例",{"2":{"281":1}}],["漏洞扫描等",{"2":{"281":1}}],["供上层调用",{"2":{"281":1}}],["供用例层使用",{"2":{"17":1}}],["部分模块会涉及到新功能开发",{"2":{"281":1}}],["部署",{"2":{"277":1}}],["部署环境",{"0":{"70":1,"80":1,"90":1,"107":1,"116":1}}],["压测自动化",{"2":{"278":1}}],["压力",{"2":{"200":1}}],["删掉跳过用例的代码",{"2":{"278":1}}],["删除确认弹窗",{"2":{"296":1}}],["删除虚拟环境",{"0":{"239":1}}],["删除弹窗",{"2":{"54":1}}],["费时费力",{"2":{"278":1}}],["很多场景下我们还需要根据用例的等级",{"2":{"278":1}}],["很明显",{"2":{"186":1}}],["很明显不适用于这类元素定位方案",{"2":{"147":1}}],["旨在回归测试时执行自动化测试用例",{"2":{"277":1}}],["验收测试",{"2":{"277":1}}],["持续集成流水线",{"2":{"277":1}}],["流程",{"2":{"277":1}}],["流水线上跑的是",{"2":{"205":1}}],["流水线的用例",{"2":{"200":1}}],["专注于业务功能逻辑",{"2":{"276":1}}],["专项测试等",{"2":{"274":1}}],["业内比较流行的实现方案是使用",{"2":{"287":1}}],["业内为了解决版本冲突问题一般都会使用",{"2":{"42":1}}],["业务层",{"2":{"281":1}}],["业务层根据实际业务需求",{"2":{"281":1}}],["业务逻辑层",{"2":{"276":1}}],["回归测试今年规划建设中",{"2":{"277":1}}],["回归测试",{"2":{"274":1,"277":1}}],["回填数据时",{"2":{"33":1}}],["冒烟测试",{"2":{"274":1,"281":1}}],["天",{"2":{"274":1}}],["天提升至",{"2":{"274":1}}],["天真",{"2":{"190":1}}],["平均编写一条用例从",{"2":{"274":1}}],["平台上的指令实际上都是通过下发给执行器",{"2":{"281":1}}],["平台不跳过",{"2":{"204":1}}],["平台跳过",{"2":{"204":1}}],["平台自动化测试的老演员了",{"2":{"113":1}}],["平台默认登陆账号是超级管理员及密码",{"2":{"75":1}}],["平台",{"2":{"75":1}}],["平台兼容适配性方面",{"2":{"14":1}}],["契合应用独立发布特性",{"2":{"274":1}}],["消除",{"2":{"274":1}}],["消除应用间的耦合关系",{"2":{"265":1}}],["意义",{"2":{"274":1}}],["意思是可以通过",{"2":{"153":1}}],["符合",{"2":{"274":1}}],["符号将两个方法分开",{"2":{"204":1}}],["符号",{"2":{"204":3}}],["符号连接",{"2":{"204":1}}],["符号隔开即可",{"2":{"22":1}}],["运用场景提供支撑",{"2":{"274":1}}],["运行",{"0":{"250":1},"1":{"251":1,"252":1,"253":1,"254":1,"255":1,"256":1,"257":1}}],["运行速度",{"2":{"186":1}}],["形成一套独立于应用间的公共方法库",{"2":{"274":1}}],["形式",{"2":{"21":1,"234":1}}],["根目录下的",{"2":{"272":1}}],["根据业务需要",{"2":{"285":1,"292":1}}],["根据业务需求封装接口业务方法",{"2":{"75":1}}],["根据现有业务需要",{"2":{"200":1}}],["根据标签执行",{"0":{"169":1}}],["根据关键词执行",{"0":{"168":1}}],["根据文件执行用例",{"2":{"159":1,"253":1}}],["根据右下角的坐标按钮的截图区域",{"2":{"150":1}}],["根据右下角的坐标按钮的中心坐标",{"2":{"150":1}}],["根据右上角的坐标按钮的截图区域",{"2":{"150":1}}],["根据右上角的坐标按钮的中心坐标",{"2":{"150":1}}],["根据左下角的坐标按钮的截图区域",{"2":{"150":1}}],["根据左下角的坐标按钮的中心坐标",{"2":{"150":1}}],["根据左上角的坐标按钮的截图区域",{"2":{"150":1}}],["根据左上角的坐标按钮的中心坐标",{"2":{"150":1}}],["根据应用程序中控件元素的相对坐标",{"2":{"150":1}}],["根据应用窗口在屏幕中的位置大小",{"2":{"148":1}}],["根据配置重试次数",{"2":{"134":1}}],["根据匹配度返回坐标",{"2":{"51":1,"134":1,"138":1}}],["根据获取",{"2":{"30":1}}],["根据",{"2":{"12":1}}],["作用和",{"2":{"272":1}}],["作为自动化测试的一个基础框架",{"2":{"263":1}}],["作为标记该用例是否已经修复",{"2":{"205":1}}],["作为变量输出出来了",{"2":{"193":1}}],["作为一个比较新的工具",{"2":{"186":1}}],["作为服务端",{"2":{"162":1,"256":1}}],["命名规则",{"2":{"271":1}}],["命令自动创建",{"2":{"249":1}}],["命令创建一个项目",{"2":{"247":1}}],["命令创建文件",{"2":{"110":1,"111":1,"112":1}}],["命令会生成在",{"2":{"246":1}}],["命令无法使用",{"2":{"246":1}}],["命令无法接收带空格的参数的问题",{"2":{"34":1}}],["命令行",{"2":{"214":1}}],["命令行执行",{"2":{"209":1}}],["命令行传递参数",{"2":{"205":1}}],["命令行传参",{"2":{"196":1}}],["命令行触发",{"2":{"196":1}}],["命令行参数的方式",{"2":{"211":1}}],["命令行参数的优先级高于配置文件配置",{"2":{"157":1}}],["命令行参数",{"0":{"159":1,"253":1}}],["命令行参数指定次数",{"2":{"54":1}}],["命令行使用方式和前面一样",{"2":{"196":1}}],["命令行使用",{"2":{"157":1}}],["命令行自动化测试是",{"2":{"113":1}}],["命令行自动化测试",{"0":{"113":1},"1":{"114":1,"115":1,"116":1},"2":{"242":1}}],["命令",{"2":{"44":1,"161":1,"255":1}}],["命令报错无法找到",{"2":{"35":1}}],["命令报错",{"2":{"26":1}}],["命令实现",{"2":{"11":1}}],["侧边栏",{"2":{"271":1}}],["构造函数的原因是通过参数构造应用",{"2":{"270":1}}],["构建地区",{"2":{"159":1,"253":1}}],["构建了一整套通用的",{"2":{"104":1}}],["见第二章节第3段目录结构内容",{"2":{"269":1}}],["局部配置了执行的用例标签",{"2":{"281":2}}],["局部配置未配置",{"2":{"281":1}}],["局部配置",{"2":{"267":2,"293":2}}],["具体要执行哪一种同样通过参数来控制",{"2":{"286":1}}],["具体功能模块及说明会在下面第四个章节详细描述",{"2":{"265":1}}],["具有可扩展性和复用性",{"2":{"276":1}}],["具有一定的模板作用",{"2":{"271":1}}],["具有较高的重复度",{"2":{"190":1}}],["灵魂",{"2":{"265":1}}],["各个模块只继承基类",{"2":{"296":1}}],["各个应用之间",{"2":{"281":1}}],["各个应用自己的仓库",{"2":{"265":1}}],["各标签所使用对应的字段名称",{"2":{"281":1}}],["各应用都有自己的迭代节奏",{"2":{"278":1}}],["各应用作为其中的一个模块",{"2":{"278":1}}],["各应用之间存在耦合",{"2":{"278":1}}],["各应用",{"2":{"274":1}}],["各应用方法里面不存在被多个应用调用的情况",{"2":{"274":1}}],["各应用能跟随自身迭代周期独立维护",{"2":{"274":1}}],["各种用例标签",{"2":{"203":1,"204":1,"205":1,"206":1,"285":1}}],["优美的执行日志",{"2":{"265":1}}],["优化终端输出失败信息冗长为简要信息输出",{"2":{"57":1}}],["优化执行",{"2":{"51":1}}],["优化远程执行",{"2":{"44":1}}],["优化基于",{"2":{"40":1}}],["优化了通过测试套件执行时pms",{"2":{"58":1}}],["优化了等待的日志输出",{"2":{"47":1}}],["优化了在线文档内容和排版",{"2":{"37":1}}],["优化了",{"2":{"36":1,"39":1,"44":1,"48":1}}],["优化数据回填逻辑",{"2":{"32":1}}],["优化",{"2":{"23":1}}],["优化ocr识别范围筛选方法",{"2":{"5":1}}],["统一成研",{"2":{"274":1}}],["统一概念",{"0":{"265":1}}],["统计功能新增",{"2":{"8":1}}],["二",{"0":{"264":1,"279":1,"291":1},"1":{"265":1,"266":1,"267":1,"280":1,"281":1,"292":1,"293":1}}],["顶配版",{"2":{"261":1}}],["外部应用的操作方法",{"2":{"284":1}}],["外部机器异步解析",{"2":{"261":1}}],["外部开发者肯定访问不到内网的文档",{"2":{"42":1}}],["低配版",{"2":{"261":1}}],["手上有什么设备就用什么方案",{"2":{"261":1}}],["手动回填",{"2":{"196":1,"230":1}}],["手动回填模式报错",{"2":{"11":1}}],["团队中普遍人员代码能力不强",{"2":{"260":1}}],["强制依赖串口线",{"2":{"260":1}}],["强大的日志和报告输出等特色功能",{"2":{"241":1}}],["需实现自动解析",{"2":{"288":1}}],["需优化解决的性能自动化问题",{"0":{"260":1}}],["需要重命名文件或目录",{"2":{"301":1}}],["需要移动",{"2":{"301":1}}],["需要对自动化架构及各功能模块进行重新设计规划",{"2":{"279":1}}],["需要调用多个应用的方法模块",{"2":{"278":1}}],["需要传递参数的采用对象组合",{"2":{"270":1}}],["需要传入参数",{"2":{"219":1}}],["需要你可以在你想要发送的时间点手动触发回填",{"2":{"230":1}}],["需要处理实例化存在异常",{"2":{"223":1}}],["需要各位看官稍微品一品",{"2":{"205":1}}],["需要在每个函数里面主动编写日志输出代码",{"2":{"190":1}}],["需要使用ctrl+shift+v",{"2":{"184":1}}],["需要查找的元素名称",{"2":{"145":1}}],["需要安装deb包的本地路径",{"2":{"159":1,"253":1}}],["需要安装",{"2":{"65":1}}],["需要流水线上把这个参数加上",{"2":{"42":1}}],["数字",{"2":{"249":1}}],["数据格式为一个二维列表",{"2":{"137":1}}],["数据权限",{"2":{"75":1}}],["数据回填的触发者",{"2":{"230":1}}],["数据回填必须关联pms测试单",{"2":{"230":1}}],["数据回填也完成了",{"2":{"196":1}}],["数据回填主要有三种方式",{"2":{"196":1}}],["数据回填",{"2":{"159":1,"253":1}}],["数据回填兼容用例库id和产品库id",{"2":{"55":1}}],["数据回填时",{"2":{"32":1}}],["数据错误的问题",{"2":{"34":1}}],["数据中修复方法数量错误的问题",{"2":{"13":1}}],["数据汇报者统计者的利器",{"2":{"13":1}}],["数据",{"2":{"12":1,"149":1}}],["快速开始",{"0":{"245":1},"1":{"246":1,"247":1,"248":1,"249":1,"250":1,"251":1,"252":1,"253":1,"254":1,"255":1,"256":1,"257":1},"2":{"300":1}}],["快捷键启动终端",{"2":{"217":1}}],["快捷键",{"2":{"184":1}}],["快捷键模块",{"2":{"182":1}}],["随处执行",{"2":{"243":1}}],["随着自动化用例数量的增加",{"2":{"286":1}}],["随着",{"2":{"122":1}}],["真正做到一套代码",{"2":{"243":1}}],["真的非常擅长构建",{"2":{"87":1}}],["硬件兼容",{"2":{"243":1}}],["软硬件兼容",{"2":{"243":1}}],["五彩斑斓的黑",{"2":{"243":1}}],["颜值也绝对在线",{"2":{"243":1}}],["满足你对执行器所有的幻想",{"2":{"243":1}}],["让他们觉得难度有点大",{"2":{"260":1}}],["让定位问题精准高效",{"2":{"243":1}}],["让你可以专注于用例和方法的编写维护",{"2":{"249":1}}],["让你可以方便的在本地执行",{"2":{"243":1}}],["让你再也不用为环境部署而烦恼",{"2":{"243":1}}],["让你能像调用本地方法一样调用远程方法",{"2":{"220":1}}],["让编写自动化测试用例成为一种享受",{"2":{"243":1}}],["爱上",{"0":{"243":1}}],["🌏",{"2":{"242":1}}],["🌟",{"2":{"6":1,"8":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"30":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"42":1,"48":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1}}],["☑",{"2":{"242":5}}],["💡",{"0":{"259":1},"1":{"260":1,"261":1}}],["🕷️",{"2":{"242":1}}],["🚀",{"2":{"242":1}}],["🚌",{"2":{"242":1}}],["💻",{"2":{"242":1}}],["🔥",{"2":{"241":1}}],["🐛ed",{"2":{"58":1}}],["🐛",{"2":{"5":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1}}],["面向服务的架构设计",{"2":{"240":1}}],["应该尽量将三方库里面使用到的部分剥离出来使用",{"2":{"240":1}}],["应用仓库",{"2":{"293":1}}],["应用解耦",{"2":{"288":6}}],["应用下载接口",{"2":{"287":1}}],["应用版本及下载地址",{"2":{"287":1}}],["应用层",{"0":{"297":1},"2":{"281":1}}],["应用层根据实际测试需求",{"2":{"281":1}}],["应用自己的方法库",{"2":{"281":1}}],["应用内局部配置",{"2":{"281":1}}],["应用内局部配置模块",{"2":{"281":1}}],["应用内包含多个测试类型",{"2":{"281":1}}],["应用间用例解耦",{"2":{"274":1}}],["应用",{"2":{"274":1}}],["应用库的仓库命名应该是长这样的",{"2":{"300":1}}],["应用库的架构设计可以参考",{"2":{"269":1}}],["应用库架构图",{"2":{"292":1}}],["应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计",{"2":{"290":1}}],["应用库里面方法基类",{"2":{"270":1}}],["应用库里面使用的时候在",{"2":{"270":1}}],["应用库设计方案",{"0":{"289":1},"1":{"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1},"2":{"269":1}}],["应用库详细目录结构请看应用库设计方案",{"2":{"267":1}}],["应用库",{"0":{"269":1},"2":{"185":1,"265":1,"267":1}}],["应用库只需要维护一套用例脚本即可",{"2":{"185":1}}],["应用库配置文件",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["应用窗口数量",{"2":{"176":1}}],["应用进程数量与期望",{"2":{"176":1}}],["应用进程数量是否为",{"2":{"176":1}}],["应用名",{"2":{"281":1}}],["应用名字",{"2":{"176":3}}],["应用名称",{"2":{"159":1,"253":1}}],["应用包名",{"2":{"150":3}}],["应用中会有相应的光标锁定",{"2":{"142":1}}],["应用的元素",{"2":{"145":2}}],["应用的自动化测试同样可以通过",{"2":{"141":1}}],["应用的方法基类",{"2":{"65":1,"85":1}}],["应用方法主类",{"2":{"85":2}}],["始终保持最少的依赖项",{"2":{"240":1}}],["激活虚拟环境",{"0":{"238":1}}],["存放一个",{"2":{"235":1}}],["存在耦合关系的方法",{"2":{"283":1}}],["存在的问题",{"0":{"278":1}}],["存在跳过标签则用例也不会被执行",{"2":{"203":1}}],["存在系统安全管控的问题",{"2":{"45":1}}],["裁剪依赖",{"0":{"235":1},"2":{"235":1}}],["起始日期",{"2":{"230":1}}],["无工程化设计的缺陷",{"2":{"274":1}}],["无处不在的代码补全",{"2":{"243":1}}],["无需添加",{"2":{"230":1}}],["无法整合性能自动化",{"2":{"278":1}}],["无法精准的划分用例范围",{"2":{"278":1}}],["无法使用上述的键鼠工具",{"2":{"183":1}}],["无法使用的问题",{"2":{"42":1}}],["无法定位到",{"2":{"131":1}}],["无法停止程序运行的问题",{"2":{"50":1}}],["无法连接",{"2":{"50":1}}],["无法管理",{"2":{"42":1}}],["无法收集到用例的问题",{"2":{"36":1}}],["无法获取到",{"2":{"18":1}}],["配合send",{"2":{"230":1}}],["配置模块",{"2":{"281":1}}],["配置的值",{"2":{"228":1}}],["配置对象获取",{"0":{"228":1}}],["配置完之后",{"2":{"196":1}}],["配置完成之后",{"2":{"160":1,"254":1}}],["配置",{"0":{"155":1}}],["配置方法",{"2":{"149":1}}],["配置说明",{"2":{"103":1}}],["配置项的值",{"2":{"134":1}}],["配置项",{"2":{"70":1,"80":1,"90":1,"107":1,"116":1,"157":1,"232":1,"248":1}}],["配置项不生效",{"2":{"26":1}}],["配置python源的几种方法",{"2":{"43":1}}],["配置文件里面",{"2":{"227":1}}],["配置文件方式",{"2":{"211":1,"212":1}}],["配置文件其他相关配置项详细说明",{"2":{"162":1,"256":1}}],["配置文件在",{"2":{"157":1}}],["配置文件",{"0":{"160":1,"227":1,"254":1},"2":{"35":1,"69":1,"79":1,"89":1,"106":1,"115":1,"148":1,"149":1,"157":2,"196":1,"214":1,"227":2,"273":2}}],["配置文件中不管是否配置均不生效",{"2":{"157":1}}],["配置文件中",{"2":{"26":1,"228":1}}],["链接",{"2":{"230":1}}],["链式调用",{"0":{"125":1}}],["套件",{"2":{"230":1}}],["한국어",{"2":{"230":1}}],["日产出用例从",{"2":{"274":1}}],["日本語",{"2":{"230":1}}],["日志模板语法",{"2":{"193":1}}],["日志模块",{"2":{"281":1}}],["日志模块增加白名单",{"2":{"48":1}}],["日志模块修改为函数执行之前打印日志",{"2":{"48":1}}],["日志相关配置",{"2":{"192":1,"230":1}}],["日志配置",{"0":{"192":1}}],["日志文件",{"2":{"178":1}}],["日志输出不仅内容丰富",{"2":{"243":1}}],["日志输出级别",{"2":{"159":1,"253":1}}],["日志输出安装的版本",{"2":{"46":1}}],["日志内容显示为红色的问题",{"2":{"58":1}}],["日志生成到",{"2":{"55":1}}],["日志",{"2":{"27":1,"58":1}}],["русский",{"2":{"230":1}}],["网络重试次数",{"2":{"230":2}}],["网络加速方式加载",{"2":{"39":1}}],["生成的报告类型",{"2":{"227":1,"273":1}}],["生成的html报告",{"2":{"178":1}}],["譬如",{"2":{"227":1,"273":1}}],["跨过",{"0":{"218":1}}],["└─",{"2":{"214":1,"230":2}}],["└──",{"2":{"62":6,"69":1,"71":6,"72":5,"79":1,"81":6,"89":1,"93":2,"96":6,"97":5,"106":1,"108":6,"115":1,"178":10,"249":6,"267":6,"281":3,"293":2}}],["┼─",{"2":{"214":1,"230":2}}],["┌─",{"2":{"214":1,"230":2}}],["附属的测试机",{"2":{"214":1,"230":1}}],["交互的基础能力",{"2":{"213":1}}],["操作的对象是什么",{"2":{"302":1}}],["操作层",{"0":{"296":1},"2":{"302":1}}],["操作层文件名均以",{"2":{"283":1}}],["操作易上手",{"2":{"241":1}}],["操作系统的自动化测试框架",{"2":{"241":1}}],["操作或命令行操作",{"2":{"213":1}}],["操作步骤",{"0":{"201":1}}],["必须要配置的配置项",{"2":{"212":1,"230":1}}],["必须且只能传入其中一组",{"2":{"176":4}}],["节点下指定",{"2":{"212":1}}],["行话叫不要重复造轮子",{"2":{"240":1}}],["行未删除的问题",{"2":{"211":1}}],["行删掉",{"2":{"211":1}}],["到",{"0":{"211":1},"2":{"211":1}}],["于是乎将所有标签使用",{"2":{"207":1}}],["废弃原因",{"2":{"206":1}}],["废弃用例",{"0":{"206":1},"2":{"200":2,"206":2}}],["该列存在",{"2":{"206":1}}],["把配置模块写好",{"2":{"302":1}}],["把",{"2":{"205":1}}],["把每个菜单选项单独截图保存",{"2":{"129":1}}],["另一个需求又不想修复了立马解除跳过",{"2":{"205":1}}],["另外",{"2":{"42":1}}],["干掉",{"2":{"205":1}}],["干嘛不用",{"2":{"137":1}}],["历史",{"2":{"205":1}}],["跑",{"2":{"205":1}}],["已修复",{"2":{"205":2,"206":1}}],["已废弃",{"2":{"200":2,"206":1}}],["固定填入字段为",{"2":{"205":1}}],["固定跳过",{"0":{"203":1}}],["针对某些用例",{"2":{"206":1}}],["针对于某些用例修复后",{"2":{"205":1}}],["针对常规场景及一些特殊场景探索出了一些实用且有效的方案",{"2":{"133":1}}],["剔除中横线和",{"2":{"204":2}}],["剔除跳过数",{"2":{"13":2}}],["若外层执行器也配置了执行标签",{"2":{"281":1}}],["若",{"2":{"230":1}}],["若需要多个",{"2":{"204":1}}],["若函数需要多个参数",{"2":{"204":1}}],["若否则执行用例",{"2":{"204":1}}],["若是",{"2":{"204":1}}],["拼接",{"2":{"204":1}}],["受新需求影响跳过的用例不好维护",{"2":{"278":1}}],["受到某新需求影响",{"2":{"203":1,"205":1,"206":1,"285":1}}],["受安全管控的问题",{"2":{"43":1}}],["转的用例",{"2":{"200":1}}],["预留",{"2":{"200":1}}],["预期值",{"2":{"176":4}}],["安全自动化等专项测试",{"2":{"278":1}}],["安全",{"2":{"200":1}}],["安装部署",{"2":{"248":1}}],["安装依赖",{"0":{"248":1}}],["安装过程耗时等等问题",{"2":{"240":1}}],["安装下载目录下的deb包",{"2":{"230":1}}],["安装它是个很麻烦的事情",{"2":{"119":1}}],["安装速度起飞",{"2":{"42":1}}],["安装之后会自动生成一个系统命令",{"2":{"42":1}}],["安装",{"0":{"68":1,"78":1,"88":1,"105":1,"114":1,"152":1,"232":1,"246":1},"2":{"42":2,"43":1,"44":2,"45":1,"68":1,"70":1,"78":1,"80":1,"88":1,"90":1,"105":1,"107":1,"114":1,"116":1,"246":1}}],["安装包是比较臃肿的",{"2":{"41":1}}],["性能测试等不同测试类型的用例是分开执行的",{"2":{"286":1}}],["性能测试",{"2":{"281":2}}],["性能自动化支持以下功能",{"2":{"261":1}}],["性能",{"2":{"200":1}}],["怎么办呢",{"2":{"205":1}}],["怎么回填一次之后",{"2":{"198":1}}],["怎么解决这个问题呢",{"2":{"132":1}}],["直到所有用例执行结束",{"2":{"196":1}}],["直白的讲就是",{"2":{"196":1}}],["直接点左下角的",{"2":{"301":1}}],["直接在编辑器里面",{"2":{"301":1}}],["直接在用例里面继承",{"2":{"297":1}}],["直接在命令行执行",{"2":{"160":1,"254":1}}],["直接调用",{"0":{"218":1}}],["直接把",{"2":{"205":1}}],["直接修复了对吧",{"2":{"153":1}}],["直接",{"2":{"42":1,"302":1}}],["直接用",{"2":{"41":1}}],["直接拆分字符串可能会导致结果列表的最后一个元素为空字符串",{"2":{"31":1}}],["异步回填",{"2":{"196":1}}],["没关系",{"2":{"271":1,"302":1}}],["没错",{"2":{"193":1}}],["没有名称的就取一个好听易懂的名字",{"2":{"296":1}}],["没有参数的使用继承",{"2":{"270":1}}],["没有进入系统",{"2":{"183":1}}],["没有做相关适配",{"2":{"41":1}}],["没有用到全局配置",{"2":{"25":1}}],["细心的同学可能还发现了一个小细节",{"2":{"193":1}}],["展示在",{"2":{"193":1}}],["终端输出的日志级别",{"2":{"192":1,"230":1}}],["终止坐标",{"2":{"184":4}}],["批量跳过",{"2":{"265":1}}],["批量跳过和批量条件跳过的功能",{"2":{"243":1}}],["批量执行时",{"2":{"192":1,"230":1}}],["批量用例id驱动执行",{"0":{"170":1}}],["给后续其他应用改造提供切实可行的思路和方案",{"2":{"291":1}}],["给想要尝试或者愿意尝试的人员造成了一些困扰",{"2":{"260":1}}],["给符合条件的函数",{"2":{"191":1}}],["给定位环境安装失败带来困难",{"2":{"28":1}}],["核心",{"2":{"278":1}}],["核心层各功能模块保持独立性",{"2":{"281":1}}],["核心层主要服务于操作层",{"2":{"276":1}}],["核心层",{"2":{"276":2,"281":1}}],["核心模块",{"2":{"266":1}}],["核心库自动化测试所要用的到所有底层核心功能",{"2":{"265":1}}],["核心库",{"0":{"270":1},"2":{"265":2,"267":1}}],["核心原理",{"2":{"191":1}}],["核心是在网页的",{"2":{"141":1}}],["那可能需要修改大量涉及到资源路径的地方",{"2":{"303":1}}],["那你只需要修改这一个地方就好了",{"2":{"303":1}}],["那你就需要导入十个",{"2":{"270":1}}],["那些好不容易尝试用起来的人员",{"2":{"260":1}}],["那此用例为失败",{"2":{"197":1}}],["那真是妙啊~",{"2":{"190":1}}],["那么工程改造就全部完成了",{"2":{"304":1}}],["那么你可能不会用到这里面的功能",{"2":{"271":1}}],["那么你需要显示的导入这个模块",{"2":{"270":1}}],["那么一定要注意多个",{"2":{"234":1}}],["那么流水线上执行时这条用例仍然是跳过的状态",{"2":{"205":1}}],["那么也就可以判断图片切换是成功的",{"2":{"139":1}}],["那么在测试切换壁纸或者切换图片的场景时就会存在一个问题",{"2":{"139":1}}],["那么实际上",{"2":{"134":1,"148":1}}],["那么通过",{"2":{"132":1}}],["省略代码部分",{"2":{"190":1}}],["全量测试",{"2":{"281":1}}],["全称为",{"2":{"265":1}}],["全自动日志",{"0":{"189":1},"1":{"190":1,"191":1,"192":1,"193":1}}],["全局替换的方式任然无法保证真的全局被替换了",{"2":{"303":1}}],["全局替换",{"2":{"303":1}}],["全局搜索代码解耦",{"2":{"288":1}}],["全局",{"2":{"162":1,"256":1}}],["全局配置未配置",{"2":{"281":1}}],["全局配置了执行的用例标签",{"2":{"281":2}}],["全局配置和局部配置的策略如下",{"2":{"281":1}}],["全局配置项",{"2":{"281":1}}],["全局配置项明细",{"0":{"230":1}}],["全局配置模块",{"2":{"227":1,"267":1,"273":1,"281":1}}],["全局配置",{"0":{"226":1},"1":{"227":1,"228":1,"229":1,"230":1},"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["稳定性",{"2":{"186":1}}],["稳定性好的元素定位方案",{"2":{"147":1}}],["智能定位",{"2":{"186":1}}],["✔",{"2":{"186":8}}],["✗",{"2":{"186":6}}],["剩下",{"2":{"186":1}}],["排除",{"2":{"186":2}}],["排序方式",{"2":{"128":1}}],["市面上耳熟能详的可用于",{"2":{"186":1}}],["市面上甚至有完全基于图像识别的自动化测试框架",{"2":{"133":1}}],["驱动",{"2":{"236":1}}],["驱动浏览器实现",{"2":{"186":1}}],["驱动执行的时候加",{"2":{"224":1}}],["驱动执行",{"0":{"224":1},"2":{"166":1}}],["完美兼容",{"2":{"243":1}}],["完全通过命令行参数传入",{"2":{"212":1}}],["完全没必要专门拉新分支进行",{"2":{"185":1}}],["完善",{"2":{"186":1}}],["完成新框架使用培训",{"2":{"288":1}}],["完成全局和局部配置的具体方案和逻辑实现",{"2":{"288":1}}],["完成标签化管理和执行",{"2":{"288":5}}],["完成公共方法的抽取整合",{"2":{"274":1}}],["完成",{"2":{"14":1}}],["简单讲就是",{"2":{"185":1}}],["简化项目根目录下文件目录结构",{"2":{"16":1}}],["清理",{"2":{"230":1}}],["清理环境",{"2":{"159":1,"253":1}}],["清空表单",{"2":{"184":2}}],["框选",{"2":{"184":1}}],["框架扩展性不足",{"2":{"278":1}}],["框架只提供",{"2":{"260":1}}],["框架统一提供断言语句",{"2":{"188":1}}],["框架会调用",{"2":{"281":1}}],["框架会根据执行时状态自动判断走不同的逻辑",{"2":{"185":1}}],["框架会自动根据当前环境走不同的代码逻辑",{"2":{"60":1}}],["框架核心库也针对性的做了适配",{"2":{"185":1}}],["框架的运行逻辑",{"2":{"281":1}}],["框架的固定配置文件",{"2":{"272":1}}],["框架的断言库",{"2":{"175":1}}],["框架的很多网络相关功能都是基于此模块实现",{"2":{"77":1}}],["框架封装",{"0":{"144":1}}],["框架默认的配置为",{"2":{"134":1}}],["框架提供导出指定标签用例的功能",{"2":{"209":1}}],["框架提供的标签功能",{"2":{"207":1}}],["框架提供的接口非常简洁",{"2":{"144":1}}],["框架提供了一个图像识别的底层接口",{"2":{"134":1}}],["框架提供灵活可配置的浏览器对象",{"2":{"104":1}}],["框架基于",{"2":{"133":1}}],["框架代码示意",{"2":{"120":1}}],["框架里面只需要调用对应的",{"2":{"119":1}}],["框架还提供一个fixture对象",{"2":{"103":1,"230":1}}],["框架从设计之初",{"2":{"87":1}}],["框架根据全局的",{"2":{"51":1}}],["框架自动回填",{"2":{"230":1}}],["框架自动加载",{"2":{"44":1}}],["框架自动做负载均衡",{"2":{"14":1}}],["框架先做异常处理",{"2":{"32":1}}],["框架移除从",{"2":{"32":1}}],["框架为",{"2":{"17":1}}],["框架必备",{"2":{"13":1,"15":1}}],["项目",{"2":{"249":1}}],["项目根目录下运行",{"2":{"232":1}}],["项目标识文件",{"2":{"97":2}}],["项",{"2":{"184":2}}],["组合按键释放",{"2":{"184":1}}],["组合按键按下不放",{"2":{"184":1}}],["组合键",{"2":{"143":1}}],["放到",{"2":{"284":1}}],["放松",{"2":{"184":1}}],["放松按键",{"2":{"184":1}}],["放入子项目的at代码即可",{"2":{"42":1}}],["间隔",{"2":{"184":1}}],["临时处理",{"2":{"184":1}}],["临时处理input",{"2":{"5":1}}],["粘贴内容后会在末尾会多出一个空格",{"2":{"184":1}}],["延迟时间",{"2":{"184":1}}],["滚动鼠标滚轮",{"2":{"184":1}}],["滚轮数",{"2":{"184":1}}],["滚轮",{"2":{"143":1}}],["松开鼠标",{"2":{"184":1}}],["松开鼠标左键",{"2":{"184":1}}],["键盘组合键",{"2":{"184":1}}],["键盘组合按键操作",{"2":{"184":1}}],["键盘按键",{"2":{"184":3}}],["键盘上指定的按键",{"2":{"184":1}}],["键",{"2":{"184":1}}],["键不放",{"2":{"184":1}}],["键鼠信号模拟模块",{"2":{"281":1}}],["键鼠的基本操作模块",{"2":{"182":1}}],["键鼠操作模块",{"2":{"281":1}}],["键鼠操作模块集成了多个键鼠操作的方案",{"2":{"181":1}}],["键鼠操作的基础方操作模块",{"2":{"276":1}}],["键鼠操作",{"0":{"181":1},"1":{"182":1,"183":1,"184":1}}],["键鼠工具没有鼠标相对移动方法",{"2":{"39":1}}],["键鼠控制方案",{"2":{"33":1}}],["处按住鼠标",{"2":{"184":1}}],["处理那种没有关联关系",{"2":{"303":1}}],["处理这个问题",{"2":{"155":1}}],["处理",{"2":{"27":2}}],["拖拽的相对位置y",{"2":{"184":1}}],["拖拽的相对位置x",{"2":{"184":1}}],["拖拽的时长",{"2":{"184":1}}],["拖拽后等待的时间",{"2":{"184":1}}],["拖拽到的位置y",{"2":{"184":1}}],["拖拽到的位置x",{"2":{"184":1}}],["拖拽到指定位置",{"2":{"184":2}}],["三",{"0":{"268":1,"282":1,"294":1},"1":{"269":1,"270":1,"271":1,"272":1,"273":1,"283":1,"284":1,"285":1,"286":1,"287":1,"295":1,"296":1,"297":1,"298":1}}],["三击鼠标左键",{"2":{"184":1}}],["三方依赖",{"2":{"54":1}}],["三方包",{"2":{"42":1}}],["速度",{"2":{"184":2}}],["特别是在一些配置较低的机器上会很明显",{"2":{"194":1}}],["特别是一些示例",{"2":{"186":1}}],["特殊场景键鼠操作",{"0":{"183":1}}],["特有的",{"2":{"169":1}}],["任何应用接入进来都能快速方便的进行方法和用例编写",{"2":{"265":1}}],["任何应用都能很方便的接入进来",{"2":{"263":1}}],["任何模块当然是希望越简洁通用越好",{"2":{"181":1}}],["任斌",{"2":{"26":1}}],["好用",{"2":{"263":1}}],["好像用不到这么多键鼠操作的东西吧",{"2":{"181":1}}],["好处是参数路径可以在终端补全",{"2":{"50":1}}],["地址",{"2":{"179":1}}],["地址修改为域名",{"2":{"52":1}}],["录屏模块",{"2":{"281":1}}],["录屏是要占用系统资源的",{"2":{"194":1}}],["录屏其实是一种视频形式的日志",{"2":{"194":1}}],["录屏",{"2":{"178":1}}],["录屏外",{"2":{"54":1}}],["缺失",{"2":{"176":2}}],["缺少",{"2":{"176":2}}],["主界面区域划分",{"2":{"296":1}}],["主要通过用例的关键词",{"2":{"278":1}}],["主要封装的底层功能实现",{"2":{"276":1}}],["主要是为了减少代码量",{"2":{"265":1}}],["主要提供配置文件读取",{"2":{"227":1,"273":1}}],["主要配置一些全局的配置项",{"2":{"227":1,"273":1}}],["主题颜色占屏幕总体颜色占比低于60",{"2":{"176":1}}],["主动传入",{"2":{"25":1}}],["深色",{"2":{"176":2}}],["浅色",{"2":{"176":2}}],["建议你使用",{"2":{"303":1}}],["建议分模块",{"2":{"201":1,"285":1}}],["建议最大化窗口",{"2":{"176":1}}],["建议现在上方工具栏点击",{"2":{"142":1}}],["共享文件夹名称",{"2":{"176":2}}],["路径处理",{"0":{"303":1}}],["路径组装方法",{"2":{"295":1}}],["路径",{"2":{"176":6}}],["期望尺寸",{"2":{"176":1}}],["期望结果",{"2":{"176":2}}],["期望的主题",{"2":{"176":1}}],["期望的进程数量",{"2":{"176":1}}],["期望元素不存在",{"2":{"176":1}}],["期望元素存在",{"2":{"176":1}}],["期望不存在文件路径",{"2":{"176":1}}],["期望存在文件路径",{"2":{"176":1}}],["期望界面不存在模板图片",{"2":{"176":1}}],["期望界面存在模板图片",{"2":{"176":1}}],["屏幕上匹配不存在图片",{"2":{"176":1}}],["屏幕上匹配图片",{"2":{"176":2}}],["屏幕恰好出现了两个",{"2":{"132":1}}],["例",{"2":{"176":3}}],["例如`ch`",{"2":{"120":1}}],["例如",{"2":{"87":1,"150":2,"176":2,"190":1,"201":1,"204":1}}],["表格中的用例编号",{"2":{"288":1}}],["表格打开进行编辑",{"2":{"281":1}}],["表达式",{"2":{"168":1,"169":1}}],["表示所有用例执行完成之后逐个回填",{"2":{"230":1}}],["表示所有测试机并行跑",{"2":{"162":1,"256":1}}],["表示逐条异步回填",{"2":{"230":1}}],["表示记录前3个进程",{"2":{"230":1}}],["表示重跑",{"2":{"230":1}}],["表示执行标签带有",{"2":{"230":1}}],["表示导出",{"2":{"209":1}}],["表示用例的id",{"2":{"201":1}}],["表示用例第1次执行失败之后开始录屏",{"2":{"194":2}}],["表示用例第",{"2":{"42":1,"230":1}}],["表示上线到",{"2":{"200":1}}],["表示不回填",{"2":{"230":1}}],["表示不管用例成功或失败都录屏",{"2":{"194":1}}],["表示不做分辨率校验",{"2":{"42":1,"230":1}}],["表示识别任意一个目标字符",{"2":{"176":1}}],["表示识别所有目标字符",{"2":{"176":1}}],["表示测试机分布式执行",{"2":{"162":1,"256":1}}],["表示扫描当前目录下所有的代码",{"2":{"153":1}}],["表示",{"2":{"135":1,"200":1,"285":1}}],["表示大图为截取的屏幕截图",{"2":{"134":1}}],["表示只返回识别到的第一个",{"2":{"134":1}}],["拿第",{"2":{"163":1,"257":1}}],["拿到整个屏幕的大图",{"2":{"134":1}}],["号机执行",{"2":{"163":2,"257":2}}],["台",{"2":{"163":1,"257":1}}],["台机器执行相同的用例",{"2":{"162":1,"256":1}}],["似乎有点难以理解",{"2":{"163":1,"257":1}}],["请提",{"2":{"183":1}}],["请查看配置文件中的注释内容",{"2":{"162":1,"256":1}}],["请手动开启",{"2":{"162":1,"256":1}}],["请求",{"2":{"138":1}}],["请求被分发到两台不同的服务器上",{"2":{"123":1}}],["请求成功",{"2":{"76":1}}],["记得加上参数",{"2":{"162":1,"256":1}}],["记录top命令查询的系统资源占用情况",{"2":{"230":1}}],["记录youqu当前的版本",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["记录依赖youqu的版本",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["除了常用的属性定位",{"2":{"243":1}}],["除了上面这种导入方式",{"2":{"228":1}}],["除了文档方面",{"2":{"186":1}}],["除了这些特有参数以外",{"2":{"162":1,"256":1}}],["除了通过",{"2":{"42":1}}],["搭建测试环境",{"2":{"162":1,"230":1,"256":1}}],["搭建了一个",{"2":{"138":1}}],["控制远程",{"2":{"162":1,"256":1}}],["控件名称",{"2":{"150":1}}],["控件名",{"2":{"150":2}}],["控件长宽",{"2":{"150":4}}],["控件右下角相对于窗口右下角的纵向距离",{"2":{"150":2}}],["控件右下角相对于窗口右下角的横向距离",{"2":{"150":2}}],["控件右上角相对于窗口右上角的纵向距离",{"2":{"150":2}}],["控件右上角相对于窗口右上角的横向距离",{"2":{"150":2}}],["控件左下角相对于窗口左下角的纵向距离",{"2":{"150":2}}],["控件左下角相对于窗口左下角的横向距离",{"2":{"150":2}}],["控件左上角相对于窗口左上角的纵向距离",{"2":{"150":2}}],["控件左上角相对于窗口左上角的横向距离",{"2":{"150":2}}],["控件的中心坐标",{"2":{"150":8}}],["控件高度",{"2":{"150":8}}],["控件宽度",{"2":{"150":8}}],["入参还支持",{"2":{"159":1}}],["过程中记录top命令中的值",{"2":{"159":1,"253":1}}],["过去我们调研和使用过的元素定位操作方法有",{"2":{"127":1}}],["过去咱们",{"2":{"42":1}}],["过去咱们都是使用这样的命令来驱动执行",{"2":{"42":1}}],["过去一段时间咱们经常出现的",{"2":{"42":1}}],["触发者",{"2":{"159":1,"253":1}}],["仅仅用于用例中导入方便",{"2":{"297":1}}],["仅用于属性定位相关操作",{"2":{"216":1}}],["仅驱动执行这一条用例",{"2":{"165":1}}],["仅执行上次失败用例",{"2":{"159":1,"253":1}}],["仅通过skip跳过用例",{"2":{"159":1,"230":1,"253":1}}],["仅支持x11下使用",{"2":{"134":1,"138":1}}],["仅支持传入工程名称的全称",{"2":{"35":1}}],["绝对位置",{"2":{"184":1}}],["绝对路径",{"2":{"150":1}}],["绝大部分的配置项均在",{"2":{"157":1}}],["举例",{"2":{"157":1,"285":2}}],["脚本id",{"2":{"200":1,"203":1,"204":1}}],["脚本",{"2":{"200":1}}],["脚本的结果",{"2":{"12":1}}],["脚手架等功能",{"2":{"156":1}}],["写",{"2":{"270":1}}],["写法",{"2":{"159":1}}],["写入json文件",{"2":{"159":3,"253":3}}],["写入错误代码",{"2":{"155":1}}],["写日志文件报权限不够的问题",{"2":{"18":1}}],["官方在线文档",{"2":{"221":1}}],["官方不支持",{"2":{"186":1}}],["官方表示是可以直接替代",{"2":{"154":1}}],["官方兴趣小组",{"0":{"61":1}}],["效果一定能惊讶到你",{"2":{"243":1}}],["效果会持续优化",{"2":{"179":1}}],["效果很不错对吧",{"2":{"154":1}}],["效果非常好",{"2":{"147":1}}],["接收一个字典",{"2":{"176":2}}],["接下来就可以进行代码格式化",{"2":{"154":1}}],["接口操作模块",{"2":{"276":1,"281":1}}],["接口操作的模块",{"2":{"67":1}}],["接口从而控制远程机器执行用例步骤",{"2":{"213":1}}],["接口",{"2":{"200":1}}],["接口就行了",{"2":{"119":1}}],["接口请求",{"2":{"123":1}}],["接口请求成功",{"2":{"76":1}}],["接口请求创建管理员",{"2":{"76":1}}],["接口测试",{"2":{"76":1,"186":1}}],["接口业务层",{"2":{"75":1}}],["接口的测试",{"2":{"67":1}}],["接口自动化测试是一个传统测试类型",{"2":{"77":1}}],["接口自动化测试",{"0":{"67":1,"77":1},"1":{"68":1,"69":1,"70":1,"78":1,"79":1,"80":1},"2":{"242":2}}],["接口保持不变",{"2":{"59":1}}],["接口改变",{"2":{"50":1}}],["问题",{"0":{"198":1},"2":{"154":1}}],["说明我们代码中没有",{"2":{"154":1}}],["说明图片已经切换了",{"2":{"139":1}}],["格式文件可以方便的使用",{"2":{"281":1}}],["格式化这块",{"2":{"154":1}}],["格式化工具",{"2":{"151":1}}],["格局没打开",{"2":{"186":1}}],["格局小了",{"2":{"137":1}}],["长宽",{"2":{"150":1}}],["长时间不输出日志连接中断的问题",{"2":{"48":1}}],["负数向上",{"2":{"184":1}}],["负数向左",{"2":{"184":1}}],["负数为向下",{"2":{"184":1}}],["负数为下移动",{"2":{"150":2}}],["负数为左移动",{"2":{"150":2}}],["负载均衡",{"0":{"122":1},"1":{"123":1,"124":1}}],["负载均衡驱动模式下自动汇总",{"2":{"12":1}}],["正数向下",{"2":{"184":1}}],["正数向右",{"2":{"184":1}}],["正数为向上",{"2":{"184":1}}],["正数为上移动",{"2":{"150":2}}],["正数为右移动",{"2":{"150":2}}],["正式启用",{"2":{"38":1}}],["高配",{"2":{"261":1}}],["高配版",{"2":{"261":1}}],["高",{"2":{"150":1}}],["高度",{"2":{"51":1,"134":1,"138":1,"139":1,"176":2}}],["您可以在任意目录下",{"2":{"247":1}}],["您可以使用",{"2":{"70":1,"80":1,"90":1,"107":1,"116":1,"232":1,"248":1}}],["您想要获取的窗口为",{"2":{"150":1}}],["窗口的实际大小",{"2":{"176":1}}],["窗口的期望大小",{"2":{"176":1}}],["窗口的基本信息",{"2":{"150":1}}],["窗口置顶并聚焦",{"2":{"150":2}}],["窗口编号列表",{"2":{"150":1}}],["窗口数量",{"2":{"150":1}}],["窗口中心坐标",{"2":{"150":1}}],["窗口右下角坐标",{"2":{"150":1}}],["窗口右上角坐标",{"2":{"150":1}}],["窗口左边界中心坐标",{"2":{"150":1}}],["窗口左下角坐标",{"2":{"150":1}}],["窗口左上角坐标",{"2":{"150":2}}],["窗口宽高等",{"2":{"150":1}}],["窗口信息",{"2":{"150":1}}],["窗管研发",{"2":{"40":1}}],["窗管获取窗口信息的接口",{"2":{"23":1}}],["拉动改变窗口大小时",{"2":{"149":1}}],["读",{"2":{"148":1}}],["读取",{"2":{"207":1}}],["读取小图和大图的rgb值",{"2":{"137":1}}],["读取配置文件config",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["设置界面弹窗",{"2":{"296":1}}],["设计理念",{"2":{"292":1}}],["设计方案",{"0":{"264":1},"1":{"265":1,"266":1,"267":1}}],["设计模式",{"2":{"249":1,"270":1}}],["设计思路",{"0":{"207":1,"281":1}}],["设计稿上点击",{"2":{"148":1}}],["设计图上获取数据",{"2":{"149":1}}],["设计图上获取",{"2":{"148":1}}],["设计图上的源数据修改对应坐标数据就好",{"2":{"147":1}}],["设计图中我们是可以获取到元素按钮相对于应用边框的距离的",{"2":{"148":1}}],["设备类型",{"2":{"35":1,"200":2}}],["带鱼屏",{"2":{"147":1}}],["宽",{"2":{"150":1}}],["宽屏",{"2":{"147":1}}],["宽度",{"2":{"51":1,"134":1,"138":1,"139":1,"176":2}}],["递归查找应用界面的元素",{"2":{"145":1}}],["递归查找子节点",{"2":{"145":2}}],["查找图片",{"2":{"193":2}}],["查找到的元素对象的列表",{"2":{"145":1}}],["查找界面元素",{"2":{"145":1}}],["查找元素的个数与期望一致",{"2":{"176":1}}],["查找元素",{"2":{"145":1}}],["查看每个方法被调用的路径和被调用次数",{"2":{"283":1}}],["查看机器的cpu型号",{"2":{"204":2}}],["查看方法和前面本地执行查看的方法一样",{"2":{"180":1}}],["查看报告",{"0":{"180":1}}],["查看子命令的帮助",{"2":{"157":1}}],["查看它的帮助",{"2":{"157":1}}],["查看",{"2":{"143":1}}],["查看应用的标签",{"2":{"142":1}}],["^",{"2":{"145":1,"155":1,"176":2}}],["位置是在元素的中心",{"2":{"145":1}}],["|",{"2":{"145":1,"184":1,"193":2,"204":4,"223":1}}],["播放所有",{"2":{"148":5}}],["播放",{"2":{"144":1}}],["双击鼠标左键",{"2":{"184":1}}],["双击元素",{"2":{"145":1}}],["双击",{"2":{"143":1}}],["双击等等",{"2":{"132":1}}],["库里面的",{"2":{"143":1}}],["元素等待",{"2":{"186":1}}],["元素个数",{"2":{"176":1}}],["元素不应存在",{"2":{"176":1}}],["元素不存在",{"2":{"176":1}}],["元素的定位和操作方法层",{"2":{"276":1}}],["元素的相对位置和参考系",{"2":{"150":1}}],["元素的对象",{"2":{"144":1,"145":1}}],["元素按钮相对于参考系位置是不变的",{"2":{"149":1}}],["元素按钮相对于应用窗口边界的位置大小",{"2":{"148":1}}],["元素对象名称",{"2":{"296":1}}],["元素对象",{"2":{"145":2}}],["元素定位操作的一些公共方法",{"2":{"295":1}}],["元素定位和操作方法层",{"2":{"276":1}}],["元素定位",{"2":{"145":2}}],["元素定位的问题就转换为",{"2":{"134":1}}],["元素双击",{"2":{"145":1}}],["元素点击",{"2":{"145":1}}],["元素右上角坐标",{"2":{"145":1}}],["元素",{"2":{"145":2}}],["元素大小",{"2":{"145":1}}],["元素左上角坐标",{"2":{"145":2}}],["元素名称",{"2":{"145":2}}],["元素中心坐标",{"2":{"144":1,"145":1}}],["元素操作",{"0":{"143":1}}],["首先想到的就是去搜索看有没有现成的工具直接能用",{"2":{"240":1}}],["首先需要将配置",{"2":{"212":1,"230":1}}],["首先",{"2":{"142":1,"205":1}}],["首先这里的主要操作对象是任务栏",{"2":{"85":1}}],["启动",{"2":{"142":1}}],["启用",{"2":{"21":1}}],["嗅探器",{"0":{"142":1}}],["借助开源工具",{"2":{"141":1}}],["树",{"2":{"141":1}}],["树上查找元素",{"2":{"141":1}}],["树里怎么也找不到",{"2":{"131":1}}],["示意图如下",{"2":{"148":1}}],["示意图",{"2":{"139":1}}],["示例",{"2":{"120":1,"176":2,"178":1,"200":1,"203":1,"204":1,"205":1}}],["壁纸顺序不同",{"2":{"139":1}}],["动作开头",{"2":{"296":1}}],["动作函数的函数对象",{"2":{"132":1}}],["动分配给各个测试机执行",{"2":{"162":1,"256":1}}],["动态加载核心层",{"2":{"281":1}}],["动态获取一些常量",{"2":{"227":1,"273":1}}],["动态获取元素在当前屏幕中的位置",{"2":{"147":1}}],["动态添加标签到用例中",{"2":{"207":1}}],["动态添加日志装饰器",{"2":{"191":1}}],["动态给该类下所有的函数及父类函数添加日志装饰器",{"2":{"191":1}}],["动态图像识别",{"0":{"139":1}}],["客户端",{"2":{"261":2}}],["客户端对象提供的",{"2":{"220":1}}],["客户端代码示意",{"2":{"138":1}}],["客户端使用",{"2":{"138":1}}],["注释的写法等等",{"2":{"271":1}}],["注册自启服务",{"2":{"230":1}}],["注册了",{"2":{"138":1}}],["注意这些修改是会影响到用例代码里面的",{"2":{"302":1}}],["注意是动词",{"2":{"296":1}}],["注意",{"2":{"157":1,"162":1,"176":2,"193":1,"194":1,"230":1,"247":1,"256":1,"301":2,"303":1}}],["注意用例继承了用例基类",{"2":{"86":1}}],["来区分用例是否为核心用例",{"2":{"278":1}}],["来标记这条用例已经修复了",{"2":{"205":1}}],["来实现",{"2":{"138":1}}],["来表示的",{"2":{"130":1}}],["许多语言都是支持的",{"2":{"138":1}}],["我也推荐使用这种方式进行重命名",{"2":{"303":1}}],["我说的是",{"2":{"301":1}}],["我想恢复跳过执行",{"2":{"205":1}}],["我之前就只用",{"2":{"181":1}}],["我用大白话举例描述下",{"2":{"163":1,"257":1}}],["我认为还是可以接受的",{"2":{"137":1}}],["我们是将所有应用看成是一个整体",{"2":{"278":1}}],["我们框架中有不少核心功能都是在这里面进行开发的",{"2":{"272":1}}],["我们还自己设计了一款终端输出主题叫",{"2":{"243":1}}],["我们还提供基于",{"2":{"243":1}}],["我们还增强了报告的功能",{"2":{"14":1}}],["我们采用最新的",{"2":{"205":1}}],["我们采用的方案是",{"2":{"135":1}}],["我们设计出了",{"2":{"190":1}}],["我们发现",{"2":{"190":1}}],["我们从一些方面做对比",{"2":{"186":1}}],["我们提供了另外一种解决方案",{"2":{"183":1}}],["我们推荐第一种使用方法",{"2":{"182":1}}],["我们推出了",{"2":{"14":1}}],["我们需要对",{"2":{"155":1}}],["我们需要截取某个元素的小图进行识别",{"2":{"134":1}}],["我们就可以对元素进行相应的操作",{"2":{"143":1}}],["我们通过索引可以取得元素",{"2":{"143":1}}],["我们只要保证自动化测试用例中",{"2":{"142":1}}],["我们只能创建一个空的同名文件",{"2":{"27":1}}],["我们称之为属性定位",{"2":{"141":1}}],["我们再拿着这张小图在当前屏幕中进行图像识别",{"2":{"139":1}}],["我们截取了当前图片中比较有代表性的位置",{"2":{"139":1}}],["我们基于",{"2":{"138":1}}],["我们的方案每次识别在",{"2":{"137":1}}],["我们承认这套方案",{"2":{"137":1}}],["我们也能实现其功能",{"2":{"137":1}}],["我们也联合研发同学一起解决此问题",{"2":{"131":1}}],["我们自己实现主要有几方面原因",{"2":{"137":1}}],["我们可以轻松的获取到按钮",{"2":{"148":1}}],["我们可以通过传入元素的",{"2":{"143":1}}],["我们可以通过将图片的每个像素的rgb值",{"2":{"137":1}}],["我们可以对元素进行获取",{"2":{"141":1}}],["我们可以截取到整个屏幕的图片",{"2":{"134":1}}],["我们约定将用于元素定位的图片资源放到",{"2":{"134":1}}],["我们实现了图像定位的功能",{"2":{"134":1}}],["我们在",{"2":{"180":1}}],["我们在长时间的思考和摸索中",{"2":{"133":1}}],["我们在右键菜单识别上的突破和创新",{"2":{"132":1}}],["我们最开始想到的方案就是通过属性定位",{"2":{"131":1}}],["我们并不推荐这种操作方案",{"2":{"130":1}}],["我们并不希望直接在",{"2":{"119":1}}],["我们想到将它做成一个",{"2":{"119":1}}],["我们使用",{"2":{"118":1,"205":1}}],["我们计划使用",{"2":{"53":1}}],["我们认为取",{"2":{"24":1}}],["我们坚信这些更新将极大地提升开发者和测试人员的效率",{"2":{"14":1}}],["我们针对用户反馈的多个问题进行了积极的调查和解决",{"2":{"14":1}}],["我们对",{"2":{"14":1,"179":1}}],["我们显著提高了文本识别的准确性和效率",{"2":{"14":1}}],["我们成功在欧拉社区开源",{"2":{"13":1}}],["整体仍然遵循",{"2":{"292":1}}],["整体的框架设计在",{"2":{"266":1}}],["整体识别效果来讲",{"2":{"137":1}}],["整个字符串中可以任意截取字符作为关键词",{"2":{"168":1,"230":1}}],["整合公共库",{"2":{"263":1}}],["整合",{"2":{"16":1}}],["左边视图区域",{"2":{"296":1}}],["左",{"2":{"184":2}}],["左下角按钮的截取区域左上角",{"2":{"150":1}}],["左下角按钮的中心坐标",{"2":{"150":1}}],["左下角的坐标",{"2":{"150":1}}],["左下",{"2":{"149":1}}],["左上",{"2":{"149":1}}],["左上角按钮的截取区域左上角",{"2":{"150":1}}],["左上角按钮的中心坐标",{"2":{"150":1}}],["左上角坐标",{"2":{"150":2}}],["左上角",{"2":{"148":1,"176":4}}],["左上角相对于屏幕左上角",{"2":{"148":1}}],["左上角纵坐标",{"2":{"51":1,"134":1,"138":1,"139":1}}],["左上角横坐标",{"2":{"51":1,"134":1,"138":1,"139":1}}],["左键",{"2":{"143":1,"145":1,"184":2}}],["左右",{"2":{"137":2}}],["虽然识别准确率没问题",{"2":{"137":1}}],["虽然操作很简单",{"2":{"119":1}}],["呢",{"2":{"137":1}}],["甚至有些就没有说明",{"2":{"186":1}}],["甚至有些应用支持自定义菜单",{"2":{"128":1}}],["甚至有没有可能在一些架构上压根儿就不能安装使用",{"2":{"137":1}}],["成功",{"2":{"137":1}}],["减少功能测试的重复劳动力",{"2":{"277":1}}],["减少方法重复编写",{"2":{"274":1}}],["减少应用库代码量和方法维护",{"2":{"263":1}}],["减少环境依赖对于任何软件工程都非常重要",{"2":{"137":1}}],["减少环境依赖",{"2":{"137":1}}],["减少因全屏识别时",{"2":{"54":1}}],["小了",{"2":{"137":1}}],["小图的rgb值",{"2":{"137":1}}],["小图",{"2":{"134":1}}],["都支持逻辑组合",{"2":{"230":1}}],["都为空表示执行",{"2":{"230":1}}],["都是通过",{"2":{"220":1}}],["都不需要再写日志代码",{"2":{"193":1}}],["都还不够好",{"2":{"186":1}}],["都没有匹配到",{"2":{"137":1}}],["都将小图所有的rgb与对应大图的值进行匹配",{"2":{"137":1}}],["赋值给一个变量small",{"2":{"137":1}}],["则调用本应用目录下重写的外部应用方法",{"2":{"284":1}}],["则这个方法存在耦合关系",{"2":{"283":1}}],["则按照局部配置执行",{"2":{"281":1}}],["则按照全局配置执行",{"2":{"281":2}}],["则会按照全局配置执行用例",{"2":{"281":1}}],["则在",{"2":{"284":1}}],["则在外部应用下新建一个",{"2":{"283":1}}],["则在执行时只会执行局部配置已配置的",{"2":{"281":1}}],["则在此列备注具体的跳过原因",{"2":{"203":1,"285":1}}],["则失败用例数达到",{"2":{"230":1}}],["则操作复杂",{"2":{"207":1}}],["则用例不会执行",{"2":{"206":1}}],["则用例不执行",{"2":{"204":1}}],["则新增一列标签名为",{"2":{"206":1}}],["则代码不会执行该条用例",{"2":{"205":1}}],["则执行该用例",{"2":{"204":1}}],["则跳过用例不执行",{"2":{"204":1}}],["则说明大图中不存在小图",{"2":{"137":1}}],["则此时返回小图在大图中的坐标点",{"2":{"137":1}}],["则移动到下一个坐标点",{"2":{"137":1}}],["则匹配成功",{"2":{"137":1}}],["则输出以",{"2":{"31":1}}],["与",{"2":{"176":4}}],["与期望",{"2":{"176":6}}],["与期望个数",{"2":{"176":1}}],["与本地",{"2":{"156":1}}],["与整个屏幕中的rgb进行对比",{"2":{"137":1}}],["与命令行的交互也是相对容易的",{"2":{"113":1}}],["帧",{"2":{"135":1}}],["适应不断丰富的测试场景",{"2":{"279":1}}],["适合在生产环境运行",{"2":{"260":1}}],["适用于各种屏幕分辨率",{"2":{"147":1}}],["适用于查找多个同名称元素",{"2":{"145":1}}],["适用于气泡类的断言",{"2":{"135":1,"176":1}}],["适配",{"0":{"185":1},"2":{"185":1}}],["适配社区版上安装自动化环境",{"2":{"58":1}}],["适配最新的接口",{"2":{"23":1}}],["肯定有至少一张图片能捕捉到气泡",{"2":{"135":1}}],["出现一下就消失",{"2":{"135":1}}],["出现的程序报错问题",{"2":{"58":1}}],["气泡识别指的是",{"2":{"135":1}}],["气泡识别",{"0":{"135":1},"2":{"135":1}}],["函数",{"2":{"200":1,"272":1}}],["函数功能说明中",{"2":{"193":1}}],["函数说明以及函数操作日志",{"2":{"190":1}}],["函数名的重命名都尽量采用这种方案",{"2":{"301":1}}],["函数名",{"2":{"204":1}}],["函数名与参数之间用",{"2":{"204":1}}],["函数名等等都可以做为关键词",{"2":{"168":1,"230":1}}],["函数名称为",{"2":{"204":1}}],["函数名称",{"2":{"72":1,"97":1}}],["函数的所有功能",{"2":{"134":1}}],["取决于应用的用例复杂度",{"2":{"201":1,"285":1}}],["取中间的名称作为",{"2":{"201":1}}],["取全局配置",{"2":{"134":1}}],["取消收藏",{"2":{"120":2}}],["取消收藏字体",{"2":{"120":1}}],["坐标的元素定位模块",{"2":{"276":1}}],["坐标",{"2":{"150":1,"176":10,"295":1}}],["坐标元组",{"2":{"134":1}}],["坐标没有拆包的问题",{"2":{"47":1}}],["隐式等待",{"2":{"134":1}}],["某些用例会因为不同的环境判断用例是否执行",{"2":{"204":1}}],["某些场景下要定位的元素是一些会消失的小弹窗",{"2":{"135":1}}],["某些场景下",{"2":{"134":1}}],["某个元素图片的截图称为",{"2":{"134":1}}],["通常来讲如果你需要使用到其中某一个功能模块",{"2":{"270":1}}],["通常是这样的",{"2":{"190":1}}],["通常在",{"2":{"134":1}}],["通过页面上的一些功能选项进行对应测试任务的管理或触发",{"2":{"287":1}}],["通过编辑器",{"2":{"283":1}}],["通过相应的配置项进行配置",{"2":{"281":1}}],["通过核心层提供一个基础能力",{"2":{"281":1}}],["通过图像识别的元素定位模块",{"2":{"276":1}}],["通过串口线连接控制",{"2":{"261":1}}],["通过远程网络连接控制",{"2":{"261":1}}],["通过服务接口",{"2":{"240":1}}],["通过以下几个配置来控制",{"2":{"212":1}}],["通过命令行参数的方式执行优先级总是最高的",{"2":{"211":1}}],["通过命令行参数配置参数",{"2":{"159":1}}],["通过一下几个配置来控制",{"2":{"211":1}}],["通过获取该函数返回的布尔值",{"2":{"204":1}}],["通过子线程去做第一条用例的数据回填",{"2":{"196":1}}],["通过观察前面的例子",{"2":{"193":1}}],["通过日志输出器将其输出即可",{"2":{"191":1}}],["通过给类加上一个装饰器",{"2":{"191":1}}],["通过经验观察",{"2":{"190":1}}],["通过ocr在范围",{"2":{"176":5}}],["通过ocr未识别到",{"2":{"120":2}}],["通过配置文件配置参数",{"2":{"160":1,"254":1}}],["通过配置元素的x",{"2":{"150":1}}],["通过层级获取元素",{"2":{"145":1}}],["通过属性进行元素定位和操作",{"2":{"145":1}}],["通过属性定位的方式",{"2":{"283":1,"284":1}}],["通过属性定位的元素定位模块",{"2":{"276":1}}],["通过属性定位",{"2":{"85":3}}],["通过返回",{"2":{"138":1}}],["通过前后图片的对比",{"2":{"132":1}}],["通过维护菜单选项",{"2":{"130":1}}],["通过使用键盘上下键",{"2":{"128":1}}],["通过键盘的",{"2":{"128":1}}],["通过",{"2":{"120":1,"137":1,"191":2,"228":1,"276":1,"281":1}}],["通过任务栏打开文件管理器",{"2":{"86":1}}],["通过类名开头",{"2":{"48":1}}],["通过选项来控制安装逻辑",{"2":{"16":1}}],["通过引入",{"2":{"14":1}}],["通过率",{"2":{"13":1}}],["通过数",{"2":{"13":2}}],["详细方案",{"0":{"268":1,"282":1,"294":1},"1":{"269":1,"270":1,"271":1,"272":1,"273":1,"283":1,"284":1,"285":1,"286":1,"287":1,"295":1,"296":1,"297":1,"298":1}}],["详细技术方案",{"2":{"221":1}}],["详细源代码请查看",{"2":{"148":1}}],["详细代码请查看",{"2":{"144":1}}],["详细代码太长不贴了",{"2":{"134":1}}],["详细记录的问题",{"2":{"18":1}}],["截取当前屏幕实时图像保存路径",{"2":{"230":1}}],["截取的左侧字符串作为函数名",{"2":{"204":1}}],["截取屏幕图片的间隔时间",{"2":{"135":1,"176":1}}],["截取屏幕图片的时间",{"2":{"135":2,"176":1}}],["截取屏幕上指定区域图片",{"2":{"134":1,"138":1,"139":1,"230":1}}],["截图的最大次数",{"2":{"135":1}}],["截图",{"2":{"54":1}}],["否则会提示无法连接",{"2":{"162":1,"256":1}}],["否则使用传入的图片",{"2":{"134":1,"138":1}}],["否则走服务",{"2":{"41":1}}],["大多数情况下",{"2":{"240":1}}],["大图的rgb值",{"2":{"137":1}}],["大图默认情况下是截取整个屏幕",{"2":{"134":1}}],["大图",{"2":{"134":2,"138":1}}],["大到添加章节帮助我们提高项目的",{"2":{"1":1}}],["要使用核心库的功能",{"2":{"270":1}}],["要安装deb包的路径",{"2":{"230":1}}],["要导出用例的标签",{"2":{"209":1}}],["要用到的元素都添加了标签即可",{"2":{"142":1}}],["要特殊说明的是",{"2":{"138":1}}],["要识别的模板图片",{"2":{"135":1,"176":1}}],["要识别的图片路径",{"2":{"120":1,"176":2}}],["要获取到目标元素在屏幕中的位置",{"2":{"134":1}}],["等所有用例执行完之后",{"2":{"196":1}}],["等等",{"2":{"185":1,"227":1,"273":1}}],["等建了不同的目录",{"2":{"180":1}}],["等",{"2":{"133":1,"176":1,"227":1,"273":1}}],["等待文件管理器启动",{"2":{"86":1}}],["从功能上将是属于核心库",{"2":{"272":1}}],["从基础框架根目录开始",{"2":{"230":1}}],["从",{"0":{"212":1},"2":{"246":1}}],["从第二列开始及之后的列",{"2":{"201":1,"285":1}}],["从而触发自动化测试任务",{"2":{"281":1}}],["从而减轻应用库代码的维护工作",{"2":{"271":1}}],["从而减少大量日志代码量和重复编写",{"2":{"190":1}}],["从而避免全量引入三方库",{"2":{"240":1}}],["从而进行定位操作",{"2":{"141":1}}],["从上面的例子也可以看出来",{"2":{"190":1}}],["从上到下",{"2":{"184":3}}],["从某个坐标开始画线",{"2":{"184":1}}],["从下到上",{"2":{"184":2}}],["从业务上将处理起来比较麻烦",{"2":{"132":1}}],["从理论上此方案是可行的",{"2":{"130":1}}],["复制",{"2":{"132":3,"184":1}}],["几乎所有多媒体应用都需要通过文管加载资源",{"2":{"284":1}}],["几乎在各方面碾压",{"2":{"186":1}}],["几乎都是指的",{"2":{"157":1}}],["几乎是最优的方案",{"2":{"132":1}}],["几乎满足了所有的断言场景",{"2":{"86":1,"174":1}}],["非常遗憾",{"2":{"131":1}}],["非常重要",{"2":{"97":1}}],["维护用例及其方法",{"2":{"290":1}}],["维护起来有难度",{"2":{"278":1}}],["维护起来有点麻烦",{"2":{"130":1}}],["维护和执行",{"2":{"274":1}}],["维护非常的方便",{"2":{"147":1}}],["维度统计",{"2":{"14":1,"16":1}}],["菜单顺序改变",{"2":{"130":1}}],["菜单选项的坐标计算方法为",{"2":{"130":1}}],["菜单选项的宽",{"2":{"130":1}}],["菜单选项的变化是很大的",{"2":{"128":1}}],["变化的影响",{"2":{"132":1}}],["变化的是菜单的长度",{"2":{"130":1}}],["变更类需求的影响",{"2":{"129":1}}],["鼠标从当前位置拖拽到相对坐标",{"2":{"184":1}}],["鼠标从当前位置拖拽到坐标",{"2":{"184":1}}],["鼠标三连击坐标",{"2":{"184":1}}],["鼠标左键双击坐标",{"2":{"184":1}}],["鼠标右键坐标",{"2":{"184":1}}],["鼠标当前的坐标",{"2":{"184":1}}],["鼠标和键盘的常用操作",{"2":{"184":1}}],["鼠标移动相对坐标位置",{"2":{"184":1}}],["鼠标移动至",{"2":{"184":1}}],["鼠标移动到元素上",{"2":{"145":1}}],["鼠标移动到元素中心位置",{"2":{"143":1}}],["鼠标移至元素",{"2":{"145":1}}],["鼠标中健",{"2":{"145":1}}],["鼠标悬停",{"2":{"143":1}}],["鼠标在桌面不同位置点击右键",{"2":{"130":1}}],["鼠标的当前坐标是可以获取到的",{"2":{"130":1}}],["鼠标点击右键的时候",{"2":{"130":1}}],["且支持用例标签可扩展",{"2":{"281":1}}],["且要方便能使用",{"2":{"208":1}}],["且大小写不敏感",{"2":{"168":1,"230":1}}],["且能明确表示这个元素按钮的名称",{"2":{"149":1}}],["且效率极高",{"2":{"147":1}}],["且包含上面介绍的",{"2":{"134":1}}],["且听我慢慢道来",{"2":{"133":1}}],["且容易受到字体",{"2":{"129":1}}],["且远程操作方法实现了编辑器代码补全",{"2":{"17":1}}],["常量",{"2":{"295":1}}],["常见的场景为在不同架构上判断是否执行",{"2":{"204":1}}],["常见问题等的文档说明",{"2":{"58":1}}],["常规键鼠操作",{"0":{"182":1}}],["常规识别很好理解",{"2":{"134":1}}],["常规识别",{"0":{"134":1}}],["常规图像识别法",{"0":{"129":1}}],["一次导入",{"2":{"270":1}}],["一",{"0":{"263":1,"275":1,"290":1},"1":{"276":1,"277":1,"278":1}}],["一键部署环境",{"2":{"243":1}}],["一切我们给你搞定了",{"2":{"243":1}}],["一些用例资源需要根据",{"2":{"303":1}}],["一些业务层相关的变量",{"2":{"295":1}}],["一些团队并不能找到那么多机器",{"2":{"260":1}}],["一些支持人工修改或自定义的配置项都在",{"2":{"227":1}}],["一些特殊场景下",{"2":{"183":1}}],["一二级bug自动化",{"2":{"200":2}}],["一个应用的功能测试",{"2":{"281":1}}],["一个应用含有大量的操作函数",{"2":{"190":1}}],["一个需求是想修复了立马解除跳过",{"2":{"205":1}}],["一个函数里面至少包含一条日志信息",{"2":{"190":1}}],["一个选项现在的步长是",{"2":{"128":1}}],["一只鸟",{"2":{"139":1}}],["一起技术报国",{"2":{"137":1}}],["一般情况下不涉及修改",{"2":{"135":1}}],["一般不对上层提供调用",{"2":{"134":1}}],["一般是固定的",{"2":{"130":1}}],["一句话讲就是",{"2":{"134":1}}],["一种是面向服务",{"2":{"41":1}}],["按钮",{"2":{"301":1}}],["按钮无效的问题",{"2":{"35":1}}],["按照我们提供给你的接口写用例的操作方法就好了",{"2":{"302":1}}],["按照我们一贯的风格",{"2":{"212":1}}],["按照",{"2":{"301":1}}],["按照文件管理器的界面区域划分为",{"2":{"296":1}}],["按照应用划分存放",{"2":{"265":1}}],["按照注释解决即可",{"2":{"185":1}}],["按照这样的规律将这一行每移动一个坐标点",{"2":{"137":1}}],["按下",{"2":{"184":1}}],["按住键盘按键不放",{"2":{"184":1}}],["按住鼠标键不放",{"2":{"184":1}}],["按住鼠标左键",{"2":{"184":1}}],["按",{"2":{"128":1}}],["按键",{"2":{"128":1}}],["步长操作法",{"0":{"128":1}}],["步骤展示",{"2":{"54":1}}],["种方式传入",{"2":{"214":1}}],["种",{"2":{"127":1}}],["现有跳过用例的方式是在用例脚本里面给用例添加装饰器",{"2":{"285":1}}],["现有右键菜单定位的方案及问题",{"0":{"127":1},"1":{"128":1,"129":1,"130":1,"131":1}}],["现at框架架构图",{"2":{"280":1}}],["现在应用走独立发布",{"2":{"278":1}}],["现在远程机器有",{"2":{"163":1,"257":1}}],["现在将开发到命令行参数",{"2":{"42":1}}],["现在开源到",{"2":{"42":1}}],["去掉用例序号后的字符串",{"2":{"201":1}}],["去掉末尾空格",{"2":{"184":1}}],["去掉批量执行前收集用例的步骤",{"2":{"54":1}}],["去干扰图像识别",{"2":{"132":1}}],["去干扰识别",{"0":{"126":1,"132":1},"1":{"127":1,"128":1,"129":1,"130":1,"131":1,"132":1}}],["段是一样的",{"2":{"123":1}}],["段做哈希",{"2":{"123":1}}],["轮询算法做负载均衡会出现两次",{"2":{"123":1}}],["第一列为用例的",{"2":{"285":1}}],["第一列为脚本",{"2":{"201":1}}],["第一个为",{"2":{"150":1}}],["第二天跑的时候同一个机器上会执行昨天没有执行到的用例",{"2":{"286":1}}],["第二条用例开始跑的时候",{"2":{"196":1}}],["第二种是原生",{"2":{"41":1}}],["第",{"2":{"123":2,"184":2}}],["单独的应用仓库",{"2":{"267":2}}],["单条用例的超时时间",{"2":{"230":1}}],["单条用例超时时间",{"2":{"159":1,"227":1,"253":1,"273":1}}],["单位为秒",{"2":{"230":1}}],["单位是秒",{"2":{"135":1}}],["单位秒",{"2":{"135":1,"176":5}}],["单击鼠标右键",{"2":{"184":1}}],["单击鼠标滚轮中间",{"2":{"184":2}}],["单击",{"2":{"132":1,"143":1}}],["单台服务远不能满足业务需求",{"2":{"122":1}}],["单词的地方都修改成",{"2":{"72":1,"97":1}}],["选择右键菜单中的子菜单选项",{"2":{"184":1}}],["选择右键菜单中的选项",{"2":{"184":2}}],["选择桌面右键菜单中的选项",{"2":{"184":2}}],["选择未收藏字体",{"2":{"120":1}}],["选中目标之后",{"2":{"128":1}}],["选项传入密码",{"2":{"70":1,"80":1,"90":1,"107":1,"116":1,"232":1,"248":1}}],["选项用于传递系统密码",{"2":{"18":1}}],["字母",{"2":{"249":1}}],["字典字段",{"2":{"176":2}}],["字体间距等等需求变更都会影响",{"2":{"129":1}}],["字体大小",{"2":{"129":1}}],["字体管理器界面右侧详情列表",{"2":{"120":1}}],["字段作为判断依据",{"2":{"28":1}}],["收藏字体",{"2":{"120":2}}],["收藏",{"2":{"120":1}}],["收集远程测试机上所有的",{"2":{"12":2}}],["右边视图区域",{"2":{"296":1}}],["右",{"2":{"184":2}}],["右侧就会出现该元素按钮的",{"2":{"149":1}}],["右侧♥",{"2":{"120":1}}],["右下角",{"2":{"176":4}}],["右下角按钮的截取区域左上角",{"2":{"150":1}}],["右下角按钮的中心坐标",{"2":{"150":1}}],["右下角的坐标",{"2":{"150":1}}],["右下",{"2":{"149":1}}],["右上角按钮的截取区域左上角",{"2":{"150":1}}],["右上角按钮的中心坐标",{"2":{"150":1}}],["右上角的坐标",{"2":{"150":1}}],["右上角坐标",{"2":{"145":1}}],["右上",{"2":{"149":1}}],["右键菜单在鼠标的左上",{"2":{"130":1}}],["右键菜单可能出现在鼠标的四个方向",{"2":{"130":1}}],["右键菜单出现的位置是不同的",{"2":{"130":1}}],["右键菜单的元素定位是一个难点",{"2":{"127":1}}],["右键菜单显示",{"2":{"120":1}}],["右键",{"2":{"120":1,"143":1,"145":1,"184":2}}],["右键不生效的问题",{"2":{"47":1}}],["监听客户端请求",{"2":{"120":1}}],["`docstring",{"2":{"155":1}}],["`",{"2":{"155":1}}],["`c901`",{"2":{"155":1}}],["`ch`",{"2":{"120":1,"176":2}}],["`w`",{"2":{"155":1}}],["`e`",{"2":{"155":1}}],["`en`",{"2":{"120":2,"176":2}}],["`f`",{"2":{"155":1}}],["`fr`",{"2":{"120":2,"176":2}}],["`japan`",{"2":{"120":2,"176":2}}],["`korean`",{"2":{"120":2,"176":2}}],["`german`",{"2":{"120":2,"176":2}}],["匹配元素个数",{"2":{"176":1}}],["匹配元素的格式",{"2":{"176":3}}],["匹配相似度",{"2":{"176":2}}],["匹配结果索引",{"2":{"145":1}}],["匹配格式",{"2":{"145":1}}],["匹配失败",{"2":{"137":1}}],["匹配小图里面所有的坐标点",{"2":{"137":1}}],["匹配小图在屏幕中的坐标",{"2":{"134":1,"138":1}}],["匹配从大图的坐标",{"2":{"137":1}}],["匹配度",{"2":{"120":1,"134":1,"138":1,"176":2}}],["匹配模式",{"2":{"19":1}}],["实施计划",{"0":{"288":1}}],["实例",{"2":{"193":1}}],["实例方法",{"2":{"191":1}}],["实际上",{"2":{"228":1}}],["实际尺寸",{"2":{"176":1}}],["实际结果",{"2":{"176":2}}],["实际占比",{"2":{"176":1}}],["实际窗口大小",{"2":{"176":1}}],["实现核心库接口",{"0":{"302":1}}],["实现一个前后端分离的系统",{"2":{"287":1}}],["实现细节",{"2":{"221":1}}],["实现步骤",{"2":{"191":1}}],["实现了一个中间件用以在用例跑测过程中对",{"2":{"124":1}}],["实现原理",{"0":{"119":1,"148":1,"191":1}}],["实践方法",{"0":{"187":1}}],["实践",{"2":{"12":1}}],["你也可以在小弹窗中修改全局替换为局部目录下替换",{"2":{"303":1}}],["你也可以不去管配置文件",{"2":{"212":1}}],["你需要按照核心库方法的调用",{"2":{"302":1}}],["你可千万别直接删了修改名称",{"2":{"301":1}}],["你可以从业务逻辑出发",{"2":{"302":1}}],["你可以参考文件管理器的实际工程代码",{"2":{"302":1}}],["你可以参考上面的设计理念来写",{"2":{"302":1}}],["你可以快速的开始你的",{"2":{"249":1}}],["你可以选择在不同的阶段进行数据回填",{"2":{"230":1}}],["你可以根据自己喜欢选择用哪个",{"2":{"228":1}}],["你可以把",{"2":{"198":1}}],["你可以通过视频文件看到失败用例执行过程都发生了什么",{"2":{"194":1}}],["你可以使用",{"2":{"157":1}}],["你可以直接在系统中使用截图录屏进行尺量",{"2":{"149":1}}],["你可以任意命名",{"2":{"149":1}}],["你可以在这些目录里面去查看对应的测试报告",{"2":{"180":1}}],["你可以在配置文件中每一个配置项上面看到该配置项的使用说明",{"2":{"157":1}}],["你可以在实例化对象的时候显式的传入",{"2":{"150":1}}],["你可以在调用函数的时候",{"2":{"134":1}}],["你可以在",{"2":{"42":1,"179":1}}],["你这个重命名的操作关联了多个模块",{"2":{"301":1}}],["你所有的方法都可以直接写在应用库的业务层",{"2":{"271":1}}],["你想输出什么报告形式都行",{"2":{"243":1}}],["你想不到一个",{"2":{"243":1}}],["你再也不用为每个方法单独写输出日志的代码",{"2":{"243":1}}],["你不需要有额外的导入代码即可使用到所有的方法",{"2":{"182":1}}],["你仍然通过命令行参数进行传参",{"2":{"162":1,"256":1}}],["你们是不是闲的啊",{"2":{"137":1}}],["你只需要在应用库根目录下",{"2":{"235":1}}],["你只需要将你的图片路径传递给这个参数就行",{"2":{"134":1}}],["你只需要知道它就是中文识别的天花板",{"2":{"118":1}}],["你看",{"2":{"132":1,"153":1}}],["你会发现一切都是那么的简单",{"2":{"302":1}}],["你会发现",{"2":{"130":1}}],["感兴趣请查看源码",{"2":{"134":1}}],["感兴趣的可以点这里了解",{"2":{"118":1}}],["感谢王波总",{"2":{"42":1}}],["感谢桌面测试部",{"2":{"40":1}}],["感谢",{"2":{"21":1,"22":1,"23":1,"27":1,"29":1,"30":1,"31":1,"34":2}}],["感谢您参与本项目",{"2":{"0":1}}],["经过前面代码检查并修复之后",{"2":{"154":1}}],["经过大量的调研",{"2":{"118":1}}],["经过和业务专家多轮次讨论和反复验证观察",{"2":{"24":1}}],["传统跳过用例的方式是在用例脚本里面给用例添加装饰器",{"2":{"202":1}}],["传统的日志输出方式",{"2":{"190":1}}],["传统的",{"2":{"118":1,"141":1}}],["传入目标小图的文件名称",{"2":{"137":1}}],["传入目标图片路径",{"2":{"51":1}}],["传入不同的识别度的值",{"2":{"134":1}}],["传入多个识别目标逻辑判断错误的问题",{"2":{"35":1}}],["传入的标签超过",{"2":{"27":1}}],["传入",{"2":{"17":1,"51":1,"57":1}}],["背景介绍",{"0":{"275":1},"1":{"276":1,"277":1,"278":1}}],["背景",{"0":{"118":1,"141":1,"147":1,"190":1},"2":{"134":1,"135":1,"139":1}}],["z0",{"2":{"155":2}}],["za",{"2":{"155":2}}],["zero",{"2":{"111":1}}],["zh",{"2":{"75":2,"230":2}}],["输入的内容",{"2":{"184":1}}],["输入字符串",{"2":{"184":2}}],["输入youqu",{"2":{"103":1}}],["输出原始数据错误的问题",{"2":{"18":1}}],["百度首页搜索",{"2":{"103":1}}],["搜索框中输入关键词",{"2":{"102":1}}],["搜索框输入youqu",{"2":{"101":1}}],["点击某个元素",{"2":{"190":2,"193":1,"283":1,"284":1}}],["点击键盘上指定的按键",{"2":{"184":1}}],["点击坐标",{"2":{"184":1}}],["点击鼠标左键",{"2":{"184":1}}],["点击新建歌单按钮",{"2":{"149":1}}],["点击",{"2":{"149":1,"184":1}}],["点击元素",{"2":{"145":1}}],["点击相应的元素控件",{"2":{"142":1}}],["点击应用名称前面的三角形图标",{"2":{"142":1}}],["点击右键菜单之后再截取一张图",{"2":{"132":1}}],["点击搜索框",{"2":{"102":1,"103":1}}],["点击任务栏上的音乐图标",{"2":{"94":1}}],["点击任务栏上的文件管理器图标",{"2":{"84":1,"85":3,"86":1}}],["访问百度首页",{"2":{"102":1}}],["访问速度更快",{"2":{"42":1}}],["发送代码到测试机",{"2":{"162":1,"230":1,"256":1}}],["发送给",{"2":{"138":1}}],["发送",{"2":{"94":1}}],["发布了新版本",{"2":{"31":2}}],["继电器",{"2":{"261":1}}],["继承操作层的所有类",{"2":{"297":1}}],["继承核心层",{"2":{"295":1}}],["继承的类符合",{"2":{"270":1}}],["继承",{"2":{"175":1,"185":1}}],["继承底层",{"2":{"94":1}}],["继续再按",{"2":{"128":1}}],["继续尝试将一些功能模块拆分为独立构件",{"2":{"35":1}}],["显示协议",{"2":{"87":1,"241":1,"243":1}}],["显示为",{"2":{"58":1}}],["桌面的操作方法",{"2":{"284":1}}],["桌面公共方法类",{"2":{"271":1}}],["桌面公共方法基类",{"2":{"271":1}}],["桌面应用性能自动化测试",{"0":{"259":1},"1":{"260":1,"261":1}}],["桌面应用",{"2":{"242":1}}],["桌面应用大多是采用",{"2":{"141":1}}],["桌面",{"0":{"87":1},"1":{"88":1,"89":1,"90":1},"2":{"87":1}}],["判断当前架构是否为",{"2":{"204":1}}],["判断",{"2":{"84":1,"86":1}}],["判断操作系统的激活状态为激活",{"2":{"64":1,"66":1}}],["封装的方法整理成一个表",{"2":{"288":1}}],["封装",{"2":{"77":1}}],["封装用例步骤的方法",{"0":{"65":1,"75":1,"85":1,"102":1,"111":1}}],["自定义断言模块",{"2":{"281":1}}],["自定义断言",{"2":{"243":1}}],["自定义断言类",{"2":{"176":1}}],["自带多种断言语句",{"2":{"174":1}}],["自带网络接口模块",{"2":{"77":1}}],["自研图像识别技术",{"0":{"137":1}}],["自动安装指定应用版本",{"2":{"281":1}}],["自动安装镜像",{"2":{"281":1}}],["自动环境清理等等",{"2":{"265":1}}],["自动生成多种报告",{"2":{"243":1}}],["自动从pms爬取数据并同步本地csv文件",{"2":{"230":1}}],["自动同步标签到",{"0":{"212":1}}],["自动同步脚本",{"0":{"211":1}}],["自动同步到",{"2":{"37":1}}],["自动将函数说明打印为日志",{"2":{"192":3,"230":3}}],["自动输出日志",{"2":{"243":1}}],["自动输出日志的配置",{"2":{"192":1,"230":1}}],["自动输出的日志",{"2":{"193":1}}],["自动输入日志增加以",{"2":{"18":1}}],["自动的将函数说明作为日志打印出来",{"2":{"190":1}}],["自动化维护变得异常困难",{"2":{"278":1}}],["自动化的应用",{"0":{"277":1}}],["自动化相关的依赖",{"2":{"235":1}}],["自动化大多都是基于浏览器的",{"2":{"141":1}}],["自动化中是不可缺少的",{"2":{"133":1}}],["自动化用例脚本",{"2":{"200":1}}],["自动化用例",{"2":{"103":1}}],["自动化项目",{"2":{"87":1}}],["自动化测试平台作为前端界面系统",{"2":{"287":1}}],["自动化测试平台",{"0":{"287":1},"2":{"281":1}}],["自动化测试架构设计规划",{"0":{"274":1},"1":{"275":1,"276":1,"277":1,"278":1,"279":1,"280":1,"281":1,"282":1,"283":1,"284":1,"285":1,"286":1,"287":1,"288":1}}],["自动化测试架构设计",{"2":{"266":1}}],["自动化测试对应的去跑这些关联的用例",{"2":{"195":1}}],["自动化测试工具",{"2":{"186":1}}],["自动化测试方案",{"2":{"104":1}}],["自动化测试方向也有非常多的技术突破",{"2":{"87":1}}],["自动化测试是一种通用的自动化测试类型",{"2":{"104":1}}],["自动化测试为基础",{"2":{"87":1}}],["自动化测试",{"0":{"87":1,"104":1},"1":{"88":1,"89":1,"90":1,"105":1,"106":1,"107":1},"2":{"186":1,"187":1,"242":2}}],["自动化测试基础框架",{"2":{"42":1,"265":1,"267":1}}],["自动化测试功能",{"2":{"17":1}}],["自动化测试功能和远程交互式控制功能",{"2":{"14":1}}],["自动化测试框架操作方法封装写法",{"2":{"190":1}}],["自动化测试框架在便捷性和稳定性方面迈出了重要的一步",{"2":{"14":1}}],["自动化测试框架迎来了一系列令人振奋的更新",{"2":{"14":1}}],["自动创建的",{"2":{"249":1}}],["自动创建",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1}}],["自动计算出",{"2":{"51":1}}],["备注信息",{"2":{"75":1}}],["管理负载均衡算法时",{"2":{"123":1}}],["管理权限管理员分组数组id",{"2":{"75":1}}],["管理部门范围",{"2":{"75":1}}],["管理员",{"2":{"76":1}}],["管理员照片",{"2":{"75":1}}],["管理员邮箱",{"2":{"75":1}}],["管理员手机号",{"2":{"75":1}}],["管理员姓名",{"2":{"75":1}}],["管理员账号",{"2":{"75":1}}],["管理员api",{"2":{"75":1}}],["角色权限",{"2":{"75":1}}],["关键词驱动支持",{"2":{"168":1}}],["关键词可以是用例对象中的任意字符",{"2":{"168":1,"230":1}}],["关于",{"2":{"132":1}}],["关联角色id",{"2":{"75":1}}],["关闭同步",{"2":{"211":1}}],["关闭终端输出捕获用例执行过程日志快照",{"2":{"57":1}}],["关闭录屏",{"2":{"42":1,"230":1}}],["密码问题",{"2":{"232":1,"248":1}}],["密码",{"2":{"75":1,"159":1,"253":1}}],["qdbus",{"2":{"176":1}}],["qt",{"2":{"141":3}}],["q=0",{"2":{"75":1}}],["quote",{"2":{"155":1}}],["quotes",{"2":{"155":1}}],["quot",{"2":{"17":4,"28":4,"31":2,"134":2,"201":2}}],["及各种网络弹窗",{"2":{"296":1}}],["及子目录无",{"2":{"176":1}}],["及大小",{"2":{"148":1,"149":1}}],["及其相关依赖存在问题",{"2":{"145":1}}],["及",{"2":{"75":1}}],["再逐个进行回填的接口请求",{"2":{"196":1}}],["再或者直接导入键鼠模块使用",{"2":{"182":1}}],["再次扫描就不会再报之前的问题",{"2":{"155":1}}],["再次执行",{"0":{"73":1,"98":1}}],["再进行",{"2":{"132":1}}],["再按",{"2":{"128":1}}],["再一个就是",{"2":{"41":1}}],["底层库用途说明文档编写",{"2":{"288":1}}],["底层核心模块包括",{"2":{"281":1}}],["底层功能库层",{"2":{"276":1}}],["底层src",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["底层基础能力的代码为上层业务服务",{"2":{"3":1}}],["编辑器推荐使用",{"2":{"301":1}}],["编辑器打开",{"0":{"63":1,"82":1,"99":1,"109":1}}],["编码规范",{"2":{"281":1}}],["编写定时自动维护本地",{"2":{"288":1}}],["编写爬虫脚本",{"2":{"288":1}}],["编写和维护用例时只需要自己应用下的方法和公共库即可",{"2":{"281":1}}],["编写和维护更高效",{"2":{"274":1}}],["编写方法时只需要导入一个包就可以使用到核心库提供的所有功能",{"2":{"243":1}}],["编写的",{"2":{"141":1}}],["编写用例时逻辑比较复杂",{"2":{"278":1}}],["编写用例",{"0":{"66":1,"76":1,"86":1,"103":1,"112":1}}],["即为公共方法库",{"2":{"284":1}}],["即应用的用例",{"2":{"276":1}}],["即它是对应用库中的用例生效的",{"2":{"272":1}}],["即使标记了skip",{"2":{"230":1}}],["即第一次用例执行失败会自动重跑",{"2":{"230":1}}],["即",{"2":{"194":1,"230":1}}],["即最后一个窗口",{"2":{"150":1}}],["即重试",{"2":{"134":1}}],["即在一定的时间内",{"2":{"134":1}}],["即可在终端激活当前虚拟环境",{"2":{"238":1}}],["即可实现条件判断跳过",{"2":{"204":1}}],["即可返回在当前屏幕中的中心坐标",{"2":{"137":1}}],["即可返回小图在大图中的中心坐标点",{"2":{"137":1}}],["即可轻松计算出菜单选项在屏幕中的坐标",{"2":{"130":1}}],["即可",{"2":{"120":1,"128":1,"134":1,"196":1,"222":1,"232":1,"270":1}}],["即可启动工具",{"2":{"65":1}}],["即任意一个匹配成功则通过",{"2":{"19":1}}],["其丰富的自定义配置项",{"2":{"243":1}}],["其使用简单且高效",{"2":{"243":1}}],["其在pms上的音乐用例库的url为",{"2":{"212":1,"230":1}}],["其根本问题就是标签分散在每一条用例的装饰器上",{"2":{"207":1}}],["其效果一定能惊讶到你",{"2":{"147":1}}],["其实",{"2":{"131":1}}],["其中功能测试设计思路",{"2":{"281":1}}],["其中有一张图片识别成功即返回结果",{"2":{"135":1,"176":1}}],["其中",{"2":{"65":1,"237":1}}],["其他人员也就可想而知",{"2":{"260":1}}],["其他的都不需要",{"2":{"235":1}}],["其他的一些配置也可以根据自己的一些需要进行配置",{"2":{"155":1}}],["其他方法类",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["其他应用的基于相对位移元素定位方案的配置文件",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["其他文字的干扰",{"2":{"54":1}}],["其他一些小小功能更新",{"2":{"42":1}}],["授权接口对象",{"2":{"65":1}}],["打开进行编辑查看",{"2":{"208":1}}],["打开",{"2":{"63":1,"82":1,"99":1,"109":1}}],["│\\t└──",{"2":{"166":1}}],["│\\t├──",{"2":{"166":1}}],["│",{"2":{"62":60,"71":60,"72":49,"81":60,"93":24,"96":60,"97":51,"108":60,"166":5,"178":14,"249":10,"267":68,"281":27,"293":15}}],["├──",{"2":{"62":21,"69":8,"71":21,"72":17,"79":8,"81":21,"89":8,"93":8,"96":21,"97":18,"106":8,"108":21,"115":8,"166":4,"178":12,"234":4,"235":2,"249":21,"267":41,"281":13,"293":18}}],["工程改造实施步骤",{"0":{"299":1},"1":{"300":1,"301":1,"302":1,"303":1,"304":1}}],["工程这部分代码即可",{"2":{"249":1}}],["工程遵循完整的",{"2":{"249":1}}],["工程中的资源",{"2":{"219":1}}],["工程的功能",{"2":{"219":1}}],["工程自有断言模块",{"2":{"175":1}}],["工程名称需要符合",{"2":{"249":1}}],["工程名称命名规范",{"2":{"249":1}}],["工程名称",{"2":{"159":1,"249":1,"253":1}}],["工程里面",{"2":{"134":1}}],["工程",{"0":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1},"1":{"63":1,"72":1,"73":1,"82":1,"97":1,"98":1,"99":1,"109":1},"2":{"62":2,"71":2,"81":2,"96":2,"108":2,"249":2}}],["工具查看",{"2":{"65":1,"85":1}}],["工具",{"2":{"56":1}}],["定位模块",{"2":{"281":1}}],["定位的方案写法",{"2":{"271":1}}],["定位的坐标配置文件",{"2":{"267":1,"293":1}}],["定位配置文件路径",{"2":{"150":1}}],["定制依赖",{"0":{"233":1},"1":{"234":1,"235":1}}],["定制",{"2":{"179":1}}],["定制报告",{"0":{"179":1}}],["定制修改allure报告logo",{"2":{"54":1}}],["定能碰撞出智慧的火花",{"2":{"61":1}}],["相关的模块是否也一起改名了",{"2":{"301":1}}],["相关环境就准备好了",{"2":{"98":1}}],["相互之间是独立的",{"2":{"271":1}}],["相互之间不影响",{"2":{"42":1}}],["相册的用例文件为",{"2":{"201":1}}],["相册切换图片类的测试场景",{"2":{"139":1}}],["相当于帧率为",{"2":{"135":1}}],["相似度",{"2":{"134":1}}],["相对项目根目录下",{"2":{"230":1}}],["相对移动到位置",{"2":{"184":1}}],["相对坐标",{"2":{"150":1}}],["相对坐标定位方案是是一种基于",{"2":{"147":1}}],["相对坐标定位",{"0":{"146":1},"1":{"147":1,"148":1,"149":1,"150":1}}],["相对于鼠标位置的距离",{"2":{"130":1}}],["相对位置",{"2":{"130":1,"184":1}}],["相对位移法",{"0":{"130":1}}],["相对位移元素定位方案的配置文件",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["相信通过大家的共同努力",{"2":{"61":1}}],["分层设计图",{"0":{"292":1}}],["分布式轮换执行的功能",{"2":{"286":1}}],["分布式轮换执行",{"2":{"286":1}}],["分布式执行",{"2":{"265":1}}],["分钟",{"2":{"274":1}}],["分钟降低至",{"2":{"274":1}}],["分割",{"2":{"214":1}}],["分别用",{"2":{"200":1,"285":1}}],["分别是",{"2":{"182":1}}],["分别按照机器的",{"2":{"180":1}}],["分别为",{"2":{"149":1}}],["分享和成长的平台",{"2":{"61":1}}],["分辨率检查功能支持多组分辨率",{"2":{"17":1}}],["致力于为广大自动化技术爱好者提供一个交流",{"2":{"61":1}}],["源代码",{"2":{"60":1}}],["兼容现有用例标签",{"2":{"281":1}}],["兼容性测试主要通过",{"2":{"281":1}}],["兼容性",{"2":{"200":1}}],["兼容",{"2":{"60":1,"87":1}}],["偶现异常",{"2":{"59":1}}],["列填入",{"2":{"204":1}}],["列填入函数名和参数",{"2":{"204":1}}],["列有的写了",{"2":{"58":1}}],["列没写表头",{"2":{"58":1}}],["忽略",{"2":{"57":1}}],["秒",{"2":{"57":1}}],["当",{"2":{"205":1}}],["当用例执行完之后",{"2":{"196":1}}],["当元素按钮位置相对于应用界面位置发生修改之后",{"2":{"147":1}}],["当前鼠标坐标",{"2":{"184":1}}],["当前子节点",{"2":{"145":2}}],["当前指定第几条",{"2":{"57":1}}],["当然你也可以直接通过",{"2":{"182":1}}],["当然你可以指定一个具体的目录或文件",{"2":{"153":1}}],["当然",{"2":{"42":2,"137":1,"271":1,"303":1}}],["总共执行",{"2":{"230":1}}],["总执行用例数为",{"2":{"230":1}}],["总结",{"2":{"186":1}}],["总数剔除",{"2":{"55":1}}],["总的来说",{"2":{"14":1}}],["更符合断言的使用习惯",{"2":{"297":1}}],["更好的发挥自动化测试的作用",{"2":{"279":1}}],["更重要的是这一切使用起来都非常简单",{"2":{"265":1}}],["更重要的是确保创建工程的规范性",{"2":{"249":1}}],["更重要的是",{"2":{"218":1}}],["更重要的是我们不想引入三方依赖",{"2":{"208":1}}],["更换成",{"2":{"55":1}}],["更新贡献者名单",{"2":{"19":1}}],["更新",{"2":{"12":1,"13":1}}],["依赖安装下载过程网络波动导致安装失败",{"2":{"240":1}}],["依赖安装的逻辑",{"2":{"48":1}}],["依赖关系就越复杂",{"2":{"240":1}}],["依赖项越多",{"2":{"240":1}}],["依赖最少化",{"2":{"240":1}}],["依赖治理的意义",{"2":{"240":1}}],["依赖治理思路",{"2":{"240":1}}],["依赖治理原则",{"2":{"240":1}}],["依赖治理",{"0":{"240":1}}],["依赖库",{"2":{"234":1}}],["依赖主控机的用例",{"2":{"200":1}}],["依赖外设的用例",{"2":{"200":1}}],["依赖",{"2":{"55":1,"138":1}}],["未来随着业务的变化可能需要增加各种各样的标签",{"2":{"286":1}}],["未来规划",{"0":{"258":1},"1":{"259":1,"260":1,"261":1}}],["未来有希望成为",{"2":{"13":1}}],["未指定版本则安装最新版",{"2":{"234":1}}],["未识别到",{"2":{"176":3}}],["未写入",{"2":{"54":1}}],["后期越容易出问题",{"2":{"240":1}}],["后面标签化管理章节会讲到",{"2":{"281":1}}],["后面第四章会讲到细节",{"2":{"272":1}}],["后面不加参数",{"2":{"247":1}}],["后面部分是生成的随机字符串",{"2":{"237":1}}],["后面一条执行开始时通过子线程对前一条用例的执行结果进行回填",{"2":{"230":1}}],["后面想再次回填就不生效了",{"2":{"198":1}}],["后面提到的一些命令行参数也都默认是在",{"2":{"157":1}}],["后无法执行用例的问题",{"2":{"54":1}}],["后续只能手动解决",{"2":{"301":1}}],["后续执行同理",{"2":{"286":1}}],["后续编写新增自动化用例时",{"2":{"285":1}}],["后续可以根据需要嫁接进来",{"2":{"281":1}}],["后续解除跳过的时候又需要找到这条脚本",{"2":{"278":1}}],["后续用例继续执行",{"2":{"230":1}}],["后续你打",{"2":{"205":1}}],["后续需要新增用例标签",{"2":{"201":1,"285":1}}],["后续就不会再此触发回填了",{"2":{"198":1}}],["后续手动回填方法",{"2":{"196":1}}],["后续手动将结果进行回填请求",{"2":{"196":1}}],["后续版本将不需要在系统中安装dogtail",{"2":{"60":1}}],["后续版本再考虑针对此接口做修改",{"2":{"41":1}}],["后续使用",{"2":{"54":1}}],["后续专注于本地执行功能开发",{"2":{"44":1}}],["后续均通过",{"2":{"42":1}}],["后续在",{"2":{"28":1}}],["后续默认不再使用",{"2":{"16":1}}],["后续将以",{"2":{"13":1}}],["ja",{"2":{"230":1}}],["javascript",{"2":{"186":2}}],["jinja2",{"2":{"193":1}}],["jenkins",{"2":{"54":1}}],["json三种形式的报告",{"2":{"178":1}}],["json报告",{"2":{"178":1}}],["json=data",{"2":{"75":2}}],["json",{"2":{"12":12,"13":2,"14":2,"16":1,"28":1,"54":1,"75":4,"178":4,"230":3}}],["断言库",{"2":{"281":1}}],["断言的图片资源目录",{"2":{"293":1}}],["断言的图片资源",{"2":{"267":1}}],["断言方法模块",{"2":{"267":1,"293":1}}],["断言方法",{"0":{"188":1}}],["断言方法类",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["断言关键字",{"2":{"176":2}}],["断言路径下是否存在以",{"2":{"176":1}}],["断言图片尺寸",{"2":{"176":1}}],["断言结果为假",{"2":{"176":1}}],["断言结果为真",{"2":{"176":1}}],["断言不相等",{"2":{"176":1}}],["断言不存在共享文件夹",{"2":{"176":1}}],["断言相等",{"2":{"176":1}}],["断言主题是否为",{"2":{"176":1}}],["断言主题",{"2":{"176":1}}],["断言共享目录中存在",{"2":{"176":1}}],["断言共享目录中不存在",{"2":{"176":1}}],["断言共享目录中是否存在",{"2":{"176":2}}],["断言存在共享文件夹",{"2":{"176":1}}],["断言应用窗口数量",{"2":{"176":3}}],["断言应用进程的数量",{"2":{"176":1}}],["断言应用进程状态",{"2":{"176":2}}],["断言应用进程是否存在",{"2":{"176":1}}],["断言实际窗口大小",{"2":{"176":1}}],["断言窗口大小与期望一致",{"2":{"176":1}}],["断言元素出现的个数",{"2":{"176":1}}],["断言元素不存在",{"2":{"176":1}}],["断言元素存在",{"2":{"176":1}}],["断言文案不存在",{"2":{"176":1}}],["断言文案存在",{"2":{"120":1,"176":1}}],["断言文件不存在",{"2":{"176":1}}],["断言文件存在",{"2":{"176":1}}],["断言",{"0":{"174":1},"1":{"175":1,"176":1},"2":{"84":1,"86":1,"176":2}}],["断言函数的调用也会自动打印日志",{"2":{"54":1}}],["断言音乐的删除弹窗中",{"2":{"54":1}}],["所属管理员分组id",{"2":{"75":1}}],["所有应用是整体发布",{"2":{"278":1}}],["所有应用库均放置在基础框架下的",{"2":{"269":1}}],["所有应用库配置对象都是继承框架的全局配置类的",{"2":{"229":1}}],["所有用例执行的超时时间",{"2":{"230":1}}],["所有用例执行完之后不做回填的接口请求",{"2":{"196":1}}],["所有用例执行完之后会在",{"2":{"162":1,"256":1}}],["所有条件判断跳过的函数写在此文件中",{"2":{"204":1}}],["所有",{"2":{"201":1}}],["所有匹配的位置的元组组成的列表",{"2":{"184":1}}],["所有功能的驱动执行都是通过",{"2":{"157":1}}],["所有标签以",{"2":{"142":1}}],["所有的编码风格都是趋于相同的",{"2":{"271":1}}],["所有的远程调用方法",{"2":{"220":1}}],["所有的方法",{"2":{"216":1}}],["所有的方法都在",{"2":{"65":1,"75":1,"85":1}}],["所有的报告相关的文件会统一存放在里面",{"2":{"178":1}}],["所有的用例都在",{"2":{"66":1,"76":1,"86":1,"103":1,"112":1}}],["所有音乐按钮",{"2":{"54":1}}],["所以你仍然需要手动看下各处是否修改到位",{"2":{"303":1}}],["所以你需要考虑是否有必要每条用例都录屏",{"2":{"194":1}}],["所以存在应用间方法交叉调用的问题",{"2":{"278":1}}],["所以需要处理这个问题",{"2":{"223":1}}],["所以",{"2":{"148":1}}],["所以逻辑也是一样的",{"2":{"141":1}}],["所以我这里是推荐加",{"2":{"42":1}}],["所以她那边的项目调用此定制接口会报",{"2":{"41":1}}],["所以本次",{"2":{"41":1}}],["​\\t",{"2":{"266":2,"276":1,"280":1,"292":1,"296":1}}],["​\\timage",{"2":{"54":1}}],["​\\t\\t后两种入参方式可以很方便在输入命令的过程中使用补全",{"2":{"48":1}}],["▀▀█",{"2":{"54":1}}],["▄",{"2":{"54":2}}],["▄█",{"2":{"54":2}}],["█",{"2":{"54":4}}],["██║▄▄",{"2":{"54":1}}],["██║",{"2":{"54":20}}],["██╔═══██╗",{"2":{"54":2}}],["██╔╝",{"2":{"54":1}}],["██████╗",{"2":{"54":2}}],["██╗",{"2":{"54":6}}],["╚══▀▀═╝",{"2":{"54":1}}],["╚═════╝",{"2":{"54":3}}],["╚═╝",{"2":{"54":1}}],["╚██████╔╝",{"2":{"54":4}}],["╚████╔╝",{"2":{"54":1}}],["╚██╔╝",{"2":{"54":1}}],["╚██╗",{"2":{"54":1}}],["最终的用例状态会被标记为",{"2":{"285":1}}],["最终的用例状态会被标签为",{"2":{"203":1}}],["最常用的方法类",{"2":{"271":1}}],["最完美的方案",{"2":{"261":1}}],["最大匹配次数",{"2":{"176":2}}],["最大匹配超时",{"2":{"176":2}}],["最大失败用例数量的占比",{"2":{"230":1}}],["最大失败率",{"2":{"159":1,"253":1}}],["最大失败次数",{"2":{"54":1}}],["最强代码检查",{"2":{"151":1}}],["最后按回车或者鼠标点",{"2":{"301":1}}],["最后进行自动化测试",{"2":{"277":2}}],["最后在断言的时候再将图片路径作为参数传入断言语句即可",{"2":{"139":1}}],["最后将识别结果返回给测试机",{"2":{"138":1}}],["最后再对这一堆图片逐个进行图像识别",{"2":{"135":1}}],["最后移除掉一些不相关的文件",{"2":{"72":1,"97":1}}],["最有名的一个开源项目",{"2":{"118":1}}],["最新版本的检查",{"2":{"34":1}}],["最新的",{"2":{"17":1,"103":1,"104":1}}],["\\tdef",{"2":{"298":1}}],["\\tpass",{"2":{"297":2}}],["\\tcls",{"2":{"134":1}}],["\\t\\t",{"2":{"120":1}}],["\\t",{"2":{"120":1,"298":1}}],["\\t200",{"2":{"54":1}}],["\\t49",{"2":{"54":1}}],["\\t11880s",{"2":{"54":1}}],["\\t1",{"2":{"54":1}}],["\\t99",{"2":{"54":1}}],["如执行哪个应用",{"2":{"287":1}}],["如功能测试",{"2":{"281":1}}],["如下图",{"2":{"266":1}}],["如下图所示",{"2":{"129":1,"130":1,"132":1}}],["如依赖关系错乱冲突导致安装失败",{"2":{"240":1}}],["如项目根目录绝对路径",{"2":{"227":1,"273":1}}],["如何使用",{"0":{"157":1}}],["如此实现时间效率最大化",{"2":{"230":1}}],["如此循环",{"2":{"196":1}}],["如此循环直到所有用例执行完",{"2":{"163":1,"257":1}}],["如此即可消除干扰",{"2":{"132":1}}],["如此",{"2":{"128":1}}],["如",{"2":{"54":1,"134":2,"219":1,"230":1,"274":1,"281":1,"283":1}}],["如果所有用例都调试通过了",{"2":{"304":1}}],["如果快捷键没反应",{"2":{"301":1}}],["如果没有被编辑器自动处理的路径问题",{"2":{"301":1}}],["如果没有开启",{"2":{"162":1,"256":1}}],["如果已经标记了跳过原因",{"2":{"285":1}}],["如果某个方法被",{"2":{"283":1,"284":1}}],["如果某条用例需要单独配置超时时间",{"2":{"230":1}}],["如果在局部配置里面配置了用例执行标签",{"2":{"281":1}}],["如果在大图的其中一个坐标点上匹配到了小图的所有rgb值",{"2":{"137":1}}],["如果在大图的",{"2":{"137":1}}],["如果确实需要引入三方库",{"2":{"240":1}}],["如果多个应用库都存在",{"2":{"234":1}}],["如果接口请求失败",{"2":{"230":1}}],["如果是远程执行",{"2":{"230":1}}],["如果是其他第三方的浏览器可以指定浏览器对应的路径",{"2":{"103":1,"230":1}}],["如果第",{"2":{"230":1}}],["如果一条用例的执行时间超时",{"2":{"230":1}}],["如果这里有值",{"2":{"230":1}}],["如果这条用例之前已经回填过了",{"2":{"198":1}}],["如果有对象实例化的",{"2":{"223":1}}],["如果有多个窗口",{"2":{"31":1}}],["如果$",{"2":{"214":1,"230":2}}],["如果应用库还需要其他",{"2":{"234":1}}],["如果应用库同样使用了系统安装的",{"2":{"60":1}}],["如果应用受到新需求影响需要跳过",{"2":{"203":1,"285":1}}],["如果比较复杂操作步骤",{"2":{"190":1}}],["如果还需要其他的操作方法",{"2":{"183":1}}],["如果远程机器没有搭建自动化测试环境",{"2":{"162":1,"256":1}}],["如果为yes",{"2":{"162":1,"230":1,"256":1}}],["如果password不传入",{"2":{"162":1,"256":1}}],["如果匹配了大图所有的坐标点",{"2":{"137":1}}],["如果匹配成功",{"2":{"134":1}}],["如果小图上的rgb值与对应大图位置的rgb都相等",{"2":{"137":1}}],["如果用常规的图像识别则有可能无法识别到",{"2":{"135":1,"176":1}}],["如果找不到",{"2":{"134":1}}],["如果识别不到",{"2":{"134":1}}],["如果你之前并没有这样的设计",{"2":{"303":1}}],["如果你原来本来就有一个函数专门用于组装路径的",{"2":{"303":1}}],["如果你是想对原来的工程进行改造",{"2":{"302":1}}],["如果你是新写项目",{"2":{"302":1}}],["如果你嫌麻烦",{"2":{"302":1}}],["如果你的应用本身是属于根本就不需要和其他应用交互的",{"2":{"271":1}}],["如果你的应用分了很多模块",{"2":{"212":1,"230":1}}],["如果你用到了十个功能模块",{"2":{"270":1}}],["如果你还没有遇到",{"2":{"181":1}}],["如果你不想通过配置文件",{"2":{"162":1,"256":1}}],["如果你不希望大图是屏幕的截图",{"2":{"134":1}}],["如果你想直接部署在本机上",{"2":{"236":1}}],["如果你想重新做回填",{"2":{"198":1}}],["如果你想执行这个",{"2":{"165":1}}],["如果你想指定不同的窗口",{"2":{"150":1}}],["如果你想每次截图存在一些间隔时间传入对应的时间间隔即可",{"2":{"135":1}}],["如果你发现使用常规的",{"2":{"147":1}}],["如果你在用例中需要调整识别度",{"2":{"134":1}}],["如果你移动鼠标到屏幕四边",{"2":{"130":1}}],["如果提示没有",{"2":{"65":1}}],["如果传入了",{"2":{"48":1}}],["如果",{"2":{"48":1,"134":1,"149":1,"247":1}}],["如果不给就是apps目录下所有的",{"2":{"209":1}}],["如果不存在",{"2":{"139":1,"211":1}}],["如果不传默认截取全屏识别",{"2":{"120":1,"176":2}}],["如果不传参",{"2":{"120":1}}],["如果不指定版本号默认是安装最新发布的",{"2":{"42":1}}],["如果不加",{"2":{"42":1}}],["如果本地执行版本不是最新的",{"2":{"34":1}}],["如果需要指定其他第三方的浏览器",{"2":{"17":1,"103":1,"104":1}}],["子命令创建子项目工程模板",{"2":{"54":1}}],["子项目工程名称可以为任意名称",{"2":{"35":1}}],["子项目需要时通过新增依赖机制进行安装",{"2":{"12":1}}],["创建",{"0":{"249":1}}],["创建项目",{"0":{"247":1}}],["创建文件",{"2":{"235":1}}],["创建管理员成功",{"2":{"76":1}}],["创建平台子管理员",{"2":{"75":1}}],["创建的app工程",{"2":{"62":1,"71":1,"72":1,"81":1,"93":1,"96":1,"97":1,"108":1}}],["创建一条在百度首页搜索",{"2":{"100":1}}],["创建一条通过任务栏打开文件管理器的测试用例",{"2":{"83":1}}],["创建一条完整的用例",{"0":{"64":1,"74":1,"83":1,"100":1,"110":1},"1":{"65":1,"66":1,"75":1,"76":1,"84":1,"85":1,"86":1,"101":1,"102":1,"103":1,"111":1,"112":1},"2":{"12":1}}],["创建一个项目",{"0":{"69":1,"79":1,"89":1,"106":1,"115":1},"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["创建一个",{"0":{"62":1,"71":1,"81":1,"96":1,"108":1},"1":{"63":1,"72":1,"73":1,"82":1,"97":1,"98":1,"99":1,"109":1},"2":{"62":1,"71":1,"81":1,"96":1,"108":1}}],["创建工程时存在工程名称时无法继续创建",{"2":{"53":1}}],["然后同步修改掉",{"2":{"301":1}}],["然后使用快捷键",{"2":{"301":1}}],["然后配合",{"2":{"281":1}}],["然后由执行器来执行相应的测试",{"2":{"281":1}}],["然后测试机安装最新的镜像",{"2":{"277":1}}],["然后才能使用该模块下的功能",{"2":{"270":1}}],["然后将这些基础能力通过",{"2":{"213":1}}],["然后",{"2":{"205":1}}],["然后在输入框中输入要重命名的名称",{"2":{"301":1}}],["然后在测试机上安装更新",{"2":{"277":1}}],["然后在浏览器访问",{"2":{"180":1}}],["然后在命令行",{"2":{"162":1,"256":1}}],["然后右键选择浏览器打开",{"2":{"180":1}}],["然后服务端就先拿着第",{"2":{"163":1,"257":1}}],["然后再通过子命令",{"2":{"157":1}}],["然后移动鼠标就就可以看到上图的参考线及数据",{"2":{"148":1}}],["然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小",{"2":{"148":1}}],["然后勾选",{"2":{"142":1}}],["然后这本身就是不确定的",{"2":{"132":1}}],["然后通过负载均衡技术将业务请求分发到",{"2":{"122":1}}],["然后通过",{"2":{"119":1}}],["然后作为稳定版本发布",{"2":{"53":1}}],["然后每次我就需要解释这个",{"2":{"27":1}}],["指定某台机器在指定镜像版本上执行用例",{"2":{"281":1}}],["指定某个目录执行",{"0":{"166":1}}],["指定安装某个版本",{"2":{"234":1}}],["指定报告生成的路径",{"2":{"230":1}}],["指定拖动的起始",{"2":{"184":2}}],["指定执行某一个用例",{"0":{"165":1}}],["指定用例执行次数",{"2":{"159":1,"230":1,"253":1}}],["指定浏览器可执行文件路径",{"2":{"103":1,"230":1}}],["指定浏览器启动的用户数据缓存目录",{"2":{"103":1,"230":1}}],["指定不同的端口",{"2":{"52":1}}],["指南",{"2":{"13":1,"15":1}}],["替换为",{"2":{"52":1,"59":1}}],["替换成",{"2":{"42":1}}],["扫描的代码风格问题",{"2":{"51":1}}],["公共库建设",{"0":{"284":1},"2":{"288":1}}],["公共库抽取",{"2":{"274":1}}],["公共库中的",{"2":{"50":1}}],["公共方法库抽离和方法文档整理",{"2":{"288":6}}],["公共方法库里面的编写形式",{"2":{"271":1}}],["公共方法库里面所封装的一些操作方法都是至少被",{"2":{"271":1}}],["公共方法库里面每个应用都是一个单独的",{"2":{"271":1}}],["公共方法库意义",{"2":{"271":1}}],["公共方法库",{"0":{"271":1},"2":{"265":2,"267":1,"281":1}}],["公共",{"2":{"227":1,"273":1,"284":1}}],["公网文档使用的是",{"2":{"42":1}}],["公网文档",{"2":{"42":1}}],["刷新源的日志在终端显示",{"2":{"48":1}}],["连接符号不可使用下划线和逗号",{"2":{"204":1}}],["连接服务器重试次数",{"2":{"176":2}}],["连接",{"2":{"48":1,"162":1,"204":1,"256":1,"281":1}}],["两对大括号中的内容",{"2":{"193":1}}],["两次点击的间隔",{"2":{"184":1}}],["两个功能接口",{"2":{"138":1}}],["两个情况的优先级是优先判断本地存在",{"2":{"41":1}}],["两张图唯一变化的就是右键菜单",{"2":{"132":1}}],["两种写法",{"2":{"48":1}}],["测试",{"2":{"287":1}}],["测试平台可能会涉及到的模块有",{"2":{"287":1}}],["测试同学可以根据自己的测试计划",{"2":{"281":1}}],["测试资源",{"2":{"281":1}}],["测试用例",{"2":{"281":1}}],["测试数据",{"2":{"267":1,"293":1}}],["测试人员在本地编写代码",{"2":{"260":1}}],["测试级别",{"2":{"230":1}}],["测试过程中立即显示报错",{"2":{"159":1,"230":1,"253":1}}],["测试单关联的用例",{"2":{"195":1}}],["测试单id为",{"2":{"230":1}}],["测试单id",{"2":{"159":1,"196":3,"253":1}}],["测试单驱动执行",{"0":{"171":1}}],["测试单驱动",{"2":{"11":1}}],["测试报告的默认语言",{"2":{"230":1}}],["测试报告的name",{"2":{"230":1}}],["测试报告的title",{"2":{"230":1}}],["测试报告",{"0":{"177":1},"1":{"178":1,"179":1,"180":1}}],["测试报告格式",{"2":{"159":1,"253":1}}],["测试报告查看",{"2":{"58":1}}],["测试机应用安装更新接口等",{"2":{"287":1}}],["测试机镜像安装接口",{"2":{"287":1}}],["测试机资源管理模块",{"2":{"287":1}}],["测试机",{"2":{"260":1}}],["测试机轮询次数",{"2":{"230":1}}],["测试机的密码",{"2":{"230":1}}],["测试机密码",{"2":{"162":1,"230":1,"256":1}}],["测试机截取当前屏幕图片以及模板图片",{"2":{"138":1}}],["测试机上不用安装",{"2":{"138":1}}],["测试机通过远程调用",{"2":{"119":1}}],["测试结果统计时",{"2":{"55":1}}],["测试套件驱动执行",{"0":{"172":1}}],["测试套件执行报错的的问题",{"2":{"46":1}}],["测试套id为",{"2":{"230":1}}],["测试套id",{"2":{"159":1,"253":1}}],["测试套执行或测试单执行时",{"2":{"55":1}}],["由",{"2":{"200":1}}],["由子项目在",{"2":{"44":1,"50":1}}],["由于测试机资源有限",{"2":{"286":1}}],["由于需求变更",{"2":{"206":1}}],["由于需要修改",{"2":{"60":1}}],["由于你的测试资源是不固定的",{"2":{"139":1}}],["由于右键菜单选项几乎都是文本",{"2":{"132":1}}],["由于内建了非常多的断言语句",{"2":{"86":1}}],["由于系统一些",{"2":{"50":1}}],["由于默认基于虚拟化环境部署方案",{"2":{"42":1}}],["由于将这个定制图像识别接口进行服务化兼容改造需要一定时间",{"2":{"41":1}}],["由于之前是预装到镜像里面的",{"2":{"41":1}}],["由于",{"2":{"12":1,"32":1}}],["由于窗管团队修改获取窗口信息的返回值",{"2":{"10":1}}],["移动的速度",{"2":{"184":1}}],["移动的倍数",{"2":{"150":4}}],["移动到的位置",{"2":{"184":6}}],["移动到某个位置点击双击",{"2":{"184":1}}],["移动到某个位置点击右键",{"2":{"184":1}}],["移动到某个位置点击",{"2":{"184":1}}],["移动到指定位置",{"2":{"184":1}}],["移动到",{"2":{"16":2}}],["移除了参数",{"2":{"51":1}}],["移除",{"2":{"44":1,"48":1,"51":1,"54":1,"59":1}}],["参考性能自动化工程完成工程化改造",{"2":{"274":1}}],["参考章节",{"2":{"187":1}}],["参考系",{"2":{"150":1}}],["参考系的选取标准",{"2":{"149":1}}],["参考",{"2":{"43":1,"300":1}}],["参数是什么",{"2":{"302":1}}],["参数说明",{"2":{"209":1}}],["参数加上",{"2":{"205":1}}],["参数为",{"2":{"204":1}}],["参数直接给你修复掉",{"2":{"153":1}}],["参数就是配置里面的",{"2":{"149":1}}],["参数介绍",{"2":{"134":1,"135":1}}],["参数可能出现与其他框架的工程依赖存在冲突",{"2":{"52":1}}],["参数",{"2":{"25":1,"134":1,"204":1}}],["参数不能对",{"2":{"21":1}}],["参数后面新增支持",{"2":{"48":1}}],["参数后",{"2":{"17":1}}],["每写一条都需要在对应的",{"2":{"285":1}}],["每日下载最新的",{"2":{"277":1}}],["每日下班之后会将各应用进行打包",{"2":{"277":1}}],["每日构建流水线",{"2":{"277":1}}],["每一列都是一个用例标签",{"2":{"201":1,"285":1}}],["每个应用内部会有一个单独的配置模块",{"2":{"281":1}}],["每个方法均对应一个元素的一个具体操作",{"2":{"276":1}}],["每个",{"2":{"271":1}}],["每个模块建立一个",{"2":{"201":1,"285":1}}],["每个操作步骤之前暂停的时间",{"2":{"150":1}}],["每个菜单选项就可以通过图像识别的方式进行元素定位",{"2":{"129":1}}],["每次执行时原",{"2":{"212":1}}],["每次操作会将",{"2":{"211":1,"212":1}}],["每次生成会被覆盖",{"2":{"176":1}}],["每次截取图片的间隔时间",{"2":{"135":1}}],["每次间隔1秒",{"2":{"134":1}}],["每次需要去量一下",{"2":{"130":1}}],["每次变更之后就需要进行大量图片资源的重新截图替换",{"2":{"129":1}}],["每次",{"2":{"123":1}}],["每次识别间隔时间",{"2":{"31":1}}],["每条用例仍然会生成json文件",{"2":{"230":1}}],["每条用例执行之后进行环境清理",{"2":{"230":1}}],["每条用例执行时日志输出当前进度",{"2":{"57":1}}],["每条用例都录屏",{"2":{"42":1,"230":1}}],[">按键",{"2":{"184":2}}],[">滑动滚轮",{"2":{"184":1}}],[">与期望尺寸",{"2":{"176":1}}],[">与实际值",{"2":{"176":4}}],[">不符",{"2":{"176":1}}],[">不为假",{"2":{"176":1}}],[">不为真",{"2":{"176":1}}],[">不相等",{"2":{"176":2}}],[">是否相等",{"2":{"176":2}}],[">主题",{"2":{"176":1}}],[">",{"2":{"42":1,"65":1,"144":1,"145":9,"150":29,"176":12,"184":6,"188":1,"230":1}}],[">=",{"2":{"42":1,"176":3,"194":1,"230":1}}],["之前这个配置项只能在",{"2":{"42":1}}],["之后拖动到目标位置即可",{"2":{"301":1}}],["之后添加使用",{"2":{"157":1}}],["之后",{"2":{"34":1,"42":1,"193":1,"197":1}}],["仍然强制执行",{"2":{"57":1}}],["仍然保留",{"2":{"42":1}}],["仍然可以通过源码获取",{"2":{"42":1}}],["内网文档",{"2":{"42":1}}],["内获取应用名称的逻辑错误的问题",{"2":{"7":1}}],["咱不能直接把",{"2":{"205":1}}],["咱们先初步排除掉一些明显不用的",{"2":{"186":1}}],["咱们",{"2":{"42":1}}],["咱也不知道为啥",{"2":{"27":1}}],["代表不跳过",{"2":{"204":1}}],["代表跳过",{"2":{"204":1}}],["代码中可以在不依赖三方库的情况下方便快速的解析它",{"2":{"281":1}}],["代码相互独立",{"2":{"274":1}}],["代码规范问题清零",{"2":{"274":1}}],["代码调试环境",{"2":{"261":1}}],["代码报错看不到报错信息",{"2":{"260":1}}],["代码补全",{"0":{"220":1}}],["代码格式化",{"0":{"154":1}}],["代码实现和维护上可能出现的分歧",{"2":{"274":1}}],["代码实现",{"2":{"137":1,"138":1}}],["代码实现请查看",{"2":{"132":1}}],["代码示例",{"2":{"132":1,"135":1,"139":1,"144":1,"148":2}}],["代码示意",{"2":{"120":1,"139":1}}],["代码检查是扫描代码中存在的问题",{"2":{"153":1}}],["代码检查",{"0":{"153":1},"2":{"21":1}}],["代理下就好了",{"2":{"42":1}}],["白嫖怪一顿狂喜~~",{"2":{"42":1}}],["了解系统的方方面面也有好处",{"2":{"271":1}}],["了解到其他应用的功能",{"2":{"271":1}}],["了",{"2":{"42":1,"154":1}}],["看到这里有些同学可能要问了",{"2":{"205":1}}],["看图相册在图片资源不一定固定",{"2":{"139":1}}],["看起来很和谐~",{"2":{"42":1}}],["看着烦人我都能接受",{"2":{"27":1}}],["就会终止测试",{"2":{"230":1}}],["就可以实现自动输出日志了",{"2":{"193":1}}],["就可以了",{"2":{"42":1}}],["就不能找到这只鸟了",{"2":{"139":1}}],["就获取了在服务端图像识别的结果",{"2":{"138":1}}],["就像有没有可能有一天国内无法使用",{"2":{"137":1}}],["就像录制视频一样",{"2":{"135":1}}],["就像气泡一样",{"2":{"135":1}}],["就需要进一步做数据处理",{"2":{"132":1}}],["就实现了对右键菜单的操作",{"2":{"128":1}}],["就是干",{"2":{"301":1}}],["就是当你写一个大型项目时",{"2":{"240":1}}],["就是你不知道预期是啥",{"2":{"139":1}}],["就是屏幕中出现多个和菜单选项文字相同的文字时",{"2":{"132":1}}],["就是右键菜单的选项位置不可能一直不变",{"2":{"128":1}}],["就是以桌面",{"2":{"87":1}}],["就是本地直接安装",{"2":{"41":1}}],["就是本地测试机不需要安装",{"2":{"41":1}}],["就好了",{"2":{"42":1,"160":1,"254":1}}],["只能执行其中一种测试类型",{"2":{"286":1}}],["只能说使用的场景还不够多",{"2":{"181":1}}],["只有一台机器",{"2":{"261":1}}],["只有想不到没有办不到",{"2":{"230":1}}],["只会安装最基础的依赖",{"2":{"235":1}}],["只会将",{"2":{"48":1}}],["只收集不执行用例",{"2":{"230":1}}],["只支持谷歌浏览器",{"2":{"186":1}}],["只支持",{"2":{"186":1}}],["只留下菜单界面",{"2":{"132":1}}],["只需要写一个导入",{"2":{"270":1}}],["只需要保存",{"2":{"249":1}}],["只需要在应用库根目录下保存一个",{"2":{"234":1}}],["只需要在出口文件加上类装饰器",{"2":{"193":1}}],["只需要给应用方法层的唯一出口类加一个装饰器",{"2":{"222":1}}],["只需要将对应的信息依次配置好就行了",{"2":{"212":1,"230":1}}],["只需要修改",{"2":{"196":1}}],["只需要根据",{"2":{"147":1}}],["只需要通过",{"2":{"120":1}}],["只需要把",{"2":{"42":1}}],["只返回第一个",{"2":{"120":1,"176":2}}],["只要标记了fixed的用例",{"2":{"230":1}}],["只要有1个机器上用例失败",{"2":{"197":1}}],["只要有接口请求能力就能做",{"2":{"77":1}}],["只要操作前后后变化的都可以",{"2":{"132":1}}],["只要是基于浏览器的项目都适用",{"2":{"104":1}}],["只不过之前是用于指定分辨率大小",{"2":{"42":1}}],["只是在",{"2":{"219":1}}],["只是需要增加一个参数",{"2":{"163":1,"257":1}}],["只是需要关注下环境变量的问题",{"2":{"42":1}}],["只是内部做了不同的事情",{"2":{"42":1}}],["可操作性和可维护性较高",{"2":{"281":1}}],["可灵活支撑不同的自动化运用场景",{"2":{"274":1}}],["可支持迭代期间独立新增",{"2":{"274":1}}],["可维护性差",{"2":{"207":1}}],["可自定义多个参数之间的连接符",{"2":{"204":1}}],["可能是编辑器的",{"2":{"303":1}}],["可能你只需要安装一些最最基础的依赖",{"2":{"235":1}}],["可能遇到的",{"0":{"198":1}}],["可能包含多条日志信息",{"2":{"190":1}}],["可能存在一些依赖报错",{"2":{"185":1}}],["可能会报错",{"2":{"60":1}}],["可能出现的程序报错的问题",{"2":{"58":1}}],["可用于本地用例驱动执行",{"2":{"156":1}}],["可用于定位断言",{"2":{"54":1}}],["可用于拉取",{"2":{"19":1}}],["可将python3",{"2":{"52":1}}],["可以配置自己的测试计划",{"2":{"287":1}}],["可以实现在全架构测试机上轮流执行用例",{"2":{"286":1}}],["可以实现不同系统版本",{"2":{"281":1}}],["可以实现多窗口的控制",{"2":{"270":1}}],["可以进行测试机管理",{"2":{"281":1}}],["可以根据需要进行灵活配置",{"2":{"281":1}}],["可以根据需要进行相应配置",{"2":{"281":1}}],["可以组合其中的标签而从驱动对应的自动化用例执行",{"2":{"281":1}}],["可以组合出任意的用例集合",{"2":{"230":1}}],["可以查看所有支持的命令行参数",{"2":{"253":1}}],["可以同时使用",{"2":{"235":1}}],["可以使用",{"2":{"235":1}}],["可以不传",{"2":{"214":1,"230":2}}],["可以直接在",{"2":{"180":1,"201":1,"285":1}}],["可以在用例中这样写",{"2":{"230":1}}],["可以在用例层优雅的调用远程方法",{"2":{"218":1}}],["可以在",{"2":{"155":1}}],["可以从",{"2":{"148":1}}],["可以展开应用的标签",{"2":{"142":1}}],["可以排除部分区域对识别结果的影响",{"2":{"134":1}}],["可以指定截取屏幕中的固定区域",{"2":{"134":1}}],["可以用于元素定位",{"2":{"120":1}}],["可以是空文件",{"2":{"93":1}}],["可以通过公共方法库里面的一些方法",{"2":{"271":1}}],["可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标",{"2":{"130":1}}],["可以通过",{"2":{"65":1,"85":1,"143":1}}],["可以给它个",{"2":{"42":1}}],["可以作为开发时的环境部署",{"2":{"42":1}}],["可以看出来和原来使用方法没有变化",{"2":{"42":1}}],["虚拟环境部署本机环境部署",{"2":{"248":1}}],["虚拟环境实际安装的位置是在",{"2":{"237":1}}],["虚拟环境解释器",{"0":{"237":1}}],["虚拟环境的工具",{"2":{"42":1}}],["虚拟环境的解释器版本没有动态获取系统中的",{"2":{"19":1}}],["虚拟化环境部署使用方法",{"2":{"42":1}}],["能支持多个标签的逻辑组合",{"2":{"286":1}}],["能做什么",{"0":{"242":1}}],["能不能基于框架执行时",{"2":{"190":1}}],["能满足对大部分的网络接口处理的需求",{"2":{"77":1}}],["能够完全管理常规的",{"2":{"42":1}}],["能自动分析统计每次提交中包含的用例和方法的增删改的数据",{"2":{"13":1}}],["值得一提的是",{"2":{"42":2}}],["还依赖较多设备",{"2":{"260":1}}],["还可以这样导入",{"2":{"228":1}}],["还搞什么确认修复干啥",{"2":{"205":1}}],["还是",{"2":{"185":1}}],["还是在",{"2":{"42":1}}],["还需要提供一个对象",{"2":{"103":1,"104":1}}],["还提供一个",{"2":{"17":1}}],["hk",{"2":{"184":3}}],["h=100",{"2":{"176":2}}],["hg",{"2":{"155":1}}],["h2",{"2":{"148":2}}],["huangmingqiang",{"2":{"145":1,"150":1,"184":1}}],["hub",{"2":{"55":1}}],["hiddenprints",{"2":{"184":2}}],["hightlight",{"2":{"142":1}}],["history",{"2":{"42":1}}],["hand",{"2":{"159":1,"196":1,"230":1,"253":1}}],["has",{"2":{"155":1}}],["hasattr",{"2":{"150":4}}],["hash",{"2":{"123":1}}],["hashlib",{"2":{"75":4}}],["have",{"2":{"103":1}}],["hook",{"2":{"267":1,"272":1}}],["hotkey",{"2":{"184":1}}],["hot",{"2":{"184":5}}],["home",{"2":{"103":1,"111":1,"230":1}}],["hostname",{"2":{"120":1}}],["host",{"2":{"75":4,"138":2,"230":2}}],["heard",{"2":{"230":1}}],["header",{"2":{"75":2}}],["headersp",{"2":{"75":2}}],["headers=headers",{"2":{"75":2}}],["headers=",{"2":{"75":1}}],["headers",{"2":{"75":15}}],["hebrew",{"2":{"230":1}}],["he",{"2":{"230":1}}],["help",{"2":{"157":2,"159":2,"162":2,"253":3,"256":2}}],["hexdigest",{"2":{"75":2}}],["height",{"2":{"54":1,"137":2,"139":2,"150":28,"184":4}}],["h",{"2":{"51":2,"130":2,"134":3,"138":2,"144":2,"145":2,"149":2,"150":30,"157":4,"159":1,"162":1,"176":20,"253":3,"256":1}}],["html",{"2":{"15":1,"178":3,"179":1,"180":5,"212":1,"230":3}}],["http",{"0":{"77":1},"1":{"78":1,"79":1,"80":1},"2":{"52":2,"76":1,"77":1,"102":1,"180":2,"242":1}}],["httperror",{"2":{"26":1}}],["http接口自动化测试",{"2":{"12":1}}],["https",{"2":{"2":1,"75":1,"212":1,"230":3}}],["会尽可能的自动解决移动导致的路径问题",{"2":{"301":1}}],["会包含一些本应用的测试资源的路径",{"2":{"281":1}}],["会引入非常非常多的依赖",{"2":{"240":1}}],["会进行重试",{"2":{"230":1}}],["会自动拷贝到远程并安装",{"2":{"230":1}}],["会自动加载",{"2":{"54":1}}],["会话超时",{"2":{"230":1}}],["会话超时时间",{"2":{"54":1,"227":1,"273":1}}],["会将整个项目下的相同地方都修改到",{"2":{"303":1}}],["会将所有远程测试机的测试报告都收集到",{"2":{"180":1}}],["会将图片的rgb值获取到",{"2":{"137":1}}],["会展示元素控件的",{"2":{"142":1}}],["会出现这样",{"2":{"128":2}}],["会出现下图",{"2":{"128":1}}],["会出现",{"2":{"42":1}}],["会打印更新提示信息",{"2":{"34":1}}],["加上类的关键词",{"2":{"296":1}}],["加上装饰器",{"2":{"193":1}}],["加架构名",{"2":{"204":1}}],["加入了",{"2":{"179":1}}],["加入了失败录屏",{"2":{"179":1}}],["加入了用例断言失败时的屏幕截图",{"2":{"179":1}}],["加",{"2":{"42":1}}],["推荐统一使用",{"2":{"204":1}}],["推荐指定版本号",{"2":{"42":1}}],["推荐使用",{"2":{"42":1,"63":1,"82":1,"99":1,"109":1}}],["推动自动化测试技术向前发展",{"2":{"14":1}}],["也就是在一次执行中",{"2":{"286":1}}],["也就是说如果您是部署自动化环境是用的",{"2":{"225":1}}],["也就是说流水线上我们是希望他继续跳过的",{"2":{"205":1}}],["也就是说同一条用例会在多台机器上同时执行",{"2":{"197":1}}],["也就是说",{"2":{"196":1}}],["也就是说我们需要写大量的日志代码",{"2":{"190":1}}],["也就是说通过命令行参数指定了对应的参数",{"2":{"157":1}}],["也就是说小图在大图中存在一个相似度",{"2":{"134":1}}],["也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向",{"2":{"130":1}}],["也就是说你得经常去维护菜单选项的步长",{"2":{"128":1}}],["也就是说从使用的角度是完全没有区别的",{"2":{"42":1}}],["也就是说后续可以使用",{"2":{"42":1}}],["也放在项目根目录",{"2":{"272":1}}],["也不做设备分辨率的检查",{"2":{"230":1}}],["也不会被执行",{"2":{"200":1}}],["也会执行",{"2":{"230":1}}],["也会正常执行",{"2":{"205":1}}],["也都挺好的",{"2":{"181":1}}],["也希望有志之士能一起优化此方案",{"2":{"137":1}}],["也有可能气泡出现的时间太短了",{"2":{"135":1}}],["也是全局配置对象",{"2":{"228":1}}],["也是极不稳定",{"2":{"139":1}}],["也是可以调用的",{"2":{"138":1}}],["也是可以的",{"2":{"42":1}}],["也是",{"2":{"118":1}}],["也可统计某两个commit之间或一段时间内用例和方法的修改数据",{"2":{"230":1}}],["也可以",{"2":{"246":1}}],["也可以使用配置文件选项",{"2":{"209":1}}],["也可以是多个操作的组合操作",{"2":{"276":1}}],["也可以是youqu特有的csv文件管理的标签",{"2":{"230":1}}],["也可以是自定义的数字代表用例序号",{"2":{"201":1}}],["也可以是传统的",{"2":{"169":1}}],["也可以用于文字断言",{"2":{"120":1}}],["也可以修改配置文件",{"2":{"70":1,"80":1,"90":1,"107":1,"116":1,"232":1,"248":1}}],["也可传入子管理账号及密码调用接口操作",{"2":{"75":1}}],["也能使用",{"2":{"56":1}}],["也能管理到",{"2":{"42":1}}],["也拓展了其功能和适用范围",{"2":{"14":1}}],["刘郑等研发同事的大力支持",{"2":{"42":1}}],["架构设计",{"0":{"280":1}}],["架构设计思路",{"2":{"274":1}}],["架构工程化",{"2":{"274":1}}],["架构图",{"0":{"266":1},"2":{"266":1}}],["架构上安装并不能保证100",{"2":{"137":1}}],["架构师徐小东",{"2":{"42":1}}],["架构环境依赖的问题",{"2":{"41":1}}],["装机完之后自动开始执行配置的测试用例",{"2":{"281":1}}],["装机模块",{"2":{"281":1}}],["装饰器方法指定次数",{"2":{"54":1}}],["装进虚拟环境",{"2":{"41":1}}],["装载到虚拟环境方案中不太好处理",{"2":{"41":1}}],["改善历史",{"2":{"274":1}}],["改完还需要测试",{"2":{"41":1}}],["改为使用",{"2":{"11":1}}],["前端平台目前还没有太多详细的方案",{"2":{"287":1}}],["前面代码检查的时候报了一个问题",{"2":{"155":1}}],["前面我们已经把",{"2":{"41":1}}],["前",{"2":{"123":1}}],["前期测试一切看起来都很和谐",{"2":{"41":1}}],["而外层执行器没有指定执行标签",{"2":{"281":1}}],["而此路径可能不在环境变量",{"2":{"246":1}}],["而通过",{"2":{"202":1,"285":1}}],["而我们自动化人员大多使用",{"2":{"186":1}}],["而我们的测试机都在同一个网段",{"2":{"123":1}}],["而是所有远程机器执行的用例之和",{"2":{"163":1,"257":1}}],["而是通过请求",{"2":{"138":1}}],["而是你自定义传入的某个图片",{"2":{"134":1}}],["而",{"2":{"137":1}}],["而不同的方向上计算方法是不同的",{"2":{"130":1}}],["而不容易关注到首次包安装失败的问题",{"2":{"28":1}}],["而且不好维护",{"2":{"278":1}}],["而且它的作用域是当前目录及以下",{"2":{"272":1}}],["而且还支持动态控制用例批量执行的总时间",{"2":{"243":1}}],["而且我们在报告中还加入了失败录屏和失败截图的功能",{"2":{"243":1}}],["而且距离是通过像素",{"2":{"130":1}}],["而且使用方法非常简单",{"2":{"120":1}}],["而且在各架构上依赖包还不尽相同",{"2":{"41":1}}],["粗略数了下依赖有",{"2":{"41":1}}],["年多以来的观察",{"2":{"41":1}}],["基类",{"0":{"295":1}}],["基本就可以进行用例代码的调试了",{"2":{"304":1}}],["基本保持不变",{"2":{"281":1}}],["基本上你能用到的键鼠操作",{"2":{"182":1}}],["基础依赖仅安装最基础的几个包",{"2":{"235":1}}],["基础框架代码拉取",{"0":{"300":1}}],["基础框架中包含应用库",{"2":{"265":1}}],["基础框架是做为一个自动化测试的基础框架来设计的",{"2":{"265":1}}],["基础框架设计方案",{"0":{"262":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"271":1,"272":1,"273":1}}],["基础框架",{"2":{"148":1,"265":2}}],["基础框架移除此模块",{"2":{"34":1}}],["基线",{"2":{"200":1}}],["基于此",{"2":{"190":1}}],["基于元素按钮在应用中的相对位置",{"2":{"147":1}}],["基于以上两个原因",{"2":{"130":1}}],["基于",{"0":{"138":1},"2":{"41":1,"104":1,"123":1,"134":1,"149":1,"169":1,"186":1,"190":1}}],["原有自动化测试架构整体分为三层",{"2":{"276":1}}],["原有架构介绍",{"0":{"276":1}}],["原at框架架构图",{"2":{"276":1}}],["原则上可实现无限扩展",{"2":{"274":1}}],["原理实现",{"2":{"134":1,"135":1}}],["原理",{"2":{"132":1,"137":1,"138":1,"139":1}}],["原来的地址",{"2":{"52":1}}],["原因就是自动化项目里面各个应用的有比较多的耦合关系",{"2":{"278":1}}],["原因为",{"2":{"41":1}}],["原因是之前我这里本地没有",{"2":{"41":1}}],["原函数接口ocr",{"2":{"14":1,"125":1}}],["原函数接口使用方法不变以保持兼容性",{"2":{"14":1,"125":1}}],["kr",{"2":{"230":1}}],["klvv",{"2":{"204":2}}],["klvvw5821",{"2":{"40":1,"204":4}}],["kde",{"2":{"150":2,"176":1}}],["kwin",{"2":{"150":2,"176":1}}],["kw",{"2":{"102":2}}],["kwargs",{"2":{"95":2,"144":2,"145":7,"218":2,"270":6}}],["khtml",{"2":{"75":1}}],["keep",{"2":{"75":1}}],["key是本地csv文件的文件名称",{"2":{"212":1,"230":1}}],["keyup",{"2":{"184":1}}],["keydown",{"2":{"184":1}}],["keyerror",{"2":{"150":3}}],["keycombo",{"2":{"143":1}}],["keywords",{"2":{"102":3,"103":1,"159":4,"230":4,"253":3}}],["key",{"2":{"27":1,"75":1,"132":1,"145":3,"149":1,"176":1,"182":1,"183":3,"184":34,"204":16}}],["k",{"2":{"42":1,"52":1,"54":1,"75":2,"159":1,"162":2,"163":1,"165":2,"166":1,"168":1,"253":2,"256":1}}],["比如纯接口自动化的项目",{"2":{"235":1}}],["比如像这样",{"2":{"234":2}}],["比如要同步音乐的数据",{"2":{"212":1,"230":1}}],["比如是此文件中定义了的函数",{"2":{"204":1}}],["比如文件管理器叫",{"2":{"265":1}}],["比如文件管理器",{"2":{"201":1,"285":1}}],["比如文管右键菜单可以自定义",{"2":{"128":1}}],["比如用例里面如果断言的图片不同",{"2":{"185":1}}],["比如终端",{"2":{"184":1}}],["比如在注销登录界面",{"2":{"183":1}}],["比如截图录屏",{"2":{"147":1}}],["比如截取播放按钮",{"2":{"134":1}}],["比如音乐",{"2":{"147":1}}],["比如输入框",{"2":{"143":1}}],["比如说服务端也可以用",{"2":{"138":1}}],["比如气泡在1秒内消失",{"2":{"135":1,"176":1}}],["比如下面这种情况",{"2":{"132":1}}],["比如",{"2":{"40":1,"42":3,"48":1,"103":1,"128":1,"129":1,"130":1,"132":1,"133":1,"134":1,"135":1,"149":1,"162":1,"168":1,"182":1,"184":1,"185":1,"194":1,"204":4,"209":1,"212":1,"228":1,"230":6,"256":1,"271":1,"276":1,"284":1,"285":1}}],["扩充",{"2":{"40":1}}],["扩展ocr断言支持区域断言",{"2":{"5":1}}],["何权",{"2":{"40":1}}],["次执行成功",{"2":{"230":1}}],["次执行失败之后开始录屏",{"2":{"42":1,"230":1}}],["次调用识别的接口做识别",{"2":{"123":1}}],["次是将当前屏幕截图并发送到",{"2":{"123":1}}],["次",{"2":{"40":1,"128":2,"134":1,"194":1,"230":3}}],["识别所有匹配的图像",{"2":{"184":1}}],["识别到不应存在的文案",{"2":{"176":2}}],["识别率",{"2":{"135":1,"176":1}}],["识别右键菜单虽然已经很完美了",{"2":{"132":1}}],["识别我们在前面已经讲到",{"2":{"132":1}}],["识别",{"2":{"132":3}}],["识别业务实际是两次",{"2":{"123":1}}],["识别一个字符串或多个字符串",{"2":{"120":1,"176":2}}],["识别的服务",{"2":{"119":1}}],["识别工具",{"2":{"118":1}}],["识别新增支持传入目标图片路径进行文字识别",{"2":{"54":1}}],["识别自动重试机制",{"2":{"40":1}}],["识别模型准确率提升",{"2":{"35":1}}],["识别模型",{"2":{"14":1}}],["开源许可证",{"0":{"244":1}}],["开源了",{"2":{"42":1}}],["开启同步",{"2":{"211":1,"230":1}}],["开始的坐标的纵坐标",{"2":{"184":1}}],["开始的坐标的横坐标",{"2":{"184":1}}],["开始坐标",{"2":{"184":2}}],["开始",{"2":{"176":4}}],["开始构建应用",{"2":{"141":1}}],["开始匹配",{"2":{"137":1}}],["开发根据用例标签文件里面的用例标签执行对应用例的功能",{"2":{"286":1}}],["开发环境部署",{"0":{"236":1}}],["开发环境部署是可能影响到正式环境",{"2":{"39":1}}],["开发了自己的图像识别功能",{"2":{"133":1}}],["开头的目录",{"2":{"197":1,"198":1}}],["开头的",{"2":{"192":1,"230":1}}],["开头的限制",{"2":{"35":1}}],["开头",{"2":{"66":1,"76":1,"86":1,"103":1,"112":1,"204":1}}],["尝试人员都觉得难搞",{"2":{"260":1}}],["尝试合入一个有趣的功能",{"2":{"39":1}}],["尝试将一些功能模块拆分为独立构件",{"2":{"36":1}}],["采用异步的方式去进行数据回填",{"2":{"196":1}}],["采用",{"2":{"39":1,"123":1}}],["剥离文档中的图片资源",{"2":{"39":1}}],["技术方案",{"2":{"38":1,"221":1}}],["上面介绍",{"2":{"207":1}}],["上用例的标签",{"2":{"288":1}}],["上用例的跳过",{"2":{"205":1}}],["上用例等级",{"2":{"285":1}}],["上用例级别",{"2":{"200":1,"285":1}}],["上线对象",{"2":{"200":2}}],["上对应的用例",{"2":{"200":1}}],["上层用例完全不用关心机器是wayland",{"2":{"185":1}}],["上层用例不用管当前测试机执行环境",{"2":{"60":1}}],["上层用例不受影响",{"2":{"59":1}}],["上",{"2":{"184":1}}],["上图的菜单是在鼠标的左下方",{"2":{"130":1}}],["上传图片",{"2":{"120":1,"138":1}}],["上调用鼠标中键",{"2":{"47":1}}],["上关闭",{"2":{"42":1}}],["上的",{"2":{"42":1}}],["上跳过",{"2":{"40":2}}],["上获取用例相关标签的功能",{"2":{"37":1}}],["上个版本此问题没有完全修复",{"2":{"29":1}}],["或为空",{"2":{"285":1}}],["或子目录存在",{"2":{"176":1}}],["或看图",{"2":{"139":1}}],["或者你可以用一个",{"2":{"180":1}}],["或者有些父窗口不需要添加",{"2":{"142":1}}],["或者或者识别的那一刻",{"2":{"134":1}}],["或者",{"2":{"128":1,"204":1}}],["或者修改",{"2":{"42":1}}],["或",{"2":{"35":1,"40":1,"48":1,"157":2,"159":1,"162":1,"176":2,"183":1,"230":2,"253":2,"256":1}}],["导包报错的问题",{"2":{"52":1}}],["导入路径",{"2":{"303":1}}],["导入全局配置对象",{"2":{"228":1}}],["导入使用",{"2":{"182":1}}],["导入的问题",{"2":{"41":1}}],["导入报错的问题",{"2":{"41":1}}],["导出的csv文件名称",{"2":{"209":1,"230":1}}],["导出csv文件",{"0":{"209":1}}],["导出",{"2":{"34":1,"209":1,"230":1}}],["导致相对距离改变",{"2":{"130":1}}],["导致程序中断的问题",{"2":{"59":1}}],["导致与",{"2":{"47":1}}],["导致子项目依赖报错",{"2":{"41":1}}],["导致",{"2":{"10":1,"32":1,"33":1}}],["暂时先回滚到",{"2":{"34":1}}],["检查分辨率",{"2":{"159":1,"253":1}}],["检查测试机分辨率",{"2":{"42":1,"230":1}}],["检测模型升级到",{"2":{"34":1,"35":1}}],["检索窗口",{"2":{"31":1}}],["禄烨",{"2":{"34":1}}],["模板匹配的效果",{"2":{"137":1}}],["模板图片路径",{"2":{"134":1}}],["模块划分",{"2":{"296":1}}],["模块方法类",{"2":{"293":4}}],["模块",{"2":{"281":1}}],["模块名称",{"2":{"168":1,"230":1}}],["模块对",{"2":{"124":1}}],["模块的问题",{"2":{"35":1}}],["模块的初始化",{"2":{"34":1}}],["模式执行用例",{"2":{"230":1}}],["模式新增参数",{"2":{"12":1}}],["模式下执行用例",{"2":{"60":1}}],["模式下",{"2":{"12":2}}],["独立发布",{"2":{"34":1}}],["产品库用例",{"2":{"33":1,"230":1}}],["解决方法也很简单",{"2":{"225":1}}],["解决方案是将代码中的",{"2":{"60":1}}],["解决在",{"2":{"48":1}}],["解决注销登录界面无法控制键鼠的问题",{"2":{"33":1}}],["解除所有交叉调用的方法",{"2":{"274":1}}],["解除跳过时将装饰器代码删掉",{"2":{"202":1,"285":1}}],["解除子项目的工程名称以",{"2":{"35":1}}],["解除",{"2":{"28":1}}],["yyy",{"2":{"253":1}}],["yy",{"2":{"197":1}}],["yoffset=int",{"2":{"184":2}}],["you",{"2":{"28":1,"212":1}}],["youqu==2",{"2":{"42":2}}],["youqu",{"0":{"1":1,"2":1,"3":1,"61":1,"124":1,"241":1,"242":1,"243":1},"1":{"242":1,"243":1,"244":1},"2":{"2":1,"10":1,"12":2,"13":6,"14":3,"16":1,"17":1,"19":1,"23":3,"26":1,"27":1,"34":2,"35":1,"41":2,"42":11,"48":3,"50":2,"52":4,"53":1,"67":1,"68":2,"70":1,"77":2,"78":2,"80":1,"87":3,"88":2,"90":1,"100":1,"103":3,"104":2,"105":2,"107":1,"114":2,"116":1,"124":1,"125":1,"133":2,"151":1,"156":1,"157":2,"158":1,"159":2,"160":1,"161":1,"162":4,"163":1,"169":1,"174":1,"175":1,"181":1,"182":1,"185":1,"186":1,"188":1,"190":2,"212":1,"213":1,"214":1,"221":1,"223":1,"230":3,"236":1,"237":3,"238":1,"239":1,"241":1,"244":1,"246":4,"247":4,"248":1,"249":1,"252":1,"253":2,"255":1,"256":4,"257":1}}],["y=int",{"2":{"184":1}}],["y=",{"2":{"184":6}}],["y=100",{"2":{"176":2}}],["y=0",{"2":{"176":4}}],["y=none",{"2":{"150":2,"184":5}}],["yes表示所有测试机并行跑",{"2":{"230":1}}],["yes",{"2":{"159":3,"162":1,"196":1,"205":3,"211":2,"224":2,"230":8,"253":3,"256":1}}],["y2",{"2":{"148":3}}],["y1",{"2":{"148":4}}],["yaml",{"2":{"55":1}}],["y",{"2":{"51":2,"54":1,"130":1,"134":5,"137":2,"138":3,"139":2,"144":4,"145":8,"149":2,"150":161,"162":1,"176":38,"184":56,"256":1}}],["ydotool=true",{"2":{"183":1}}],["ydotool",{"2":{"33":1,"183":1,"184":8}}],["集成测试",{"2":{"274":1,"281":1}}],["集成了自研的",{"2":{"221":1}}],["集成",{"2":{"33":1}}],["是很有代表性的",{"2":{"291":1}}],["是测试执行的入口",{"2":{"281":1}}],["是对应用提交集成的版本进行测试",{"2":{"277":1}}],["是对研发每日提交的代码进行测试",{"2":{"277":1}}],["是你的",{"2":{"249":1}}],["是你根据对应的元素按钮命名",{"2":{"149":1}}],["是统信公司开源的一个用于",{"2":{"241":1}}],["是什么",{"0":{"241":1},"1":{"242":1,"243":1,"244":1}}],["是不冲突的",{"2":{"235":1}}],["是不是",{"2":{"185":1}}],["是根据全局超时配置和用例单独超时配置自动计算的",{"2":{"230":1}}],["是无法使用此技术方案的",{"2":{"225":1}}],["是在最新的代码上提交的",{"2":{"205":1}}],["是类装饰器",{"2":{"193":1}}],["是否失败录屏",{"2":{"227":1,"273":1}}],["是否分模块维护",{"2":{"201":1,"285":1}}],["是否相同",{"2":{"176":3}}],["是否递归查找",{"2":{"176":2}}],["是否返回匹配到的多个目标",{"2":{"134":2,"138":1}}],["是说在",{"2":{"155":1}}],["是固定写法",{"2":{"149":1}}],["是该元素按钮的相对与参考系的",{"2":{"149":1}}],["是配置该元素的参考系",{"2":{"149":1}}],["是按钮",{"2":{"148":2}}],["是我们自研的一个使用简单",{"2":{"147":1}}],["是应用对象使用child",{"2":{"143":1}}],["是因为开发人员在添加标签的时候没有添加",{"2":{"142":1}}],["是一种名称空间的设计",{"2":{"155":1}}],["是一种协议",{"2":{"138":1}}],["是一个前端系统",{"2":{"281":1}}],["是一个为应用程序间通信的消息总线系统",{"2":{"67":1}}],["是一个相对平衡识别准确性和用例稳定性的值",{"2":{"24":1}}],["是框架提供的常规图像识别函数接口",{"2":{"134":1}}],["是小图的绝对路径",{"2":{"134":1}}],["是鼠标事件",{"2":{"132":1}}],["是个比较麻烦的事情",{"2":{"129":1}}],["是",{"2":{"103":1,"214":1,"228":1,"272":1}}],["是由于特殊机型下",{"2":{"32":1}}],["失败自动录屏和截图",{"2":{"265":1}}],["失败亦为失败",{"2":{"230":1}}],["失败用例重跑次数",{"2":{"194":1,"230":1}}],["失败重跑用例重跑之前延迟",{"2":{"57":1}}],["失败重跑次数",{"2":{"54":1,"159":1,"227":1,"253":1,"273":1}}],["失败录屏从第几次开始录制视频",{"2":{"194":1}}],["失败录屏从第几次失败开始录制视频",{"2":{"42":1,"159":1,"230":1,"253":1}}],["失败录屏",{"0":{"194":1}}],["失败录屏进程阻塞的问题",{"2":{"32":1}}],["失败数",{"2":{"13":2}}],["华为w525",{"2":{"32":1}}],["华为机型安装键鼠工具时依赖不兼容的问题",{"2":{"48":1}}],["华为机型",{"2":{"22":1}}],["反向同步标签到",{"2":{"32":1}}],["图形图像应用代码解耦",{"2":{"288":1}}],["图上没有提供你想要的元素数据",{"2":{"149":1}}],["图上的按钮",{"2":{"149":1}}],["图标",{"2":{"148":1}}],["图标到任务栏",{"2":{"94":1}}],["图像断言需要用到的图片资源",{"2":{"219":1}}],["图像的路径",{"2":{"184":1}}],["图像定位",{"2":{"147":1}}],["图像识别模块",{"2":{"281":1}}],["图像识别元素定位要用的图片",{"2":{"267":1,"293":1}}],["图像识别端口",{"2":{"230":1}}],["图像识别匹配度",{"2":{"230":1}}],["图像识别重试每次间隔等待时间",{"2":{"230":1}}],["图像识别重试次数",{"2":{"134":1,"230":1}}],["图像识别的最大次数",{"2":{"230":1}}],["图像识别的总超时",{"2":{"230":1}}],["图像识别的结果是",{"2":{"139":1}}],["图像识别的的匹配度或者说相似度",{"2":{"134":1}}],["图像识别目标文件的存放路径",{"2":{"134":1,"138":1}}],["图像识别在",{"2":{"133":1}}],["图像识别方法所需要的资源",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["图像识别新增指定目标图片",{"2":{"51":1}}],["图像识别新增指定区域识别",{"2":{"51":1}}],["图像识别",{"0":{"133":1},"1":{"134":1,"135":1,"136":1,"137":1,"138":1,"139":1},"2":{"31":1,"134":1,"138":1,"243":1}}],["图片中颜色大于50",{"2":{"176":1}}],["图片中仅包含一个菜单选项",{"2":{"129":1}}],["图片路径",{"2":{"139":1,"176":2}}],["图片的名称以用例的名称命名",{"2":{"134":1}}],["图片的名称以实际的元素名称命名",{"2":{"134":1}}],["图片入参支持多种图片格式",{"2":{"12":1,"13":1}}],["类似",{"2":{"272":1}}],["类方法",{"2":{"191":1,"193":1}}],["类里面一个函数只包含一个操作或多次调用的一系列可合并的操作",{"2":{"190":1}}],["类",{"2":{"94":1,"191":1,"283":1,"284":1}}],["类名以",{"2":{"283":1}}],["类名",{"2":{"72":1,"97":1,"168":1,"230":1,"301":1}}],["类型时",{"2":{"31":1}}],["类自动化",{"2":{"18":1}}],["版",{"2":{"30":1}}],["版本将修复期间出现的",{"2":{"53":1}}],["版本运行一段时间",{"2":{"53":1}}],["版本适配持续集成流水线且新增了较多新特性",{"2":{"53":1}}],["版本为",{"2":{"47":1}}],["版本升级到",{"2":{"47":1}}],["版本",{"2":{"42":2}}],["版本我们大胆的将图像识别的默认功能修改为面向服务的方式",{"2":{"41":1}}],["版本指定",{"2":{"30":1}}],["版本不匹配",{"2":{"30":1}}],["版本过高与",{"2":{"30":1}}],["版本问题",{"2":{"29":1}}],["版本的问题",{"2":{"19":1}}],["版本上线",{"2":{"17":1}}],["版本更新记录",{"0":{"4":1},"1":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1}}],["缓存",{"2":{"30":1}}],["玉婷",{"2":{"29":1,"30":1}}],["里面把该写的都写好",{"2":{"302":1}}],["里面可实现",{"2":{"301":1}}],["里面可以看到系统中已启动的应用",{"2":{"142":1}}],["里面填入镜像的下载地址",{"2":{"281":1}}],["里面为空即可",{"2":{"281":1}}],["里面写入应用包名",{"2":{"281":1}}],["里面写入需要安装的三方依赖",{"2":{"234":2}}],["里面进行配置",{"2":{"281":1}}],["里面进行维护",{"2":{"50":1}}],["里面只需要唯一继承",{"2":{"270":1}}],["里面我们设计成这样",{"2":{"270":1}}],["里面主要包含的是用例",{"2":{"265":1}}],["里面执行",{"2":{"260":1}}],["里面不需要写任何内容",{"2":{"235":1}}],["里面保存了所有远程测试机的测试结果",{"2":{"197":1}}],["里面配置测试机",{"2":{"281":1}}],["里面配置为",{"2":{"281":2}}],["里面配置以下参数",{"2":{"196":1}}],["里面配置关注",{"2":{"194":1}}],["里面找到",{"2":{"180":1}}],["里面支持配置对执行的一些参数进行配置",{"2":{"160":1,"254":1}}],["里面点击进入应用的标签",{"2":{"142":1}}],["里面需要定义",{"2":{"85":1}}],["里面",{"2":{"55":1,"214":1,"284":1}}],["里面增加指定",{"2":{"47":1}}],["里面通过配置文件定位桌面文件的方法",{"2":{"47":1}}],["里面定义登陆接口",{"2":{"75":1}}],["里面定义接口对象",{"2":{"65":1}}],["里面定义",{"2":{"44":1}}],["里面包含了基础框架所有的代码",{"2":{"42":1}}],["里面查看有哪些版本",{"2":{"42":1}}],["里面优化了标签化管理章节的描述",{"2":{"38":1}}],["里面细化了远程执行章节的描述",{"2":{"38":1}}],["里面报错",{"2":{"28":1}}],["里面的路径配置进行资源路径的拼接",{"2":{"303":1}}],["里面的参数",{"2":{"194":1}}],["里面的配置",{"2":{"42":2}}],["里面的",{"2":{"28":1,"70":1,"80":1,"90":1,"107":1,"116":1,"134":1,"232":1,"248":1}}],["里面的导入全部设置别名",{"2":{"27":1}}],["容易出现某些包安装失败",{"2":{"28":1}}],["因地制宜",{"2":{"261":1}}],["因为编辑器会自动给我们找到关联的地方",{"2":{"301":1}}],["因为大家都应该参照公共库里面的一些写法来写自己应用库里面的一些方法类",{"2":{"271":1}}],["因为大图中可能存在多个相同的小图",{"2":{"134":1}}],["因为代码编辑器调试代码只能通过入口文件执行",{"2":{"260":1}}],["因为重启类场景需要注册自启服务以及对用例执行过程的处理",{"2":{"224":1}}],["因为有些情况下需要用到",{"2":{"219":1}}],["因为在用例收集阶段可以指定到具体的应用库",{"2":{"196":1,"212":1}}],["因为理论上用例的执行时间是大于数据回填的接口请求时间的",{"2":{"196":1}}],["因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因",{"2":{"194":1}}],["因为你写用例层肯定是会导入方法层出口类的",{"2":{"182":1}}],["因为你得明确知道菜单在左边还是右边",{"2":{"132":1}}],["因为",{"2":{"180":1,"185":1,"223":1}}],["因为此类场景不仅仅在右键存在",{"2":{"132":1}}],["因为用法上更加简洁",{"2":{"77":1}}],["因为用固定的源替换之后",{"2":{"28":1}}],["因此将",{"2":{"284":1}}],["因此将修改后的源码放入到核心库里面",{"2":{"60":1}}],["因此您需要添加环境变量",{"2":{"246":1}}],["因此你不用担心脚本执行导致你的数据丢失",{"2":{"212":1}}],["因此应该配置为",{"2":{"212":1,"230":1}}],["因此用例的录屏能让我们看到用例在执行过程",{"2":{"194":1}}],["因此会导致负载不均衡",{"2":{"123":1}}],["因此我们选取文件管理器作为应用库改造的实验应用",{"2":{"291":1}}],["因此我们将它放到项目根目录",{"2":{"272":1}}],["因此我们大胆的设想",{"2":{"190":1}}],["因此我们形象的称之为",{"2":{"135":1}}],["因此我们需要进行解耦",{"2":{"278":1}}],["因此我们需要一种等待机制",{"2":{"134":1}}],["因此我们需要将",{"2":{"122":1}}],["因此我们增加了一个系统命令",{"2":{"42":1}}],["因此它可以使用",{"2":{"103":1}}],["因此",{"2":{"87":1,"119":1,"155":1,"197":1,"205":1}}],["因此方法里面不用写日志的代码",{"2":{"85":1}}],["因此在方法基类",{"2":{"85":1}}],["因此在底层将这部分日志输出屏蔽掉",{"2":{"27":1}}],["因此需要将文档部署到公网",{"2":{"42":1}}],["因此先把",{"2":{"41":1}}],["因此没有装载到虚拟环境里面",{"2":{"41":1}}],["因此暂留",{"2":{"16":1}}],["机器信息有",{"2":{"214":1}}],["机器密码不对时报错",{"2":{"15":1}}],["机制",{"2":{"28":1}}],["vue",{"2":{"287":1}}],["virtualenvs",{"2":{"237":1}}],["view",{"2":{"230":1,"293":4}}],["vscode",{"2":{"155":1}}],["venv",{"2":{"155":2}}],["verify=false",{"2":{"75":2}}],["version",{"2":{"28":1,"155":1,"204":6}}],["val",{"2":{"184":1}}],["value是对应pms上的模块id",{"2":{"212":1,"230":1}}],["valueerror",{"2":{"150":3,"176":6,"270":1}}],["values",{"2":{"120":1,"137":1,"176":3}}],["value",{"2":{"65":1,"149":1,"176":2}}],["variable",{"2":{"155":1}}],["variables",{"2":{"155":1}}],["variety",{"2":{"155":1}}],["v",{"2":{"75":2,"184":1}}],["v23",{"2":{"55":1}}],["v3",{"2":{"34":1}}],["v4",{"2":{"14":2,"34":1,"35":1,"75":1}}],["个及以上的外部应用调用",{"2":{"284":1}}],["个外部应用调用",{"2":{"283":1}}],["个应用都用到的",{"2":{"271":1}}],["个理由",{"0":{"243":1}}],["个参数",{"2":{"194":1}}],["个问题",{"2":{"124":1}}],["个执行最慢的用例列表",{"2":{"57":1}}],["个小点要注意",{"2":{"42":1}}],["个",{"2":{"27":1,"41":1,"132":1}}],["不然你可能会花上一天的时间来解决重命名的问题",{"2":{"301":1}}],["不然我为什么不用文管的重命名功能呢",{"2":{"301":1}}],["不做其他事情",{"2":{"297":1}}],["不关心元素的定位和操作",{"2":{"276":1}}],["不插串口线",{"2":{"260":1}}],["不好定位问题",{"2":{"260":1}}],["不好做时",{"2":{"147":1}}],["不能适应自动化测试在多场景下的应用",{"2":{"278":1}}],["不能在编辑器中直接执行单个用例脚本",{"2":{"260":1}}],["不能接受的是经常会导致大家在分析用例失败原因的时候将矛头指向它",{"2":{"27":1}}],["不要以",{"2":{"247":1}}],["不仅支持单条用例超时控制",{"2":{"243":1}}],["不会在每条用例执行完之后生成json结果文件",{"2":{"230":1}}],["不会受到字体",{"2":{"132":1}}],["不会受到菜单选项顺序改变的影响",{"2":{"132":1}}],["不跳过用例",{"2":{"230":1}}],["不建议在组合步骤中间插入一个reboot",{"2":{"223":1}}],["不管配置文件是否配置",{"2":{"211":1}}],["不管send",{"2":{"162":1,"230":1,"256":1}}],["不适合马上放到流水线去跑",{"2":{"205":1}}],["不适用于界面不固定的应用",{"2":{"147":1}}],["不打印构造函数和魔法函数的功能说明",{"2":{"192":1,"230":1}}],["不熟悉",{"2":{"186":1}}],["不存在以",{"2":{"176":1}}],["不相同",{"2":{"176":4}}],["不符",{"2":{"176":1}}],["不含report目录",{"2":{"162":1,"230":1,"256":1}}],["不需要",{"2":{"155":1}}],["不妨考虑使用这种",{"2":{"147":1}}],["不同测试类型的用例执行",{"2":{"286":1}}],["不同测试类型的配置都在同一个配置文件里面",{"2":{"281":1}}],["不同应用版本环境上都可以进行自动化的",{"2":{"281":1}}],["不同的定位方案调用不同的定位工具对象",{"2":{"296":1}}],["不同的维度来挑选要执行的用例",{"2":{"278":1}}],["不同的at项目在同一台机器上部署环境时依赖版本冲突的问题",{"2":{"42":1}}],["不同版本的系统壁纸不同",{"2":{"139":1}}],["不依赖",{"0":{"136":1},"1":{"137":1,"138":1}}],["不停的截取这段时间内的大图",{"2":{"135":1}}],["不容易捕捉到",{"2":{"135":1}}],["不用担心",{"2":{"302":1}}],["不用安装",{"2":{"137":1}}],["不用保存大量的图片",{"2":{"132":1}}],["不用再单独处理远程执行的参数逻辑",{"2":{"44":1}}],["不想步长那么只管",{"2":{"130":1}}],["不生效的问题",{"2":{"57":1}}],["不输出异常日志的问题",{"2":{"50":1}}],["不传入",{"2":{"48":1}}],["不兼容",{"2":{"47":1}}],["不过没关系",{"2":{"42":1}}],["不加",{"2":{"42":1,"246":2}}],["不在系统",{"2":{"42":1}}],["不应该把含有业务相关的代码提交到框架底层",{"2":{"3":1}}],["但可能出现",{"2":{"246":1}}],["但可能会出现文档速度慢的问题",{"2":{"42":1}}],["但这样做有一个很严重的问题",{"2":{"240":1}}],["但框架不会进行数据回填",{"2":{"230":1}}],["但我们仍然实现了",{"2":{"220":1}}],["但仍然想要跳过用例",{"2":{"205":1}}],["但不能立即删除跳过原因",{"2":{"205":1}}],["但基本的使用该有的都有",{"2":{"186":1}}],["但基础框架不需要",{"2":{"41":1}}],["但问题是没有一种方案是通用的",{"2":{"181":1}}],["但远程机器执行的用例不同",{"2":{"163":1,"257":1}}],["但没有被使用",{"2":{"155":1}}],["但实际获取的窗口为",{"2":{"150":1}}],["但最好有具体含义",{"2":{"149":1}}],["但最终还是没能解决",{"2":{"131":1}}],["但在识别效率上还没有达到",{"2":{"137":1}}],["但其实安装包有点大",{"2":{"119":1}}],["但大多数同学喜欢用三方模块",{"2":{"77":1}}],["但写了",{"2":{"58":1}}],["但终端没有错误日志输出的问题",{"2":{"55":1}}],["但有些接口的项目不需要这个检查",{"2":{"42":1}}],["但是又是相同名称的重命名",{"2":{"303":1}}],["但是由于它的特殊性",{"2":{"272":1}}],["但是我们想让事情变得简单",{"2":{"270":1}}],["但是没有串口线",{"2":{"261":1}}],["但是没注意到之前给海燕姐那边项目单独定制做了个图像识别接口",{"2":{"41":1}}],["但是对测试人员本地编写代码安装环境很不友好",{"2":{"260":1}}],["但是方法类同样会进行实例化",{"2":{"223":1}}],["但是此时",{"2":{"205":1}}],["但是执行结果可能不一致",{"2":{"197":1}}],["但是填了可以提高用例的执行速度",{"2":{"196":1,"212":1}}],["但是你不能直接通过浏览器打开",{"2":{"180":1}}],["但是几乎所有的命令行参数都对应提供了配置文件配置项",{"2":{"157":1}}],["但是这样的区分太宽泛了",{"2":{"278":1}}],["但是这是我特意这样写的",{"2":{"155":1}}],["但是这里仍然存在两个严重的问题",{"2":{"130":1}}],["但是位置是固定的",{"2":{"143":1}}],["但是在一些情况下仍然存在一点问题",{"2":{"132":1}}],["但是在属性的",{"2":{"131":1}}],["但是需要保存大量的图片",{"2":{"129":1}}],["但是",{"2":{"128":1,"278":1}}],["但是它对于中文的识别非常差",{"2":{"118":1}}],["但是都有个问题",{"2":{"42":1}}],["但本次时间比较紧",{"2":{"41":1}}],["但",{"2":{"27":1,"32":1,"211":1}}],["但考虑到有些同学仍然有使用",{"2":{"16":1}}],["执行入口提供给测试平台的接口包括",{"2":{"287":1}}],["执行入口能随意通过用例标签指定要执行的用例",{"2":{"286":1}}],["执行入口加载相应的用例集并控制执行",{"2":{"281":1}}],["执行一个或多个应用的用例",{"2":{"281":1}}],["执行一下",{"2":{"225":1}}],["执行器",{"2":{"267":1}}],["执行所需环境",{"2":{"248":1}}],["执行",{"2":{"234":1,"281":1}}],["执行包含用例标签的用例",{"2":{"230":1}}],["执行包含关键词的用例",{"2":{"168":1,"230":1}}],["执行结束之后在",{"2":{"197":1}}],["执行完之后会在",{"2":{"194":1}}],["执行完之后所有测试机的测试结果会返回给服务端",{"2":{"162":1,"256":1}}],["执行的应用名称",{"2":{"230":1}}],["执行的时候会自动输出",{"2":{"193":1}}],["执行的业务线",{"2":{"159":1,"253":1}}],["执行某个app工程的所有用例",{"0":{"167":1}}],["执行前确保远程机器已经开启了",{"2":{"162":1,"256":1}}],["执行相同的测试用例",{"2":{"162":1,"230":1,"256":1}}],["执行环境要对编码人员更加友好",{"2":{"261":1}}],["执行环境",{"0":{"225":1},"2":{"70":1,"80":1,"90":1,"107":1,"116":1}}],["执行开始时打印",{"2":{"54":1}}],["执行用例的范围",{"2":{"287":1}}],["执行用例的标签配置等等",{"2":{"281":1}}],["执行用例默认读取到",{"2":{"194":1}}],["执行用例",{"2":{"52":1}}],["执行时间",{"2":{"287":1}}],["执行时间会越来越长",{"2":{"286":1}}],["执行时日志级别",{"2":{"227":1,"273":1}}],["执行时会在根目录下动态生成",{"2":{"178":1}}],["执行时",{"2":{"42":1}}],["执行会报错",{"2":{"27":1}}],["执行管理器",{"0":{"156":1,"251":1},"1":{"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1},"2":{"13":1,"69":1,"79":1,"89":1,"106":1,"115":1}}],["有没有网络无所谓",{"2":{"261":1}}],["有没有可能有一天国内无法使用",{"2":{"137":1}}],["有网络",{"2":{"261":1}}],["有两台机器",{"2":{"261":2}}],["有趣",{"2":{"241":1}}],["有必要自己实现一个图像识别的功能吗",{"2":{"137":1}}],["有",{"2":{"137":1}}],["有同学可能会发现",{"2":{"198":1}}],["有同学肯定要问",{"2":{"181":1}}],["有同学要问了",{"2":{"137":1}}],["有同学说干嘛不通过属性定位呢",{"2":{"131":1}}],["有可能图像识别的时候气泡已经消失了",{"2":{"135":1}}],["有可能存在识别的那一刻页面也没有跳转出来",{"2":{"134":1}}],["有时候页面跳转有延时",{"2":{"134":1}}],["有的没写",{"2":{"58":1}}],["有些骚操作编辑器是无法自动处理的",{"2":{"301":1}}],["有些地方可能不支持ctrl+v粘贴",{"2":{"184":1}}],["有些机器可能",{"2":{"42":1}}],["有些镜像没有",{"2":{"27":1}}],["有志",{"2":{"21":1,"22":1,"27":1,"31":2,"34":1}}],["英文数字字符等使用",{"2":{"27":1}}],["~$",{"2":{"48":2,"142":1}}],["~",{"2":{"26":1,"85":1,"112":1,"134":1,"176":2,"230":1,"297":1}}],["孙翠",{"2":{"26":1,"40":1}}],["佳斌",{"2":{"26":1}}],["本项目是一个自动化测试的基础框架",{"2":{"265":1}}],["本身无法提供代码补全",{"2":{"220":1}}],["本机同步解析",{"2":{"261":1}}],["本机执行",{"2":{"261":2}}],["本机执行方案",{"2":{"261":1}}],["本机执行时回填",{"0":{"196":1}}],["本机",{"2":{"227":1,"273":1}}],["本机部署的功能仍然保留",{"2":{"42":1}}],["本地插件模块",{"2":{"267":1}}],["本地插件",{"2":{"267":1,"293":1}}],["本地文件测试套",{"2":{"230":1}}],["本地用例文件驱动执行",{"0":{"173":1}}],["本地执行子命令为",{"2":{"158":1}}],["本地执行",{"0":{"158":1,"252":1},"1":{"159":1,"160":1,"253":1,"254":1},"2":{"180":1}}],["本地再次调用报属性找不到的问题",{"2":{"17":1}}],["本章节主要讲基于",{"2":{"132":1}}],["本次设计主要集中在后端这部分架构的设计上",{"2":{"287":1}}],["本次我们解决了这个问题",{"2":{"42":1}}],["本次彻底解决",{"2":{"29":1}}],["本次功能更新离不开多个部门领导和同事们的协助",{"2":{"26":1}}],["堪称完美",{"2":{"26":1}}],["至此基于",{"2":{"26":1}}],["默认配置文件",{"2":{"267":1}}],["默认的项目名称为",{"2":{"247":1}}],["默认采用虚拟化部署",{"2":{"237":1}}],["默认在所有测试完成之后输出报错信息",{"2":{"230":1}}],["默认失败重跑的次数是",{"2":{"194":1}}],["默认",{"2":{"184":1}}],["默认值为",{"2":{"176":1}}],["默认值设置为",{"2":{"24":1}}],["默认使用虚拟环境执行",{"2":{"225":1}}],["默认使用",{"2":{"151":1}}],["默认使用系统自带的浏览器进行测试",{"2":{"103":1,"104":1}}],["默认参考点",{"2":{"150":2}}],["默认不间隔",{"2":{"135":1,"176":1}}],["默认不传参",{"2":{"134":1}}],["默认image",{"2":{"134":1}}],["默认情况下同时生成",{"2":{"178":1}}],["默认情况下是一刻不停的截图",{"2":{"135":1}}],["默认情况下",{"2":{"134":2}}],["默认大图是截取屏幕",{"2":{"134":1,"138":1}}],["默认为空",{"2":{"230":1}}],["默认为",{"2":{"120":1,"143":1,"150":1,"176":2}}],["默认开启",{"2":{"59":1}}],["默认备份至",{"2":{"57":1}}],["默认语言",{"2":{"54":1}}],["默认取sett",{"2":{"162":1,"256":1}}],["默认取",{"2":{"48":1,"123":1}}],["默认重试1次",{"2":{"51":1}}],["默认重试",{"2":{"40":1}}],["默认最大递归深度的问题",{"2":{"27":1}}],["默认环境中移除此模块",{"2":{"12":1}}],["泽铭",{"2":{"23":1,"26":1,"40":1}}],["换了调用逻辑",{"2":{"23":1}}],["global",{"2":{"267":1}}],["globalconfig",{"2":{"26":1,"35":3,"42":2,"70":1,"80":1,"90":1,"103":1,"107":1,"116":1,"120":2,"134":4,"138":2,"145":5,"150":11,"157":2,"160":1,"162":1,"176":11,"184":5,"185":2,"194":2,"196":1,"204":7,"214":1,"228":5,"229":3,"232":1,"248":1,"254":1,"256":1,"267":2,"281":3}}],["g",{"2":{"230":2}}],["gpl",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1,"244":1}}],["gti",{"2":{"230":1}}],["gt",{"2":{"143":3}}],["grab",{"2":{"176":1}}],["graph",{"2":{"137":4}}],["grep",{"2":{"145":1}}],["group",{"2":{"75":8,"145":1}}],["goto",{"2":{"102":2,"103":3,"230":2}}],["genericpredicate",{"2":{"145":2}}],["generate",{"2":{"76":2}}],["gecko",{"2":{"75":1}}],["getmembers",{"2":{"191":1}}],["getattr",{"2":{"150":4}}],["getallwindowstateslist",{"2":{"23":1,"26":1,"150":4}}],["getwindowinformation",{"2":{"150":4}}],["get",{"2":{"51":1,"65":2,"66":1,"75":7,"135":1,"148":2,"150":27,"176":29,"184":2,"204":1,"270":3,"296":1,"297":1}}],["gzip",{"2":{"75":1}}],["git仓库的分支",{"2":{"230":1}}],["git仓库的密码",{"2":{"230":1}}],["git仓库的用户名",{"2":{"230":1}}],["git仓库的地址",{"2":{"230":1}}],["git子命令用于拉取子项目仓库代码",{"2":{"230":1}}],["gitmodules",{"2":{"58":1}}],["gitignore",{"2":{"20":1}}],["gitlab",{"2":{"18":1}}],["git",{"2":{"6":1,"8":1,"12":4,"19":2,"42":1,"54":1,"155":2,"230":4,"249":1}}],["github",{"2":{"2":1,"42":2}}],["调试和编写用例",{"0":{"304":1}}],["调试模式",{"2":{"159":1,"253":1}}],["调起的文管对话框实际为",{"2":{"284":1}}],["调用其他应用的方法库",{"2":{"281":1}}],["调用上述方法会报错",{"2":{"183":1}}],["调用所有的断言语句",{"2":{"175":1}}],["调用方法时",{"2":{"193":1}}],["调用方法",{"2":{"149":1}}],["调用相关方法失败~",{"2":{"145":1}}],["调用",{"2":{"86":1,"216":1,"217":1}}],["调用的函数增加了",{"2":{"54":1}}],["调用函数同时传入可变参数和默认参数",{"2":{"14":1}}],["调整工程目录",{"0":{"301":1}}],["调整",{"2":{"23":1}}],["布局",{"2":{"23":1}}],["切换图片之后再次识别这张图片",{"2":{"139":1}}],["切换",{"2":{"23":1}}],["多种报告输出",{"2":{"265":1}}],["多种元素定位方案",{"2":{"243":1}}],["多机器分布式异步负载均衡执行也是用本地作为服务端控制远程机器执行",{"2":{"163":1,"257":1}}],["多机器分布式异步负载均衡执行",{"0":{"163":1}}],["多机器分布式异步执行就是由本地",{"2":{"162":1,"256":1}}],["多机器分布式异步执行",{"0":{"162":1}}],["多的不说了",{"2":{"118":1}}],["多样的元素定位方案",{"2":{"87":1}}],["多个应用之间用",{"2":{"281":1}}],["多个应用都要用到的一些操作方法",{"2":{"265":1}}],["多个分辨率检查用英文逗号连接",{"2":{"230":1}}],["多个机器之间用斜线分割",{"2":{"214":1,"230":2}}],["多个机器信息用",{"2":{"214":1}}],["多个机器用",{"2":{"48":1,"162":1,"256":1}}],["多个参数用",{"2":{"204":1}}],["多个参数以逗号隔开",{"2":{"192":3,"230":3}}],["多个架构之间使用",{"2":{"204":1}}],["多个以",{"2":{"22":1}}],["多条件跳过用例功能",{"2":{"22":1}}],["阻塞问题",{"2":{"21":1}}],["阻塞在密码输入",{"2":{"5":1}}],["获取被装饰的类下所有函数",{"2":{"191":1}}],["获取当前鼠标位置",{"2":{"184":1}}],["获取屏幕分辨率",{"2":{"184":1}}],["获取屏幕大小",{"2":{"184":1}}],["获取活动应用窗口id",{"2":{"150":1}}],["获取窗口下边界中心的坐标",{"2":{"150":2}}],["获取窗口右边界中心坐标",{"2":{"150":2}}],["获取窗口上边界中心坐标",{"2":{"150":2}}],["获取窗口左边界中心坐标",{"2":{"150":1}}],["获取窗口左上角坐标错误",{"2":{"150":1}}],["获取窗口左上角坐标",{"2":{"150":1}}],["获取窗口的中心点坐标",{"2":{"150":1}}],["获取窗口的大小",{"2":{"150":1}}],["获取窗口的位置及大小",{"2":{"150":1}}],["获取窗口大小错误",{"2":{"150":2}}],["获取窗口大小",{"2":{"150":2}}],["获取配置",{"2":{"148":1}}],["获取应用的所有窗口编号",{"2":{"150":1}}],["获取应用所有窗口数量",{"2":{"150":1}}],["获取应用窗口的信息",{"2":{"148":1}}],["获取应用对象的时候",{"2":{"143":1}}],["获取应用对象",{"2":{"143":1}}],["获取app元素的对象",{"2":{"144":1,"145":1}}],["获取到当前的显示服务器",{"2":{"185":1}}],["获取到应用窗口在当前屏幕中的位置",{"2":{"148":1}}],["获取到这个元素下面所有的元素列表",{"2":{"143":1}}],["获取到相应元素的对象",{"2":{"143":1}}],["获取元素按钮相对与应用窗口边界的位置及大小",{"2":{"148":1}}],["获取元素中心坐标",{"2":{"145":1}}],["获取元素右上角的坐标",{"2":{"145":1}}],["获取元素的左上角坐标及长宽",{"2":{"150":1}}],["获取元素的中心坐标",{"2":{"150":1}}],["获取元素的中心位置",{"2":{"144":1,"145":1}}],["获取元素的大小",{"2":{"145":1}}],["获取元素",{"2":{"145":2}}],["获取元素左上角的坐标",{"2":{"145":1}}],["获取元素对象列表",{"2":{"143":1}}],["获取元素对象",{"2":{"143":2,"145":1}}],["获取元素控件的标签名称",{"2":{"142":1}}],["获取管理员登陆",{"2":{"75":1}}],["获取激活状态",{"2":{"65":1}}],["获取控件左上角坐标及长宽",{"2":{"54":1}}],["获取以外",{"2":{"42":1}}],["获取的窗口名称为空",{"2":{"28":1}}],["获取不到有效信息会有一些",{"2":{"27":1}}],["获取",{"2":{"21":1}}],["获取数据",{"2":{"17":1}}],["标定操作方法",{"2":{"296":1}}],["标题栏方法类",{"2":{"296":1}}],["标题栏",{"2":{"296":1}}],["标记所有已实现的用例标签",{"2":{"285":1}}],["标准库",{"2":{"138":1}}],["标准库difflib",{"2":{"18":1}}],["标识文件",{"0":{"93":1}}],["标签支持扩展",{"2":{"285":1}}],["标签和资源都是相互独立的",{"2":{"281":1}}],["标签化执行驱动程序编写",{"2":{"288":1}}],["标签化执行",{"2":{"265":1}}],["标签化管理的驱动执行逻辑功能实现",{"2":{"286":1}}],["标签化管理",{"0":{"199":1},"1":{"200":1,"201":1,"202":1,"203":1,"204":1,"205":1,"206":1,"207":1,"208":1}}],["标签化管理支持判断系统版本跳过用例",{"2":{"28":1}}],["标签可以是传统的pytest标签",{"2":{"230":1}}],["标签自动同步",{"0":{"210":1},"1":{"211":1,"212":1}}],["标签的用例",{"2":{"209":1,"230":1}}],["标签记录为",{"2":{"204":2}}],["标签说明",{"0":{"200":1}}],["标签驱动支持",{"2":{"169":1}}],["标签",{"2":{"35":1,"58":1,"169":1,"267":1}}],["标签生效的问题",{"2":{"21":1}}],["español",{"2":{"230":1}}],["es",{"2":{"230":1}}],["esc",{"2":{"150":1}}],["eg",{"2":{"230":1}}],["eggs",{"2":{"155":1}}],["ec",{"2":{"209":1}}],["echo",{"2":{"184":1,"204":2,"223":1}}],["easy",{"2":{"185":1}}],["each",{"2":{"137":1}}],["e9",{"2":{"155":1}}],["e712",{"2":{"155":1}}],["e711",{"2":{"155":1}}],["e731",{"2":{"155":1}}],["e722",{"2":{"155":1}}],["e721",{"2":{"155":1}}],["e7",{"2":{"155":1}}],["e402",{"2":{"155":1}}],["e4",{"2":{"155":1}}],["eval",{"2":{"150":2}}],["evalx",{"2":{"145":4}}],["effect",{"2":{"155":1}}],["ef",{"2":{"145":1}}],["e",{"2":{"134":2,"162":3,"230":2,"256":3}}],["eles",{"2":{"145":3}}],["ele",{"2":{"145":5}}],["elementexpressionerror",{"2":{"176":2}}],["elements",{"2":{"145":6,"176":1,"193":5}}],["elementnotfound",{"2":{"145":5,"176":2}}],["element",{"2":{"85":2,"94":1,"134":2,"143":2,"144":7,"145":58,"176":5,"193":2,"216":9,"296":1}}],["elif",{"2":{"120":1,"145":1,"150":10,"176":4}}],["else",{"2":{"120":2,"134":1,"145":10,"150":24,"176":25,"184":14,"185":1,"270":1}}],["email",{"2":{"75":3}}],["email=none",{"2":{"75":1}}],["examples",{"2":{"155":1}}],["export",{"2":{"209":1,"230":2}}],["exp",{"2":{"176":2}}],["expanduser",{"2":{"176":4}}],["expr=",{"2":{"145":1,"176":2}}],["expr",{"2":{"145":27,"176":15}}],["expect",{"2":{"76":3,"103":2,"176":38,"188":1}}],["extents",{"2":{"144":1,"145":1}}],["excel",{"2":{"208":1,"281":1}}],["exception",{"2":{"134":1,"145":2,"150":5,"176":11}}],["exceptions",{"2":{"75":1}}],["except",{"2":{"75":1,"134":1,"138":1,"145":5,"150":6,"176":9,"223":1}}],["exclude",{"2":{"155":2}}],["exc",{"2":{"138":2,"150":15,"176":12,"184":3}}],["executable",{"2":{"103":1,"230":1}}],["exit",{"2":{"54":2,"159":1,"162":1,"184":1,"253":1,"256":1}}],["exists",{"2":{"176":4,"297":3}}],["exist",{"2":{"19":1,"25":1,"35":1,"54":2,"112":1,"120":2,"176":10,"185":2,"223":1}}],["equal",{"2":{"66":1,"176":2}}],["etc",{"2":{"28":1}}],["error",{"2":{"22":1,"28":1,"145":1,"178":1,"192":1,"230":1}}],["english",{"2":{"230":1}}],["en",{"2":{"230":1}}],["enabled",{"2":{"155":2}}],["enable",{"2":{"155":3,"162":1,"256":1}}],["endwith=endwith",{"2":{"176":1}}],["endwith",{"2":{"176":5}}],["ending",{"2":{"155":2}}],["endswith",{"2":{"145":2,"192":1,"230":1}}],["end",{"2":{"145":2,"176":42,"184":6,"230":1}}],["enddate",{"2":{"13":1}}],["enter",{"2":{"128":2,"183":1,"184":4}}],["encoding",{"2":{"75":1}}],["encode",{"2":{"75":2}}],["environ",{"2":{"184":1}}],["environmenterror",{"2":{"138":1,"145":1}}],["env",{"0":{"73":1,"98":1,"231":1},"1":{"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1,"240":1},"2":{"13":1,"16":3,"17":1,"18":1,"19":1,"28":2,"30":1,"39":2,"42":2,"43":1,"44":2,"46":1,"47":1,"48":3,"51":2,"54":4,"55":2,"58":1,"69":1,"70":2,"73":1,"79":1,"80":2,"89":1,"90":2,"98":1,"106":1,"107":2,"115":1,"116":2,"119":1,"145":1,"150":1,"162":1,"176":1,"184":1,"185":1,"204":1,"225":2,"230":1,"232":3,"234":2,"235":1,"236":1,"248":3,"256":1}}],["azərbaycanca",{"2":{"230":1}}],["az",{"2":{"230":1}}],["awk",{"2":{"204":2}}],["aarch64",{"2":{"204":7,"243":1}}],["amount",{"2":{"176":1,"184":5}}],["amp",{"2":{"22":2,"151":1,"204":7}}],["absolute",{"2":{"150":2}}],["abspath",{"2":{"120":4,"134":5,"138":3,"176":14}}],["abspath=",{"2":{"134":1}}],["abspath=picture",{"2":{"134":1,"176":2}}],["abspath=pic",{"2":{"120":1,"176":2}}],["abspath=none",{"2":{"120":2,"134":1,"176":2}}],["abspath=deepinmusicwidget",{"2":{"54":1}}],["add",{"2":{"149":1,"223":1}}],["admin123",{"2":{"214":1,"230":2}}],["adminapi",{"2":{"75":2,"76":1}}],["admin",{"2":{"75":21,"76":3}}],["arch",{"2":{"204":1,"229":1}}],["arrch64",{"2":{"204":1}}],["arguments",{"2":{"145":1,"253":1}}],["args",{"2":{"120":3,"144":2,"145":7,"176":10,"184":10,"204":14}}],["are",{"2":{"137":2,"155":1}}],["asan",{"2":{"281":1}}],["async",{"2":{"159":1,"171":1,"172":1,"196":2,"230":1,"253":1}}],["assume",{"2":{"155":1}}],["assertoptionerror",{"2":{"176":4}}],["assertionerror",{"2":{"120":2,"176":30}}],["assertcommon",{"2":{"25":1,"175":2,"176":1}}],["assert",{"2":{"19":1,"25":1,"35":1,"54":4,"62":2,"66":2,"71":2,"72":2,"76":2,"81":2,"86":3,"93":1,"96":2,"97":2,"103":4,"108":2,"112":2,"120":2,"134":1,"175":5,"176":25,"185":2,"188":1,"192":1,"223":1,"230":1,"249":2,"267":2,"281":1,"293":2,"297":7}}],["as",{"2":{"134":1,"138":3,"150":5,"155":1,"176":7,"184":1}}],["airtest",{"2":{"133":1}}],["an",{"2":{"155":1}}],["and",{"2":{"120":1,"137":3,"145":2,"150":13,"155":2,"159":1,"162":1,"168":2,"169":1,"176":6,"184":7,"230":1,"253":1,"256":1,"301":1}}],["any",{"2":{"19":1,"176":3}}],["actions",{"2":{"142":1}}],["action",{"2":{"132":4}}],["actual",{"2":{"76":2,"176":10}}],["accept",{"2":{"75":3}}],["agent",{"2":{"75":1}}],["album",{"2":{"201":2,"209":3,"281":4}}],["alt",{"2":{"184":1,"217":2,"218":2,"219":1}}],["also",{"2":{"137":1}}],["all",{"2":{"155":3,"176":6,"184":1,"230":1}}],["allow",{"2":{"120":1,"138":2,"155":2}}],["allure报告备份",{"2":{"178":1}}],["allure报告",{"2":{"178":1}}],["allure",{"2":{"46":1,"54":1,"57":2,"178":3,"179":1,"180":6,"193":2,"230":3}}],["alive",{"2":{"75":1}}],["apiresponseassertions",{"2":{"188":1}}],["apiresponse",{"2":{"188":1}}],["api",{"2":{"72":5,"75":10,"76":7,"200":1}}],["app工程",{"2":{"249":1}}],["app工程配置对象",{"0":{"229":1}}],["app工程的名称",{"2":{"219":1}}],["appropriate",{"2":{"155":1}}],["append",{"2":{"145":1}}],["appname",{"2":{"94":3}}],["appname=",{"2":{"17":1,"219":1}}],["applewebkit",{"2":{"75":1}}],["applicationstarterror",{"2":{"145":2,"150":6,"223":1}}],["applications",{"2":{"94":1}}],["application",{"2":{"21":1,"75":2,"143":2,"144":1,"145":1}}],["app",{"0":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1},"1":{"63":1,"72":1,"73":1,"82":1,"97":1,"98":1,"99":1,"109":1},"2":{"35":2,"36":1,"48":3,"54":1,"62":6,"65":1,"66":4,"71":6,"72":3,"76":2,"81":6,"85":4,"86":6,"93":1,"95":2,"96":6,"97":3,"102":1,"103":4,"108":6,"112":4,"143":3,"144":2,"145":6,"148":4,"150":61,"159":5,"166":1,"167":1,"175":5,"176":18,"196":3,"212":1,"219":3,"230":4,"249":7,"253":3,"270":9,"271":3,"295":3,"298":5}}],["apps",{"0":{"269":1},"2":{"19":1,"35":1,"42":1,"48":3,"50":2,"54":1,"57":1,"62":1,"65":1,"66":3,"69":1,"71":1,"72":1,"75":2,"76":3,"79":1,"81":1,"85":1,"86":3,"89":1,"93":1,"95":2,"96":1,"97":1,"102":1,"103":3,"106":1,"108":1,"112":3,"115":1,"159":2,"167":1,"168":1,"171":1,"172":1,"173":3,"175":1,"176":2,"182":1,"196":1,"197":1,"209":2,"230":3,"249":3,"253":2,"256":1,"265":2,"267":1,"269":1,"272":1,"281":1,"296":1,"297":3,"298":6,"300":1}}],["attr",{"2":{"85":2,"86":1,"94":2,"95":1,"145":7,"176":3,"216":3,"223":1,"271":1,"283":1,"284":1,"296":2}}],["at",{"0":{"262":1,"289":1},"1":{"263":1,"264":1,"265":1,"266":1,"267":1,"268":1,"269":1,"270":1,"271":1,"272":1,"273":1,"290":1,"291":1,"292":1,"293":1,"294":1,"295":1,"296":1,"297":1,"298":1,"299":1,"300":1,"301":1,"302":1,"303":1,"304":1},"2":{"56":1,"134":1,"137":1,"142":1,"148":1,"205":2,"249":1,"265":2,"269":1,"274":7,"277":2,"281":2,"290":1}}],["autostart",{"2":{"159":2,"224":2,"230":1,"253":2}}],["auto",{"2":{"155":2,"159":1,"196":2,"230":2,"253":1}}],["automatically",{"2":{"155":1}}],["autotool",{"2":{"43":1,"181":1}}],["autotest",{"2":{"35":3,"42":2,"48":4,"50":2,"54":1,"62":2,"65":1,"66":3,"71":2,"72":1,"75":2,"76":3,"81":2,"85":1,"86":3,"93":1,"95":2,"96":2,"97":1,"102":1,"103":3,"108":2,"112":3,"159":4,"162":2,"163":1,"167":1,"168":1,"171":1,"172":1,"173":4,"175":1,"176":2,"178":2,"182":1,"196":1,"197":1,"209":2,"219":1,"230":3,"249":4,"253":3,"256":1,"265":2,"267":2,"296":1,"297":2,"298":5,"300":1,"302":1}}],["author",{"2":{"145":1,"150":1,"184":1}}],["authorizationstate",{"2":{"65":1}}],["authorization",{"2":{"65":1,"66":3}}],["auotest",{"2":{"54":1}}],["a",{"2":{"35":3,"48":3,"52":1,"54":1,"155":4,"159":1,"162":2,"163":1,"167":1,"171":1,"172":1,"184":2,"196":1,"197":1,"204":2,"209":3,"253":2,"256":2,"257":1}}],["环境也无法部署",{"2":{"260":1}}],["环境不好搭建",{"2":{"260":1}}],["环境问题",{"2":{"260":1}}],["环境以提供",{"2":{"213":1}}],["环境影响或评估不再适用于自动化测试时",{"2":{"206":1}}],["环境依赖这块后面会单独详细讲",{"2":{"137":1}}],["环境部署简单",{"2":{"241":1}}],["环境部署",{"0":{"231":1},"1":{"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1,"240":1},"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"260":1}}],["环境执行",{"2":{"56":1}}],["环境安装",{"2":{"261":1}}],["环境安装难度",{"2":{"186":1}}],["环境安装移除",{"2":{"54":1}}],["环境安装失败的问题",{"2":{"48":1}}],["环境变量指向错误",{"2":{"52":1}}],["环境变量缺失问题",{"2":{"19":1}}],["环境目录下",{"2":{"42":1}}],["环境下能顺畅运行",{"2":{"243":1}}],["环境下使用命令行参数会更加方便",{"2":{"159":1,"253":1}}],["环境下安装无法读取密码的问题",{"2":{"55":1}}],["环境下多个工程存在",{"2":{"52":1}}],["环境下运行提示",{"2":{"50":1}}],["环境下",{"2":{"19":1,"48":1,"54":1}}],["x4",{"2":{"256":1}}],["x3",{"2":{"256":1}}],["x3c",{"2":{"28":1,"97":1,"145":3,"150":3,"176":24,"184":10,"249":1}}],["xoffset=int",{"2":{"184":2}}],["xy",{"2":{"176":6}}],["x=int",{"2":{"184":1}}],["x=",{"2":{"184":6}}],["x=100",{"2":{"176":2}}],["x=0",{"2":{"176":4}}],["x=none",{"2":{"150":2,"184":5}}],["xwininfo",{"2":{"148":2,"150":1,"185":1}}],["x26",{"2":{"204":8}}],["x2",{"2":{"148":3}}],["x1",{"2":{"148":4}}],["x11",{"2":{"26":1,"40":1,"75":1,"150":7,"176":1,"184":1,"185":5,"204":1,"241":1,"243":1}}],["x86",{"2":{"75":1,"193":1,"243":1}}],["xsrf",{"2":{"75":2}}],["xml报告",{"2":{"178":1}}],["xmlrpc",{"2":{"120":1,"138":4}}],["xml",{"2":{"57":1,"178":3,"230":3}}],["x",{"2":{"51":2,"54":1,"75":1,"120":2,"130":1,"134":5,"137":2,"138":7,"139":2,"144":4,"145":8,"149":2,"150":152,"176":42,"184":61,"193":2}}],["xx",{"2":{"48":6,"145":1,"162":6,"163":2,"197":1,"256":2}}],["xxx的用例不跳过",{"2":{"230":1}}],["xxxwidget",{"2":{"190":1}}],["xxxx",{"2":{"171":1,"172":1,"196":1,"197":1,"296":1}}],["xxx",{"2":{"13":1,"17":2,"48":2,"50":1,"54":2,"58":1,"103":3,"145":4,"159":3,"162":4,"163":2,"165":5,"171":1,"172":1,"175":1,"176":1,"185":2,"190":1,"192":3,"193":1,"196":1,"197":2,"198":2,"200":4,"201":2,"203":1,"205":5,"216":5,"217":1,"219":1,"230":6,"234":2,"235":1,"253":1,"256":2,"267":1,"271":1,"283":1,"284":1,"285":1,"293":2,"296":2,"297":2,"298":5,"300":1}}],["xdg",{"2":{"40":1,"204":3}}],["xdotool",{"2":{"31":1,"148":2,"150":5,"181":1,"184":4,"185":1}}],["xauth",{"2":{"27":1}}],["xauthorty",{"2":{"26":1}}],["xauthority",{"2":{"19":1,"27":1,"43":1}}],["xlib",{"2":{"22":1,"27":1}}],["中期任务计划",{"2":{"288":1}}],["中配版",{"2":{"261":1}}],["中文",{"2":{"230":1}}],["中文按现有",{"2":{"27":1}}],["中同时填入后",{"2":{"205":1}}],["中横线",{"2":{"204":1}}],["中键",{"2":{"184":2}}],["中编写用例所在路径",{"2":{"173":1}}],["中编写方法",{"2":{"85":1}}],["中心坐标",{"2":{"148":1}}],["中心",{"2":{"145":1}}],["中有些地方是空白的或者是",{"2":{"142":1}}],["中后",{"2":{"142":1}}],["中鼠标选中元素标签的时候",{"2":{"142":1}}],["中也是从最顶层的",{"2":{"141":1}}],["中去做匹配",{"2":{"134":1}}],["中加入它",{"2":{"119":1}}],["中间层主要服务于用例层",{"2":{"276":1}}],["中间层",{"2":{"276":2}}],["中间操作",{"2":{"54":2}}],["中间的失败结果被后续用例更新为成功的问题",{"2":{"32":1}}],["中安装",{"2":{"46":1}}],["中的类",{"2":{"284":1}}],["中的标签全部删掉就可以了",{"2":{"205":1}}],["中的标签同步到",{"2":{"35":1}}],["中的任意一个",{"2":{"176":1}}],["中的",{"2":{"35":1}}],["中英文场景检测模型准确率提升",{"2":{"35":1}}],["中某个",{"2":{"28":1}}],["中",{"2":{"19":1,"48":1,"184":2,"246":1}}],["条",{"2":{"274":2}}],["条件判断组合",{"2":{"204":1}}],["条件判断跳过",{"0":{"204":1}}],["条件跳过的功能函数",{"2":{"40":1}}],["条件跳过逻辑",{"2":{"13":1}}],["条用例给远程",{"2":{"163":2,"257":2}}],["条用例",{"2":{"163":1,"257":1}}],["条示例用例和一个方法",{"2":{"19":1}}],["初步断言主题失败",{"2":{"176":1}}],["初步适配欧拉系统",{"2":{"17":1}}],["初始化工程中的错误",{"2":{"20":1}}],["初始化工程新增",{"2":{"20":1}}],["初始化应用新增",{"2":{"19":1}}],["做一个简单",{"2":{"263":1}}],["做网络接口",{"2":{"77":1}}],["做",{"2":{"18":1}}],["时会将多个",{"2":{"234":1}}],["时会一并将其安装",{"2":{"234":1}}],["时的深度",{"2":{"230":1}}],["时的日志输出",{"2":{"51":1}}],["时间字符串",{"2":{"227":1,"273":1}}],["时",{"2":{"18":1,"28":1,"31":1,"35":1,"42":1,"235":1,"246":1}}],["以上几个步骤做完",{"2":{"304":1}}],["以上例子为用例执行时",{"2":{"204":1}}],["以实现应用库高效的编写",{"2":{"290":1}}],["以应用为维度划分",{"2":{"281":2}}],["以便进行一些开发调试",{"2":{"238":1}}],["以便后续各组件重命名之后仍能保持接口一致性和兼容性",{"2":{"27":1}}],["以此激活虚拟环境即可",{"2":{"225":1}}],["以此确保在截取的一堆图片中",{"2":{"135":1}}],["以处理人工删除了用例脚本文件",{"2":{"211":1}}],["以",{"2":{"201":1}}],["以绝对优势获胜",{"2":{"186":1}}],["以及分布式执行的一些策略配置项等等",{"2":{"227":1,"273":1}}],["以及汇总的结果",{"2":{"197":1}}],["以及此时图像对比的模板图片",{"2":{"179":1}}],["以及用例自定义的",{"2":{"51":1}}],["以子命令",{"2":{"157":1}}],["以下操作均在",{"2":{"301":1}}],["以下流水线指的是每日构建的流水线",{"2":{"205":1}}],["以下涉及到的参数配置都是在配置文件里面进行配置",{"2":{"196":1}}],["以下为",{"2":{"159":1,"162":1,"256":1}}],["以下我将整个屏幕的截图称为",{"2":{"134":1}}],["以下配置项默认值为系统自带的浏览器的配置",{"2":{"103":1,"230":1}}],["以右键菜单来讲解此方案",{"2":{"126":1}}],["以域管服务端平台创建子管理员为例",{"2":{"74":1}}],["以解决远程开发时无法同步文件的问题",{"2":{"27":1}}],["以确保程序能正常运行",{"2":{"27":1}}],["以适应应用不同的迭代周期",{"2":{"278":1}}],["以适应",{"2":{"18":1}}],["以保持统一的断言语句风格",{"2":{"17":1,"188":1}}],["名称空间下直接导入",{"2":{"155":1}}],["名称",{"2":{"18":1}}],["结构举例",{"2":{"281":1}}],["结果返回接口",{"2":{"287":1}}],["结果展示模块",{"2":{"287":1}}],["结果展示输出等",{"2":{"281":1}}],["结果成功",{"2":{"230":1}}],["结果的文件",{"2":{"176":1}}],["结果",{"2":{"176":3}}],["结果以",{"2":{"14":1}}],["结束日期",{"2":{"230":1}}],["结束",{"2":{"48":1,"176":4}}],["结尾",{"2":{"31":1,"66":1,"76":1,"86":1,"103":1,"112":1,"283":2}}],["结尾的文件",{"2":{"176":1}}],["结尾的",{"2":{"18":1,"192":1,"230":1}}],["增加用例标签",{"2":{"281":1}}],["增加执行过程中立即显示错误的功能",{"2":{"58":1}}],["增加执行前显示执行的python文件数量",{"2":{"35":1}}],["增加函数",{"2":{"54":1}}],["增加开始执行时打印一些执行参数",{"2":{"54":1}}],["增加了用例执行过程中对",{"2":{"58":1}}],["增加了在线文档的显示宽度",{"2":{"35":1}}],["增加了",{"2":{"34":1}}],["增加了识别的总耗时",{"2":{"31":1}}],["增加了留言模块",{"2":{"23":1}}],["增加清理",{"2":{"30":1}}],["增加",{"2":{"18":1,"22":1,"40":1,"58":1}}],["同一个应用的用例分散到不同架构的测试机上执行",{"2":{"286":1}}],["同样匹配小图里面所有的坐标点",{"2":{"137":1}}],["同步pms数据到本地csv文件",{"2":{"212":1,"230":1}}],["同步到",{"2":{"35":1}}],["同步标签到",{"2":{"17":1,"53":1}}],["同时可以标记区域",{"2":{"296":1}}],["同时由于",{"2":{"281":1}}],["同时在用例标签化管理",{"2":{"265":1}}],["同时在流水线上将",{"2":{"205":1}}],["同时新建好工程模板目录和模板文件",{"2":{"249":1}}],["同时完美兼容",{"2":{"241":1}}],["同时也在修复一些用例",{"2":{"205":1}}],["同时标记了skip",{"2":{"205":1}}],["同时我们应该充分考虑后期的可维护性",{"2":{"201":1,"285":1}}],["同时推出了",{"2":{"42":1}}],["同时启用",{"2":{"14":1}}],["同时",{"2":{"14":1,"301":1}}],["方便在用例里面使用",{"2":{"297":1}}],["方便在输入命令的过程中使用补全",{"2":{"159":1}}],["方便使用断言语句",{"2":{"297":1}}],["方便应用库使用",{"2":{"263":1}}],["方便统一拉取代码",{"2":{"58":1}}],["方案设计",{"0":{"279":1,"291":1},"1":{"280":1,"281":1,"292":1,"293":1},"2":{"301":1}}],["方案",{"0":{"261":1},"2":{"118":1}}],["方案大多采用谷歌",{"2":{"118":1}}],["方案使用场景较少",{"2":{"12":1}}],["方法和用例中都会涉及到导入路径的修改",{"2":{"303":1}}],["方法内所要用到不同定位方法的写法修改",{"2":{"302":1}}],["方法的统一出口",{"2":{"293":1}}],["方法的使用说明",{"2":{"186":1}}],["方法调用逻辑得到简化",{"2":{"274":1}}],["方法库",{"2":{"267":1,"281":1}}],["方法库里面",{"2":{"193":1}}],["方法及一些测试资源",{"2":{"265":1}}],["方法可以不用在方法层定义了",{"2":{"218":1}}],["方法只能有一个入参",{"2":{"204":1}}],["方法必须有返回结果并且为布尔值",{"2":{"204":1}}],["方法名必须以",{"2":{"204":1}}],["方法二",{"2":{"196":1}}],["方法一",{"2":{"196":1}}],["方法加入了此功能",{"2":{"183":1}}],["方法明细",{"0":{"145":1,"150":1,"176":1,"184":1}}],["方法编写规范",{"2":{"204":1}}],["方法编写",{"0":{"94":1},"2":{"296":1}}],["方法主文件",{"2":{"75":1}}],["方法主文件里面",{"2":{"65":1,"102":1,"111":1}}],["方法唯一出口类",{"2":{"62":1,"71":1,"72":1,"81":1,"96":1,"97":1,"108":1,"249":1}}],["方法基类",{"2":{"62":1,"65":1,"71":1,"72":1,"75":1,"81":1,"96":1,"97":1,"102":1,"108":1,"249":1,"270":1,"281":1,"293":1,"295":1,"298":1}}],["方法层所有的函数",{"2":{"193":1}}],["方法层",{"2":{"62":1,"71":1,"72":1,"81":1,"96":1,"97":1,"108":1,"249":1}}],["方法将不再维护",{"2":{"50":1}}],["方法",{"2":{"25":1,"143":2,"191":1,"281":1,"293":1}}],["方法没有返回值",{"2":{"17":1}}],["tb",{"2":{"184":1}}],["tbody",{"2":{"103":1}}],["t",{"2":{"155":1,"159":1,"162":2,"163":1,"169":1,"170":1,"209":3,"217":2,"218":2,"219":1,"253":2,"256":1}}],["typing",{"2":{"145":1,"176":1}}],["typewrite",{"2":{"184":1}}],["type=",{"2":{"184":1}}],["typetext",{"2":{"143":1}}],["type",{"2":{"40":1,"75":1,"184":4,"204":3}}],["tpl",{"2":{"138":2}}],["this",{"2":{"155":3,"159":1,"162":1,"253":1,"256":1}}],["than",{"2":{"155":1}}],["theme",{"2":{"176":1,"230":1}}],["the",{"2":{"137":11,"145":1,"155":5,"184":1}}],["threadxmlrpcserver",{"2":{"120":2,"138":2}}],["threadingmixin",{"2":{"120":2,"138":2}}],["tuple",{"2":{"120":1,"144":1,"145":4,"150":21,"176":2,"184":4,"193":1}}],["tag",{"2":{"205":3,"267":1,"281":1,"293":1}}],["tags",{"2":{"159":4,"201":1,"230":5,"253":3,"281":4}}],["task",{"2":{"159":2,"171":1,"196":4,"197":1,"230":1,"253":2}}],["tabs",{"2":{"155":1}}],["table",{"2":{"103":1}}],["take",{"2":{"137":2}}],["target",{"2":{"120":2,"155":1}}],["tripleclick",{"2":{"184":1}}],["triple",{"2":{"184":1}}],["trigger",{"2":{"159":1,"196":3,"230":1,"253":1}}],["trailing",{"2":{"155":2}}],["trace",{"2":{"145":3,"191":2}}],["transfer",{"2":{"17":1,"219":1}}],["tr",{"2":{"103":1}}],["tree",{"2":{"75":3,"142":3,"143":2,"145":5}}],["tree=",{"2":{"75":1}}],["true",{"2":{"75":1,"86":1,"145":1,"176":5,"184":1,"204":6}}],["try",{"2":{"75":1,"134":1,"138":1,"145":5,"150":6,"176":5,"223":1}}],["touch",{"2":{"235":1}}],["tox",{"2":{"155":1}}],["too",{"2":{"145":2}}],["to",{"2":{"94":2,"103":1,"132":1,"145":2,"150":1,"155":1,"184":13,"211":1,"230":1}}],["token=",{"2":{"75":1}}],["token",{"2":{"75":9}}],["tomlignore",{"2":{"155":1}}],["toml",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1,"155":2}}],["top",{"2":{"55":2,"149":3,"150":17,"159":2,"230":2,"253":2}}],["tmpdir",{"2":{"230":2}}],["tmp",{"2":{"54":1,"75":2,"120":1,"230":2}}],["terminal",{"2":{"217":3,"218":2,"219":2}}],["technology",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["templateelementfound",{"2":{"176":4}}],["templateelementnotfound",{"2":{"134":1,"176":6}}],["template",{"2":{"138":4}}],["temporary",{"2":{"54":4,"139":1,"176":2}}],["tesseract",{"2":{"118":1}}],["testddefilemanager",{"2":{"298":1}}],["testfilemanager",{"2":{"297":1}}],["testtask",{"2":{"230":1}}],["testsuite",{"2":{"230":1}}],["testmusic",{"2":{"168":1,"173":2,"223":1,"230":1}}],["testmycase005",{"2":{"112":1}}],["testmycase003",{"2":{"95":1,"218":1}}],["testmycase004",{"2":{"66":1}}],["testmycase",{"2":{"86":1,"103":1,"175":1}}],["testcase",{"2":{"165":1,"230":1}}],["testudcpapi",{"2":{"76":1}}],["test",{"2":{"54":3,"62":2,"66":4,"71":2,"72":2,"76":4,"81":2,"86":4,"93":2,"95":3,"96":2,"97":2,"103":6,"108":2,"112":4,"120":1,"165":5,"166":2,"168":2,"173":7,"175":1,"178":1,"201":2,"218":1,"223":1,"230":5,"249":2,"293":1,"297":1,"298":1}}],["text",{"2":{"75":1,"103":1}}],["teardown",{"2":{"58":1,"76":1}}],["txtapps",{"2":{"173":1}}],["txt",{"2":{"44":1,"54":1,"173":2,"176":4,"230":1,"234":7}}],["tip",{"2":{"281":1,"287":1,"296":1}}],["titlewidget",{"2":{"222":1,"223":1,"296":2,"297":1,"298":3}}],["title",{"2":{"33":1,"54":1,"179":1,"230":1,"293":2,"296":1,"298":2}}],["time",{"2":{"134":1,"135":3,"137":1,"150":1,"176":5,"184":4,"230":2}}],["timeout时间内重试间隔",{"2":{"230":1}}],["timeout=60",{"2":{"184":1}}],["timeout=timeout",{"2":{"176":4}}],["timeout=5",{"2":{"94":1}}],["timeout",{"2":{"33":1,"51":3,"57":2,"159":2,"176":6,"230":4,"253":2}}],["timestr",{"2":{"12":3}}],["返回最新创建的窗口编号",{"2":{"150":1}}],["返回图片路径",{"2":{"139":1}}],["返回图片中识别到的所有字符串",{"2":{"120":1}}],["返回匹配到的多个目标",{"2":{"134":1}}],["返回小图在大图中的坐标",{"2":{"134":1}}],["返回",{"2":{"132":1,"204":2}}],["返回识别到的所有数据",{"2":{"120":1,"176":2}}],["返回识别的原生数据",{"2":{"120":1}}],["返回的",{"2":{"103":1}}],["返回值为",{"2":{"17":1}}],["返回坐标",{"2":{"14":1,"125":1,"134":1}}],["信息文件",{"2":{"159":1,"253":1}}],["信息",{"2":{"17":1,"75":1}}],["信息获取",{"2":{"8":1}}],["浏览器进行测试",{"2":{"17":1,"103":1,"104":1}}],["它被多个地方都使用到了",{"2":{"301":1}}],["它提供接口给自动化测试平台",{"2":{"281":1}}],["它提供了自动化测试所要用的基础功能",{"2":{"265":1}}],["它会根据配置里面的配置项",{"2":{"281":1}}],["它都提供了完善的解决方案",{"2":{"265":1}}],["它不需要",{"2":{"235":1}}],["它保存了远程测试机的信息列表",{"2":{"214":1}}],["它们都有自己存在的问题或者说不适用的场景",{"2":{"181":1}}],["它继承了",{"2":{"175":1}}],["它同样支持本地执行的所有参数",{"2":{"162":1,"256":1}}],["它是一个执行器入口",{"2":{"251":1}}],["它是一个开源的基于深度学习的",{"2":{"118":1}}],["它是全局的入口文件",{"2":{"157":1}}],["它可以方便的用于界面元素的定位和断言",{"2":{"133":1}}],["它基于标准库",{"2":{"77":1}}],["它使用最新的chromium浏览器进行测试",{"2":{"103":1,"230":1}}],["它使用",{"2":{"17":1,"103":1,"104":1}}],["它默认使用系统自带的浏览器进行测试",{"2":{"17":1,"103":1,"230":1}}],["重启步骤最好是一个简单的reboot操作",{"2":{"223":1}}],["重启步骤前面的步骤",{"2":{"223":1}}],["重启之后继续执行",{"2":{"223":1}}],["重启之后虽然重启步骤前面的步骤函数不会执行",{"2":{"223":1}}],["重启之后如何让用例能继续重启前的步骤继续执行",{"2":{"221":1}}],["重启类场景",{"0":{"221":1},"1":{"222":1,"223":1,"224":1,"225":1}}],["重启类场景开启letmego执行方案",{"2":{"159":1,"253":1}}],["重要",{"2":{"204":1}}],["重试间隔时间",{"2":{"176":2}}],["重复去识别",{"2":{"134":1}}],["重跑失败之后才会关闭文件选择框",{"2":{"60":1}}],["重新设计了测试报告主题",{"2":{"51":1}}],["重新构建了文档",{"2":{"23":1}}],["重新整理了章节结构和排版",{"2":{"17":1}}],["重写了",{"2":{"17":1}}],["重点对统计",{"2":{"13":1}}],["添加跳过用例的代码",{"2":{"278":1}}],["添加",{"2":{"16":1,"97":1}}],["目标",{"0":{"263":1,"290":1},"2":{"274":1}}],["目标字符",{"2":{"120":1,"176":2}}],["目录删掉",{"2":{"198":1}}],["目录结构调整",{"2":{"288":1}}],["目录结构",{"0":{"178":1,"267":1,"293":1},"2":{"301":1}}],["目录",{"2":{"42":1,"54":1,"57":1,"176":2,"178":1,"230":1}}],["目录权限",{"2":{"27":1}}],["目录下的",{"2":{"272":1}}],["目录下的文件名称",{"2":{"72":1,"97":1}}],["目录下为自动化测试的底层核心组件",{"2":{"270":1}}],["目录下可以存在任意多个",{"2":{"249":1}}],["目录下所有应用的用例",{"2":{"230":1}}],["目录下所有用例",{"2":{"166":1}}],["目录下会创建一个子项目工程",{"2":{"249":1}}],["目录下会有",{"2":{"197":1,"198":1}}],["目录下会生成一堆文本文件",{"2":{"180":1}}],["目录下保存失败用例的录屏和断言的那个时间点的截屏",{"2":{"194":1}}],["目录下给你生成了",{"2":{"180":1}}],["目录下回收各个测试机执行的测试报告",{"2":{"162":1,"256":1}}],["目录下新建一个",{"2":{"284":1}}],["目录下新建",{"2":{"95":1}}],["目录下进行",{"2":{"57":1}}],["目录下子项目存在",{"2":{"54":1}}],["目录下",{"2":{"16":2,"19":1,"34":1,"42":1,"48":1,"57":1,"65":1,"66":1,"75":1,"76":1,"85":1,"86":1,"103":1,"112":1,"134":2,"157":1,"162":1,"180":1,"201":1,"211":1,"212":2,"237":1,"256":1,"269":1,"300":1}}],["目前需要跳过的用例都需要在对应的用例脚本里面",{"2":{"278":1}}],["目前自动化用例执行时",{"2":{"278":1}}],["目前的策略是全用例覆盖全架构",{"2":{"277":1}}],["目前的方案中",{"2":{"184":1}}],["目前配置了一些通用的命令行执行参数",{"2":{"272":1}}],["目前支持",{"2":{"230":1}}],["目前支持三种参数传入方式",{"2":{"48":1}}],["目前仅对",{"2":{"183":1}}],["目前已经启用了更先进的",{"2":{"16":1}}],["目前我们欢迎以下方面的贡献",{"2":{"0":1}}],["章节",{"2":{"15":1,"300":1}}],["远程多机器分布式异步负载均衡执行",{"0":{"257":1}}],["远程多机器分布式异步执行",{"0":{"256":1}}],["远程测试机",{"2":{"253":1}}],["远程过程调用等方式提供功能",{"2":{"240":1}}],["远程机器执行的用例相同",{"2":{"161":1,"255":1}}],["远程机器的user",{"2":{"48":1,"162":1,"256":1}}],["远程用例驱动执行",{"2":{"156":1}}],["远程交互式控制标识文件",{"2":{"93":1}}],["远程交互式控制可以在用例步骤中实现对远程机器的交互式控制",{"2":{"91":1}}],["远程交互式控制",{"0":{"91":1,"213":1},"1":{"92":1,"93":1,"94":1,"95":1,"214":1,"215":1,"216":1,"217":1,"218":1,"219":1,"220":1},"2":{"243":1}}],["远程交互式控制等等",{"2":{"87":1}}],["远程执行等的功能",{"2":{"251":1}}],["远程执行任何用例集的用例",{"2":{"243":1}}],["远程执行测试机",{"2":{"230":1}}],["远程执行的数据回填需要等所有测试机执行结束之后",{"2":{"197":1}}],["远程执行需要控制多台测试机同时执行用例",{"2":{"197":1}}],["远程执行结束之后",{"2":{"180":1}}],["远程执行同样通过配置文件",{"2":{"162":1,"256":1}}],["远程执行就是用本地作为服务端控制远程机器执行",{"2":{"161":1,"255":1}}],["远程执行",{"0":{"161":1,"255":1},"1":{"162":1,"163":1,"256":1,"257":1},"2":{"180":1}}],["远程执行时回填",{"0":{"197":1}}],["远程执行时",{"2":{"48":1,"50":1}}],["远程执行新增从命令行传入测试机信息",{"2":{"48":1}}],["远程执行自动适用",{"2":{"44":1}}],["远程路径错误的问题",{"2":{"17":1}}],["远程调用的稳定性和兼容性等问题",{"2":{"14":1}}],["远端无法解析默认参数的问题",{"2":{"14":1}}],["f6",{"2":{"301":1}}],["français",{"2":{"230":1}}],["frame",{"2":{"227":1,"265":1,"273":1}}],["fr",{"2":{"230":1}}],["from",{"2":{"60":1,"65":1,"66":3,"75":3,"76":3,"85":4,"86":4,"94":1,"95":2,"103":4,"111":2,"112":3,"120":2,"138":3,"145":16,"150":15,"175":3,"176":22,"182":1,"184":9,"193":2,"204":1,"216":1,"230":1,"270":5,"297":1,"298":2}}],["f8cab367",{"2":{"178":1}}],["f841",{"2":{"155":1}}],["ffb324f3",{"2":{"178":1}}],["ffmpeg",{"2":{"32":2}}],["f541",{"2":{"155":1}}],["f507",{"2":{"155":1}}],["f403",{"2":{"155":1}}],["f401",{"2":{"155":2}}],["flake8",{"2":{"155":1}}],["flag=false",{"2":{"94":1,"150":6,"176":2}}],["float",{"2":{"134":3,"135":3,"138":1,"150":4,"176":13,"184":1}}],["folder",{"2":{"176":12}}],["focus",{"2":{"150":1}}],["font",{"2":{"120":1}}],["formats",{"2":{"159":2,"253":2}}],["format`",{"2":{"155":1}}],["formatting",{"2":{"155":2}}],["format",{"2":{"154":1,"155":2,"230":1}}],["form",{"2":{"142":1}}],["forever",{"2":{"120":1,"138":1}}],["for",{"2":{"75":1,"134":2,"137":2,"145":2,"148":2,"150":11,"155":3,"176":5,"184":7,"204":4,"301":1}}],["finish",{"2":{"159":1,"196":3,"197":1,"230":1,"253":1}}],["findimage",{"2":{"270":2}}],["findall",{"2":{"150":7}}],["findchildren",{"2":{"145":2}}],["find",{"2":{"134":2,"145":8,"176":7,"193":4,"267":1,"270":1,"283":1,"296":1}}],["first=return",{"2":{"120":1,"176":2}}],["first=false",{"2":{"120":2,"176":2}}],["first",{"2":{"120":2,"176":4,"223":1}}],["filter",{"2":{"120":1,"132":2,"176":2}}],["fill",{"2":{"102":1}}],["files",{"2":{"176":5}}],["filesize",{"2":{"111":2,"112":2}}],["file=none",{"2":{"176":2}}],["filectl",{"2":{"176":3}}],["filecopyrighttext",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["filepath",{"2":{"112":3}}],["filename",{"2":{"111":2,"176":16}}],["file",{"2":{"85":2,"86":2,"111":1,"112":2,"120":2,"138":1,"150":1,"159":5,"176":19,"209":1,"230":3,"253":5,"265":1,"267":1,"270":2,"293":1,"295":2,"296":1,"297":9,"298":8,"302":1}}],["fixed",{"2":{"200":2,"205":3,"206":1,"230":1}}],["fixed不生效",{"2":{"159":1,"230":1,"253":1}}],["fix`",{"2":{"155":1}}],["fixable",{"2":{"153":1,"155":1}}],["fixture",{"2":{"17":3,"62":1,"71":1,"81":1,"96":1,"108":1,"249":1,"272":1}}],["fix",{"2":{"5":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":2,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":2,"59":1,"60":1,"153":2,"155":1}}],["future",{"2":{"155":1}}],["func",{"2":{"191":1,"200":2}}],["function",{"2":{"120":2,"138":2,"281":3}}],["funnylog",{"0":{"189":1},"1":{"190":1,"191":1,"192":1,"193":1},"2":{"46":1}}],["full",{"2":{"75":1}}],["fullname=self",{"2":{"76":1}}],["fullname",{"2":{"75":3}}],["feet",{"2":{"65":3}}],["f",{"2":{"46":1,"75":2,"94":1,"111":1,"112":1,"120":4,"138":1,"145":13,"148":2,"150":44,"155":1,"159":1,"173":1,"176":56,"184":25,"193":1,"204":2,"253":1,"297":1}}],["failsafe",{"2":{"184":1}}],["fail",{"2":{"159":2,"230":3,"253":2}}],["failed",{"2":{"42":6,"159":2,"194":5,"230":5,"253":2}}],["false",{"2":{"75":1,"120":4,"134":2,"138":1,"139":1,"145":7,"155":2,"176":13,"184":5,"204":6}}],["favicon",{"2":{"14":1}}],["系统部相关编码规范要求",{"2":{"274":1}}],["系统主题",{"2":{"230":1}}],["系统架构",{"2":{"227":1,"273":1}}],["系统版本不跳过",{"2":{"204":1}}],["系统版本跳过",{"2":{"204":1}}],["系统信息",{"2":{"179":1}}],["系统应用软件包",{"2":{"150":1}}],["系统适配",{"2":{"14":1}}],["系统完成了适配",{"2":{"14":1}}],["确保",{"2":{"243":1}}],["确保了框架的稳定性和可靠性",{"2":{"14":1}}],["确认勾选",{"2":{"301":1}}],["确认修复",{"0":{"205":1},"2":{"58":2,"200":2,"205":6,"206":1}}],["确认",{"2":{"54":2}}],["确定",{"2":{"14":3,"125":5}}],["新建歌单+",{"2":{"149":3}}],["新图片的路径",{"2":{"132":1}}],["新方案不同的项目会动态生成自己的虚拟环境",{"2":{"42":1}}],["新的文档地址",{"2":{"42":1}}],["新的驱动方式",{"2":{"42":1}}],["新的驱动命令",{"2":{"42":1}}],["新的at虚拟化环境部署方案",{"2":{"42":1}}],["新的基础框架代码获取方式及新的初始化工程命令",{"2":{"42":1}}],["新的函数接口ocrx",{"2":{"14":1,"125":1}}],["新增依赖",{"0":{"234":1},"2":{"235":1}}],["新增一列标签名为",{"2":{"205":1}}],["新增pms数据回填功能",{"2":{"58":1}}],["新增收集阶段报错",{"2":{"57":1}}],["新增终端输出显示",{"2":{"57":1}}],["新增终端输出用例执行结束之后所有失败用例的列表",{"2":{"57":1}}],["新增执行进度显示",{"2":{"57":1}}],["新增测试结果表情显示",{"2":{"55":1}}],["新增测试套执行",{"2":{"55":1}}],["新增环境安装",{"2":{"55":1}}],["新增图像断言成功输出匹配度",{"2":{"55":1}}],["新增裁剪依赖的方案",{"2":{"54":1}}],["新增安装子项目",{"2":{"54":1}}],["新增指定用例执行次数",{"2":{"54":1}}],["新增指定用例重复执行次数",{"2":{"54":1}}],["新增气泡类图像识别方案",{"2":{"51":1}}],["新增系统命令",{"2":{"50":1}}],["新增失败录屏从第几次失败开始录制视频的命令行参数",{"2":{"42":1}}],["新增关闭分辨率检测的参数值",{"2":{"42":1}}],["新增自动从",{"2":{"37":1}}],["新增用例脚本",{"2":{"37":1}}],["新增用例驱动方式章节",{"2":{"13":1}}],["新增导入全局配置对象",{"2":{"35":1}}],["新增贡献者名单及贡献规则文档",{"2":{"26":1}}],["新增定制依赖功能支持应用库定义",{"2":{"21":1}}],["新增子命令",{"2":{"19":1}}],["新增命令行入参或配置文件传入远程机器的",{"2":{"17":1}}],["新增远程控制功能",{"2":{"17":1}}],["新增尝鲜版",{"2":{"17":1}}],["新增支持链式调用函数接口",{"2":{"14":1}}],["新增了生成的",{"2":{"14":1}}],["新增的链式调用函数接口使操作更加直观和便捷",{"2":{"14":1}}],["新增",{"2":{"11":1,"13":1,"19":1,"25":1,"51":1,"54":2,"55":1,"57":1,"58":1,"60":1}}],["新增在所有属性中查找同名节点的功能",{"2":{"6":1}}],["进来",{"2":{"270":1}}],["进入项目根目录",{"2":{"248":1}}],["进程期望结果",{"2":{"176":1}}],["进一步优化了",{"2":{"43":1}}],["进一步提高识别稳定性和准确性",{"2":{"14":1}}],["进行目录调整",{"2":{"301":1}}],["进行测试",{"2":{"281":1}}],["进行测试用例范围选择",{"2":{"281":1}}],["进行用例的加载和执行",{"2":{"281":1}}],["进行用例相关配置",{"2":{"162":1,"256":1}}],["进行自动装机",{"2":{"281":1}}],["进行",{"2":{"277":1}}],["进行分割",{"2":{"204":1}}],["进行的",{"2":{"157":1}}],["进行配置",{"2":{"155":1}}],["进行元素定位",{"2":{"141":1}}],["进行了封装",{"2":{"133":1}}],["进行选择菜单选择",{"2":{"128":1}}],["进行识别",{"2":{"120":1}}],["进行日志分段",{"2":{"58":1}}],["进行断言",{"2":{"54":1,"297":1}}],["进行安装",{"2":{"42":2}}],["进行包的发布",{"2":{"42":1}}],["进行开发适配并兼容新老接口",{"2":{"26":1}}],["进行适配",{"2":{"10":1}}],["使用鼠标选中并按住",{"2":{"301":1}}],["使用所有",{"2":{"270":1}}],["使用一段时间后会痛恨",{"2":{"260":1}}],["使用一定的算法即可计算出元素按钮在当前屏幕中的位置",{"2":{"148":1}}],["使用标准库",{"2":{"240":1}}],["使用时需要为每一个用例添加标签装饰器",{"2":{"207":1}}],["使用全局配置里面的常量进行逻辑编写即可",{"2":{"185":1}}],["使用正则获取窗口的位置及大小",{"2":{"148":1}}],["使用的是",{"2":{"143":1}}],["使用的默认密码是",{"2":{"70":1,"80":1,"90":1,"107":1,"116":1,"232":1,"248":1}}],["使用说明",{"0":{"120":1}}],["使用方法二",{"2":{"209":1,"211":1,"212":1}}],["使用方法一",{"2":{"209":1,"211":1,"212":1}}],["使用方法很简单",{"2":{"193":1,"222":1}}],["使用方法和前面一样",{"2":{"163":1,"257":1}}],["使用方法和过去一样",{"2":{"42":1}}],["使用方法",{"0":{"149":1,"193":1,"222":1},"2":{"50":1,"194":1,"196":2,"197":1}}],["使用它可以初始化工程",{"2":{"42":1}}],["使用窗管最新提供的二进制接口",{"2":{"40":1}}],["使用更方便更符合语义",{"2":{"14":1,"125":1}}],["使用",{"0":{"142":1},"2":{"14":1,"31":2,"42":1,"62":1,"71":1,"81":1,"96":1,"108":1,"110":1,"111":1,"112":1,"132":1,"148":1,"161":1,"184":1,"194":1,"204":3,"247":1,"249":1,"253":1,"255":1,"281":2}}],["包括类和方法的命名",{"2":{"302":1}}],["包括实例方法",{"2":{"193":1}}],["包括高分屏",{"2":{"147":1}}],["包括报告生成时的错误处理",{"2":{"14":1}}],["包未指定版本时",{"2":{"46":1}}],["包形式发布的",{"2":{"42":2}}],["包的大小才",{"2":{"42":1}}],["包含以下几个方面",{"2":{"230":1}}],["包含静态方法",{"2":{"191":1}}],["包含一个区域",{"2":{"176":2}}],["包含气泡从出现到消失",{"2":{"135":1}}],["包含",{"2":{"72":1,"97":1}}],["包含了以下配置文件",{"2":{"227":1,"273":1}}],["包含了",{"2":{"54":1}}],["包含等关键字控制需要打印的函数日志",{"2":{"48":1}}],["包含多个用例",{"2":{"32":1}}],["包含每条",{"2":{"12":1}}],["包安装失败后替换源",{"2":{"28":1}}],["包",{"2":{"21":1,"42":2,"234":1,"277":1}}],["社区做好准备",{"2":{"14":1}}],["为什么使用csv格式",{"2":{"281":1}}],["为什么基于",{"0":{"123":1}}],["为解决以上问题",{"2":{"279":1}}],["为将来适配更多的",{"2":{"274":1}}],["为空",{"2":{"230":1}}],["为空表示执行",{"2":{"230":1}}],["为空的问题",{"2":{"33":1}}],["为互斥关系",{"2":{"176":4}}],["为断言主题准确性",{"2":{"176":1}}],["为你想要执行的用例集",{"2":{"163":1,"257":1}}],["为应用左上角相对于屏幕左上角",{"2":{"148":1}}],["为web",{"2":{"103":1,"230":1}}],["为属性名称",{"2":{"85":1}}],["为自动化测试框架的发展和演进贡献力量",{"2":{"61":1}}],["为自动化测试提供了更加丰富和灵活的手段",{"2":{"14":1}}],["为了突显本文的重点",{"2":{"266":1}}],["为了方便查看元素控件对应的位置",{"2":{"142":1}}],["为了方便描述后面经常提到的",{"2":{"157":1}}],["为了方便描述",{"2":{"134":1}}],["为了实现识别图像的目的",{"2":{"137":1}}],["为了能稳定的识别气泡类场景",{"2":{"135":1}}],["为了能简单平滑的迁移到",{"2":{"41":1}}],["为了解决上面",{"2":{"124":1}}],["为了解决以下问题",{"2":{"42":1}}],["为",{"2":{"35":1,"176":1}}],["为一个脚本",{"2":{"16":1}}],["为后续开源到",{"2":{"14":1}}],["为测试数据的分析和解读提供了更多维度",{"2":{"14":1}}],["在修改路径时",{"2":{"303":1}}],["在编辑器里面选中文件",{"2":{"301":1}}],["在编辑模式下",{"2":{"149":1}}],["在系统所有应用中",{"2":{"291":1}}],["在哪台机器上执行",{"2":{"287":1}}],["在每个应用目录下新建",{"2":{"285":1}}],["在每日构建和持续集成流程落地使用",{"2":{"274":1}}],["在类中重写此方法",{"2":{"283":1,"284":1}}],["在跳过用例较多的情况下",{"2":{"278":1}}],["在新需求快速变化的过程中",{"2":{"278":1}}],["在自动化测试项目初期",{"2":{"278":1}}],["在各验收节点进行自动化验收",{"2":{"277":1}}],["在文件中写一个",{"2":{"283":1,"284":1}}],["在文件选择框点击音乐目录",{"2":{"271":1}}],["在文档方便确实没有老牌的",{"2":{"186":1}}],["在你的远程",{"2":{"249":1}}],["在写一些功能时",{"2":{"240":1}}],["在项目根目录下有一个",{"2":{"251":1}}],["在项目根目录下输入",{"2":{"239":1}}],["在项目目录路径下存在文件",{"2":{"204":1}}],["在框架根目录下命令行输入",{"2":{"238":1}}],["在开发过程中有可能需要在终端激活虚拟环境",{"2":{"238":1}}],["在开发过程中",{"2":{"236":1}}],["在开发调试时也会记录执行过程的问题",{"2":{"37":1}}],["在执行",{"2":{"234":1}}],["在pms上查看测试单链接",{"2":{"230":1}}],["在pms上查看用例",{"2":{"230":1}}],["在调用的时候",{"2":{"219":1}}],["在调用时",{"2":{"144":1}}],["在远程测试机上部署一个完整的",{"2":{"213":1}}],["在远程服务器上部署",{"2":{"138":1}}],["在命令行执行",{"2":{"212":1}}],["在命令行这样运行",{"2":{"162":1,"256":1}}],["在report目录下会自动生成",{"2":{"209":1}}],["在日常跳过用例的过程中",{"2":{"205":1}}],["在csv文件中",{"2":{"204":2}}],["在子项目目录下新建",{"2":{"201":1}}],["在子项目根目录下写",{"2":{"54":1}}],["在进行数据回填",{"2":{"197":1}}],["在报告中更能一目了然的看到用例执行步骤",{"2":{"193":1}}],["在屏幕中相似度大于",{"2":{"193":2}}],["在屏幕中区寻找小图",{"2":{"134":1}}],["在应用库根目录下保存一个",{"2":{"234":1}}],["在应用库",{"2":{"193":1}}],["在应用库方法层这样写",{"2":{"149":1}}],["在此基础上",{"2":{"249":1}}],["在此装饰器中我们能动态的捕获所调用函数的功能说明",{"2":{"191":1}}],["在此时间内会不断的进行截图操作",{"2":{"135":1}}],["在菜单中的位置数",{"2":{"184":3}}],["在坐标",{"2":{"184":1}}],["在区域内进行识别",{"2":{"176":2}}],["在data",{"2":{"176":1}}],["在配置文件",{"2":{"160":1,"254":1}}],["在一些",{"2":{"159":1,"253":1}}],["在一段时间内截图多张图片进行识别",{"2":{"135":1,"176":1}}],["在一段时间内",{"2":{"135":1}}],["在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明",{"2":{"157":1}}],["在上面配置文件中",{"2":{"155":1}}],["在根目录下",{"2":{"155":1}}],["在扫描日志最后可以看到一个",{"2":{"153":1}}],["在获取到元素之后",{"2":{"143":1}}],["在工具下方",{"2":{"142":1}}],["在切换图片之后再用这张小图在当前屏幕中进行图像识别",{"2":{"139":1}}],["在切换图片之前截图保存并返回图片的路径",{"2":{"139":1}}],["在测试机上可以通过",{"2":{"138":1}}],["在测试过程中需要获取的坐标是相对于整个屏幕的坐标",{"2":{"134":1}}],["在其他国产",{"2":{"137":1}}],["在某些情况下",{"2":{"235":1}}],["在某些情况下无法生成测试报告的问题",{"2":{"42":1}}],["在某些场景下你可能需要全部获取到所有匹配到的坐标",{"2":{"134":1}}],["在元素识别的过程中",{"2":{"134":1}}],["在游戏等特定领域也有不错的效果",{"2":{"133":1}}],["在点击右键菜单之前截一张图",{"2":{"132":1}}],["在需求迭代的过程中",{"2":{"128":1}}],["在右键菜单呼出来之后",{"2":{"128":1}}],["在浏览器访问百度首页",{"2":{"101":1,"103":1}}],["在用例层修改用例中类的导入路径",{"2":{"284":1}}],["在用例脚本中添加关键字需要人工一条条的改",{"2":{"278":1}}],["在用例执行过程中控制远程机器执行复杂的",{"2":{"213":1}}],["在用例执行的过程中",{"2":{"196":1}}],["在用例收集阶段会以第一个",{"2":{"204":1}}],["在用例里面只需要通过方法层的类对象直接调用即可",{"2":{"182":1}}],["在用例中使用断言",{"2":{"120":1}}],["在用例",{"2":{"95":1}}],["在用例步骤中操作远程机器",{"2":{"17":1}}],["在方法层新建",{"2":{"94":1}}],["在桌面壁纸切换",{"2":{"139":1}}],["在桌面点击右键菜单之后",{"2":{"128":1}}],["在桌面",{"2":{"87":1}}],["在出口类",{"2":{"85":1}}],["在终端输入",{"2":{"65":1,"85":1,"142":1}}],["在这里可以和众多自动化爱好者共同探讨自动化领域的前沿动态和技术难题",{"2":{"61":1}}],["在没有安装",{"2":{"56":1}}],["在传入",{"2":{"54":1}}],["在服务端通过调用",{"2":{"213":1}}],["在服务端",{"2":{"50":1}}],["在不添加环境变量的情况下",{"2":{"42":1}}],["在识别某些文本情况下出现不能识别的问题",{"2":{"34":1}}],["在环境部署阶段进行",{"2":{"34":1}}],["在迭代窗口",{"2":{"31":1}}],["在原始代码中",{"2":{"31":1}}],["在",{"2":{"28":1,"55":1,"124":1,"137":1,"141":1,"142":3,"148":2,"150":1,"180":1,"185":2,"194":1,"196":1,"198":1,"202":1,"204":2,"212":1,"214":1,"244":1,"260":1,"270":2,"281":6,"285":1,"302":1}}],["在线文档地址修改为域名",{"2":{"52":1}}],["在线文档",{"2":{"17":1}}],["在线文档增加团队页",{"2":{"16":1}}],["在问题修复方面",{"2":{"14":1}}],["在功能创新方面",{"2":{"14":1}}],["在wayland输入中文末尾多出空格的问题",{"2":{"5":1}}],["服务打开",{"2":{"180":1}}],["服务的方式提供出来",{"2":{"213":1}}],["服务的方式进行图像识别",{"2":{"138":1}}],["服务的方式使用它",{"2":{"119":1}}],["服务实现图像识别",{"0":{"138":1}}],["服务集群进行负载均衡",{"2":{"124":1}}],["服务集群化部署",{"2":{"14":1}}],["服务集群化部署和模型",{"2":{"14":1}}],["服务器对测试机进行装机",{"2":{"281":1}}],["服务器",{"2":{"123":1,"138":1}}],["服务器上",{"2":{"122":1}}],["服务器链接重试",{"2":{"51":1}}],["服务做分布式集群化部署",{"2":{"122":1}}],["服务端收集到测试结果",{"2":{"197":1}}],["服务端想要执行",{"2":{"163":1,"257":1}}],["服务端会根据收集到的测试用例自动分配给各个测试机执行",{"2":{"230":1}}],["服务端会根据收集到的测试用例自",{"2":{"162":1,"256":1}}],["服务端拿到两张图片进行图像识别",{"2":{"138":1}}],["服务端",{"2":{"138":1,"260":1,"261":2}}],["服务端参考插件",{"2":{"121":1}}],["服务端代码示意",{"2":{"120":1,"138":1}}],["服务将功能提供出来",{"2":{"119":1}}],["服务在自动化测试子项目中被广泛使用",{"2":{"122":1}}],["服务在其他机器上部署",{"2":{"119":1}}],["服务在并发时可能出现无法返回结果的问题",{"2":{"53":1}}],["服务高并发稳定性",{"2":{"53":1}}],["服务",{"2":{"52":1,"138":1,"162":1,"256":1}}],["服务性能优化",{"2":{"14":1}}],["服务不响应的问题",{"2":{"11":1}}],["这部分工作主要解决你之前几个步骤遗漏的问题",{"2":{"304":1}}],["这部分基本可以复制文管的代码",{"2":{"302":1}}],["这时候你可能你的代码中可能会有一些报错",{"2":{"302":1}}],["这不废话吗",{"2":{"301":1}}],["这两个选项",{"2":{"301":1}}],["这两个参数也可以同时使用",{"2":{"230":1}}],["这条用例会被停止",{"2":{"230":1}}],["这点如果了解方案实现原理很容易理解",{"2":{"223":1}}],["这一列标签删掉不就好了",{"2":{"205":1}}],["这一系列的更新标志着",{"2":{"14":1}}],["这是最重要的一个部分",{"2":{"265":1}}],["这是因为不加",{"2":{"246":1}}],["这是因为为了应对前面提到的多种数据回填的方式",{"2":{"198":1}}],["这是一个全局统一配置",{"2":{"230":1}}],["这是一个预设值",{"2":{"135":1}}],["这是一种不推荐但能用的方法",{"2":{"149":1}}],["这就是",{"2":{"205":1}}],["这就是我们参考django",{"2":{"193":1}}],["这就是负载均衡执行",{"2":{"163":1,"257":1}}],["这就要说到本章的主题",{"2":{"132":1}}],["这也不是个问题",{"2":{"155":1}}],["这四个数据可以通过",{"2":{"149":1}}],["这么问的话",{"2":{"137":1}}],["这类用例相对特殊",{"2":{"223":1}}],["这类场景在用例执行过程中进行图像识别时就可能存在不稳定性",{"2":{"135":1}}],["这类自动化测试也比较简单",{"2":{"113":1}}],["这明显是错误的",{"2":{"123":1}}],["这会让整个自动化环境变得非常臃肿",{"2":{"119":1}}],["这并不符合我们对框架依赖治理的理解",{"2":{"119":1}}],["这样从最初的设计来讲确实能够减少重复代码的编写",{"2":{"278":1}}],["这样使得从公司的角度去看所有应用的自动化测试项目都是统一的",{"2":{"271":1}}],["这样即使是各个应用库都独立维护",{"2":{"271":1}}],["这样做可以减少整体代码量",{"2":{"271":1}}],["这样执行",{"2":{"235":1}}],["这样可以获取到",{"2":{"228":1}}],["这样可以查看到子命令支持的各项参数及参数使用说明",{"2":{"157":1}}],["这样可以查看它支持的子命令",{"2":{"157":1}}],["这样的写法就和本地方法的调用写法是一样的",{"2":{"218":1}}],["这样才能将pms与本地csv文件建立联系",{"2":{"212":1,"230":1}}],["这样你本地调试用例的时候这条已修复的用例是会执行的",{"2":{"205":1}}],["这样这条用例即使同时标记了",{"2":{"205":1}}],["这样这条用例脚本在",{"2":{"185":1}}],["这样运行是从配置文件去读取相关配置",{"2":{"162":1,"256":1}}],["这样在子项目就可以使用到所有的全局配置",{"2":{"229":1}}],["这样在日志输出的时候就能把调用函数时参数的值输出出来",{"2":{"193":1}}],["这样在",{"2":{"142":1,"249":1}}],["这样在当前图片中",{"2":{"139":1}}],["这样是为了方便管理和维护",{"2":{"134":1}}],["这样维护起来可以说非常复杂",{"2":{"130":1}}],["这样我们只需要在服务端部署好",{"2":{"119":1}}],["这样我们就完成了一条简单的",{"2":{"103":1}}],["这样",{"2":{"98":1,"129":1,"138":1,"139":1}}],["这样所有的断言语句都是通过",{"2":{"86":1}}],["这样就可以重新做数据回填了",{"2":{"198":1}}],["这样就能获取到此元素的中心坐标",{"2":{"144":1}}],["这样就不会有干扰了",{"2":{"132":1}}],["这样就完成了一个简单的命令行自动化用例编写",{"2":{"112":1}}],["这样就完成了一个简单的用例编写",{"2":{"86":1}}],["这样就完成了一个简单的",{"2":{"66":1,"76":1}}],["这样就会在当前目录下生成一个",{"2":{"42":1}}],["这个方法存在被外部应用调用的情况",{"2":{"283":1}}],["这个方法适用于有些标签没有添加",{"2":{"143":1}}],["这个命令",{"2":{"236":1}}],["这个标签的背景",{"2":{"205":1}}],["这个参数可填可不填",{"2":{"196":1,"212":1}}],["这个参数一直都有的",{"2":{"42":1}}],["这个就是标签名称",{"2":{"142":1}}],["这个函数",{"2":{"137":1}}],["这个函数提供了隐式等待的功能",{"2":{"134":1}}],["这个版本中",{"2":{"13":1}}],["这里介绍以前的at框架情况以及存在的一些问题",{"2":{"275":1}}],["这里贴一下整体的架构图",{"2":{"266":1}}],["这里主要介绍写用例的时候注意事项",{"2":{"223":1}}],["这里就矛盾了",{"2":{"205":1}}],["这里就不多介绍",{"2":{"42":1}}],["这里给各位看官稍微解释一下",{"2":{"205":1}}],["这里都包含了",{"2":{"182":1}}],["这里以音乐举例",{"2":{"42":1}}],["这里有",{"2":{"42":1}}],["这里特别感谢",{"2":{"26":1}}],["这种方案的时间效率最高的",{"2":{"196":1}}],["这种方式安装的环境不会有",{"2":{"236":1}}],["这种方式需要修改用例代码",{"2":{"202":1,"285":1}}],["这种方式不用担心菜单选项的顺序或位置",{"2":{"129":1}}],["这种方式有个很烦人的问题",{"2":{"128":1}}],["这种全新的元素定位方案有它的适用条件",{"2":{"147":1}}],["这种在实际业务中是不影响的",{"2":{"142":1}}],["这种写法和之前的写法效果是一样的",{"2":{"35":1}}],["这种情况会导致错误",{"2":{"31":1}}],["这些是",{"2":{"180":1}}],["这些问题值得思考",{"2":{"137":1}}],["这些工具实际上也是用的",{"2":{"133":1}}],["这些修复进一步提升了用户体验",{"2":{"14":1}}],["这些更新不仅提升了框架的性能和稳定性",{"2":{"14":1}}],["近期任务计划",{"2":{"288":1}}],["近期",{"2":{"14":1}}],["报错重复注册的问题",{"2":{"52":1}}],["报错",{"2":{"28":1}}],["报错超过",{"2":{"27":1}}],["报错的问题",{"2":{"13":1,"16":1,"33":1,"56":1}}],["报告",{"2":{"179":1}}],["报告默认语言为中文",{"2":{"179":1}}],["报告进行了一系列的定制",{"2":{"179":1}}],["报告生成路径异常的问题",{"2":{"57":1}}],["报告备份功能",{"2":{"57":1}}],["报告中",{"2":{"193":1}}],["报告中直接看录制的视频",{"2":{"179":1}}],["报告中定位问题除了日志",{"2":{"54":1}}],["报告中用例总数为包含跳过用例数量",{"2":{"15":1}}],["报告新增显示当前目录",{"2":{"21":1}}],["报告增加",{"2":{"16":1}}],["报告失败数量没有剔除跳过数量的问题",{"2":{"14":1}}],["报告计算逻辑",{"2":{"13":1}}],["报告内容进行了重新规划",{"2":{"13":1}}],["报告的路径",{"2":{"13":1}}],["报告功能优化",{"2":{"12":1}}],["跳过的原因统一标记为",{"2":{"285":1}}],["跳过的原因统一标签开头为",{"2":{"203":1}}],["跳过的原因标签为",{"2":{"204":1}}],["跳过用例标签化",{"2":{"285":1}}],["跳过用例的标签",{"2":{"205":1}}],["跳过用例",{"0":{"202":1},"1":{"203":1,"204":1}}],["跳过用例数",{"2":{"13":1}}],["跳过原因",{"2":{"200":2,"202":1,"203":1,"204":3,"205":3,"206":1,"285":3}}],["跳过数",{"2":{"13":1}}],["+|",{"2":{"155":1}}],["+=",{"2":{"145":1}}],["+",{"2":{"13":1,"50":1,"75":4,"120":1,"134":1,"144":2,"145":4,"148":6,"150":40,"155":2,"176":12,"261":1,"287":1,"301":1,"303":2}}],["=========",{"2":{"223":1}}],["==========",{"2":{"223":3}}],["================",{"2":{"192":1,"230":1}}],["==============================================",{"2":{"192":1,"230":1}}],["===================================",{"2":{"103":1,"214":1,"230":9}}],["===============================",{"2":{"103":1,"214":1,"230":9}}],["=============",{"2":{"192":1,"230":1}}],["==",{"2":{"120":1,"138":1,"145":7,"150":2,"176":9,"184":1,"204":5,"216":1,"217":1,"219":1}}],["=",{"2":{"13":2,"42":4,"54":2,"65":4,"66":2,"75":29,"76":4,"85":2,"86":1,"94":1,"95":2,"103":3,"111":2,"112":3,"120":9,"132":1,"134":13,"135":4,"137":2,"138":11,"143":3,"144":6,"145":41,"148":5,"149":3,"150":140,"155":17,"176":85,"184":23,"192":4,"193":1,"194":5,"196":18,"204":5,"209":1,"211":1,"212":6,"214":1,"216":1,"217":1,"218":2,"219":1,"223":2,"229":1,"230":87,"270":8,"271":2,"295":2,"298":3}}],["用这个功能就是想把关联到的都修改",{"2":{"301":1}}],["用下划线连接是",{"2":{"281":1}}],["用户",{"2":{"287":1}}],["用户执行命令",{"2":{"247":1}}],["用户名",{"2":{"159":1,"253":1}}],["用两对大括号把函数的参数括起来",{"2":{"193":1}}],["用中括号括起来就行",{"2":{"149":1}}],["用于管理模块内的用例标签",{"2":{"285":1}}],["用于给每条用例打标签",{"2":{"281":1}}],["用于图像识别坐标",{"2":{"230":1}}],["用于其他操作",{"2":{"217":1}}],["用于自动同步",{"2":{"212":1}}],["用于自动输出方法的日志",{"2":{"85":1}}],["用于保存用例标签",{"2":{"201":1,"285":1}}],["用于标记已经废弃的用例",{"2":{"200":1}}],["用于标记用例的修复状态",{"2":{"200":1}}],["用于标记所有子项目",{"2":{"58":1}}],["用于控制用例是否执行",{"2":{"200":1}}],["用于控制重复识别的次数",{"2":{"134":1}}],["用于干扰较大时提升ocr识别精准度",{"2":{"176":2}}],["用于用例断言的图片资源放到",{"2":{"134":1}}],["用于放置app工程",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["用于记录了用例的执行结果和回填情况",{"2":{"198":1}}],["用于记录历史发布版本的更新内容",{"2":{"60":1}}],["用于记录系统资源占用情况",{"2":{"55":1}}],["用于只跑上次失败用例的功能",{"2":{"57":1}}],["用于动态的截取元素的图片",{"2":{"54":1}}],["用于静态代码扫描",{"2":{"50":1}}],["用于获取桌面所有窗口的信息",{"2":{"26":1}}],["用起来很稳定",{"2":{"41":1}}],["用",{"2":{"28":1}}],["用例代码调用逻辑举例",{"2":{"298":1}}],["用例逻辑上更清楚",{"2":{"297":1}}],["用例里面本来也应该被关联修改",{"2":{"302":1}}],["用例里面直接继承",{"2":{"297":1}}],["用例里面来判断用哪个",{"2":{"132":1}}],["用例也不会被执行",{"2":{"285":1}}],["用例来源",{"2":{"285":3}}],["用例来源等等",{"2":{"278":1}}],["用例可以添加对应的标签",{"2":{"285":1}}],["用例解耦",{"0":{"283":1}}],["用例触发执行控制",{"2":{"281":1}}],["用例层",{"2":{"276":2}}],["用例层可能需要对这部分用例做逻辑判断",{"2":{"185":1}}],["用例实现标签化管理",{"2":{"274":1}}],["用例超时控制",{"2":{"243":1}}],["用例超时时间",{"2":{"54":1}}],["用例名称默认存在第一列",{"2":{"230":1}}],["用例注意事项",{"0":{"223":1}}],["用例模块的对应关系",{"2":{"212":1}}],["用例需要用到的资源",{"2":{"267":1,"293":1}}],["用例需要废弃",{"2":{"206":1}}],["用例需要添加的标签有",{"2":{"200":1}}],["用例id",{"2":{"205":1,"206":1,"285":2}}],["用例id兼容用例库id和产品库id",{"2":{"55":1}}],["用例标签文件",{"2":{"293":1}}],["用例标签目录",{"2":{"293":1}}],["用例标签分类评估",{"2":{"288":1}}],["用例标签的驱动方式必须能支持标签的扩展",{"2":{"286":1}}],["用例标签",{"2":{"281":1}}],["用例标签化管理",{"0":{"285":1},"2":{"243":1}}],["用例标签化管理和执行",{"2":{"241":1}}],["用例标签数据至本地",{"2":{"212":1}}],["用例标签可以无序",{"2":{"201":1}}],["用例标签管理文件",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["用例脚本的",{"2":{"201":1}}],["用例类型和用例来源",{"2":{"285":1}}],["用例类型",{"2":{"200":2,"230":1,"285":2}}],["用例级别",{"2":{"200":2,"230":1,"285":2}}],["用例库",{"2":{"200":1,"230":1}}],["用例失败重跑的次数不能小于失败录屏次数",{"2":{"194":1}}],["用例失败录屏",{"2":{"87":1}}],["用例兼容",{"2":{"185":1}}],["用例驱动方式",{"0":{"164":1},"1":{"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1}}],["用例的类型",{"2":{"278":1}}],["用例的前置和后置要写在同一个用例文件里面",{"2":{"223":1}}],["用例的标签",{"2":{"159":1,"253":1}}],["用例的关键词",{"2":{"159":1,"253":1}}],["用例操作动态的",{"2":{"139":1}}],["用例继承了用例基类",{"2":{"103":1}}],["用例步骤过程中控制远程机器",{"2":{"243":1}}],["用例步骤中与其他机器进行交互",{"2":{"214":1,"230":1}}],["用例步骤",{"0":{"84":1,"101":1}}],["用例编写",{"0":{"95":1},"2":{"66":1,"76":1}}],["用例",{"2":{"66":1,"76":1,"86":1,"103":1,"112":1,"211":1,"267":1,"274":1,"281":1,"293":1}}],["用例文件以",{"2":{"66":1,"76":1,"86":1,"103":1,"112":1}}],["用例执行接口",{"2":{"287":1}}],["用例执行控制模块",{"2":{"287":1}}],["用例执行",{"0":{"286":1}}],["用例执行模块",{"2":{"281":1}}],["用例执行的范围不够精准",{"2":{"278":1}}],["用例执行都使用",{"2":{"236":1}}],["用例执行完后生成的测试报告格式",{"2":{"230":1}}],["用例执行完之后回填",{"2":{"196":1}}],["用例执行时判断",{"2":{"203":1,"285":1}}],["用例执行时配置",{"2":{"196":1}}],["用例执行过程中进行图像识别时",{"2":{"134":1}}],["用例执行过程中输出执行进度百分比",{"2":{"30":1}}],["用例执行所需要的资源",{"2":{"62":1,"71":1,"72":1,"81":1,"96":1,"97":1,"108":1,"249":1}}],["用例示例",{"2":{"62":2,"71":2,"81":2,"96":2,"108":2,"249":2}}],["用例基类用于继承断言模块",{"2":{"86":1}}],["用例基类",{"2":{"62":1,"66":2,"71":1,"76":2,"81":1,"86":1,"96":1,"103":1,"108":1,"112":2,"175":2,"249":1}}],["用例断言所需要的资源",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["用例目录",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["用例收集时仅在",{"2":{"57":1}}],["用例顺序被调整的问题",{"2":{"54":1}}],["用例中通过",{"2":{"175":1}}],["用例中通过框架提供的",{"2":{"17":1}}],["用例中使用方法",{"0":{"175":1}}],["用例中的图像识别会通过远程服务接口进行图像识别和结果获取",{"2":{"41":1}}],["用例管理系统存在缺陷",{"2":{"32":1}}],["用例在收集阶段报错",{"2":{"20":1}}],["用例结果以",{"2":{"16":1}}],["用例维度统计数据",{"2":{"16":1}}],["用例总数",{"2":{"13":2,"57":1}}],["用以集中说明",{"2":{"13":1}}],["用以控制拉取",{"2":{"12":1}}],["和前面配置项client",{"2":{"230":1}}],["和前面配置项password一样",{"2":{"214":1,"230":1}}],["和端口进行",{"2":{"138":1}}],["和当前版本",{"2":{"54":1}}],["和命令行参数",{"2":{"35":1}}],["和",{"2":{"13":1,"16":1,"21":1,"48":1,"54":1,"57":1,"138":1,"148":1,"182":1,"185":1,"193":1,"205":3,"230":2,"235":1,"243":1,"260":1,"301":1}}],["将你之前写的每个方案进行对应的修改",{"2":{"302":1}}],["将应用库代码拉到基础框架下",{"2":{"300":1}}],["将自动化基础框架的功能拉到本地",{"2":{"300":1}}],["将文管业务层进行",{"2":{"292":1}}],["将所有的功能模块都进入到",{"2":{"270":1}}],["将功能进行服务化封装部署",{"2":{"240":1}}],["将测试结果数据回填到pms",{"2":{"230":1}}],["将要执行的用例写入指定的",{"2":{"230":1}}],["将以上信息配置好之后",{"2":{"212":1}}],["将py文件的case",{"2":{"211":1,"230":1}}],["将跳过用例操作也整合进入用例标签",{"2":{"202":1,"285":1}}],["将小图与大图的rgb值进行匹配",{"2":{"137":1}}],["将截图的小图",{"2":{"134":1}}],["将相同的部分给消除掉",{"2":{"132":1}}],["将两种图做前后对比提取可以得到这样的图",{"2":{"132":1}}],["将其他相同的地方都屏蔽掉",{"2":{"132":1}}],["将方法层大目录",{"2":{"72":1,"97":1}}],["将不在使用",{"2":{"52":1}}],["将上述路径添加到环境变量之后也是可以用的",{"2":{"42":1}}],["将有趣的文档系统迁移到",{"2":{"39":1}}],["将",{"2":{"24":1,"27":1,"35":1,"48":1,"53":1}}],["将生成的",{"2":{"16":1}}],["将项目根目录下",{"2":{"16":2}}],["将删除虚拟环境的命令修改为",{"2":{"13":1}}],["将在下一个版本开发并发布",{"2":{"13":1}}],["将run",{"2":{"5":1}}],["文管界面分为四个区域",{"2":{"296":1}}],["文管代码解耦",{"2":{"288":1}}],["文管方法库出口",{"2":{"193":2}}],["文本输入",{"2":{"143":1}}],["文件右键菜单",{"2":{"301":1}}],["文件或目录",{"2":{"301":1}}],["文件脚本",{"2":{"288":1}}],["文件实际是以都好分隔的文本文件",{"2":{"281":1}}],["文件维护用例与标签的对应关系",{"2":{"281":1}}],["文件操作模块",{"2":{"281":1}}],["文件只会用来写",{"2":{"272":2}}],["文件命名规范",{"2":{"249":1}}],["文件原来能干这么多事情",{"2":{"243":1}}],["文件可能存在相同的依赖被指定安装不同版本等等兼容性问题",{"2":{"234":1}}],["文件一并加载",{"2":{"234":1}}],["文件是不需要人工去修改的",{"2":{"227":1}}],["文件会自动备份在",{"2":{"212":1}}],["文件会直接创建一个并写入用例脚本的",{"2":{"211":1}}],["文件先备份到",{"2":{"211":1,"212":1}}],["文件几乎是唯一能满足所有的要求的文件格式",{"2":{"208":1}}],["文件进行集中管理",{"2":{"207":1}}],["文件覆盖历史",{"2":{"205":1}}],["文件跳过原因一栏中填写为",{"2":{"204":1}}],["文件来管理跳过用例则会方便很多",{"2":{"202":1,"285":1}}],["文件里面跳过原因列是否存在跳过标记",{"2":{"285":1}}],["文件里面跳过原因列是否存在跳过标签",{"2":{"203":1}}],["文件里面标记此条用例的标签",{"2":{"285":1}}],["文件里面分不同的",{"2":{"281":1}}],["文件里面分不同的类",{"2":{"281":1}}],["文件里面是该应用的方法类",{"2":{"271":1}}],["文件里面对应的",{"2":{"211":1}}],["文件里面添加对应的列即可",{"2":{"201":1,"285":1}}],["文件里面写了一个导入",{"2":{"155":1}}],["文件太多了也是一个很糟糕的事情",{"2":{"201":1,"285":1}}],["文件建议放在一个",{"2":{"201":1}}],["文件去掉首字符串",{"2":{"201":1}}],["文件后缀",{"2":{"176":1}}],["文件夹",{"2":{"176":4}}],["文件存在",{"2":{"176":2}}],["文件全路径",{"2":{"176":1}}],["文件全路径或目录",{"2":{"176":1}}],["文件名与",{"2":{"212":1}}],["文件名就应为",{"2":{"201":1}}],["文件名",{"2":{"176":2,"283":1}}],["文件名称可以自定义",{"2":{"209":1}}],["文件名称",{"2":{"13":1,"168":1}}],["文件标签关联管理",{"2":{"156":1}}],["文件管理的标签",{"2":{"169":1}}],["文件管理",{"2":{"156":1}}],["文件管理器从业务复杂度和用例量来讲",{"2":{"291":1}}],["文件管理器",{"2":{"85":3,"292":1}}],["文件管理器已经启动",{"2":{"84":1,"86":1}}],["文件中多余的",{"2":{"211":1}}],["文件中查找是否有同名函数",{"2":{"204":1}}],["文件中新增一列为",{"2":{"202":1,"285":1}}],["文件中所有的用例",{"2":{"165":1}}],["文件中没有配置",{"2":{"150":1}}],["文件中",{"2":{"58":1,"157":1}}],["文件中可以使用此方法进行条件跳过",{"2":{"28":1}}],["文件时配置的字段名",{"2":{"230":1}}],["文件时",{"2":{"54":1}}],["文件不支持用例库的问题",{"2":{"53":1}}],["文件不存在",{"2":{"26":1,"176":2}}],["文件功能",{"2":{"37":1}}],["文件的增删改查操作模块等",{"2":{"276":1}}],["文件的",{"2":{"211":1}}],["文件的字段格式已经适配了",{"2":{"209":1}}],["文件的设计来实现了对历史",{"2":{"205":1}}],["文件的文件名",{"2":{"201":1}}],["文件的问题",{"2":{"35":1,"43":1}}],["文件的名称一样",{"2":{"34":1}}],["文件写入为",{"2":{"35":1}}],["文件找不到",{"2":{"28":1}}],["文件",{"0":{"211":1},"2":{"20":1,"27":1,"37":1,"49":1,"54":1,"58":1,"60":1,"176":2,"180":3,"201":2,"207":1,"211":1,"212":1,"230":1,"234":3,"271":1,"281":1,"283":1,"284":1,"285":2}}],["文件对比时",{"2":{"18":1}}],["文件用例列表不完整的问题",{"2":{"17":1}}],["文档目录",{"2":{"267":1}}],["文档里面已经有详细描述了",{"2":{"266":1}}],["文档工程迁移到单独的仓库",{"2":{"53":1}}],["文档内容一样",{"2":{"42":1}}],["文档内容及排版",{"2":{"36":1}}],["文档界面ui调整",{"2":{"15":1}}],["文档新增",{"2":{"15":1}}],["文档更新",{"2":{"12":1,"13":1}}],["文档",{"0":{"1":1},"2":{"121":1,"186":1,"269":1}}],["对照",{"2":{"285":1}}],["对用例实现标签化管理",{"2":{"281":1}}],["对断言进行了二次封装",{"2":{"243":1}}],["对比指标",{"2":{"186":1}}],["对比下文件前后",{"2":{"153":1}}],["对比动作前后两张图片",{"2":{"132":1}}],["对元素的操作",{"2":{"143":1}}],["对应",{"2":{"200":1,"285":3}}],["对应应用里面的父窗口和子窗口",{"2":{"142":1}}],["对应的所有小图的rgb值不相等",{"2":{"137":1}}],["对于我们需求理解",{"2":{"271":1}}],["对于重启类场景的用例需要解决的核心问题是",{"2":{"221":1}}],["对于用例规模比较大的应用",{"2":{"201":1,"285":1}}],["对于一些文案的场景非常适用",{"2":{"120":1}}],["对于任何形式的贡献我们都欢迎",{"2":{"0":1}}],["对操作系统的接口测试通常指的是对",{"2":{"67":1}}],["对",{"2":{"38":2,"186":1}}],["对多个文档模块及文档内容进行了修改",{"2":{"23":1}}],["对象组合",{"2":{"270":1}}],["对象能获取到所有可获取的配置项的值",{"2":{"228":1}}],["对象包含了",{"2":{"216":1}}],["对象",{"2":{"17":3,"103":1}}],["对生成的",{"2":{"13":1}}],["drf",{"2":{"287":1}}],["draw",{"2":{"184":1}}],["dragrel",{"2":{"184":1}}],["dragto",{"2":{"184":1}}],["drag",{"2":{"184":7}}],["dmidecode",{"2":{"204":4}}],["dfmassert",{"2":{"297":4}}],["dfmwidget",{"2":{"193":2,"297":3,"298":3}}],["dfm",{"2":{"193":7,"267":1,"293":2,"297":2,"298":5}}],["dynamic",{"2":{"155":1}}],["duration=1",{"2":{"184":1}}],["duration=duration",{"2":{"184":3}}],["duration=0",{"2":{"184":4}}],["duration",{"2":{"184":7}}],["duringfail",{"2":{"159":1,"253":1}}],["during",{"2":{"51":1,"135":1,"176":2,"230":1}}],["dummy",{"2":{"155":1}}],["d+",{"2":{"150":6}}],["dd",{"2":{"110":1,"111":3,"112":2}}],["ddedesktoppublicwidget",{"2":{"271":1,"284":1}}],["ddedesktoppublicbasewidget",{"2":{"271":2}}],["ddedockpublicwidget",{"2":{"223":1}}],["dde",{"2":{"47":1,"85":8,"86":3,"94":3,"150":2,"176":1,"265":1,"267":7,"270":2,"271":3,"284":2,"293":1,"295":2,"296":1,"297":3,"298":8,"302":1}}],["dict",{"2":{"120":2,"145":1,"150":4,"176":6}}],["direnv",{"2":{"155":1}}],["direct",{"2":{"184":3}}],["directories",{"2":{"155":1}}],["direction",{"2":{"148":2,"149":2,"150":19}}],["dirname",{"2":{"120":1,"138":1}}],["dir",{"2":{"103":1,"120":1,"138":1,"227":1,"230":3,"271":1,"273":1}}],["display",{"2":{"184":1,"204":1}}],["displayconnectionerror",{"2":{"22":1}}],["dist",{"2":{"155":1}}],["disabled",{"2":{"155":1}}],["disable=ungrouped",{"2":{"184":1}}],["disable=eval",{"2":{"150":2}}],["disable=too",{"2":{"145":1}}],["disable=c0114",{"2":{"145":1}}],["disable",{"2":{"75":1}}],["d",{"2":{"65":3,"155":1,"236":1,"248":1}}],["dbuswidget",{"2":{"65":1,"66":2}}],["dbusutils",{"2":{"65":3,"67":1}}],["dbus",{"0":{"67":1},"1":{"68":1,"69":1,"70":1},"2":{"50":2,"65":5,"66":2,"67":3,"94":1,"150":3,"242":1,"276":1,"281":1}}],["doesn",{"2":{"155":1}}],["dom",{"2":{"131":1,"141":2}}],["domain",{"2":{"75":4}}],["downloads",{"2":{"230":1}}],["down",{"2":{"128":3,"184":6}}],["doubleclick",{"2":{"143":1,"184":1}}],["double",{"2":{"125":1,"132":1,"145":2,"155":2,"184":3,"296":1}}],["dogutils",{"2":{"216":1}}],["dog",{"2":{"85":2,"144":1,"270":1,"296":2,"298":3}}],["dogtails",{"2":{"267":1,"270":1}}],["dogtailutils",{"2":{"144":1,"145":1,"176":4}}],["dogtail",{"2":{"21":1,"56":1,"60":5,"141":2,"143":2,"144":1,"145":9,"176":1,"270":3}}],["doctests",{"2":{"155":1}}],["doc",{"2":{"111":1,"112":1,"191":1}}],["docker",{"2":{"260":2}}],["dock的信息",{"2":{"85":1}}],["dock",{"2":{"85":5,"86":1,"94":6,"95":1,"223":1,"267":3}}],["docstring",{"2":{"155":2}}],["docstrings",{"2":{"155":2}}],["docs",{"2":{"36":1,"38":2,"267":1}}],["date",{"2":{"103":1,"230":3}}],["data",{"2":{"75":2,"120":1,"137":3,"138":1}}],["daemon",{"2":{"94":3,"176":1}}],["dagtail",{"2":{"25":1}}],["darklii",{"2":{"13":1,"17":1,"19":2}}],["deutsch",{"2":{"230":1}}],["de",{"2":{"230":1}}],["demo可以看",{"2":{"221":1}}],["delay",{"2":{"184":6}}],["delay=1",{"2":{"184":1}}],["delete",{"2":{"76":1}}],["detect",{"2":{"155":1}}],["detail",{"2":{"12":3}}],["degree",{"2":{"137":2}}],["dest=com",{"2":{"94":1}}],["desc=self",{"2":{"270":1,"271":1,"295":1,"298":1}}],["description",{"2":{"144":3,"145":3}}],["description=none",{"2":{"144":1,"145":1}}],["desc",{"2":{"85":1,"270":7,"271":2,"295":2,"298":3}}],["desktop",{"2":{"47":1,"94":1,"111":1,"112":1,"134":1,"176":2,"267":3,"271":3,"284":2,"297":4}}],["department",{"2":{"75":4}}],["depends",{"2":{"60":2,"145":5,"184":3}}],["depth",{"2":{"12":1,"230":2}}],["default",{"2":{"120":1,"150":12,"155":3}}],["default=false",{"2":{"120":1}}],["deflate",{"2":{"75":1}}],["def",{"2":{"54":1,"65":2,"66":1,"75":5,"76":2,"85":2,"86":1,"94":2,"95":1,"102":4,"103":3,"111":1,"112":1,"120":4,"137":4,"138":2,"144":3,"145":17,"150":28,"165":2,"175":1,"176":23,"184":36,"188":1,"190":1,"193":2,"204":7,"216":2,"217":2,"218":2,"219":1,"223":2,"230":3,"270":2,"271":3,"283":2,"284":2,"295":1,"296":1,"297":2,"298":5}}],["deepinmusicwidget",{"2":{"54":4,"182":3,"222":1,"223":4}}],["deepin",{"2":{"35":2,"42":2,"48":3,"50":2,"52":1,"54":3,"55":1,"65":3,"94":5,"95":1,"143":1,"159":3,"162":2,"163":1,"168":2,"173":4,"178":2,"182":2,"209":3,"212":1,"230":5,"249":6,"253":3,"256":1,"267":1,"281":4,"300":1}}],["debug",{"2":{"58":1,"94":1,"145":10,"150":29,"159":2,"176":2,"178":1,"184":22,"192":1,"230":4,"253":2}}],["deb",{"2":{"21":1,"28":1,"42":2,"48":1,"159":2,"230":1,"234":3,"253":2,"277":1}}],["devnull",{"2":{"184":1}}],["dev",{"2":{"16":1,"17":1,"29":1,"30":2,"39":1,"42":1,"48":1,"111":1,"225":1}}],["nl",{"2":{"230":1}}],["nederlands",{"2":{"230":1}}],["net",{"2":{"176":2}}],["network",{"2":{"176":10,"230":2}}],["next",{"2":{"145":3}}],["new",{"2":{"6":1,"8":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"30":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"42":1,"48":1,"50":1,"51":1,"52":1,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1}}],["np",{"2":{"138":1}}],["nginx",{"0":{"123":1},"2":{"123":3}}],["nz",{"2":{"103":1}}],["nubmer=nubmer",{"2":{"298":2}}],["nubmer=",{"2":{"298":2}}],["num",{"2":{"176":7}}],["numbers",{"2":{"176":1}}],["number=number",{"2":{"270":1,"295":1,"298":1}}],["number=max",{"2":{"176":2}}],["number=match",{"2":{"176":2}}],["number=",{"2":{"145":1,"270":1,"295":1,"298":1}}],["number",{"2":{"55":1,"134":7,"145":2,"148":1,"150":9,"176":19,"184":11,"230":4,"270":9,"298":3}}],["numpy",{"2":{"45":1,"138":1}}],["null",{"2":{"35":2}}],["name=self",{"2":{"270":1,"271":1,"295":1,"298":1}}],["name=spur",{"2":{"75":2}}],["name=app",{"2":{"176":1}}],["name=none",{"2":{"137":1,"144":1,"145":1}}],["name=name",{"2":{"75":1}}],["name",{"2":{"35":1,"36":1,"40":2,"48":2,"54":1,"65":3,"75":2,"76":4,"85":1,"86":1,"120":2,"138":1,"142":1,"143":3,"144":3,"145":17,"148":3,"150":49,"159":2,"192":3,"196":3,"204":12,"212":2,"216":1,"217":1,"219":1,"230":8,"253":2,"270":8,"271":2,"295":2,"297":2,"298":4}}],["native",{"2":{"17":1,"103":4,"104":1,"230":3}}],["n",{"0":{"243":1},"2":{"31":2,"148":1,"150":4,"162":1,"176":3,"204":2,"256":1}}],["no表示测试机分布式执行",{"2":{"230":1}}],["nox",{"2":{"155":1}}],["nosetreferencepoint",{"2":{"150":3}}],["nosectionerror",{"2":{"150":3}}],["noskip",{"2":{"21":1,"159":1,"230":1,"253":1}}],["node=none",{"2":{"145":1}}],["node",{"2":{"145":16,"155":1}}],["no",{"2":{"42":3,"145":3,"162":1,"163":1,"211":1,"230":10,"256":1,"257":1}}],["none=true",{"2":{"120":1,"138":2}}],["none",{"2":{"16":1,"17":1,"120":2,"134":8,"135":2,"138":3,"145":4,"150":7,"176":66,"270":2}}],["not逻辑组合",{"2":{"159":2,"253":2}}],["not",{"2":{"13":1,"35":1,"120":1,"134":1,"145":4,"150":2,"168":1,"169":1,"176":40,"204":10,"230":1}}],["此层在框架中提供一些通用的接口能力",{"2":{"276":1}}],["此目录名称前面部分是你的代码根目录的名称",{"2":{"237":1}}],["此功能默认会将",{"2":{"211":1}}],["此功能目前还处于内部灰度阶段",{"2":{"13":1}}],["此配置文件需要维护大量的标签数据",{"2":{"208":1}}],["此配置文件用于标签化管理方案实现条件判断跳过的配置项",{"2":{"204":1}}],["此时编辑器可能会提示你",{"2":{"301":1}}],["此时",{"2":{"201":1}}],["此时要定位到菜单中的",{"2":{"132":1}}],["此用例标签不会被添加",{"2":{"200":1}}],["此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用",{"2":{"147":1}}],["此函数用于在操作之前截图一张临时图片",{"2":{"139":1}}],["此方案时间效率比较低",{"2":{"196":1}}],["此方案用到的场景不多",{"2":{"183":1}}],["此方案在框架内没有引入任何三方依赖完全采用标准库实现",{"2":{"120":1}}],["此方法直接返回坐标",{"2":{"120":1}}],["此接口底层没有兼容服务化",{"2":{"41":1}}],["此外",{"2":{"13":1}}],["功能测试",{"2":{"286":1}}],["功能测试用例",{"2":{"281":1}}],["功能模块相对独立",{"2":{"276":1}}],["功能强大的自动化测试框架",{"2":{"263":1}}],["功能强大的执行管理器",{"2":{"243":1}}],["功能进行了增强",{"2":{"124":1}}],["功能进行了优化和",{"2":{"13":1}}],["功能做了服务化",{"2":{"41":1}}],["功能的一些信息输出",{"2":{"39":1}}],["功能",{"2":{"13":1,"32":1,"134":1,"200":1}}],["功能增加显示明细数据",{"2":{"6":1}}],["希望欧拉系统上使用到",{"2":{"13":1}}],["的配置比较灵活",{"2":{"281":1}}],["的配置均不生效",{"2":{"230":1}}],["的内容",{"2":{"272":1}}],["的名称空间",{"2":{"270":1}}],["的公共方法",{"2":{"267":2}}],["的普通文件",{"2":{"235":1}}],["的表达式",{"2":{"230":1}}],["的所有用例",{"2":{"230":1}}],["的所有方法",{"2":{"103":1}}],["的别名",{"2":{"228":1}}],["的对象实例化默认会检测应用是否启动",{"2":{"223":1}}],["的基础上增加了发送",{"2":{"219":1}}],["的要求",{"2":{"209":1}}],["的钩子函数",{"2":{"207":1}}],["的时候",{"2":{"205":1}}],["的全量用例",{"2":{"205":1}}],["的模板语法设计出的日志模板语法",{"2":{"193":1}}],["的模板匹配",{"2":{"134":1}}],["的方式",{"2":{"191":1,"193":1}}],["的方式持续在欧拉社区进行代码更新",{"2":{"13":1}}],["的日志系统",{"2":{"190":1}}],["的想法",{"2":{"190":1}}],["的键鼠操作模块主要有两个",{"2":{"182":1}}],["的报告都是基于在线的服务",{"2":{"180":1}}],["的执行管理器",{"2":{"156":1}}],["的文件",{"2":{"155":1}}],["的文字",{"2":{"54":1}}],["的距离",{"2":{"149":1}}],["的中心坐标为",{"2":{"148":1}}],["的左上角相对于应用窗口左上角",{"2":{"148":1}}],["的位置为",{"2":{"148":1}}],["的位置",{"2":{"148":1}}],["的元素定位采用这种",{"2":{"147":1}}],["的元素定位方案的数据源是应用库中的",{"2":{"149":1}}],["的元素定位方案",{"2":{"147":1,"243":1}}],["的元素定位方案在",{"2":{"26":1,"40":1}}],["的大致流程",{"2":{"277":2}}],["的大小",{"2":{"145":1,"148":1}}],["的大力支持",{"2":{"40":1}}],["的形式展示",{"2":{"142":1}}],["的项目介绍可以猛戳这里",{"2":{"141":1}}],["的环境",{"2":{"138":1}}],["的图像识别方案",{"0":{"136":1},"1":{"137":1,"138":1}}],["的图像识别功能几乎满足了你的所有要求",{"2":{"133":1}}],["的图像识别功能兼容两种情况",{"2":{"41":1}}],["的图标即返回其在大图中的坐标",{"2":{"134":1}}],["的坐标",{"2":{"132":1,"148":1,"193":2}}],["的步长为",{"2":{"128":1}}],["的解决方案",{"0":{"124":1}}],["的前",{"2":{"123":1}}],["的负载均衡方案不能满足业务需求",{"0":{"123":1}}],["的调用逻辑",{"2":{"119":1}}],["的专用断言语句",{"2":{"103":1}}],["的用例中标记了",{"2":{"209":1}}],["的用例",{"2":{"100":1,"205":1}}],["的用例数量",{"2":{"21":1}}],["的情况下",{"2":{"56":1}}],["的数量",{"2":{"55":1}}],["的目录发送到测试机",{"2":{"48":1}}],["的值",{"2":{"48":1,"51":1}}],["的参数直接传给远程机器的",{"2":{"44":1}}],["的三方源",{"2":{"43":1,"44":1}}],["的在线文档是部署在公司内网的",{"2":{"42":1}}],["的初始化工程命令",{"2":{"42":1}}],["的机器",{"2":{"41":1}}],["的",{"0":{"243":1},"2":{"32":1,"103":1,"123":1,"154":1,"192":1,"230":1,"272":1,"283":1,"284":1}}],["的正式域名为",{"2":{"23":1}}],["的断言语句",{"2":{"17":1}}],["的需求",{"2":{"16":1}}],["的另一个亮点",{"2":{"13":1}}],["的同学们能给我们反馈使用情况",{"2":{"13":1}}],["的问题",{"2":{"8":1,"13":1,"14":1,"39":2,"50":1,"54":1,"58":1,"260":1}}],["ohtm7l7g",{"2":{"237":2}}],["option",{"2":{"281":1}}],["opt",{"2":{"155":1}}],["operate",{"2":{"150":1}}],["open",{"2":{"138":2,"184":1,"223":1}}],["opencv服务端地址",{"2":{"230":1}}],["opencv",{"0":{"136":1},"1":{"137":1,"138":1},"2":{"41":4,"133":2,"134":4,"137":7,"138":10,"230":7}}],["openeuler",{"2":{"13":1,"14":3}}],["org",{"2":{"150":2,"176":1}}],["or",{"2":{"134":1,"145":1,"155":1,"159":2,"168":1,"169":2,"170":3,"176":3,"184":1,"204":1,"230":2,"253":2,"270":2,"281":2}}],["original",{"2":{"184":2}}],["origin",{"2":{"75":1}}],["out",{"2":{"94":1,"150":6,"155":2,"176":2,"184":7,"230":1}}],["onlyvisible",{"2":{"148":1,"150":4}}],["only",{"2":{"145":1,"150":1,"155":1,"176":1,"184":1,"204":1}}],["on",{"2":{"85":2,"86":1,"94":1,"95":1,"137":2,"150":1,"184":3}}],["obj就是应用的对象",{"2":{"143":1}}],["object",{"2":{"65":3,"150":3}}],["obj",{"2":{"65":2,"143":2,"144":2,"145":10}}],["other",{"2":{"50":1,"62":2,"71":2,"81":2,"96":2,"108":2,"249":2,"281":1}}],["oserror",{"2":{"138":1}}],["os",{"2":{"28":1,"176":12,"184":4,"204":8,"223":1}}],["offset",{"2":{"150":20}}],["of=",{"2":{"111":1}}],["of",{"2":{"16":1,"137":3,"155":3,"184":5}}],["ocr端口",{"2":{"230":1}}],["ocr服务端地址",{"2":{"230":1}}],["ocrutils",{"2":{"176":1}}],["ocr识别以外",{"2":{"243":1}}],["ocr识别的最大次数",{"2":{"230":1}}],["ocr识别的总超时",{"2":{"230":1}}],["ocr识别",{"0":{"117":1},"1":{"118":1,"119":1,"120":1,"121":1,"122":1,"123":1,"124":1,"125":1}}],["ocrx",{"2":{"14":2,"125":4}}],["ocr",{"2":{"11":1,"14":10,"19":1,"31":1,"34":1,"35":2,"40":1,"41":1,"51":1,"53":2,"54":2,"118":3,"119":1,"120":13,"122":3,"123":1,"124":2,"125":8,"132":6,"176":10,"230":8,"281":1}}],["scan",{"2":{"230":1}}],["scroll为传入滚轮数",{"2":{"184":1}}],["scroll",{"2":{"184":6}}],["screenshotfullscreen",{"2":{"176":1}}],["screenshot",{"2":{"176":1}}],["screen",{"2":{"120":4,"134":8,"135":3,"137":2,"138":8,"176":13,"184":2,"230":2}}],["sys",{"2":{"184":5,"204":1,"227":1,"229":1,"230":1,"273":1}}],["systemctl",{"2":{"162":2,"256":2}}],["system",{"2":{"65":1,"184":1,"204":4,"223":1}}],["smoke",{"2":{"166":3,"169":1,"230":1,"281":1,"285":1}}],["small",{"2":{"137":12}}],["snippets",{"2":{"155":1}}],["sniff",{"0":{"142":1},"2":{"26":1,"35":1,"56":1,"85":3,"142":5,"143":1}}],["svn",{"2":{"155":1}}],["s",{"2":{"150":8,"162":1,"204":6,"223":1,"256":1}}],["some",{"2":{"249":6,"253":1}}],["somke",{"2":{"230":1}}],["so",{"2":{"185":1}}],["sort",{"2":{"150":2}}],["software",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["socketserver",{"2":{"120":1,"138":1}}],["sdata",{"2":{"137":2}}],["singer",{"2":{"223":2}}],["site",{"2":{"155":1}}],["sikuli",{"2":{"133":1}}],["simplexmlrpcserver",{"2":{"120":2,"138":2}}],["similarity=similarity",{"2":{"120":1,"176":2}}],["similarity=0",{"2":{"120":2,"176":2}}],["similarity",{"2":{"120":1,"176":2}}],["size=",{"2":{"176":1}}],["sizes",{"2":{"150":12}}],["size",{"2":{"54":3,"145":6,"150":3,"176":6,"184":2}}],["slave",{"2":{"214":4,"230":4}}],["slaves对象提供远程机器信息",{"0":{"214":1}}],["slaves",{"2":{"17":1,"95":2,"214":3,"218":2,"230":1,"253":2}}],["sleep",{"2":{"86":2,"134":1,"150":7,"176":5,"184":15}}],["stdout",{"2":{"184":6}}],["style",{"2":{"155":2}}],["strftime",{"2":{"227":1,"273":1}}],["str",{"2":{"134":3,"135":1,"138":2,"150":13,"176":6,"184":4,"200":1,"204":7}}],["strings",{"2":{"120":2,"155":1,"301":1}}],["string",{"2":{"76":2,"94":1,"143":1}}],["strip",{"2":{"75":1,"148":1,"150":7,"176":1}}],["str2",{"2":{"75":2}}],["staticmethod",{"2":{"137":3,"145":1,"176":20,"188":1,"223":1}}],["status=200",{"2":{"76":1}}],["status=status",{"2":{"76":1}}],["status",{"2":{"75":4,"76":1,"86":1,"176":2}}],["state",{"2":{"65":1,"66":3}}],["startswith",{"2":{"145":3,"192":1,"230":1}}],["start",{"2":{"145":1,"176":44,"184":12,"217":3,"218":2,"219":2,"230":1}}],["start=true",{"2":{"145":1}}],["startproject",{"2":{"39":1,"42":3,"69":1,"79":1,"89":1,"106":1,"115":1,"246":2,"247":3}}],["startapp",{"2":{"19":1,"20":2,"53":1,"54":2,"62":2,"71":2,"81":2,"96":2,"108":2,"249":2}}],["step",{"2":{"54":1,"193":1}}],["same",{"2":{"155":1}}],["safari",{"2":{"75":1}}],["save",{"2":{"54":4,"139":1,"176":3}}],["saifeilee",{"2":{"19":1}}],["space",{"2":{"155":1}}],["spaces",{"2":{"155":1}}],["spdx",{"2":{"145":2,"150":2,"176":2,"184":2,"204":2}}],["spi",{"2":{"142":1}}],["spur",{"2":{"75":4}}],["sphinx",{"2":{"53":1}}],["split",{"2":{"31":1,"75":4,"120":1,"148":2,"150":7,"176":2,"204":6}}],["sec",{"2":{"200":1}}],["section",{"2":{"149":3}}],["several",{"2":{"137":1}}],["serve",{"2":{"120":1,"138":1}}],["serverproxy",{"2":{"138":2}}],["server",{"2":{"75":4,"76":1,"120":5,"138":12,"180":1,"204":1,"230":4}}],["service",{"2":{"120":1,"138":1}}],["searchcutoffcount",{"2":{"145":1}}],["searcherror",{"2":{"145":7}}],["search",{"2":{"102":1,"103":1,"145":2,"148":1,"150":4,"301":2}}],["send2task",{"2":{"196":1}}],["send",{"2":{"94":3,"159":1,"162":1,"171":1,"172":1,"196":5,"197":1,"230":3,"253":1,"256":1}}],["selenium",{"2":{"186":5}}],["selected",{"2":{"137":1}}],["select",{"2":{"75":4,"155":1,"184":3}}],["self",{"2":{"54":5,"65":3,"66":2,"75":27,"76":9,"85":4,"86":3,"94":5,"95":1,"102":7,"103":3,"111":2,"112":2,"120":2,"144":10,"145":52,"148":3,"149":4,"150":99,"165":2,"175":3,"184":4,"185":2,"190":1,"193":1,"216":4,"217":4,"218":3,"219":2,"223":2,"270":5,"271":6,"283":1,"284":1,"295":2,"296":5,"297":5,"298":13}}],["setattr",{"2":{"191":1}}],["set",{"2":{"75":2,"137":1,"155":1}}],["setup",{"2":{"54":1,"58":1}}],["setting",{"0":{"226":1,"273":1},"1":{"227":1,"228":1,"229":1,"230":1},"2":{"16":1,"28":2,"35":2,"42":2,"48":1,"57":1,"69":1,"70":1,"79":1,"80":1,"89":1,"90":1,"103":1,"106":1,"107":1,"111":1,"115":1,"116":1,"134":1,"145":1,"150":1,"153":1,"154":1,"155":2,"157":2,"160":1,"162":1,"176":1,"184":1,"185":1,"204":2,"214":1,"227":1,"228":2,"229":1,"232":1,"248":1,"254":1,"256":1,"267":1}}],["sessionbus",{"2":{"150":1}}],["sessiontimeout",{"2":{"51":1}}],["session",{"2":{"51":1,"57":1,"94":1,"123":1}}],["ssh",{"2":{"50":1,"162":3,"256":3}}],["sw64",{"2":{"243":1}}],["sw",{"2":{"41":2}}],["skiped",{"2":{"203":1,"285":1}}],["skip",{"2":{"20":1,"21":1,"55":1,"155":1,"200":2,"202":1,"203":2,"204":8,"205":6,"206":1,"230":1,"285":2}}],["skipif",{"2":{"13":1,"21":2,"28":2,"40":4,"204":31}}],["shift",{"2":{"184":3,"301":1,"303":1}}],["shehllyouqu",{"2":{"166":1}}],["shell命令",{"2":{"295":1}}],["shelloptional",{"2":{"253":1}}],["shellexport",{"2":{"246":1}}],["shell>>",{"2":{"193":1}}],["shell$",{"2":{"157":2,"158":1,"159":1,"160":1,"161":1,"162":4,"163":1,"232":1,"236":2,"238":1,"239":1,"246":1,"247":1,"248":3,"249":1,"252":1,"253":2,"255":1,"256":4,"257":1}}],["shellruff",{"2":{"153":2,"154":1}}],["shellbig",{"2":{"137":1}}],["shellbash",{"2":{"42":1}}],["shellsmall",{"2":{"137":1}}],["shellsudo",{"2":{"68":1,"78":1,"88":1,"105":1,"114":1}}],["shelltouch",{"2":{"97":1}}],["shellmikigo",{"2":{"85":1,"142":1}}],["shellmy",{"2":{"62":1,"69":1,"71":1,"79":1,"81":1,"89":1,"96":1,"106":1,"108":1,"115":1,"249":1}}],["shellautotest",{"2":{"72":1,"93":1,"97":1,"166":1,"234":2,"235":1,"293":1}}],["shellcd",{"2":{"70":1,"73":1,"80":1,"90":1,"98":1,"107":1,"116":1,"180":1}}],["shell用例收集数量",{"2":{"54":1}}],["shell~$",{"2":{"48":1}}],["shellpyyaml==6",{"2":{"234":1}}],["shellpython3",{"2":{"42":1,"48":1,"54":1,"205":1}}],["shellpip3",{"2":{"152":1,"246":1}}],["shellpdocr",{"2":{"46":1}}],["shellyouqu",{"2":{"35":1,"42":2,"52":1,"62":1,"69":1,"71":1,"79":1,"81":1,"89":1,"96":1,"106":1,"108":1,"115":1,"165":2,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"196":3,"197":1,"209":2,"211":1,"212":1,"214":1,"224":1,"267":1}}],["shell",{"2":{"13":1,"54":1,"178":1,"238":1,"274":1,"281":1}}],["show",{"2":{"159":1,"162":1,"253":1,"256":1}}],["shortcut",{"2":{"150":3,"182":4,"192":1,"230":1}}],["share",{"2":{"94":1,"176":12,"237":1}}],["sha512",{"2":{"75":2}}],["shyouqu",{"2":{"42":2,"211":1}}],["shsudo",{"2":{"42":1}}],["sh",{"0":{"73":1,"98":1,"231":1},"1":{"232":1,"233":1,"234":1,"235":1,"236":1,"237":1,"238":1,"239":1,"240":1},"2":{"13":1,"16":4,"17":1,"18":1,"19":1,"28":2,"30":1,"39":2,"42":2,"43":1,"44":2,"46":1,"47":1,"48":3,"50":2,"51":2,"54":4,"55":2,"58":1,"69":1,"70":2,"73":1,"79":1,"80":2,"89":1,"90":2,"98":1,"106":1,"107":2,"115":1,"116":2,"119":1,"185":1,"225":2,"232":3,"234":2,"235":1,"236":1,"248":3}}],["src",{"0":{"270":1},"2":{"13":1,"14":1,"16":1,"27":1,"35":1,"57":1,"60":2,"65":1,"69":1,"79":1,"85":5,"86":1,"89":1,"94":1,"102":1,"103":1,"106":1,"111":3,"115":1,"120":1,"125":1,"132":2,"144":1,"145":10,"148":1,"150":7,"175":2,"176":13,"182":7,"183":1,"184":7,"188":1,"193":2,"216":1,"217":1,"265":2,"267":1,"270":11,"271":4,"272":1,"295":6,"298":2}}],["submenu",{"2":{"184":1}}],["subset",{"2":{"155":1}}],["suit",{"2":{"172":1}}],["suite",{"2":{"159":2,"173":2,"230":1,"253":2}}],["supported",{"2":{"155":1}}],["super",{"2":{"102":1}}],["summarize",{"2":{"12":4}}],["sudo",{"2":{"5":1,"17":1,"42":5,"162":2,"204":4,"223":1,"246":4,"256":2}}],["并在",{"2":{"281":1}}],["并通过",{"2":{"207":1}}],["并将测试数据和测试资源整合进来",{"2":{"281":1}}],["并将截取的右侧作为参数传递给该函数",{"2":{"204":1}}],["并将其部署为",{"2":{"138":1}}],["并将其转换为",{"2":{"31":1}}],["并对外提供唯一的接口",{"2":{"263":1}}],["并对测试结果做处理",{"2":{"197":1}}],["并对其进行定位操作",{"2":{"141":1}}],["并没有再补充其对应的命令行参数",{"2":{"157":1}}],["并且传递",{"2":{"270":1}}],["并且有串口线",{"2":{"261":1}}],["并且将执行的结果回填的测试用例的状态里面",{"2":{"195":1}}],["并且所有调用的方法会以",{"2":{"193":1}}],["并且迅速爱上他",{"2":{"147":1}}],["并且帮助我们改进",{"0":{"0":1},"1":{"1":1,"2":1,"3":1}}],["并返回编号最大的窗口id",{"2":{"150":1}}],["并返回用于鼠标和键盘操作的坐标",{"2":{"150":1}}],["并返回图片路径",{"2":{"139":1}}],["并返回新图片的路径",{"2":{"132":1}}],["并返回其在图片中的坐标",{"2":{"120":1}}],["并指定虚拟解释器",{"2":{"63":1,"82":1,"99":1,"109":1}}],["并提供可调用的配置对象config",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["并生成大量模板代码",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1}}],["并详细列出各个阶段的耗时",{"2":{"57":1}}],["并优化了进度获取的算法",{"2":{"55":1}}],["并优化了日志的排版",{"2":{"55":1}}],["并兼容不带文件后缀名入参方式",{"2":{"12":1,"13":1}}],["支持标签的逻辑组合",{"2":{"281":1}}],["支持标签反向同步",{"2":{"35":1}}],["支持多元化元素定位和断言",{"2":{"241":1}}],["支持多种数据回填模式",{"2":{"58":1}}],["支持同时生成",{"2":{"230":1}}],["支持自动同步脚本",{"2":{"211":1}}],["支持类名包含",{"2":{"192":1,"230":1}}],["支持类名以",{"2":{"192":2,"230":2}}],["支持and",{"2":{"159":2,"253":2}}],["支持指定屏幕区域截图并返回图片存放的本地路径",{"2":{"54":1}}],["支持使用系统命令",{"2":{"52":1}}],["支持动态传入参数",{"2":{"51":1}}],["支持动态传入重试次数",{"2":{"40":1}}],["支持通过位置参数传入文件路径",{"2":{"50":1}}],["支持不同",{"2":{"40":1}}],["支持统计分析仓库新增修复的用例或方法数量",{"2":{"19":1}}],["支持链式调用函数接口",{"2":{"125":1}}],["支持链式调用",{"2":{"14":1,"125":1}}],["支持",{"2":{"13":1,"40":1}}],["支持的驱动方式",{"2":{"13":1}}],["支持windows和macos",{"2":{"12":1}}],["支持将测试结果回传给测试平台",{"2":{"12":1}}],["插件生成的报告源数据",{"2":{"180":1}}],["插件库",{"2":{"62":1,"69":1,"71":1,"79":1,"81":1,"89":1,"96":1,"106":1,"108":1,"115":1,"249":1}}],["插件中实现了此功能",{"2":{"28":1}}],["插件",{"2":{"12":2,"13":1}}],["l4",{"2":{"200":1,"285":1}}],["l3",{"2":{"200":1,"285":1}}],["l2",{"2":{"200":1,"285":1}}],["l1",{"2":{"169":2,"200":2,"230":3,"285":2}}],["level",{"2":{"159":2,"192":1,"230":1,"253":2}}],["length",{"2":{"155":3}}],["len",{"2":{"150":2,"176":9,"184":2}}],["leftviewwidget",{"2":{"296":1,"297":1}}],["left",{"2":{"145":3,"149":3,"150":20,"293":2}}],["letmego",{"2":{"12":1,"37":1,"38":1,"221":2,"222":3,"223":2}}],["ltd",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["lastest",{"2":{"150":1}}],["lastfailed",{"2":{"57":1,"159":1,"253":1}}],["large",{"2":{"137":2}}],["lambda",{"2":{"120":1,"176":2,"193":1}}],["lang",{"2":{"120":3,"176":2}}],["lang=lang",{"2":{"120":1,"176":2}}],["lang=",{"2":{"120":2,"176":2}}],["language",{"2":{"75":1,"230":1}}],["loongarch64",{"2":{"243":1}}],["lower",{"2":{"176":1,"184":2}}],["load",{"2":{"137":3}}],["loads",{"2":{"75":1}}],["location",{"2":{"148":1,"149":2,"150":17,"159":2,"184":6,"253":2}}],["locateallonscreen",{"2":{"184":1}}],["locate",{"2":{"134":3,"184":1}}],["locatorassertions",{"2":{"188":1}}],["locator",{"2":{"102":2,"103":4,"188":4}}],["locals",{"2":{"145":1}}],["local",{"2":{"42":1,"237":1,"246":2}}],["lo",{"2":{"65":2}}],["log=true",{"2":{"184":1}}],["log=false",{"2":{"94":1,"150":6,"176":2,"184":5}}],["logdebugtofile",{"2":{"145":1}}],["logdebugtostdout",{"2":{"145":2}}],["logger",{"2":{"85":2,"145":12,"150":24,"176":18,"184":23,"190":1,"193":1}}],["logging",{"2":{"59":1}}],["login",{"2":{"75":8}}],["loguru",{"2":{"59":2}}],["log",{"2":{"55":1,"85":3,"159":2,"176":2,"178":2,"184":1,"191":1,"192":2,"193":5,"230":2,"253":2}}],["logs",{"2":{"55":1,"178":1}}],["logo",{"2":{"54":1,"179":1}}],["limit",{"2":{"155":1}}],["literal",{"2":{"155":1}}],["litaoa",{"2":{"145":1,"150":1,"184":1}}],["litao",{"2":{"145":1,"150":1,"184":1}}],["library",{"2":{"150":4}}],["libkf5waylandclient5",{"2":{"30":2}}],["libkf5wayland",{"2":{"29":1,"30":2}}],["lint",{"2":{"155":1}}],["line",{"2":{"155":5,"159":2,"184":1,"253":2}}],["link",{"2":{"94":2,"212":2,"230":1}}],["linux",{"0":{"67":1,"87":1},"1":{"68":1,"69":1,"70":1,"88":1,"89":1,"90":1},"2":{"75":1,"87":1,"113":1,"141":1,"241":1,"242":2}}],["linuxdeepin",{"2":{"2":1,"39":1}}],["like",{"2":{"75":1,"155":4}}],["license",{"2":{"65":5,"145":1,"150":1,"176":1,"184":1,"204":1}}],["list类型",{"2":{"75":1}}],["list",{"2":{"54":1,"134":2,"137":1,"138":1,"143":2,"145":2,"148":2,"149":1,"150":14,"176":6,"209":3,"230":3}}],["仓库中",{"2":{"249":1}}],["仓库代码到",{"2":{"19":1}}],["仓库代码",{"2":{"12":1}}],["仓库提交代码",{"0":{"3":1}}],["u9fff",{"2":{"184":1}}],["u4e00",{"2":{"184":1}}],["u",{"2":{"159":1,"171":1,"172":1,"196":1,"197":1,"212":1,"253":1}}],["ut00xxxx",{"2":{"212":1}}],["ut001234",{"2":{"171":1,"172":1,"196":1,"197":1,"230":1}}],["utf",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["utils",{"2":{"16":1,"51":1,"54":1,"65":1,"124":1,"144":1,"176":3,"193":1}}],["upper",{"2":{"145":4}}],["up",{"2":{"128":1,"184":5}}],["usages",{"2":{"283":1}}],["use",{"2":{"155":1}}],["used",{"2":{"150":2,"155":1}}],["user=",{"2":{"216":1,"217":1,"219":1}}],["usershare",{"2":{"176":2}}],["username=self",{"2":{"76":1}}],["username",{"2":{"75":6,"111":1,"227":1,"273":1}}],["user",{"2":{"12":1,"17":1,"75":1,"103":1,"159":3,"196":3,"212":1,"214":5,"230":13,"253":3}}],["usr",{"2":{"85":1,"94":1,"103":1,"145":1,"150":1,"176":1,"184":1,"204":1,"230":1,"270":1,"271":1,"295":1,"298":1}}],["udcpapi",{"2":{"76":4}}],["udcp",{"2":{"75":4,"76":4}}],["underscore",{"2":{"155":1}}],["unused",{"2":{"155":1}}],["unfixable",{"2":{"155":1}}],["unlike",{"2":{"155":1}}],["union",{"2":{"145":2,"176":3,"188":2}}],["uniontech",{"2":{"23":1,"52":2,"55":1,"145":3,"150":3,"176":1,"184":3,"204":1,"212":1,"230":3}}],["unknown",{"2":{"28":1}}],["uos",{"2":{"26":1,"48":6,"54":1,"55":1,"56":1,"57":1,"162":6,"163":2,"193":1,"197":2,"256":4}}],["uim",{"2":{"75":1}}],["ui自动化测试提供一个fixture对象",{"2":{"103":1,"230":1}}],["ui自动化测试提供一个",{"2":{"17":1}}],["ui",{"0":{"87":1,"104":1},"1":{"88":1,"89":1,"90":1,"105":1,"106":1,"107":1},"2":{"14":1,"17":1,"18":1,"23":1,"26":1,"40":1,"54":2,"62":1,"71":1,"81":1,"87":3,"96":1,"97":2,"98":1,"103":3,"104":2,"108":1,"129":1,"132":1,"133":1,"141":1,"147":2,"148":3,"149":8,"150":1,"179":1,"186":1,"187":1,"213":2,"223":5,"230":1,"235":1,"242":2,"243":1,"249":1,"267":4,"270":1,"271":2,"276":1,"281":1,"293":2,"296":4,"298":7}}],["urllib",{"2":{"77":1}}],["urllib3",{"2":{"75":2}}],["url",{"2":{"12":1,"75":7,"227":1,"230":1,"273":1,"281":1}}],["$nf",{"2":{"204":2}}],["$根节点",{"2":{"145":2}}],["$home",{"2":{"27":1,"42":1,"237":1,"246":2}}],["$",{"2":{"12":5,"70":1,"80":1,"90":1,"107":1,"116":1,"145":4,"155":1,"162":1,"176":1,"214":12,"230":24,"232":1,"248":1,"256":1}}],["pl",{"2":{"230":1}}],["plus",{"0":{"219":1},"2":{"219":2}}],["plc",{"2":{"212":1}}],["platform",{"2":{"204":11}}],["planned",{"2":{"155":1}}],["play",{"2":{"134":2}}],["playwright",{"2":{"17":2,"103":2,"104":2,"186":7}}],["plain",{"2":{"75":1}}],["ppl",{"2":{"200":2}}],["perf",{"2":{"200":1}}],["pexpect",{"2":{"41":1}}],["ps",{"2":{"145":1}}],["pxe",{"2":{"277":1,"281":3,"287":1}}],["px",{"2":{"130":1,"176":2}}],["png",{"2":{"120":2,"134":3,"176":6,"193":2,"230":1,"267":1}}],["po",{"2":{"249":1,"292":1}}],["polski",{"2":{"230":1}}],["pop",{"2":{"293":2}}],["popwidget",{"2":{"222":1,"223":1,"296":1,"297":1}}],["popen",{"2":{"120":1,"176":1,"184":1,"204":2}}],["position",{"2":{"145":8,"148":1,"150":38,"184":4}}],["post",{"2":{"75":2}}],["points",{"2":{"137":3}}],["point",{"2":{"137":2,"143":1,"145":1,"150":12}}],["port",{"2":{"120":2,"230":2}}],["pc",{"2":{"85":1,"142":1}}],["pwd",{"2":{"76":2}}],["photo",{"2":{"75":3}}],["photo=none",{"2":{"75":1}}],["phone",{"2":{"75":3}}],["phone=none",{"2":{"75":1}}],["pic",{"2":{"54":4,"62":1,"71":1,"81":1,"96":1,"108":1,"120":7,"134":1,"137":6,"150":5,"176":19,"193":1,"249":1,"267":1,"293":1}}],["picture",{"2":{"54":5,"120":6,"134":7,"138":2,"139":1,"176":20}}],["pip3",{"2":{"42":2,"68":1,"78":1,"88":1,"105":1,"114":1,"246":1}}],["pip",{"2":{"30":1,"42":3}}],["p2c",{"2":{"34":1,"211":1,"212":2}}],["puppeteer",{"2":{"186":2}}],["put",{"2":{"120":3,"138":6}}],["pubilic",{"2":{"47":1}}],["public",{"0":{"271":1},"2":{"27":1,"34":2,"47":1,"57":1,"145":1,"265":2,"267":5,"271":1,"281":1,"284":5,"297":1}}],["pull",{"2":{"1":1}}],["p",{"2":{"18":1,"70":2,"80":2,"90":2,"107":2,"116":2,"159":1,"162":1,"171":1,"172":1,"196":1,"197":1,"212":1,"232":2,"248":2,"253":1,"256":1}}],["pms回填的重试次数",{"2":{"230":1}}],["pms配置使用",{"2":{"230":1}}],["pms测试套的id",{"2":{"230":1}}],["pms测试套执行",{"2":{"230":1}}],["pms相关配置",{"2":{"230":1}}],["pms2csv",{"2":{"212":1}}],["pms的密码",{"2":{"212":1,"230":1}}],["pms的用户名",{"2":{"212":1,"230":1}}],["pms用例id",{"2":{"200":2}}],["pmsctl",{"2":{"196":1,"212":4,"230":2}}],["pms密码",{"2":{"196":3}}],["pms账号",{"2":{"196":3}}],["pms数据回填",{"0":{"195":1},"1":{"196":1,"197":1,"198":1},"2":{"230":1}}],["pms",{"0":{"212":1},"2":{"16":1,"17":1,"32":2,"33":2,"35":2,"37":1,"53":1,"55":1,"156":1,"159":13,"171":1,"172":1,"196":9,"197":2,"198":2,"200":2,"212":7,"230":10,"253":13,"285":3,"288":1}}],["primary",{"2":{"184":3}}],["print",{"2":{"94":1,"120":1,"204":3,"298":6}}],["printscreen",{"2":{"35":1}}],["prefixed",{"2":{"155":1}}],["predicate",{"2":{"145":3}}],["pre",{"2":{"137":3}}],["press",{"2":{"27":1,"183":2,"184":17}}],["prc",{"2":{"123":1}}],["product",{"2":{"204":4}}],["proportion",{"2":{"176":3}}],["properties",{"2":{"65":1}}],["property",{"2":{"65":1}}],["provided",{"2":{"155":1,"176":10}}],["proxy",{"2":{"150":2}}],["process",{"2":{"86":1,"176":4}}],["project$",{"2":{"85":1}}],["project",{"2":{"62":1,"69":2,"70":1,"71":1,"72":1,"73":1,"79":2,"80":1,"81":1,"89":2,"90":1,"93":1,"96":1,"97":1,"98":1,"106":2,"107":1,"108":1,"115":2,"116":1,"159":2,"247":1,"248":1,"249":1,"253":2}}],["pr",{"2":{"13":1,"17":1,"19":3,"183":1}}],["parallel",{"2":{"162":3,"163":2,"230":1,"256":3,"257":2}}],["param",{"2":{"75":11,"120":2,"132":1,"134":9,"135":5,"138":5,"139":4,"144":1,"145":10,"150":49,"176":60,"184":58,"193":2,"270":2}}],["pants",{"2":{"155":1}}],["package",{"2":{"150":1,"267":2}}],["packages",{"2":{"75":1,"155":1}}],["pause=pause",{"2":{"176":4}}],["pause",{"2":{"135":4,"150":6,"176":9,"184":1,"230":2}}],["paddle",{"2":{"120":3}}],["paddlepaddle",{"2":{"118":1}}],["paddleocr目前支持的多语言语种可以通过修改lang参数进行切换",{"2":{"120":1}}],["paddleocr",{"2":{"118":1,"120":2}}],["pass",{"2":{"54":1,"120":2,"138":1,"176":6,"185":2,"223":1,"229":1,"271":1,"298":1}}],["password一样",{"2":{"230":1}}],["password2",{"2":{"214":1}}],["password1",{"2":{"214":2}}],["password的值",{"2":{"162":1,"256":1}}],["password=self",{"2":{"76":1}}],["password=spur",{"2":{"75":2}}],["password=",{"2":{"75":1,"216":1,"217":1,"219":1}}],["password=password",{"2":{"75":1}}],["password",{"2":{"12":1,"17":1,"48":3,"70":2,"75":14,"80":2,"90":2,"107":2,"116":2,"159":3,"162":4,"171":1,"172":1,"196":4,"197":1,"204":2,"212":2,"214":3,"228":2,"230":10,"232":2,"248":2,"253":3,"256":4}}],["pattern",{"2":{"150":5,"281":1}}],["path=$path",{"2":{"246":1}}],["path=none",{"2":{"137":1}}],["path=",{"2":{"75":1,"176":1}}],["path",{"2":{"42":1,"54":4,"65":3,"103":1,"120":1,"134":4,"135":2,"138":7,"148":1,"150":11,"159":2,"176":18,"184":3,"193":1,"230":5,"246":1,"253":2}}],["patch",{"2":{"13":1}}],["pageassertions",{"2":{"188":1}}],["pages",{"2":{"42":1}}],["page",{"2":{"17":2,"18":1,"97":5,"102":7,"103":12,"104":2,"188":1,"230":7}}],["pdocr",{"2":{"12":2,"31":1,"121":1,"124":1}}],["pyaudio",{"2":{"234":1}}],["pyautogui",{"2":{"47":1,"181":2,"184":38,"185":1}}],["py文件名称",{"2":{"230":1}}],["pyfrom",{"2":{"228":2}}],["pyflakes",{"2":{"155":1}}],["pyid2csv",{"2":{"211":1}}],["pyscreenshot",{"2":{"176":2}}],["py37",{"2":{"155":1}}],["pypackages",{"2":{"155":1}}],["pypinyin",{"2":{"51":1}}],["pypi",{"2":{"42":2,"45":1,"246":1}}],["pyenv",{"2":{"155":1}}],["pyconf",{"2":{"228":1}}],["pycodestyle",{"2":{"155":2}}],["pycharm",{"2":{"63":1,"82":1,"99":1,"109":1,"180":1,"301":3}}],["pycreeze",{"2":{"47":2}}],["py新增参数",{"2":{"57":1}}],["pytype",{"2":{"155":1}}],["pytest",{"2":{"54":1,"62":1,"69":3,"71":1,"79":3,"81":1,"89":3,"96":1,"106":3,"108":1,"115":3,"155":1,"169":2,"202":1,"207":2,"230":2,"249":1,"267":4,"272":2,"293":1}}],["pythonby",{"2":{"296":1}}],["pythonimport",{"2":{"222":1}}],["pythonif",{"2":{"185":1}}],["pythondfmwidget",{"2":{"193":1}}],["pythondef",{"2":{"54":2,"132":1,"134":2,"135":1,"139":1,"149":1}}],["pythonclick",{"2":{"296":1}}],["pythonclass",{"2":{"85":1,"137":1,"175":1,"190":1,"216":1,"217":1,"218":2,"219":1,"283":1,"284":1,"297":1,"298":1}}],["pythonconfig",{"2":{"229":1}}],["pythonconf",{"2":{"148":1}}],["pythonapp",{"2":{"148":1}}],["pythonelement",{"2":{"143":8}}],["pythonself",{"2":{"103":1,"144":1,"296":1}}],["python最强代码扫描工具",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["python3",{"2":{"42":1,"48":2,"54":1,"145":1,"150":1,"162":1,"176":1,"180":1,"184":1,"204":1,"234":1,"236":2,"256":1}}],["python",{"2":{"18":1,"19":2,"21":1,"27":1,"28":1,"42":4,"43":1,"44":1,"46":1,"52":1,"54":3,"65":1,"66":2,"75":2,"76":2,"85":2,"86":2,"94":1,"95":1,"103":2,"111":1,"112":2,"120":2,"138":2,"144":1,"145":1,"150":1,"151":1,"155":1,"165":1,"175":2,"176":1,"184":1,"186":2,"188":1,"193":2,"204":1,"216":1,"223":2,"234":2,"249":1,"270":1,"281":1,"283":1,"284":1}}],["pythonfrom",{"2":{"14":1,"35":2,"65":1,"102":2,"120":2,"125":1,"132":1,"138":2,"143":1,"182":3,"183":1,"185":1,"217":1,"229":1,"270":1,"271":1,"295":1,"296":1,"297":3,"298":4}}],["pyyaml",{"2":{"44":1}}],["pylint",{"2":{"16":3,"50":4,"51":1,"145":2,"150":2,"184":1,"274":1}}],["py",{"0":{"156":1,"272":1,"295":1},"1":{"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1},"2":{"12":1,"14":1,"16":1,"19":1,"27":1,"28":2,"32":1,"34":2,"35":2,"37":1,"42":4,"48":2,"50":1,"51":2,"52":1,"54":4,"55":1,"56":1,"57":1,"62":13,"65":3,"66":4,"69":2,"71":13,"72":11,"75":4,"76":4,"79":2,"81":13,"85":4,"86":4,"89":2,"93":4,"94":2,"95":2,"96":13,"97":11,"102":2,"103":4,"106":2,"108":13,"111":2,"112":4,"115":2,"132":1,"144":1,"148":1,"155":1,"156":1,"157":4,"158":1,"159":2,"160":2,"161":1,"162":4,"163":1,"165":4,"166":5,"167":1,"168":3,"169":1,"170":1,"171":1,"172":1,"173":5,"175":3,"188":1,"193":2,"194":1,"196":3,"197":1,"201":2,"204":2,"205":1,"209":2,"211":4,"212":2,"214":1,"216":1,"224":1,"227":2,"230":2,"236":1,"249":13,"251":1,"252":1,"253":2,"254":1,"255":1,"256":4,"257":1,"267":20,"270":2,"271":3,"272":4,"273":1,"281":2,"283":1,"284":1,"293":11,"301":1,"303":1}}],["范围识别",{"2":{"11":1}}],["3个remote远程对象",{"0":{"215":1},"1":{"216":1,"217":1,"218":1,"219":1}}],["3s",{"2":{"184":1}}],["3>right",{"2":{"145":1}}],["36",{"2":{"75":2}}],["3小时18分0秒",{"2":{"54":1}}],["300",{"2":{"184":1,"230":2}}],["30",{"0":{"53":1},"2":{"135":2,"274":1}}],["30+",{"2":{"41":1}}],["31",{"0":{"39":1}}],["37",{"2":{"21":1,"176":3}}],["3840x1080",{"2":{"230":1}}],["38",{"2":{"21":1}}],["3",{"0":{"11":1,"17":1,"27":1,"28":1,"29":1,"30":1,"31":2,"32":1,"33":1,"34":1,"36":1,"43":1,"50":1,"55":1,"130":1,"255":1,"256":1,"257":1,"267":1,"271":1,"278":1,"285":1,"297":1,"302":1},"1":{"256":1,"257":1},"2":{"17":1,"42":1,"46":1,"123":2,"128":2,"134":1,"137":1,"143":1,"145":3,"150":3,"155":1,"184":7,"196":1,"223":1,"230":2,"260":1,"283":1,"285":5,"286":1,"288":1,"292":1,"302":4}}],["下划线",{"2":{"249":1}}],["下发布",{"2":{"244":1}}],["下线cd",{"2":{"230":1}}],["下同",{"2":{"196":1,"212":1}}],["下都可以跑",{"2":{"185":1}}],["下有些应用的界面显示和功能本身存在一些差异",{"2":{"185":1}}],["下执行时会安装自研的键鼠操作服务",{"2":{"185":1}}],["下兼容适配",{"2":{"185":1}}],["下的键鼠操作方法无法使用",{"2":{"185":1}}],["下自动化主要问题是",{"2":{"185":1}}],["下面的远程执行功能同样支持",{"2":{"159":1}}],["下面介绍两个常用的用例执行的功能",{"2":{"157":1}}],["下个迭代可能就是",{"2":{"128":1}}],["下使用",{"2":{"58":1}}],["下获取窗口信息的方法",{"2":{"40":1}}],["下获取窗口信息功能模块中环境变量的问题",{"2":{"39":1}}],["下系统监视器使用",{"2":{"28":1}}],["下输入的方法区分中英文",{"2":{"27":1}}],["下",{"2":{"26":1,"48":1,"176":1,"184":1,"246":1}}],["下表现一致",{"2":{"26":1}}],["下表现和",{"2":{"26":1}}],["下窗管团队提供了新的接口",{"2":{"26":1}}],["下窗管返回的应用名称错误的问题",{"2":{"8":1}}],["下窗管返回的",{"2":{"7":1}}],["下报错",{"2":{"22":1}}],["下中文写入剪贴版问题",{"2":{"11":1}}],["下相对位移定位方案报错",{"2":{"10":1}}],["495",{"2":{"230":2}}],["47",{"2":{"193":1}}],["48",{"2":{"193":1}}],["4eea",{"2":{"178":1}}],["4103",{"2":{"75":1}}],["44aa",{"2":{"178":1}}],["44",{"2":{"20":1}}],["43",{"2":{"20":1}}],["400",{"2":{"150":1,"176":3}}],["40",{"2":{"19":1,"176":6,"274":1}}],["46",{"2":{"19":1}}],["4",{"0":{"10":1,"16":1,"21":1,"22":1,"23":2,"24":1,"25":1,"26":1,"30":1,"35":1,"49":1,"54":1,"131":1,"272":1,"286":1,"298":1,"303":1},"2":{"35":1,"42":1,"53":2,"127":1,"128":1,"134":1,"137":1,"155":1,"184":4,"260":1,"285":1,"286":3,"288":9,"303":2}}],["1>left",{"2":{"145":1}}],["1s",{"2":{"137":1}}],["1m",{"2":{"111":1,"112":1}}],["180",{"2":{"149":1}}],["18",{"0":{"41":1},"2":{"28":1}}],["168",{"2":{"214":4,"219":1,"230":2}}],["16",{"0":{"35":1,"42":1,"48":1,"58":1},"2":{"28":1,"274":1}}],["13",{"0":{"28":1,"37":1},"2":{"48":6,"162":6,"163":2,"197":2,"230":4,"256":4,"288":1}}],["175",{"2":{"230":1}}],["17",{"2":{"27":1,"31":1,"193":1,"288":1}}],["127",{"2":{"180":1}}],["120",{"2":{"176":1}}],["12",{"0":{"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"53":1,"54":1,"60":1},"2":{"230":1,"274":1,"288":3}}],["196",{"2":{"216":1,"217":1}}],["192",{"2":{"214":4,"216":1,"217":1,"219":1,"230":2}}],["1920",{"2":{"150":3,"176":2}}],["1920x1080",{"2":{"42":3,"230":2}}],["19",{"0":{"23":1,"57":1},"2":{"28":1}}],["1060",{"2":{"204":2}}],["1081333",{"2":{"178":1}}],["1080x1920",{"2":{"230":1}}],["1080",{"2":{"150":3}}],["100",{"2":{"155":1,"176":1,"230":4}}],["10000",{"2":{"135":1}}],["1000",{"2":{"27":1,"145":1}}],["1070",{"2":{"22":1,"23":1,"26":1}}],["10",{"0":{"15":1,"34":1,"35":1,"43":1,"55":1},"2":{"48":6,"52":2,"57":1,"137":1,"162":6,"163":3,"178":2,"197":2,"230":5,"256":4,"257":1,"288":1}}],["14",{"0":{"14":1,"19":1,"32":1,"54":1}}],["1",{"0":{"13":1,"19":1,"25":1,"33":1,"37":1,"39":1,"40":1,"41":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":2,"53":1,"54":2,"55":2,"56":2,"57":3,"58":2,"59":1,"60":2,"128":1,"137":1,"159":1,"162":1,"203":1,"234":1,"251":1,"253":1,"256":1,"265":1,"269":1,"276":1,"280":1,"283":1,"292":1,"295":1,"300":1},"2":{"41":1,"42":6,"46":5,"47":2,"48":2,"53":5,"57":1,"62":1,"66":1,"70":1,"71":1,"75":5,"76":1,"80":1,"81":1,"90":1,"96":1,"103":1,"107":1,"108":1,"111":1,"112":1,"116":1,"120":1,"123":1,"128":1,"134":4,"135":1,"137":4,"143":2,"145":8,"150":36,"162":1,"163":2,"165":2,"176":10,"180":1,"184":20,"194":5,"196":1,"214":5,"216":2,"217":2,"219":2,"223":2,"227":1,"230":19,"232":1,"248":1,"249":1,"256":1,"257":2,"260":2,"261":1,"270":2,"273":1,"283":5,"284":1,"285":1,"286":1,"287":1,"288":1,"295":1,"298":3,"300":3,"301":1,"302":1,"303":1}}],["1111",{"2":{"75":1}}],["116",{"2":{"75":1}}],["11",{"0":{"9":1,"31":1,"32":1,"33":1},"2":{"31":2,"178":3,"214":1,"230":2,"288":7}}],["15时14分09秒",{"2":{"178":1}}],["15",{"0":{"6":1,"7":1,"27":1,"36":1}}],["500",{"2":{"230":1}}],["50",{"2":{"230":1}}],["540",{"2":{"150":3}}],["5s",{"2":{"137":1}}],["537",{"2":{"75":2}}],["53",{"2":{"47":1,"212":1}}],["59",{"2":{"28":1}}],["55",{"2":{"19":2,"230":1}}],["51",{"2":{"19":1}}],["5",{"0":{"9":1,"15":2,"16":1,"17":1,"18":1,"19":1,"20":1,"22":1,"29":1,"39":1,"48":1,"273":1,"287":1,"304":1},"2":{"42":1,"75":1,"128":1,"134":1,"137":1,"163":1,"176":1,"230":3,"257":1,"287":2,"288":15}}],["mk",{"2":{"296":1}}],["m",{"2":{"180":1}}],["mp4",{"2":{"178":1}}],["mccabe",{"2":{"155":1}}],["ms",{"2":{"135":1}}],["msg=",{"2":{"76":1}}],["msg",{"2":{"8":1}}],["multiplier",{"2":{"150":16}}],["multiple=multiple",{"2":{"134":1,"176":2,"193":1}}],["multiple=true",{"2":{"134":1}}],["multiple=false",{"2":{"134":1,"193":1}}],["multiple",{"2":{"134":5,"138":3,"176":2,"193":1}}],["musicwidget",{"2":{"283":1}}],["music",{"2":{"35":2,"42":2,"48":3,"50":2,"52":1,"54":4,"94":2,"95":1,"134":1,"143":1,"149":2,"159":3,"162":2,"163":1,"168":4,"173":9,"178":3,"182":2,"212":4,"223":18,"230":8,"253":2,"256":1,"267":1,"271":1,"281":1,"283":1}}],["movie",{"2":{"281":1}}],["moveto",{"2":{"184":1}}],["move",{"2":{"132":1,"145":1,"184":16}}],["moverel",{"2":{"39":1,"184":1}}],["mode",{"2":{"176":6,"223":2}}],["modules",{"2":{"155":1}}],["modulenotfounderror",{"2":{"145":1,"176":1}}],["mouseup",{"2":{"184":1}}],["mousedown",{"2":{"184":1}}],["mousedownup=true",{"2":{"184":2}}],["mousemove",{"2":{"184":2}}],["mousekey",{"2":{"132":5,"145":2,"176":3,"182":3,"183":2,"184":1}}],["mouse",{"2":{"132":1,"145":3,"176":1,"182":1,"183":1,"184":6}}],["mozilla",{"2":{"75":1}}],["mypy",{"2":{"155":1}}],["myappwidget",{"2":{"85":3,"86":2}}],["myappassert",{"2":{"66":2,"76":2,"86":2,"103":2,"112":2,"175":5}}],["mycase",{"2":{"62":3,"66":3,"71":3,"72":3,"76":2,"81":3,"86":3,"93":2,"95":3,"96":3,"97":3,"103":3,"108":3,"112":3,"166":2,"175":1,"218":1,"249":3}}],["my",{"2":{"62":4,"65":1,"66":4,"69":1,"70":2,"71":4,"72":4,"73":1,"76":2,"79":1,"80":2,"81":4,"85":4,"86":5,"89":1,"90":2,"93":2,"95":3,"96":4,"97":4,"98":1,"102":1,"103":4,"106":1,"107":2,"108":4,"112":4,"115":1,"116":2,"166":1,"167":1,"171":1,"172":1,"175":5,"196":1,"197":1,"218":1,"219":1,"232":1,"247":1,"248":2}}],["menu",{"2":{"184":2}}],["methods",{"2":{"145":1}}],["method",{"2":{"76":1}}],["meant",{"2":{"28":1}}],["message=str",{"2":{"184":1}}],["message",{"2":{"27":1,"159":1,"162":1,"184":11,"253":1,"256":1}}],["message方法",{"2":{"5":1}}],["mixin",{"2":{"270":1}}],["mips64",{"2":{"204":2}}],["middleclick",{"2":{"184":1}}],["middle",{"2":{"145":1,"184":2}}],["minorversion",{"2":{"28":1,"204":1}}],["mikigo",{"2":{"13":6,"14":6,"15":4,"16":8,"17":10,"18":5,"19":2,"20":3,"21":5,"22":1,"23":2,"24":1,"25":2,"27":3,"28":1,"30":2,"31":1,"32":3,"33":3,"34":3,"35":12,"36":3,"37":4,"38":3,"39":5,"40":2,"41":3,"42":3,"43":2,"44":3,"45":1,"46":2,"47":4,"48":9,"49":1,"50":6,"51":9,"52":5,"53":5,"54":18,"55":12,"56":2,"57":12,"58":11,"59":4,"60":5,"85":1,"142":1,"145":1,"150":1,"184":1,"214":1,"230":2}}],["make",{"2":{"296":1}}],["master",{"2":{"214":1,"230":1}}],["map",{"2":{"193":1}}],["magic",{"2":{"155":2}}],["many",{"2":{"145":3}}],["manager",{"2":{"85":2,"86":2,"120":1,"150":1,"176":1,"265":1,"267":1,"270":2,"293":1,"295":2,"296":1,"297":3,"298":8,"302":1}}],["manage",{"0":{"156":1},"1":{"157":1,"158":1,"159":1,"160":1,"161":1,"162":1,"163":1,"164":1,"165":1,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1},"2":{"19":1,"34":1,"35":2,"42":4,"48":2,"51":1,"52":1,"54":3,"57":1,"62":1,"69":1,"71":1,"79":1,"81":1,"89":1,"96":1,"106":1,"108":1,"115":1,"156":1,"157":4,"158":1,"159":2,"160":2,"161":1,"162":4,"163":1,"165":2,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"194":1,"196":3,"197":1,"205":1,"209":2,"211":2,"212":2,"214":1,"224":1,"236":1,"249":1,"251":1,"252":1,"253":2,"254":1,"255":1,"256":4,"257":1,"267":1,"281":1}}],["max",{"2":{"135":2,"159":2,"176":8,"230":4,"253":2}}],["matching",{"2":{"137":5}}],["match",{"2":{"134":11,"137":4,"138":6,"145":1,"176":12,"230":4}}],["matchtemplate",{"2":{"134":1}}],["mainwindow",{"2":{"141":1}}],["main",{"2":{"120":1,"138":1,"204":1,"216":1,"217":1,"219":1}}],["markdown",{"2":{"155":1}}],["mark",{"2":{"54":1,"169":1,"202":1,"207":1,"222":2,"223":1,"230":2}}],["maybe",{"2":{"28":1}}],["macos",{"2":{"13":1}}],["md",{"2":{"16":1,"58":1,"60":1}}],["icon",{"2":{"223":2}}],["ignore",{"2":{"155":2,"223":1,"230":1}}],["ignored",{"2":{"155":1}}],["iso",{"2":{"277":1}}],["isinstance",{"2":{"120":2,"145":1,"150":10,"176":5,"270":1}}],["is",{"2":{"120":3,"134":1,"137":1,"150":10,"155":4,"176":34,"184":3,"185":4,"270":2}}],["issues",{"0":{"2":1},"2":{"2":2,"16":1,"19":2,"20":2,"21":2,"26":6,"27":1,"28":4,"183":1}}],["i",{"2":{"120":1,"145":6,"148":2,"150":14}}],["ifixed",{"2":{"159":1,"205":3,"230":1,"253":1}}],["if=",{"2":{"111":1}}],["if",{"2":{"75":1,"120":6,"134":2,"138":1,"145":20,"148":1,"150":43,"176":68,"184":19,"185":2,"204":5,"216":1,"217":1,"219":1,"270":3}}],["items",{"2":{"75":1,"120":1,"142":1,"176":2}}],["it",{"2":{"55":1,"155":1}}],["id同步到csv文件",{"2":{"211":1,"230":1}}],["id4",{"2":{"170":1}}],["id3",{"2":{"170":1}}],["id2",{"2":{"170":1}}],["id1",{"2":{"170":1}}],["idea",{"2":{"155":1}}],["identifier",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["ids",{"2":{"75":4}}],["ids=none",{"2":{"75":1}}],["id=1",{"2":{"75":1}}],["id",{"0":{"211":1},"2":{"31":2,"37":1,"66":1,"75":3,"76":1,"86":1,"103":1,"112":1,"148":8,"150":35,"159":4,"171":1,"172":1,"196":4,"197":1,"200":4,"201":1,"211":6,"230":3,"253":4,"285":1}}],["ing",{"2":{"162":1,"256":1}}],["indent",{"2":{"155":3}}],["indexerror",{"2":{"145":2,"150":2}}],["index",{"2":{"145":6,"178":1,"180":2}}],["index=0",{"2":{"145":3}}],["in",{"2":{"75":1,"120":1,"134":2,"137":2,"145":2,"148":2,"149":1,"150":15,"155":3,"176":8,"184":7,"204":4,"223":5,"296":1,"297":3,"301":1}}],["inspect",{"2":{"191":1}}],["insert",{"2":{"184":1}}],["insecurerequestwarning",{"2":{"75":2}}],["install",{"2":{"42":1,"68":1,"78":1,"88":1,"105":1,"114":1,"152":1,"246":2}}],["interval=interval",{"2":{"184":5}}],["interval=0",{"2":{"184":4}}],["interval",{"2":{"184":5}}],["inter",{"2":{"145":3}}],["interrupt=false",{"2":{"94":1,"150":6,"176":2}}],["interface",{"2":{"65":3,"150":1}}],["int32",{"2":{"94":1}}],["int",{"2":{"31":1,"134":6,"135":3,"138":1,"139":4,"145":2,"148":2,"150":47,"176":18,"184":7,"270":1}}],["input",{"2":{"27":1,"102":1,"103":1,"184":1}}],["iniapp",{"2":{"212":1}}],["inipms",{"2":{"196":3}}],["ini中client",{"2":{"162":1,"256":1}}],["ini配置文件",{"2":{"69":1,"79":1,"89":1,"106":1,"115":1}}],["ini里面的配置",{"2":{"62":1,"71":1,"81":1,"96":1,"108":1,"249":1}}],["init",{"2":{"27":1,"62":3,"71":3,"72":3,"75":1,"81":3,"93":1,"96":3,"97":3,"102":2,"108":3,"144":1,"145":1,"150":1,"155":1,"166":1,"249":3,"267":6,"270":5,"271":2,"293":1,"295":2,"298":6}}],["ini",{"2":{"26":1,"35":1,"42":4,"48":1,"62":3,"69":1,"70":1,"71":3,"72":1,"79":1,"80":1,"81":3,"89":1,"90":1,"96":3,"97":1,"103":2,"106":1,"107":1,"108":3,"115":1,"116":1,"134":1,"148":1,"149":2,"157":2,"160":1,"162":1,"192":1,"194":3,"196":1,"209":2,"211":1,"212":1,"214":2,"227":2,"228":1,"230":1,"232":1,"248":1,"249":3,"254":1,"256":1,"267":6,"272":1,"273":1,"281":1,"293":2}}],["info",{"2":{"7":1,"28":1,"58":2,"65":2,"85":1,"150":51,"159":2,"176":17,"190":1,"192":2,"193":1,"230":1,"253":2}}],["img",{"2":{"296":1}}],["imports",{"2":{"184":1}}],["import",{"2":{"14":1,"35":2,"60":2,"65":2,"66":3,"75":8,"76":3,"85":4,"86":4,"94":1,"95":2,"102":2,"103":4,"111":2,"112":3,"120":4,"125":1,"132":1,"138":6,"143":1,"145":13,"150":12,"175":3,"176":18,"182":4,"183":1,"184":11,"185":1,"193":2,"204":2,"216":1,"217":1,"223":1,"228":2,"229":1,"270":6,"271":1,"295":1,"296":1,"297":4,"298":6}}],["imagergb",{"2":{"137":1}}],["imageutils",{"2":{"176":8}}],["imageutil",{"2":{"51":1}}],["image",{"2":{"13":1,"24":1,"25":2,"26":1,"31":1,"51":1,"54":3,"120":3,"132":2,"134":13,"135":2,"137":7,"138":14,"176":8,"184":3,"185":2,"193":4,"223":1,"230":4,"267":1,"270":1}}],["ip=",{"2":{"216":1,"217":1,"219":1}}],["ipynb",{"2":{"155":1}}],["ip",{"2":{"12":2,"17":1,"48":1,"52":1,"120":2,"123":3,"138":1,"162":1,"179":1,"180":1,"214":5,"227":1,"230":10,"256":1,"273":1,"281":2}}],["w5821",{"2":{"204":2}}],["wh",{"2":{"176":4}}],["when",{"2":{"155":4}}],["w=100",{"2":{"176":2}}],["wwininfo",{"2":{"150":11}}],["www",{"2":{"102":1,"103":2,"230":2}}],["w和h来定位元素在屏幕中的位置",{"2":{"150":1}}],["w2",{"2":{"148":2}}],["w",{"2":{"51":2,"130":2,"134":3,"138":2,"144":2,"145":2,"149":2,"150":38,"176":20,"184":1}}],["wininfo",{"2":{"150":4}}],["windowwidget",{"2":{"222":1,"223":1}}],["windowactivate",{"2":{"150":1}}],["windowmove",{"2":{"150":1}}],["windows",{"2":{"13":1,"137":1,"150":6,"176":1}}],["window",{"2":{"7":1,"28":1,"150":221,"176":2}}],["with",{"2":{"137":1,"155":1,"184":1}}],["width",{"2":{"54":1,"137":2,"139":2,"150":28,"155":1,"184":4}}],["widget",{"0":{"295":1},"2":{"47":1,"50":1,"62":4,"65":6,"66":4,"71":4,"72":3,"81":4,"85":7,"86":1,"94":2,"95":2,"96":4,"97":3,"108":4,"111":2,"112":2,"134":5,"176":37,"182":2,"192":1,"193":3,"216":1,"230":1,"249":4,"267":6,"270":2,"271":1,"281":5,"283":5,"284":3,"293":7,"296":1,"297":2,"298":5}}],["walk",{"2":{"176":2}}],["wait",{"2":{"134":1,"230":1}}],["warnings",{"2":{"75":1,"155":1}}],["warning",{"2":{"27":2}}],["wayland上",{"2":{"184":1}}],["waylandwindowinfo",{"2":{"28":1,"150":7}}],["wayland",{"0":{"185":1},"2":{"7":1,"8":1,"10":1,"11":1,"19":1,"22":1,"26":3,"27":1,"28":1,"39":2,"40":2,"43":1,"47":1,"48":1,"58":1,"60":1,"87":1,"150":3,"181":1,"184":6,"185":10,"204":3,"241":1,"243":1}}],["webassert",{"2":{"103":2,"175":1,"188":1}}],["web文件中不用写任何东西",{"2":{"97":1}}],["webui",{"0":{"186":1},"1":{"187":1,"188":1},"2":{"97":3,"102":3,"103":1,"175":1,"186":1,"188":1}}],["web",{"0":{"104":1},"1":{"105":1,"106":1,"107":1},"2":{"14":1,"17":2,"18":1,"75":1,"97":2,"98":1,"103":3,"104":2,"186":1,"187":1,"230":1,"242":1}}],["wl",{"2":{"11":1,"184":1}}],["修改为失败之后会关闭文件选择框",{"2":{"60":1}}],["修改为",{"2":{"60":1,"72":1,"97":1}}],["修改失败用例回溯日志为详细级别",{"2":{"55":1}}],["修改工程名称为",{"2":{"53":1}}],["修改",{"0":{"72":1,"97":1},"2":{"11":1,"13":1,"15":1,"27":1,"49":1}}],["修改部署客户端设备youqu环境时",{"2":{"5":1}}],["修复的这些用例可能还不稳定",{"2":{"205":1}}],["修复后的这些用例在本地调试的时候我们不希望继续跳过",{"2":{"205":1}}],["修复持续集成流水线中没有安装",{"2":{"56":1}}],["修复自动生成",{"2":{"54":1}}],["修复单独运行方法时无日志输出的",{"2":{"52":1}}],["修复youqu",{"2":{"50":1}}],["修复运行时程序退出",{"2":{"50":1}}],["修复1060",{"2":{"48":1}}],["修复子项目",{"2":{"41":1}}],["修复子项目单独需要三方包",{"2":{"41":1}}],["修复了第一次失败不会关闭文件选择框的问题",{"2":{"59":1}}],["修复了三方库",{"2":{"59":1}}],["修复了用例收集阶段报错看不到详细信息的问题",{"2":{"58":1}}],["修复了部分机器上",{"2":{"58":1}}],["修复了同一应用内多个",{"2":{"58":1}}],["修复了在没有指定应用名称执行时",{"2":{"57":1}}],["修复了执行进度未计算跳过用例的问题",{"2":{"55":1}}],["修复了一些",{"2":{"51":1}}],["修复了wayland下偶现找不到",{"2":{"43":1}}],["修复了特殊场景下",{"2":{"39":1}}],["修复了远程执行传入",{"2":{"36":1}}],["修复了",{"2":{"35":1,"37":1,"39":2,"45":1,"53":1,"55":1,"57":1,"58":2}}],["修复了键盘",{"2":{"35":1}}],["修复了不同的",{"2":{"34":1}}],["修复无法导出",{"2":{"35":1}}],["修复无法连续多次调用对远程终端的键鼠操作",{"2":{"16":1}}],["修复反向同步标签",{"2":{"33":1}}],["修复更新太耗时",{"2":{"32":1}}],["修复某些机型下",{"2":{"32":1}}],["修复同一个用例",{"2":{"32":1}}],["修复在低版本系统上安装的",{"2":{"29":1,"30":1}}],["修复用例收集阶段报错",{"2":{"55":1}}],["修复用例收集数量为",{"2":{"28":1}}],["修复用例在",{"2":{"54":1}}],["修复用例失败截图添加到测试报告时报错的问题",{"2":{"9":1}}],["修复通过标签批量执行时",{"2":{"27":1}}],["修复偶现测试报告生成阶段报错",{"2":{"26":1}}],["修复域管环境下",{"2":{"18":1}}],["修复基于",{"2":{"18":1}}],["修复从",{"2":{"17":1,"35":1}}],["修复实例化远程类时",{"2":{"17":1}}],["修复使用远程执行命令时",{"2":{"17":1}}],["修复生成测试报告阶段",{"2":{"15":1}}],["修复远程执行数据回填过程中报",{"2":{"26":1}}],["修复远程调用报错后",{"2":{"17":1}}],["修复远程调用返回",{"2":{"16":1}}],["修复远程调用时",{"2":{"14":1}}],["修复远程交互控制测试机注销后",{"2":{"11":1}}],["修复内网文档不能加载",{"2":{"14":1}}],["修复统计用例和方法数量功能在子项目为",{"2":{"18":1}}],["修复统计",{"2":{"13":2}}],["修复服务器系统获取显示协议错误的问题",{"2":{"12":1}}],["修复测试单驱动执行报错的问题",{"2":{"12":1}}],["修复测试单驱动收集用例数量为",{"2":{"8":1}}],["修复",{"2":{"7":1,"8":1,"13":2,"14":1,"17":1,"19":2,"20":2,"21":2,"22":1,"25":1,"26":2,"28":2,"33":1,"34":1,"35":1,"41":1,"42":1,"43":1,"46":1,"47":2,"48":1,"50":1,"52":2,"53":2,"54":1,"55":1}}],["71f6",{"2":{"178":1}}],["7",{"0":{"7":1,"27":1,"46":1},"2":{"155":1,"230":1,"288":7}}],["81",{"2":{"212":3,"230":2}}],["8000",{"2":{"180":1}}],["8a6f",{"2":{"178":1}}],["8810",{"2":{"178":1}}],["8889",{"2":{"138":1,"230":1}}],["8890",{"2":{"120":1,"230":1}}],["83",{"2":{"75":1}}],["8",{"0":{"6":1,"45":1},"2":{"24":2,"28":1,"48":6,"52":1,"145":1,"150":1,"162":6,"163":2,"176":1,"184":1,"197":2,"204":1,"214":1,"230":8,"256":4,"288":1}}],["提高兼容性测试效率",{"2":{"281":1}}],["提高代码利用率",{"2":{"274":1}}],["提高架构专业性",{"2":{"274":1}}],["提取不同的部分生成一张新的图片",{"2":{"132":1}}],["提供通用的接口能力",{"2":{"281":1}}],["提供所有自动化测试所需要的底层功能",{"2":{"263":1}}],["提供更友好化的错误提示",{"2":{"243":1}}],["提供用例标签化管理",{"2":{"243":1}}],["提供统一的接口",{"2":{"243":1}}],["提供的一个全局对象",{"2":{"214":1}}],["提供的一些参数选项",{"2":{"162":1,"256":1}}],["提供的一些常用的参数选项",{"2":{"159":1}}],["提供了本地执行",{"2":{"251":1}}],["提供了丰富的配置和命令行参数",{"2":{"156":1}}],["提供了对",{"2":{"67":1}}],["提供一个全局默认的对象",{"2":{"103":1,"104":1}}],["提供配置项可以指定浏览器对应的路径",{"2":{"17":1,"103":1,"104":1}}],["提升",{"2":{"53":1}}],["提升精准度",{"2":{"5":1}}],["提示",{"2":{"275":1}}],["提示不是问题",{"2":{"27":1}}],["提示找不到",{"2":{"13":1}}],["提交地址",{"2":{"2":1}}],["提交",{"0":{"2":1}}],["b2ae5ab1d3a5",{"2":{"178":1}}],["be",{"2":{"155":1}}],["blocks",{"2":{"155":1}}],["black",{"2":{"154":1,"155":5}}],["bzr",{"2":{"155":1}}],["b",{"2":{"150":48}}],["bdata",{"2":{"137":2}}],["big",{"2":{"134":1,"137":1}}],["binary",{"2":{"138":3}}],["bin",{"2":{"5":1,"42":1,"85":1,"103":1,"145":1,"150":1,"176":1,"184":1,"204":1,"230":1,"246":2,"270":1,"271":1,"295":1,"298":1}}],["bbox=screen",{"2":{"134":1}}],["bbox",{"2":{"134":6,"138":2,"176":30}}],["boundary",{"2":{"150":6}}],["bottom",{"2":{"149":2,"150":20}}],["bool",{"2":{"134":2,"138":1,"145":1,"176":5,"184":3,"185":1}}],["box",{"2":{"102":1,"103":1}}],["bs=",{"2":{"111":1}}],["brazil",{"2":{"230":1}}],["branch",{"2":{"12":1,"230":1}}],["br",{"2":{"230":1}}],["browse",{"2":{"212":1,"230":1}}],["browser",{"2":{"103":6,"142":1,"230":2}}],["break",{"2":{"150":2}}],["baidu",{"2":{"102":5,"103":6,"230":2}}],["backspace",{"2":{"184":2}}],["back",{"2":{"57":1,"178":1,"211":1,"212":1}}],["basic",{"2":{"265":1}}],["basicenv",{"2":{"235":3}}],["baseline",{"2":{"200":1}}],["based",{"2":{"150":1}}],["basepage",{"2":{"102":4}}],["baseapi",{"2":{"75":4}}],["basecase",{"2":{"66":4,"76":4,"86":4,"95":2,"103":4,"112":4,"175":3,"218":1,"223":1,"297":3,"298":2}}],["basewidget",{"2":{"65":4,"85":5,"270":1,"295":1,"296":2,"298":7,"302":2}}],["base",{"0":{"295":1},"2":{"16":1,"62":2,"65":2,"66":3,"71":2,"72":2,"75":9,"76":2,"81":2,"85":3,"86":2,"93":1,"95":1,"96":2,"97":2,"102":2,"103":2,"108":2,"112":3,"166":1,"175":1,"227":1,"249":2,"267":1,"270":1,"273":1,"281":1,"293":1}}],["bash",{"2":{"5":1,"50":1,"65":1,"70":2,"73":1,"80":2,"90":2,"98":1,"107":2,"116":2,"225":1,"232":2,"234":1,"236":1,"248":3}}],["btn",{"2":{"54":3,"85":3,"94":1,"134":2,"148":2,"149":3,"150":68,"223":2,"271":1,"296":1}}],["but",{"2":{"155":1}}],["button=cls",{"2":{"184":2}}],["button=1",{"2":{"143":2,"145":1,"184":2}}],["buttoncenter",{"2":{"150":1,"176":2,"270":2}}],["button",{"2":{"54":1,"143":1,"145":5,"148":1,"150":124,"176":1,"184":6,"267":1,"270":2}}],["buck",{"2":{"155":1}}],["build",{"2":{"155":2,"159":2,"162":1,"230":1,"253":2,"256":1}}],["bug",{"2":{"13":1,"32":1,"52":1,"53":1,"200":3,"303":1}}],["by",{"2":{"13":1,"16":1,"17":1,"19":5,"20":2,"21":2,"75":3,"76":2,"85":2,"86":1,"94":2,"95":1,"111":1,"112":1,"134":3,"137":3,"138":6,"145":7,"149":1,"150":10,"155":3,"176":3,"216":3,"223":7,"271":2,"283":1,"284":1,"296":5,"298":4}}],["rdog",{"0":{"216":1},"2":{"216":4}}],["rgx",{"2":{"155":1}}],["rgb",{"2":{"137":3}}],["r",{"2":{"145":1,"150":6,"216":2,"217":2,"219":2,"303":1}}],["round",{"2":{"176":1}}],["root",{"2":{"143":2,"144":1,"145":5,"214":3,"216":1,"217":1,"219":1,"247":1}}],["role",{"2":{"75":1}}],["roleids",{"2":{"75":2}}],["roleids=",{"2":{"75":1}}],["rb",{"2":{"138":8}}],["rightviewwidget",{"2":{"296":1,"297":1,"298":3}}],["rightclick",{"2":{"184":1}}],["right",{"2":{"125":1,"132":1,"145":3,"149":2,"150":29,"184":4,"293":2,"296":1,"298":2}}],["rctl",{"0":{"217":1,"218":1,"219":1},"1":{"218":1},"2":{"94":1,"217":3,"219":3}}],["rar",{"2":{"176":1}}],["rather",{"2":{"155":1}}],["rate=rate",{"2":{"176":2}}],["rate=0",{"2":{"137":1,"193":1}}],["rate",{"2":{"24":1,"25":2,"26":1,"134":9,"135":2,"137":2,"138":3,"176":7,"193":1,"230":1}}],["range",{"2":{"134":1,"135":2,"150":2,"184":3}}],["randomly",{"2":{"137":2}}],["random",{"2":{"76":2,"137":4}}],["raise",{"2":{"120":2,"134":2,"138":1,"145":6,"150":13,"176":41,"270":1}}],["ru",{"2":{"230":1}}],["rules",{"2":{"155":1}}],["ruff",{"0":{"151":1},"1":{"152":1,"153":1,"154":1,"155":1},"2":{"16":1,"21":1,"69":2,"79":2,"89":2,"106":2,"115":2,"151":1,"152":1,"154":1,"155":5}}],["ruff代码检查",{"2":{"15":1}}],["run",{"2":{"5":1,"12":1,"17":1,"35":2,"42":4,"44":1,"48":3,"52":1,"54":1,"94":1,"111":1,"145":1,"148":2,"150":6,"157":2,"158":2,"159":2,"160":1,"165":2,"166":1,"167":1,"168":1,"169":1,"170":1,"171":1,"172":1,"173":1,"176":2,"184":3,"196":2,"205":1,"214":1,"224":1,"230":2,"236":1,"252":1,"253":2}}],["rm",{"2":{"13":2,"239":1}}],["references",{"2":{"301":1}}],["refactor",{"2":{"301":3}}],["rename",{"2":{"301":1}}],["reboot",{"2":{"223":5}}],["reverse",{"2":{"184":1}}],["reversed",{"2":{"184":1}}],["relative",{"2":{"184":1}}],["rel",{"2":{"184":13}}],["release",{"2":{"42":1,"60":1}}],["really",{"2":{"176":3}}],["real",{"2":{"176":5}}],["read",{"2":{"120":1,"138":2,"148":1,"150":4,"176":1,"204":2}}],["readme",{"2":{"58":1,"62":3,"71":3,"72":2,"81":3,"93":1,"96":3,"97":2,"108":3,"249":3}}],["rewrite",{"2":{"155":1}}],["recovery",{"2":{"223":1}}],["record",{"2":{"42":6,"159":2,"178":1,"194":6,"230":5,"253":2}}],["recur",{"2":{"145":3}}],["recursive=false",{"2":{"145":1,"176":2}}],["recursive=true",{"2":{"145":1}}],["recursive=recursive",{"2":{"145":1}}],["recursive",{"2":{"145":1,"176":4}}],["re",{"2":{"145":2,"150":15}}],["register",{"2":{"120":2,"138":2}}],["repeat",{"2":{"159":2,"184":1,"230":1,"253":2}}],["replace",{"2":{"145":1,"204":2}}],["reply",{"2":{"94":1}}],["report",{"2":{"12":8,"55":1,"159":2,"162":2,"178":2,"180":4,"194":1,"197":1,"198":2,"211":1,"212":2,"230":17,"253":2,"256":2}}],["removed",{"2":{"200":2,"206":2}}],["remotewidget",{"2":{"94":1,"95":2,"216":3,"217":3,"218":2,"219":2}}],["remotectl",{"2":{"94":1,"216":1,"217":1}}],["remote",{"0":{"216":1,"217":1,"219":1},"1":{"218":1},"2":{"12":5,"42":1,"44":1,"48":4,"50":1,"93":1,"94":6,"95":3,"161":2,"162":5,"163":1,"197":1,"216":6,"217":5,"218":3,"219":3,"230":2,"255":2,"256":5,"257":1}}],["remark",{"2":{"75":3}}],["remark=none",{"2":{"75":1}}],["ret",{"2":{"75":6}}],["returned",{"2":{"137":1}}],["return",{"2":{"65":2,"75":5,"120":7,"132":1,"134":2,"138":1,"139":1,"144":4,"145":25,"148":1,"150":61,"176":9,"184":37,"188":1,"193":2,"204":11}}],["retry=network",{"2":{"176":4}}],["retry=false",{"2":{"144":1,"145":1}}],["retry",{"2":{"28":1,"150":5,"176":10,"230":3}}],["requestdock",{"2":{"94":1}}],["requestx",{"2":{"77":1}}],["requests",{"2":{"1":1,"75":5,"77":1,"234":1}}],["requirement",{"2":{"44":1,"54":1,"234":7}}],["rerun",{"2":{"42":2,"159":2,"194":2,"230":4,"253":2}}],["res这个目录下生成一张临时的图",{"2":{"176":1}}],["restart",{"2":{"162":1,"256":1}}],["restructuredtext",{"2":{"155":1}}],["respect",{"2":{"155":1}}],["response",{"2":{"76":1}}],["res",{"2":{"62":3,"71":3,"72":2,"81":3,"93":1,"96":3,"97":2,"108":3,"120":8,"134":2,"176":21,"193":1,"249":3,"267":5,"281":1,"293":3}}],["resolution",{"2":{"42":4,"159":2,"176":9,"230":1,"253":2}}],["result",{"2":{"28":1,"54":1,"145":7,"150":7,"176":4,"178":1}}],["rpc服务器链接失败",{"2":{"138":1}}],["rpc服务端部署",{"0":{"121":1}}],["rpc",{"0":{"138":1},"2":{"11":1,"12":2,"31":1,"46":1,"52":1,"119":5,"121":1,"123":2,"124":1,"138":6,"213":2,"220":1}}],["cd",{"2":{"248":1}}],["cdn",{"2":{"39":1}}],["cfg",{"2":{"204":1}}],["cts",{"2":{"200":1}}],["ctrl",{"2":{"50":1,"182":3,"184":3,"217":2,"218":2,"219":1,"303":1}}],["cypress",{"2":{"186":2}}],["c0103",{"2":{"145":1}}],["c++",{"2":{"138":1}}],["create",{"2":{"75":1,"76":1,"111":1,"112":1}}],["cn",{"2":{"75":1}}],["csrf",{"2":{"75":5}}],["csv文件里面标记了",{"2":{"230":1}}],["csv文件里面标记了skip跳过的用例不生效",{"2":{"159":1,"253":1}}],["csv文件名称为music",{"2":{"212":1,"230":1}}],["csv文件格式",{"0":{"208":1}}],["csvctl",{"2":{"34":1,"209":2,"211":3,"230":1}}],["csv",{"0":{"211":1,"212":1},"2":{"17":1,"22":1,"28":1,"32":1,"35":3,"37":1,"53":1,"54":1,"58":1,"62":1,"71":1,"72":1,"81":1,"96":1,"97":1,"108":1,"156":2,"169":1,"201":9,"202":2,"203":1,"204":1,"205":2,"207":2,"208":1,"209":5,"211":6,"212":7,"230":8,"243":1,"249":1,"281":5,"285":9,"288":2,"293":1}}],["curl",{"2":{"54":1}}],["currently",{"2":{"155":1}}],["current",{"2":{"49":1,"69":1,"79":1,"89":1,"106":1,"115":1,"120":1,"138":1,"184":6}}],["custom",{"2":{"46":1,"145":2,"150":3,"176":5}}],["c",{"2":{"48":2,"50":1,"162":3,"163":1,"182":3,"184":10,"197":1,"256":2}}],["cv2",{"2":{"138":1}}],["cv",{"2":{"41":2,"134":1,"138":1}}],["cpu",{"2":{"40":3,"137":1,"204":7}}],["camera",{"2":{"281":1}}],["call",{"2":{"58":1}}],["case\\t",{"2":{"234":2,"235":1}}],["cases",{"2":{"230":1,"281":3}}],["caselib",{"2":{"212":1,"230":3}}],["case",{"2":{"34":1,"42":6,"54":1,"62":3,"66":5,"71":3,"72":3,"76":4,"81":3,"86":4,"93":2,"95":4,"96":3,"97":3,"103":4,"108":3,"112":5,"134":1,"159":5,"166":2,"168":1,"173":4,"175":2,"194":5,"209":3,"218":1,"230":13,"249":3,"253":5,"267":3,"293":2,"297":1,"298":1}}],["cache",{"2":{"28":1,"120":3,"155":3,"176":8,"230":1}}],["cicd",{"2":{"42":1,"200":3,"209":4}}],["ci",{"2":{"28":1,"48":1,"52":1,"54":2,"55":1,"56":1,"57":1,"159":1,"243":1,"253":1,"274":1,"277":1,"286":1}}],["chinese",{"2":{"184":3}}],["childrenlimit",{"2":{"145":1}}],["children",{"2":{"143":1,"145":5}}],["child",{"2":{"143":1,"144":1,"145":1}}],["ch",{"2":{"120":2,"176":2,"184":2}}],["chrome",{"2":{"75":1}}],["chromium",{"2":{"17":1,"103":1,"104":1}}],["checkpoints",{"2":{"155":1}}],["check",{"2":{"28":1,"75":1,"137":1,"145":2,"153":2,"184":3,"274":1}}],["clear",{"2":{"184":1}}],["clean",{"2":{"159":1,"230":3,"253":1}}],["close",{"2":{"138":2,"184":1}}],["clone",{"2":{"42":1,"230":1}}],["cls",{"2":{"134":1,"135":1,"137":1,"176":3,"184":64,"193":2}}],["cli",{"2":{"192":1,"230":1}}],["clients",{"2":{"162":3,"230":1,"256":3}}],["client",{"2":{"48":1,"120":1,"138":3,"162":3,"230":5,"256":3}}],["click",{"2":{"14":1,"85":4,"86":1,"94":2,"95":1,"102":2,"103":1,"125":3,"132":3,"143":1,"145":12,"149":2,"182":3,"184":18,"190":1,"193":1,"216":5,"223":4,"271":3,"283":1,"284":1,"296":5,"298":4}}],["classname",{"2":{"148":1,"150":4}}],["classmethod",{"2":{"137":1,"176":3,"184":33,"193":1}}],["class",{"2":{"18":1,"65":2,"66":2,"75":2,"76":2,"85":2,"86":2,"94":1,"95":1,"102":2,"103":2,"111":1,"112":2,"120":1,"138":1,"144":1,"145":1,"150":1,"165":1,"175":2,"176":1,"184":2,"188":1,"192":3,"193":2,"216":1,"217":1,"222":1,"223":2,"229":1,"230":3,"270":2,"271":2,"295":1,"296":1,"297":3,"298":4}}],["center",{"2":{"13":1,"14":1,"25":1,"31":1,"54":1,"125":1,"144":2,"145":4,"148":1,"149":2,"150":31,"176":1,"267":1,"270":2,"271":1,"296":1}}],["ccrazypeter",{"2":{"12":1,"13":1}}],["col",{"2":{"200":1}}],["color",{"2":{"176":6}}],["coffeescript",{"2":{"159":1,"162":1,"256":1}}],["core",{"2":{"278":1,"281":1,"285":2}}],["coredump",{"2":{"59":1}}],["corner",{"2":{"145":4}}],["co",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["coding",{"2":{"145":1,"150":1,"176":1,"184":1,"204":1}}],["code是否为yes都会发送代码到测试机",{"2":{"162":1,"230":1,"256":1}}],["codes",{"2":{"155":1}}],["code=0",{"2":{"76":1}}],["code",{"2":{"16":1,"75":1,"155":6,"162":1,"230":1,"256":1}}],["coordinates",{"2":{"137":2}}],["cookie0",{"2":{"75":2}}],["cookie",{"2":{"75":8}}],["count=1",{"2":{"111":1}}],["count",{"2":{"52":1,"54":2,"176":2}}],["contain",{"2":{"192":1,"230":1}}],["container",{"2":{"178":2}}],["content=content",{"2":{"76":1}}],["content",{"2":{"75":4,"76":1}}],["control",{"2":{"62":1,"71":1,"72":1,"81":1,"96":1,"97":1,"108":1,"249":1}}],["connection",{"2":{"75":1}}],["conftest",{"0":{"272":1},"2":{"62":1,"69":1,"71":1,"72":1,"79":1,"81":1,"89":1,"96":1,"97":1,"106":1,"108":1,"115":1,"249":1,"267":2,"272":4,"293":1}}],["configparser",{"2":{"148":1,"150":5}}],["config",{"2":{"62":2,"71":2,"72":2,"75":5,"81":2,"96":2,"97":2,"103":2,"108":2,"145":6,"148":1,"150":13,"176":3,"185":1,"193":1,"214":1,"229":3,"230":10,"249":2,"267":3,"273":1,"281":1,"293":2,"303":1}}],["conf",{"0":{"226":1},"1":{"227":1,"228":1,"229":1,"230":1},"2":{"35":1,"111":2,"148":3,"150":13,"185":4,"228":3}}],["conduct",{"2":{"16":1}}],["copy",{"2":{"11":1,"184":1}}],["complexity",{"2":{"155":1}}],["compile",{"2":{"150":2}}],["comparing",{"2":{"137":1}}],["combovalue",{"2":{"145":1}}],["combostring",{"2":{"143":1}}],["com>",{"2":{"145":2,"150":2,"184":2}}],["comments",{"2":{"301":1}}],["common",{"2":{"175":1}}],["commonly",{"2":{"155":1}}],["comma",{"2":{"155":1}}],["commas",{"2":{"155":1}}],["command",{"2":{"28":1,"94":1,"150":6,"176":2}}],["commit",{"2":{"6":1,"8":2,"13":3,"18":2}}],["com",{"2":{"2":1,"23":1,"52":2,"55":2,"65":3,"94":2,"102":1,"103":2,"212":1,"230":5}}],["cmdtrl",{"2":{"267":1}}],["cmdwidget",{"2":{"111":1,"112":2}}],["cmdctl",{"2":{"17":1,"145":3,"148":2,"150":8,"176":6,"184":5,"270":3}}],["cmd固定shell默认指定为",{"2":{"5":1}}],["cmd增加workdir功能",{"2":{"5":1}}],["cmd",{"2":{"5":1,"17":1,"94":3,"111":4,"112":4,"145":1,"148":2,"150":12,"176":2,"184":3,"223":1}}],["0s",{"2":{"54":1}}],["005",{"2":{"112":2}}],["003",{"2":{"95":4,"173":1,"218":2}}],["003307",{"2":{"12":1}}],["004",{"2":{"66":3,"76":2,"112":1,"173":1}}],["002",{"2":{"62":1,"71":1,"72":1,"81":1,"93":1,"96":1,"97":1,"108":1,"166":1,"173":1,"249":1,"298":1}}],["001",{"2":{"52":1,"54":1,"62":1,"71":1,"72":1,"76":1,"81":1,"86":3,"93":1,"96":1,"97":1,"103":5,"108":1,"134":1,"165":5,"166":1,"168":2,"173":2,"175":2,"193":2,"204":1,"230":5,"249":1,"285":2,"293":1,"297":1}}],["09",{"0":{"36":1,"37":1,"38":1,"45":1,"56":1,"57":1,"58":1},"2":{"178":1}}],["01",{"0":{"22":1,"23":1,"52":1}}],["021",{"2":{"120":1}}],["02",{"0":{"21":1,"49":1,"50":1,"51":1},"2":{"193":1}}],["03分20秒",{"2":{"54":1}}],["03",{"0":{"18":1,"19":1,"20":1},"2":{"135":1,"184":3}}],["04",{"0":{"17":1,"20":1,"29":1,"30":1}}],["06",{"0":{"9":1,"10":1,"11":1,"44":1,"45":1,"46":1,"47":1,"52":1}}],["0",{"0":{"14":1,"20":1,"26":1,"34":1,"38":1,"41":1,"42":2,"43":1,"53":1,"58":1,"59":1,"60":1},"2":{"8":1,"17":1,"24":2,"28":1,"41":1,"42":6,"46":1,"47":3,"53":1,"75":3,"94":1,"95":1,"120":1,"134":1,"135":1,"137":9,"143":1,"145":4,"148":4,"150":22,"176":7,"180":2,"184":10,"193":1,"194":1,"204":3,"218":1,"230":3,"234":1,"244":1}}],["07",{"0":{"6":1,"7":1,"8":1,"10":1,"11":1,"43":1,"47":1}}],["05",{"0":{"5":1,"8":1,"12":1,"13":1,"14":1,"15":1,"16":1,"38":1,"48":1}}],["08",{"0":{"5":1,"16":1,"33":1,"39":1,"40":1,"41":1,"42":1,"46":1,"51":1,"59":1,"60":1}}],["960",{"2":{"150":3}}],["99",{"2":{"147":1}}],["90",{"2":{"134":1}}],["9",{"0":{"5":1,"44":1},"2":{"35":1,"47":1,"75":1,"134":1,"137":1,"155":2,"193":2}}],["66",{"2":{"230":1}}],["600",{"2":{"150":1}}],["600+",{"2":{"42":1}}],["679537",{"2":{"54":3,"178":1,"200":2,"203":1,"205":1,"206":1,"223":2}}],["62",{"2":{"17":1}}],["64",{"2":{"16":1,"75":1,"193":1,"243":1}}],["68",{"2":{"13":1,"28":1}}],["6",{"0":{"5":1,"6":1,"7":1,"8":2,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"21":1,"28":1,"47":1},"2":{"120":2,"176":3,"193":1,"288":6}}],["2d7e77ce1718",{"2":{"178":1}}],["2>middle",{"2":{"145":1}}],["28",{"0":{"55":1},"2":{"47":1,"193":1,"288":2}}],["25",{"2":{"26":1,"288":1}}],["23",{"2":{"26":1,"288":2}}],["22",{"0":{"26":1,"31":1,"40":1,"59":1},"2":{"26":1,"31":1,"288":2}}],["20747",{"2":{"230":2}}],["20221109134736",{"2":{"178":2}}],["20221108114823",{"2":{"178":1}}],["2022",{"0":{"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":1,"60":1},"2":{"178":3,"288":34}}],["2023",{"0":{"24":1,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":1,"36":1,"37":1,"38":1,"39":1,"40":1,"41":1,"42":1,"43":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":1,"52":1},"2":{"31":2,"145":1,"150":1,"176":1,"184":1,"204":1}}],["2024",{"0":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":1,"13":1,"14":1,"15":1,"16":1,"17":1,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1}}],["20",{"0":{"22":1},"2":{"28":1,"137":1,"288":4}}],["268",{"2":{"149":1}}],["26",{"0":{"21":1,"25":1,"44":1},"2":{"26":1,"288":1}}],["27",{"0":{"18":1,"24":1,"34":1,"49":1,"50":1},"2":{"288":1}}],["248",{"2":{"176":3}}],["24",{"0":{"17":1},"2":{"26":1}}],["2199",{"2":{"178":1}}],["215",{"2":{"52":1}}],["21",{"0":{"13":1,"56":1},"2":{"26":1,"149":2,"288":1}}],["29",{"0":{"12":1},"2":{"47":1}}],["2",{"0":{"5":1,"6":1,"7":1,"8":1,"9":1,"10":1,"11":1,"12":2,"13":1,"14":1,"15":1,"16":1,"17":1,"18":2,"19":1,"20":1,"21":1,"22":1,"23":1,"24":2,"25":1,"26":1,"27":1,"28":1,"29":1,"30":1,"31":1,"32":2,"33":1,"34":1,"35":2,"36":2,"37":2,"38":2,"39":1,"40":2,"41":1,"42":1,"44":1,"45":1,"46":1,"47":1,"48":1,"49":1,"50":1,"51":2,"52":1,"53":1,"56":1,"59":1,"129":1,"138":1,"160":1,"163":1,"204":1,"235":1,"252":1,"253":1,"254":2,"257":1,"266":1,"270":1,"277":1,"281":1,"284":1,"293":1,"296":1,"301":1},"1":{"253":1,"254":1},"2":{"19":1,"35":1,"40":1,"41":1,"42":6,"46":2,"48":1,"53":1,"54":2,"62":1,"71":1,"75":1,"81":1,"86":1,"96":1,"108":1,"123":1,"124":1,"128":1,"130":1,"132":1,"134":1,"135":1,"137":2,"143":1,"144":2,"145":5,"148":2,"150":22,"163":2,"165":1,"176":2,"178":1,"184":6,"194":1,"196":1,"204":1,"214":2,"223":1,"227":1,"230":6,"244":1,"249":1,"257":2,"260":2,"261":1,"271":1,"273":1,"283":1,"284":4,"285":1,"286":1,"287":1,"288":1,"300":1,"301":3,"302":1,"303":1}}],["向量的纵坐标",{"2":{"184":1}}],["向量的横坐标",{"2":{"184":1}}],["向元素对象输入字符串",{"2":{"143":1}}],["向",{"0":{"2":1,"3":1},"2":{"184":1}}],["欢迎任何微如错别字",{"2":{"1":1}}],["帮助改进",{"0":{"1":1}}],["贡献",{"0":{"0":1},"1":{"1":1,"2":1,"3":1}}]],"serializationVersion":2}';export{t as default}; diff --git a/assets/chunks/VPLocalSearchBox.6bnhNGDg.js b/assets/chunks/VPLocalSearchBox.DH5uDbJr.js similarity index 99% rename from assets/chunks/VPLocalSearchBox.6bnhNGDg.js rename to assets/chunks/VPLocalSearchBox.DH5uDbJr.js index 29fc0452..ee1c1056 100644 --- a/assets/chunks/VPLocalSearchBox.6bnhNGDg.js +++ b/assets/chunks/VPLocalSearchBox.DH5uDbJr.js @@ -1,4 +1,4 @@ -var Nt=Object.defineProperty;var kt=(o,e,t)=>e in o?Nt(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Oe=(o,e,t)=>kt(o,typeof e!="symbol"?e+"":e,t);import{X as It,h as oe,y as $e,aj as Dt,ak as Ot,d as Rt,G as xe,al as tt,k as Fe,am as _t,an as Mt,z as Lt,ao as zt,l as Re,R as de,P as Ee,ap as Pt,aq as Bt,Y as Vt,j as $t,ar as Wt,o as ee,b as jt,m as E,a1 as Kt,p as U,as as Jt,at as Ut,au as Ht,c as re,n as rt,e as Se,E as at,F as nt,a as ve,t as pe,av as Gt,q as qt,s as Qt,aw as it,a3 as Yt,a9 as Zt,af as Xt,ax as er,_ as tr}from"./framework.DIzwIJpr.js";import{u as rr,d as ar}from"./theme.B7K9K7dh.js";const nr={root:()=>It(()=>import("./@localSearchIndexroot.CQo7c1MN.js"),[])};/*! +var Nt=Object.defineProperty;var kt=(o,e,t)=>e in o?Nt(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Oe=(o,e,t)=>kt(o,typeof e!="symbol"?e+"":e,t);import{X as It,h as oe,y as $e,aj as Dt,ak as Ot,d as Rt,G as xe,al as tt,k as Fe,am as _t,an as Mt,z as Lt,ao as zt,l as Re,R as de,P as Ee,ap as Pt,aq as Bt,Y as Vt,j as $t,ar as Wt,o as ee,b as jt,m as E,a1 as Kt,p as U,as as Jt,at as Ut,au as Ht,c as re,n as rt,e as Se,E as at,F as nt,a as ve,t as pe,av as Gt,q as qt,s as Qt,aw as it,a3 as Yt,a9 as Zt,af as Xt,ax as er,_ as tr}from"./framework.DIzwIJpr.js";import{u as rr,d as ar}from"./theme.BIU4L49Z.js";const nr={root:()=>It(()=>import("./@localSearchIndexroot.C_5et46b.js"),[])};/*! * tabbable 6.2.0 * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE */var mt=["input:not([inert])","select:not([inert])","textarea:not([inert])","a[href]:not([inert])","button:not([inert])","[tabindex]:not(slot):not([inert])","audio[controls]:not([inert])","video[controls]:not([inert])",'[contenteditable]:not([contenteditable="false"]):not([inert])',"details>summary:first-of-type:not([inert])","details:not([inert])"],Te=mt.join(","),yt=typeof Element>"u",ue=yt?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector,Ne=!yt&&Element.prototype.getRootNode?function(o){var e;return o==null||(e=o.getRootNode)===null||e===void 0?void 0:e.call(o)}:function(o){return o==null?void 0:o.ownerDocument},ke=function o(e,t){var r;t===void 0&&(t=!0);var n=e==null||(r=e.getAttribute)===null||r===void 0?void 0:r.call(e,"inert"),a=n===""||n==="true",i=a||t&&e&&o(e.parentNode);return i},ir=function(e){var t,r=e==null||(t=e.getAttribute)===null||t===void 0?void 0:t.call(e,"contenteditable");return r===""||r==="true"},gt=function(e,t,r){if(ke(e))return[];var n=Array.prototype.slice.apply(e.querySelectorAll(Te));return t&&ue.call(e,Te)&&n.unshift(e),n=n.filter(r),n},bt=function o(e,t,r){for(var n=[],a=Array.from(e);a.length;){var i=a.shift();if(!ke(i,!1))if(i.tagName==="SLOT"){var s=i.assignedElements(),u=s.length?s:i.children,l=o(u,!0,r);r.flatten?n.push.apply(n,l):n.push({scopeParent:i,candidates:l})}else{var h=ue.call(i,Te);h&&r.filter(i)&&(t||!e.includes(i))&&n.push(i);var d=i.shadowRoot||typeof r.getShadowRoot=="function"&&r.getShadowRoot(i),v=!ke(d,!1)&&(!r.shadowRootFilter||r.shadowRootFilter(i));if(d&&v){var m=o(d===!0?i.children:d.children,!0,r);r.flatten?n.push.apply(n,m):n.push({scopeParent:i,candidates:m})}else a.unshift.apply(a,i.children)}}return n},wt=function(e){return!isNaN(parseInt(e.getAttribute("tabindex"),10))},se=function(e){if(!e)throw new Error("No node provided");return e.tabIndex<0&&(/^(AUDIO|VIDEO|DETAILS)$/.test(e.tagName)||ir(e))&&!wt(e)?0:e.tabIndex},or=function(e,t){var r=se(e);return r<0&&t&&!wt(e)?0:r},sr=function(e,t){return e.tabIndex===t.tabIndex?e.documentOrder-t.documentOrder:e.tabIndex-t.tabIndex},xt=function(e){return e.tagName==="INPUT"},ur=function(e){return xt(e)&&e.type==="hidden"},lr=function(e){var t=e.tagName==="DETAILS"&&Array.prototype.slice.apply(e.children).some(function(r){return r.tagName==="SUMMARY"});return t},cr=function(e,t){for(var r=0;rsummary:first-of-type"),i=a?e.parentElement:e;if(ue.call(i,"details:not([open]) *"))return!0;if(!r||r==="full"||r==="legacy-full"){if(typeof n=="function"){for(var s=e;e;){var u=e.parentElement,l=Ne(e);if(u&&!u.shadowRoot&&n(u)===!0)return ot(e);e.assignedSlot?e=e.assignedSlot:!u&&l!==e.ownerDocument?e=l.host:e=u}e=s}if(vr(e))return!e.getClientRects().length;if(r!=="legacy-full")return!0}else if(r==="non-zero-area")return ot(e);return!1},mr=function(e){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(e.tagName))for(var t=e.parentElement;t;){if(t.tagName==="FIELDSET"&&t.disabled){for(var r=0;r=0)},gr=function o(e){var t=[],r=[];return e.forEach(function(n,a){var i=!!n.scopeParent,s=i?n.scopeParent:n,u=or(s,i),l=i?o(n.candidates):s;u===0?i?t.push.apply(t,l):t.push(s):r.push({documentOrder:a,tabIndex:u,item:n,isScope:i,content:l})}),r.sort(sr).reduce(function(n,a){return a.isScope?n.push.apply(n,a.content):n.push(a.content),n},[]).concat(t)},br=function(e,t){t=t||{};var r;return t.getShadowRoot?r=bt([e],t.includeContainer,{filter:We.bind(null,t),flatten:!1,getShadowRoot:t.getShadowRoot,shadowRootFilter:yr}):r=gt(e,t.includeContainer,We.bind(null,t)),gr(r)},wr=function(e,t){t=t||{};var r;return t.getShadowRoot?r=bt([e],t.includeContainer,{filter:Ie.bind(null,t),flatten:!0,getShadowRoot:t.getShadowRoot}):r=gt(e,t.includeContainer,Ie.bind(null,t)),r},le=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,Te)===!1?!1:We(t,e)},xr=mt.concat("iframe").join(","),_e=function(e,t){if(t=t||{},!e)throw new Error("No node provided");return ue.call(e,xr)===!1?!1:Ie(t,e)};/*! diff --git a/assets/chunks/diagram-definition.ae1f7a29.BteD-_ze.js b/assets/chunks/diagram-definition.ae1f7a29.Cn2DCAkm.js similarity index 99% rename from assets/chunks/diagram-definition.ae1f7a29.BteD-_ze.js rename to assets/chunks/diagram-definition.ae1f7a29.Cn2DCAkm.js index 49ff3374..1895e924 100644 --- a/assets/chunks/diagram-definition.ae1f7a29.BteD-_ze.js +++ b/assets/chunks/diagram-definition.ae1f7a29.Cn2DCAkm.js @@ -1,4 +1,4 @@ -import{c as ms,g as cc}from"./theme.B7K9K7dh.js";import"./framework.DIzwIJpr.js";var hc={value:()=>{}};function Ru(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(a+1),r=r.slice(0,a)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Oa.prototype=Ru.prototype={constructor:Oa,on:function(t,e){var r=this._,n=vc(t+"",r),a,i=-1,s=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(a),n=0,a,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),no.hasOwnProperty(e)?{space:no[e],local:t}:t}function gc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===qi&&e.documentElement.namespaceURI===qi?e.createElement(t):e.createElementNS(r,t)}}function pc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Pu(t){var e=oi(t);return(e.local?pc:gc)(e)}function yc(){}function bs(t){return t==null?yc:function(){return this.querySelector(t)}}function mc(t){typeof t!="function"&&(t=bs(t));for(var e=this._groups,r=e.length,n=new Array(r),a=0;a=m&&(m=b+1);!(C=p[m])&&++m=0;)(s=n[a])&&(i&&s.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(s,i),i=s);return this}function Uc(t){t||(t=Hc);function e(c,v){return c&&v?t(c.__data__,v.__data__):!c-!v}for(var r=this._groups,n=r.length,a=new Array(n),i=0;ie?1:t>=e?0:NaN}function Yc(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Xc(){return Array.from(this)}function qc(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?ah:typeof e=="function"?sh:ih)(t,e,r??"")):nn(this.node(),t)}function nn(t,e){return t.style.getPropertyValue(e)||zu(t).getComputedStyle(t,null).getPropertyValue(e)}function uh(t){return function(){delete this[t]}}function lh(t,e){return function(){this[t]=e}}function fh(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function ch(t,e){return arguments.length>1?this.each((e==null?uh:typeof e=="function"?fh:lh)(t,e)):this.node()[t]}function $u(t){return t.trim().split(/^|\s+/)}function ws(t){return t.classList||new Vu(t)}function Vu(t){this._node=t,this._names=$u(t.getAttribute("class")||"")}Vu.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Uu(t,e){for(var r=ws(t),n=-1,a=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Gh(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,a=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?pa(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?pa(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=Wh.exec(t))?new yt(e[1],e[2],e[3],1):(e=Kh.exec(t))?new yt(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Zh.exec(t))?pa(e[1],e[2],e[3],e[4]):(e=Qh.exec(t))?pa(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Jh.exec(t))?fo(e[1],e[2]/100,e[3]/100,1):(e=jh.exec(t))?fo(e[1],e[2]/100,e[3]/100,e[4]):ao.hasOwnProperty(t)?oo(ao[t]):t==="transparent"?new yt(NaN,NaN,NaN,0):null}function oo(t){return new yt(t>>16&255,t>>8&255,t&255,1)}function pa(t,e,r,n){return n<=0&&(t=e=r=NaN),new yt(t,e,r,n)}function rv(t){return t instanceof ia||(t=Un(t)),t?(t=t.rgb(),new yt(t.r,t.g,t.b,t.opacity)):new yt}function Wi(t,e,r,n){return arguments.length===1?rv(t):new yt(t,e,r,n??1)}function yt(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}Es(yt,Wi,qu(ia,{brighter(t){return t=t==null?Ya:Math.pow(Ya,t),new yt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?$n:Math.pow($n,t),new yt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new yt(Ar(this.r),Ar(this.g),Ar(this.b),Xa(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:uo,formatHex:uo,formatHex8:nv,formatRgb:lo,toString:lo}));function uo(){return`#${Dr(this.r)}${Dr(this.g)}${Dr(this.b)}`}function nv(){return`#${Dr(this.r)}${Dr(this.g)}${Dr(this.b)}${Dr((isNaN(this.opacity)?1:this.opacity)*255)}`}function lo(){const t=Xa(this.opacity);return`${t===1?"rgb(":"rgba("}${Ar(this.r)}, ${Ar(this.g)}, ${Ar(this.b)}${t===1?")":`, ${t})`}`}function Xa(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Ar(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Dr(t){return t=Ar(t),(t<16?"0":"")+t.toString(16)}function fo(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new Pt(t,e,r,n)}function Wu(t){if(t instanceof Pt)return new Pt(t.h,t.s,t.l,t.opacity);if(t instanceof ia||(t=Un(t)),!t)return new Pt;if(t instanceof Pt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,a=Math.min(e,r,n),i=Math.max(e,r,n),s=NaN,o=i-a,u=(i+a)/2;return o?(e===i?s=(r-n)/o+(r0&&u<1?0:s,new Pt(s,o,u,t.opacity)}function av(t,e,r,n){return arguments.length===1?Wu(t):new Pt(t,e,r,n??1)}function Pt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}Es(Pt,av,qu(ia,{brighter(t){return t=t==null?Ya:Math.pow(Ya,t),new Pt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?$n:Math.pow($n,t),new Pt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,a=2*r-n;return new yt(Mi(t>=240?t-240:t+120,a,n),Mi(t,a,n),Mi(t<120?t+240:t-120,a,n),this.opacity)},clamp(){return new Pt(co(this.h),ya(this.s),ya(this.l),Xa(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=Xa(this.opacity);return`${t===1?"hsl(":"hsla("}${co(this.h)}, ${ya(this.s)*100}%, ${ya(this.l)*100}%${t===1?")":`, ${t})`}`}}));function co(t){return t=(t||0)%360,t<0?t+360:t}function ya(t){return Math.max(0,Math.min(1,t||0))}function Mi(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}const Ku=t=>()=>t;function iv(t,e){return function(r){return t+r*e}}function sv(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function ov(t){return(t=+t)==1?Zu:function(e,r){return r-e?sv(e,r,t):Ku(isNaN(e)?r:e)}}function Zu(t,e){var r=e-t;return r?iv(t,r):Ku(isNaN(t)?e:t)}const ho=function t(e){var r=ov(e);function n(a,i){var s=r((a=Wi(a)).r,(i=Wi(i)).r),o=r(a.g,i.g),u=r(a.b,i.b),l=Zu(a.opacity,i.opacity);return function(f){return a.r=s(f),a.g=o(f),a.b=u(f),a.opacity=l(f),a+""}}return n.gamma=t,n}(1);function or(t,e){return t=+t,e=+e,function(r){return t*(1-r)+e*r}}var Ki=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Oi=new RegExp(Ki.source,"g");function uv(t){return function(){return t}}function lv(t){return function(e){return t(e)+""}}function fv(t,e){var r=Ki.lastIndex=Oi.lastIndex=0,n,a,i,s=-1,o=[],u=[];for(t=t+"",e=e+"";(n=Ki.exec(t))&&(a=Oi.exec(e));)(i=a.index)>r&&(i=e.slice(r,i),o[s]?o[s]+=i:o[++s]=i),(n=n[0])===(a=a[0])?o[s]?o[s]+=a:o[++s]=a:(o[++s]=null,u.push({i:s,x:or(n,a)})),r=Oi.lastIndex;return r180?f+=360:f-l>180&&(l+=360),v.push({i:c.push(a(c)+"rotate(",null,n)-2,x:or(l,f)})):f&&c.push(a(c)+"rotate("+f+n)}function o(l,f,c,v){l!==f?v.push({i:c.push(a(c)+"skewX(",null,n)-2,x:or(l,f)}):f&&c.push(a(c)+"skewX("+f+n)}function u(l,f,c,v,h,d){if(l!==c||f!==v){var y=h.push(a(h)+"scale(",null,",",null,")");d.push({i:y-4,x:or(l,c)},{i:y-2,x:or(f,v)})}else(c!==1||v!==1)&&h.push(a(h)+"scale("+c+","+v+")")}return function(l,f){var c=[],v=[];return l=t(l),f=t(f),i(l.translateX,l.translateY,f.translateX,f.translateY,c,v),s(l.rotate,f.rotate,c,v),o(l.skewX,f.skewX,c,v),u(l.scaleX,l.scaleY,f.scaleX,f.scaleY,c,v),l=f=null,function(h){for(var d=-1,y=v.length,p;++d=0&&t._call.call(void 0,e),t=t._next;--an}function go(){Nr=(Wa=Hn.now())+ui,an=An=0;try{pv()}finally{an=0,mv(),Nr=0}}function yv(){var t=Hn.now(),e=t-Wa;e>ju&&(ui-=e,Wa=t)}function mv(){for(var t,e=qa,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:qa=r);Nn=t,Qi(n)}function Qi(t){if(!an){An&&(An=clearTimeout(An));var e=t-Nr;e>24?(t<1/0&&(An=setTimeout(go,t-Hn.now()-ui)),xn&&(xn=clearInterval(xn))):(xn||(Wa=Hn.now(),xn=setInterval(yv,ju)),an=1,el(go))}}function po(t,e,r){var n=new Ka;return e=e==null?0:+e,n.restart(a=>{n.stop(),t(a+e)},e,r),n}var bv=Ru("start","end","cancel","interrupt"),wv=[],rl=0,yo=1,Ji=2,ka=3,mo=4,ji=5,Ia=6;function li(t,e,r,n,a,i){var s=t.__transition;if(!s)t.__transition={};else if(r in s)return;Ev(t,r,{name:e,index:n,group:a,on:bv,tween:wv,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:rl})}function Ts(t,e){var r=Ft(t,e);if(r.state>rl)throw new Error("too late; already scheduled");return r}function Xt(t,e){var r=Ft(t,e);if(r.state>ka)throw new Error("too late; already running");return r}function Ft(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function Ev(t,e,r){var n=t.__transition,a;n[e]=r,r.timer=tl(i,0,r.time);function i(l){r.state=yo,r.timer.restart(s,r.delay,r.time),r.delay<=l&&s(l-r.delay)}function s(l){var f,c,v,h;if(r.state!==yo)return u();for(f in n)if(h=n[f],h.name===r.name){if(h.state===ka)return po(s);h.state===mo?(h.state=Ia,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete n[f]):+fJi&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function Jv(t,e,r){var n,a,i=Qv(e)?Ts:Xt;return function(){var s=i(this,t),o=s.on;o!==n&&(a=(n=o).copy()).on(e,r),s.on=a}}function jv(t,e){var r=this._id;return arguments.length<2?Ft(this.node(),r).on.on(t):this.each(Jv(r,t,e))}function ed(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function td(){return this.on("end.remove",ed(this._id))}function rd(t){var e=this._name,r=this._id;typeof t!="function"&&(t=bs(t));for(var n=this._groups,a=n.length,i=new Array(a),s=0;st.length)&&(e=t.length);for(var r=0,n=new Array(e);r{}};function Ru(){for(var t=0,e=arguments.length,r={},n;t=0&&(n=r.slice(a+1),r=r.slice(0,a)),r&&!e.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}Oa.prototype=Ru.prototype={constructor:Oa,on:function(t,e){var r=this._,n=vc(t+"",r),a,i=-1,s=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(a),n=0,a,i;n=0&&(e=t.slice(0,r))!=="xmlns"&&(t=t.slice(r+1)),no.hasOwnProperty(e)?{space:no[e],local:t}:t}function gc(t){return function(){var e=this.ownerDocument,r=this.namespaceURI;return r===qi&&e.documentElement.namespaceURI===qi?e.createElement(t):e.createElementNS(r,t)}}function pc(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Pu(t){var e=oi(t);return(e.local?pc:gc)(e)}function yc(){}function bs(t){return t==null?yc:function(){return this.querySelector(t)}}function mc(t){typeof t!="function"&&(t=bs(t));for(var e=this._groups,r=e.length,n=new Array(r),a=0;a=m&&(m=b+1);!(C=p[m])&&++m=0;)(s=n[a])&&(i&&s.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(s,i),i=s);return this}function Uc(t){t||(t=Hc);function e(c,v){return c&&v?t(c.__data__,v.__data__):!c-!v}for(var r=this._groups,n=r.length,a=new Array(n),i=0;ie?1:t>=e?0:NaN}function Yc(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Xc(){return Array.from(this)}function qc(){for(var t=this._groups,e=0,r=t.length;e1?this.each((e==null?ah:typeof e=="function"?sh:ih)(t,e,r??"")):nn(this.node(),t)}function nn(t,e){return t.style.getPropertyValue(e)||zu(t).getComputedStyle(t,null).getPropertyValue(e)}function uh(t){return function(){delete this[t]}}function lh(t,e){return function(){this[t]=e}}function fh(t,e){return function(){var r=e.apply(this,arguments);r==null?delete this[t]:this[t]=r}}function ch(t,e){return arguments.length>1?this.each((e==null?uh:typeof e=="function"?fh:lh)(t,e)):this.node()[t]}function $u(t){return t.trim().split(/^|\s+/)}function ws(t){return t.classList||new Vu(t)}function Vu(t){this._node=t,this._names=$u(t.getAttribute("class")||"")}Vu.prototype={add:function(t){var e=this._names.indexOf(t);e<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var e=this._names.indexOf(t);e>=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Uu(t,e){for(var r=ws(t),n=-1,a=e.length;++n=0&&(r=e.slice(n+1),e=e.slice(0,n)),{type:e,name:r}})}function Gh(t){return function(){var e=this.__on;if(e){for(var r=0,n=-1,a=e.length,i;r>8&15|e>>4&240,e>>4&15|e&240,(e&15)<<4|e&15,1):r===8?pa(e>>24&255,e>>16&255,e>>8&255,(e&255)/255):r===4?pa(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|e&240,((e&15)<<4|e&15)/255):null):(e=Wh.exec(t))?new yt(e[1],e[2],e[3],1):(e=Kh.exec(t))?new yt(e[1]*255/100,e[2]*255/100,e[3]*255/100,1):(e=Zh.exec(t))?pa(e[1],e[2],e[3],e[4]):(e=Qh.exec(t))?pa(e[1]*255/100,e[2]*255/100,e[3]*255/100,e[4]):(e=Jh.exec(t))?fo(e[1],e[2]/100,e[3]/100,1):(e=jh.exec(t))?fo(e[1],e[2]/100,e[3]/100,e[4]):ao.hasOwnProperty(t)?oo(ao[t]):t==="transparent"?new yt(NaN,NaN,NaN,0):null}function oo(t){return new yt(t>>16&255,t>>8&255,t&255,1)}function pa(t,e,r,n){return n<=0&&(t=e=r=NaN),new yt(t,e,r,n)}function rv(t){return t instanceof ia||(t=Un(t)),t?(t=t.rgb(),new yt(t.r,t.g,t.b,t.opacity)):new yt}function Wi(t,e,r,n){return arguments.length===1?rv(t):new yt(t,e,r,n??1)}function yt(t,e,r,n){this.r=+t,this.g=+e,this.b=+r,this.opacity=+n}Es(yt,Wi,qu(ia,{brighter(t){return t=t==null?Ya:Math.pow(Ya,t),new yt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?$n:Math.pow($n,t),new yt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new yt(Ar(this.r),Ar(this.g),Ar(this.b),Xa(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:uo,formatHex:uo,formatHex8:nv,formatRgb:lo,toString:lo}));function uo(){return`#${Dr(this.r)}${Dr(this.g)}${Dr(this.b)}`}function nv(){return`#${Dr(this.r)}${Dr(this.g)}${Dr(this.b)}${Dr((isNaN(this.opacity)?1:this.opacity)*255)}`}function lo(){const t=Xa(this.opacity);return`${t===1?"rgb(":"rgba("}${Ar(this.r)}, ${Ar(this.g)}, ${Ar(this.b)}${t===1?")":`, ${t})`}`}function Xa(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Ar(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Dr(t){return t=Ar(t),(t<16?"0":"")+t.toString(16)}function fo(t,e,r,n){return n<=0?t=e=r=NaN:r<=0||r>=1?t=e=NaN:e<=0&&(t=NaN),new Pt(t,e,r,n)}function Wu(t){if(t instanceof Pt)return new Pt(t.h,t.s,t.l,t.opacity);if(t instanceof ia||(t=Un(t)),!t)return new Pt;if(t instanceof Pt)return t;t=t.rgb();var e=t.r/255,r=t.g/255,n=t.b/255,a=Math.min(e,r,n),i=Math.max(e,r,n),s=NaN,o=i-a,u=(i+a)/2;return o?(e===i?s=(r-n)/o+(r0&&u<1?0:s,new Pt(s,o,u,t.opacity)}function av(t,e,r,n){return arguments.length===1?Wu(t):new Pt(t,e,r,n??1)}function Pt(t,e,r,n){this.h=+t,this.s=+e,this.l=+r,this.opacity=+n}Es(Pt,av,qu(ia,{brighter(t){return t=t==null?Ya:Math.pow(Ya,t),new Pt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?$n:Math.pow($n,t),new Pt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,e=isNaN(t)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*e,a=2*r-n;return new yt(Mi(t>=240?t-240:t+120,a,n),Mi(t,a,n),Mi(t<120?t+240:t-120,a,n),this.opacity)},clamp(){return new Pt(co(this.h),ya(this.s),ya(this.l),Xa(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=Xa(this.opacity);return`${t===1?"hsl(":"hsla("}${co(this.h)}, ${ya(this.s)*100}%, ${ya(this.l)*100}%${t===1?")":`, ${t})`}`}}));function co(t){return t=(t||0)%360,t<0?t+360:t}function ya(t){return Math.max(0,Math.min(1,t||0))}function Mi(t,e,r){return(t<60?e+(r-e)*t/60:t<180?r:t<240?e+(r-e)*(240-t)/60:e)*255}const Ku=t=>()=>t;function iv(t,e){return function(r){return t+r*e}}function sv(t,e,r){return t=Math.pow(t,r),e=Math.pow(e,r)-t,r=1/r,function(n){return Math.pow(t+n*e,r)}}function ov(t){return(t=+t)==1?Zu:function(e,r){return r-e?sv(e,r,t):Ku(isNaN(e)?r:e)}}function Zu(t,e){var r=e-t;return r?iv(t,r):Ku(isNaN(t)?e:t)}const ho=function t(e){var r=ov(e);function n(a,i){var s=r((a=Wi(a)).r,(i=Wi(i)).r),o=r(a.g,i.g),u=r(a.b,i.b),l=Zu(a.opacity,i.opacity);return function(f){return a.r=s(f),a.g=o(f),a.b=u(f),a.opacity=l(f),a+""}}return n.gamma=t,n}(1);function or(t,e){return t=+t,e=+e,function(r){return t*(1-r)+e*r}}var Ki=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Oi=new RegExp(Ki.source,"g");function uv(t){return function(){return t}}function lv(t){return function(e){return t(e)+""}}function fv(t,e){var r=Ki.lastIndex=Oi.lastIndex=0,n,a,i,s=-1,o=[],u=[];for(t=t+"",e=e+"";(n=Ki.exec(t))&&(a=Oi.exec(e));)(i=a.index)>r&&(i=e.slice(r,i),o[s]?o[s]+=i:o[++s]=i),(n=n[0])===(a=a[0])?o[s]?o[s]+=a:o[++s]=a:(o[++s]=null,u.push({i:s,x:or(n,a)})),r=Oi.lastIndex;return r180?f+=360:f-l>180&&(l+=360),v.push({i:c.push(a(c)+"rotate(",null,n)-2,x:or(l,f)})):f&&c.push(a(c)+"rotate("+f+n)}function o(l,f,c,v){l!==f?v.push({i:c.push(a(c)+"skewX(",null,n)-2,x:or(l,f)}):f&&c.push(a(c)+"skewX("+f+n)}function u(l,f,c,v,h,d){if(l!==c||f!==v){var y=h.push(a(h)+"scale(",null,",",null,")");d.push({i:y-4,x:or(l,c)},{i:y-2,x:or(f,v)})}else(c!==1||v!==1)&&h.push(a(h)+"scale("+c+","+v+")")}return function(l,f){var c=[],v=[];return l=t(l),f=t(f),i(l.translateX,l.translateY,f.translateX,f.translateY,c,v),s(l.rotate,f.rotate,c,v),o(l.skewX,f.skewX,c,v),u(l.scaleX,l.scaleY,f.scaleX,f.scaleY,c,v),l=f=null,function(h){for(var d=-1,y=v.length,p;++d=0&&t._call.call(void 0,e),t=t._next;--an}function go(){Nr=(Wa=Hn.now())+ui,an=An=0;try{pv()}finally{an=0,mv(),Nr=0}}function yv(){var t=Hn.now(),e=t-Wa;e>ju&&(ui-=e,Wa=t)}function mv(){for(var t,e=qa,r,n=1/0;e;)e._call?(n>e._time&&(n=e._time),t=e,e=e._next):(r=e._next,e._next=null,e=t?t._next=r:qa=r);Nn=t,Qi(n)}function Qi(t){if(!an){An&&(An=clearTimeout(An));var e=t-Nr;e>24?(t<1/0&&(An=setTimeout(go,t-Hn.now()-ui)),xn&&(xn=clearInterval(xn))):(xn||(Wa=Hn.now(),xn=setInterval(yv,ju)),an=1,el(go))}}function po(t,e,r){var n=new Ka;return e=e==null?0:+e,n.restart(a=>{n.stop(),t(a+e)},e,r),n}var bv=Ru("start","end","cancel","interrupt"),wv=[],rl=0,yo=1,Ji=2,ka=3,mo=4,ji=5,Ia=6;function li(t,e,r,n,a,i){var s=t.__transition;if(!s)t.__transition={};else if(r in s)return;Ev(t,r,{name:e,index:n,group:a,on:bv,tween:wv,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:rl})}function Ts(t,e){var r=Ft(t,e);if(r.state>rl)throw new Error("too late; already scheduled");return r}function Xt(t,e){var r=Ft(t,e);if(r.state>ka)throw new Error("too late; already running");return r}function Ft(t,e){var r=t.__transition;if(!r||!(r=r[e]))throw new Error("transition not found");return r}function Ev(t,e,r){var n=t.__transition,a;n[e]=r,r.timer=tl(i,0,r.time);function i(l){r.state=yo,r.timer.restart(s,r.delay,r.time),r.delay<=l&&s(l-r.delay)}function s(l){var f,c,v,h;if(r.state!==yo)return u();for(f in n)if(h=n[f],h.name===r.name){if(h.state===ka)return po(s);h.state===mo?(h.state=Ia,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete n[f]):+fJi&&n.state=0&&(e=e.slice(0,r)),!e||e==="start"})}function Jv(t,e,r){var n,a,i=Qv(e)?Ts:Xt;return function(){var s=i(this,t),o=s.on;o!==n&&(a=(n=o).copy()).on(e,r),s.on=a}}function jv(t,e){var r=this._id;return arguments.length<2?Ft(this.node(),r).on.on(t):this.each(Jv(r,t,e))}function ed(t){return function(){var e=this.parentNode;for(var r in this.__transition)if(+r!==t)return;e&&e.removeChild(this)}}function td(){return this.on("end.remove",ed(this._id))}function rd(t){var e=this._name,r=this._id;typeof t!="function"&&(t=bs(t));for(var n=this._groups,a=n.length,i=new Array(a),s=0;st.length)&&(e=t.length);for(var r=0,n=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(u){throw u},f:a}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,s=!1,o;return{s:function(){r=r.call(t)},n:function(){var u=r.next();return i=u.done,u},e:function(u){s=!0,o=u},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(s)throw o}}}}var Ye=typeof window>"u"?null:window,wo=Ye?Ye.navigator:null;Ye&&Ye.document;var Od=qe(""),ll=qe({}),kd=qe(function(){}),Id=typeof HTMLElement>"u"?"undefined":qe(HTMLElement),sa=function(e){return e&&e.instanceString&&ze(e.instanceString)?e.instanceString():null},ve=function(e){return e!=null&&qe(e)==Od},ze=function(e){return e!=null&&qe(e)===kd},Pe=function(e){return!wt(e)&&(Array.isArray?Array.isArray(e):e!=null&&e instanceof Array)},De=function(e){return e!=null&&qe(e)===ll&&!Pe(e)&&e.constructor===Object},Rd=function(e){return e!=null&&qe(e)===ll},ae=function(e){return e!=null&&qe(e)===qe(1)&&!isNaN(e)},Pd=function(e){return ae(e)&&Math.floor(e)===e},Za=function(e){if(Id!=="undefined")return e!=null&&e instanceof HTMLElement},wt=function(e){return oa(e)||fl(e)},oa=function(e){return sa(e)==="collection"&&e._private.single},fl=function(e){return sa(e)==="collection"&&!e._private.single},Ls=function(e){return sa(e)==="core"},cl=function(e){return sa(e)==="stylesheet"},Bd=function(e){return sa(e)==="event"},hr=function(e){return e==null?!0:!!(e===""||e.match(/^\s+$/))},Fd=function(e){return typeof HTMLElement>"u"?!1:e instanceof HTMLElement},_d=function(e){return De(e)&&ae(e.x1)&&ae(e.x2)&&ae(e.y1)&&ae(e.y2)},Gd=function(e){return Rd(e)&&ze(e.then)},zd=function(){return wo&&wo.userAgent.match(/msie|trident|edge/i)},Yn=function(e,r){r||(r=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return"undefined";for(var i=[],s=0;sr?1:0},qd=function(e,r){return-1*vl(e,r)},be=Object.assign!=null?Object.assign.bind(Object):function(t){for(var e=arguments,r=1;r1&&(p-=1),p<1/6?d+(y-d)*6*p:p<1/2?y:p<2/3?d+(y-d)*(2/3-p)*6:d}var c=new RegExp("^"+Ud+"$").exec(e);if(c){if(n=parseInt(c[1]),n<0?n=(360- -1*n%360)%360:n>360&&(n=n%360),n/=360,a=parseFloat(c[2]),a<0||a>100||(a=a/100,i=parseFloat(c[3]),i<0||i>100)||(i=i/100,s=c[4],s!==void 0&&(s=parseFloat(s),s<0||s>1)))return;if(a===0)o=u=l=Math.round(i*255);else{var v=i<.5?i*(1+a):i+a-i*a,h=2*i-v;o=Math.round(255*f(h,v,n+1/3)),u=Math.round(255*f(h,v,n)),l=Math.round(255*f(h,v,n-1/3))}r=[o,u,l,s]}return r},Zd=function(e){var r,n=new RegExp("^"+$d+"$").exec(e);if(n){r=[];for(var a=[],i=1;i<=3;i++){var s=n[i];if(s[s.length-1]==="%"&&(a[i]=!0),s=parseFloat(s),a[i]&&(s=s/100*255),s<0||s>255)return;r.push(Math.floor(s))}var o=a[1]||a[2]||a[3],u=a[1]&&a[2]&&a[3];if(o&&!u)return;var l=n[4];if(l!==void 0){if(l=parseFloat(l),l<0||l>1)return;r.push(l)}}return r},Qd=function(e){return jd[e.toLowerCase()]},Jd=function(e){return(Pe(e)?e:null)||Qd(e)||Wd(e)||Zd(e)||Kd(e)},jd={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},dl=function(e){for(var r=e.map,n=e.keys,a=n.length,i=0;i=e||w<0||c&&x>=i}function g(){var D=ki();if(p(D))return b(D);o=setTimeout(g,y(D))}function b(D){return o=void 0,v&&n?h(D):(n=a=void 0,s)}function m(){o!==void 0&&clearTimeout(o),l=0,n=u=a=o=void 0}function E(){return o===void 0?s:b(ki())}function C(){var D=ki(),w=p(D);if(n=arguments,a=this,u=D,w){if(o===void 0)return d(u);if(c)return clearTimeout(o),o=setTimeout(g,e),h(u)}return o===void 0&&(o=setTimeout(g,e)),s}return C.cancel=m,C.flush=E,C}var hi=Fg,Ii=Ye?Ye.performance:null,ml=Ii&&Ii.now?function(){return Ii.now()}:function(){return Date.now()},_g=function(){if(Ye){if(Ye.requestAnimationFrame)return function(t){Ye.requestAnimationFrame(t)};if(Ye.mozRequestAnimationFrame)return function(t){Ye.mozRequestAnimationFrame(t)};if(Ye.webkitRequestAnimationFrame)return function(t){Ye.webkitRequestAnimationFrame(t)};if(Ye.msRequestAnimationFrame)return function(t){Ye.msRequestAnimationFrame(t)}}return function(t){t&&setTimeout(function(){t(ml())},1e3/60)}}(),Qa=function(e){return _g(e)},jt=ml,Wr=9261,bl=65599,kn=5381,wl=function(e){for(var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Wr,n=r,a;a=e.next(),!a.done;)n=n*bl+a.value|0;return n},Xn=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Wr;return r*bl+e|0},qn=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:kn;return(r<<5)+r+e|0},Gg=function(e,r){return e*2097152+r},ar=function(e){return e[0]*2097152+e[1]},ba=function(e,r){return[Xn(e[0],r[0]),qn(e[1],r[1])]},zg=function(e,r){var n={value:0,done:!1},a=0,i=e.length,s={next:function(){return a=0;a--)e[a]===r&&e.splice(a,1)},Os=function(e){e.splice(0,e.length)},qg=function(e,r){for(var n=0;n"u"?"undefined":qe(Set))!==Kg?Set:Zg,vi=function(e,r){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(e===void 0||r===void 0||!Ls(e)){$e("An element must have a core reference and parameters set");return}var a=r.group;if(a==null&&(r.data&&r.data.source!=null&&r.data.target!=null?a="edges":a="nodes"),a!=="nodes"&&a!=="edges"){$e("An element must be of type `nodes` or `edges`; you specified `"+a+"`");return}this.length=1,this[0]=this;var i=this._private={cy:e,single:!0,data:r.data||{},position:r.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:a,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!r.selected,selectable:r.selectable===void 0?!0:!!r.selectable,locked:!!r.locked,grabbed:!1,grabbable:r.grabbable===void 0?!0:!!r.grabbable,pannable:r.pannable===void 0?a==="edges":!!r.pannable,active:!1,classes:new fn,animation:{current:[],queue:[]},rscratch:{},scratch:r.scratch||{},edges:[],children:[],parent:r.parent&&r.parent.isNode()?r.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(i.position.x==null&&(i.position.x=0),i.position.y==null&&(i.position.y=0),r.renderedPosition){var s=r.renderedPosition,o=e.pan(),u=e.zoom();i.position={x:(s.x-o.x)/u,y:(s.y-o.y)/u}}var l=[];Pe(r.classes)?l=r.classes:ve(r.classes)&&(l=r.classes.split(/\s+/));for(var f=0,c=l.length;fb?1:0},f=function(g,b,m,E,C){var D;if(m==null&&(m=0),C==null&&(C=n),m<0)throw new Error("lo must be non-negative");for(E==null&&(E=g.length);mS;0<=S?T++:T--)x.push(T);return x}).apply(this).reverse(),w=[],E=0,C=D.length;EL;0<=L?++x:--x)N.push(s(g,m));return N},y=function(g,b,m,E){var C,D,w;for(E==null&&(E=n),C=g[m];m>b;){if(w=m-1>>1,D=g[w],E(C,D)<0){g[m]=D,m=w;continue}break}return g[m]=C},p=function(g,b,m){var E,C,D,w,x;for(m==null&&(m=n),C=g.length,x=b,D=g[b],E=2*b+1;E0;){var D=b.pop(),w=p(D),x=D.id();if(v[x]=w,w!==1/0)for(var T=D.neighborhood().intersect(d),S=0;S0)for(P.unshift(R);c[_];){var G=c[_];P.unshift(G.edge),P.unshift(G.node),F=G.node,_=F.id()}return o.spawn(P)}}}},ep={kruskal:function(e){e=e||function(m){return 1};for(var r=this.byGroup(),n=r.nodes,a=r.edges,i=n.length,s=new Array(i),o=n,u=function(E){for(var C=0;C0;){if(C(),w++,E===f){for(var x=[],T=i,S=f,L=g[S];x.unshift(T),L!=null&&x.unshift(L),T=p[S],T!=null;)S=T.id(),L=g[S];return{found:!0,distance:c[E],path:this.spawn(x),steps:w}}h[E]=!0;for(var N=m._private.edges,O=0;OL&&(d[S]=L,b[S]=T,m[S]=C),!i){var N=T*f+x;!i&&d[N]>L&&(d[N]=L,b[N]=x,m[N]=C)}}}for(var O=0;O1&&arguments[1]!==void 0?arguments[1]:s,Ne=m(fe),Te=[],Ee=Ne;;){if(Ee==null)return r.spawn();var Se=b(Ee),ee=Se.edge,M=Se.pred;if(Te.unshift(Ee[0]),Ee.same(pe)&&Te.length>0)break;ee!=null&&Te.unshift(ee),Ee=M}return u.spawn(Te)},D=0;D=0;f--){var c=l[f],v=c[1],h=c[2];(r[v]===o&&r[h]===u||r[v]===u&&r[h]===o)&&l.splice(f,1)}for(var d=0;da;){var i=Math.floor(Math.random()*r.length);r=up(i,e,r),n--}return r},lp={kargerStein:function(){var e=this,r=this.byGroup(),n=r.nodes,a=r.edges;a.unmergeBy(function(P){return P.isLoop()});var i=n.length,s=a.length,o=Math.ceil(Math.pow(Math.log(i)/Math.LN2,2)),u=Math.floor(i/op);if(i<2){$e("At least 2 nodes are required for Karger-Stein algorithm");return}for(var l=[],f=0;f1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,a=1/0,i=r;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,a=-1/0,i=r;i1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,a=0,i=0,s=r;s1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,a=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;a?e=e.slice(r,n):(n0&&e.splice(0,r));for(var o=0,u=e.length-1;u>=0;u--){var l=e[u];s?isFinite(l)||(e[u]=-1/0,o++):e.splice(u,1)}i&&e.sort(function(v,h){return v-h});var f=e.length,c=Math.floor(f/2);return f%2!==0?e[c+1+o]:(e[c-1+o]+e[c+o])/2},gp=function(e){return Math.PI*e/180},wa=function(e,r){return Math.atan2(r,e)-Math.PI/2},ks=Math.log2||function(t){return Math.log(t)/Math.log(2)},Ll=function(e){return e>0?1:e<0?-1:0},kr=function(e,r){return Math.sqrt(Er(e,r))},Er=function(e,r){var n=r.x-e.x,a=r.y-e.y;return n*n+a*a},pp=function(e){for(var r=e.length,n=0,a=0;a=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(e.w!=null&&e.h!=null&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},mp=function(e){return{x1:e.x1,x2:e.x2,w:e.w,y1:e.y1,y2:e.y2,h:e.h}},bp=function(e){e.x1=1/0,e.y1=1/0,e.x2=-1/0,e.y2=-1/0,e.w=0,e.h=0},wp=function(e,r,n){return{x1:e.x1+r,x2:e.x2+r,y1:e.y1+n,y2:e.y2+n,w:e.w,h:e.h}},Al=function(e,r){e.x1=Math.min(e.x1,r.x1),e.x2=Math.max(e.x2,r.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,r.y1),e.y2=Math.max(e.y2,r.y2),e.h=e.y2-e.y1},Ep=function(e,r,n){e.x1=Math.min(e.x1,r),e.x2=Math.max(e.x2,r),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,n),e.y2=Math.max(e.y2,n),e.h=e.y2-e.y1},Ra=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return e.x1-=r,e.x2+=r,e.y1-=r,e.y2+=r,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Pa=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],n,a,i,s;if(r.length===1)n=a=i=s=r[0];else if(r.length===2)n=i=r[0],s=a=r[1];else if(r.length===4){var o=kt(r,4);n=o[0],a=o[1],i=o[2],s=o[3]}return e.x1-=s,e.x2+=a,e.y1-=n,e.y2+=i,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Ao=function(e,r){e.x1=r.x1,e.y1=r.y1,e.x2=r.x2,e.y2=r.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1},Is=function(e,r){return!(e.x1>r.x2||r.x1>e.x2||e.x2r.y2||r.y1>e.y2)},on=function(e,r,n){return e.x1<=r&&r<=e.x2&&e.y1<=n&&n<=e.y2},xp=function(e,r){return on(e,r.x,r.y)},Nl=function(e,r){return on(e,r.x1,r.y1)&&on(e,r.x2,r.y2)},Ml=function(e,r,n,a,i,s,o){var u=arguments.length>7&&arguments[7]!==void 0?arguments[7]:"auto",l=u==="auto"?Ir(i,s):u,f=i/2,c=s/2;l=Math.min(l,f,c);var v=l!==f,h=l!==c,d;if(v){var y=n-f+l-o,p=a-c-o,g=n+f-l+o,b=p;if(d=lr(e,r,n,a,y,p,g,b,!1),d.length>0)return d}if(h){var m=n+f+o,E=a-c+l-o,C=m,D=a+c-l+o;if(d=lr(e,r,n,a,m,E,C,D,!1),d.length>0)return d}if(v){var w=n-f+l-o,x=a+c+o,T=n+f-l+o,S=x;if(d=lr(e,r,n,a,w,x,T,S,!1),d.length>0)return d}if(h){var L=n-f-o,N=a-c+l-o,O=L,A=a+c-l+o;if(d=lr(e,r,n,a,L,N,O,A,!1),d.length>0)return d}var k;{var I=n-f+l,R=a-c+l;if(k=In(e,r,n,a,I,R,l+o),k.length>0&&k[0]<=I&&k[1]<=R)return[k[0],k[1]]}{var P=n+f-l,F=a-c+l;if(k=In(e,r,n,a,P,F,l+o),k.length>0&&k[0]>=P&&k[1]<=F)return[k[0],k[1]]}{var _=n+f-l,G=a+c-l;if(k=In(e,r,n,a,_,G,l+o),k.length>0&&k[0]>=_&&k[1]>=G)return[k[0],k[1]]}{var B=n-f+l,$=a+c-l;if(k=In(e,r,n,a,B,$,l+o),k.length>0&&k[0]<=B&&k[1]>=$)return[k[0],k[1]]}return[]},Tp=function(e,r,n,a,i,s,o){var u=o,l=Math.min(n,i),f=Math.max(n,i),c=Math.min(a,s),v=Math.max(a,s);return l-u<=e&&e<=f+u&&c-u<=r&&r<=v+u},Cp=function(e,r,n,a,i,s,o,u,l){var f={x1:Math.min(n,o,i)-l,x2:Math.max(n,o,i)+l,y1:Math.min(a,u,s)-l,y2:Math.max(a,u,s)+l};return!(ef.x2||rf.y2)},Dp=function(e,r,n,a){n-=a;var i=r*r-4*e*n;if(i<0)return[];var s=Math.sqrt(i),o=2*e,u=(-r+s)/o,l=(-r-s)/o;return[u,l]},Sp=function(e,r,n,a,i){var s=1e-5;e===0&&(e=s),r/=e,n/=e,a/=e;var o,u,l,f,c,v,h,d;if(u=(3*n-r*r)/9,l=-(27*a)+r*(9*n-2*(r*r)),l/=54,o=u*u*u+l*l,i[1]=0,h=r/3,o>0){c=l+Math.sqrt(o),c=c<0?-Math.pow(-c,1/3):Math.pow(c,1/3),v=l-Math.sqrt(o),v=v<0?-Math.pow(-v,1/3):Math.pow(v,1/3),i[0]=-h+c+v,h+=(c+v)/2,i[4]=i[2]=-h,h=Math.sqrt(3)*(-v+c)/2,i[3]=h,i[5]=-h;return}if(i[5]=i[3]=0,o===0){d=l<0?-Math.pow(-l,1/3):Math.pow(l,1/3),i[0]=-h+2*d,i[4]=i[2]=-(d+h);return}u=-u,f=u*u*u,f=Math.acos(l/Math.sqrt(f)),d=2*Math.sqrt(u),i[0]=-h+d*Math.cos(f/3),i[2]=-h+d*Math.cos((f+2*Math.PI)/3),i[4]=-h+d*Math.cos((f+4*Math.PI)/3)},Lp=function(e,r,n,a,i,s,o,u){var l=1*n*n-4*n*i+2*n*o+4*i*i-4*i*o+o*o+a*a-4*a*s+2*a*u+4*s*s-4*s*u+u*u,f=1*9*n*i-3*n*n-3*n*o-6*i*i+3*i*o+9*a*s-3*a*a-3*a*u-6*s*s+3*s*u,c=1*3*n*n-6*n*i+n*o-n*e+2*i*i+2*i*e-o*e+3*a*a-6*a*s+a*u-a*r+2*s*s+2*s*r-u*r,v=1*n*i-n*n+n*e-i*e+a*s-a*a+a*r-s*r,h=[];Sp(l,f,c,v,h);for(var d=1e-7,y=[],p=0;p<6;p+=2)Math.abs(h[p+1])=0&&h[p]<=1&&y.push(h[p]);y.push(1),y.push(0);for(var g=-1,b,m,E,C=0;C=0?El?(e-i)*(e-i)+(r-s)*(r-s):f-v},pt=function(e,r,n){for(var a,i,s,o,u,l=0,f=0;f=e&&e>=s||a<=e&&e<=s)u=(e-a)/(s-a)*(o-i)+i,u>r&&l++;else continue;return l%2!==0},er=function(e,r,n,a,i,s,o,u,l){var f=new Array(n.length),c;u[0]!=null?(c=Math.atan(u[1]/u[0]),u[0]<0?c=c+Math.PI/2:c=-c-Math.PI/2):c=u;for(var v=Math.cos(-c),h=Math.sin(-c),d=0;d0){var p=ei(f,-l);y=ja(p)}else y=f;return pt(e,r,y)},Np=function(e,r,n,a,i,s,o,u){for(var l=new Array(n.length*2),f=0;f=0&&p<=1&&b.push(p),g>=0&&g<=1&&b.push(g),b.length===0)return[];var m=b[0]*u[0]+e,E=b[0]*u[1]+r;if(b.length>1){if(b[0]==b[1])return[m,E];var C=b[1]*u[0]+e,D=b[1]*u[1]+r;return[m,E,C,D]}else return[m,E]},Pi=function(e,r,n){return r<=e&&e<=n||n<=e&&e<=r?e:e<=r&&r<=n||n<=r&&r<=e?r:n},lr=function(e,r,n,a,i,s,o,u,l){var f=e-i,c=n-e,v=o-i,h=r-s,d=a-r,y=u-s,p=v*h-y*f,g=c*h-d*f,b=y*c-v*d;if(b!==0){var m=p/b,E=g/b,C=.001,D=0-C,w=1+C;return D<=m&&m<=w&&D<=E&&E<=w?[e+m*c,r+m*d]:l?[e+m*c,r+m*d]:[]}else return p===0||g===0?Pi(e,n,o)===o?[o,u]:Pi(e,n,i)===i?[i,s]:Pi(i,o,n)===n?[n,a]:[]:[]},Zn=function(e,r,n,a,i,s,o,u){var l=[],f,c=new Array(n.length),v=!0;s==null&&(v=!1);var h;if(v){for(var d=0;d0){var y=ei(c,-u);h=ja(y)}else h=c}else h=n;for(var p,g,b,m,E=0;E2){for(var d=[f[0],f[1]],y=Math.pow(d[0]-e,2)+Math.pow(d[1]-r,2),p=1;pf&&(f=E)},get:function(m){return l[m]}},v=0;v0?I=k.edgesTo(A)[0]:I=A.edgesTo(k)[0];var R=a(I);A=A.id(),x[A]>x[N]+R&&(x[A]=x[N]+R,T.nodes.indexOf(A)<0?T.push(A):T.updateItem(A),w[A]=0,D[A]=[]),x[A]==x[N]+R&&(w[A]=w[A]+w[N],D[A].push(N))}else for(var P=0;P0;){for(var B=C.pop(),$=0;$0&&o.push(n[u]);o.length!==0&&i.push(a.collection(o))}return i},Yp=function(e,r){for(var n=0;n5&&arguments[5]!==void 0?arguments[5]:Wp,o=a,u,l,f=0;f=2?Cn(e,r,n,0,Io,Kp):Cn(e,r,n,0,ko)},squaredEuclidean:function(e,r,n){return Cn(e,r,n,0,Io)},manhattan:function(e,r,n){return Cn(e,r,n,0,ko)},max:function(e,r,n){return Cn(e,r,n,-1/0,Zp)}};un["squared-euclidean"]=un.squaredEuclidean;un.squaredeuclidean=un.squaredEuclidean;function gi(t,e,r,n,a,i){var s;return ze(t)?s=t:s=un[t]||un.euclidean,e===0&&ze(t)?s(a,i):s(e,r,n,a,i)}var Qp=rt({k:2,m:2,sensitivityThreshold:1e-4,distance:"euclidean",maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),Ps=function(e){return Qp(e)},ti=function(e,r,n,a,i){var s=i!=="kMedoids",o=s?function(c){return n[c]}:function(c){return a[c](n)},u=function(v){return a[v](r)},l=n,f=r;return gi(e,a.length,o,u,l,f)},Bi=function(e,r,n){for(var a=n.length,i=new Array(a),s=new Array(a),o=new Array(r),u=null,l=0;ln)return!1}return!0},ey=function(e,r,n){for(var a=0;ao&&(o=r[l][f],u=f);i[u].push(e[l])}for(var c=0;c=i.threshold||i.mode==="dendrogram"&&e.length===1)return!1;var d=r[s],y=r[a[s]],p;i.mode==="dendrogram"?p={left:d,right:y,key:d.key}:p={value:d.value.concat(y.value),key:d.key},e[d.index]=p,e.splice(y.index,1),r[d.key]=p;for(var g=0;gn[y.key][b.key]&&(u=n[y.key][b.key])):i.linkage==="max"?(u=n[d.key][b.key],n[d.key][b.key]0&&a.push(i);return a},Go=function(e,r,n){for(var a=[],i=0;io&&(s=l,o=r[i*e+l])}s>0&&a.push(s)}for(var f=0;fl&&(u=f,l=c)}n[i]=s[u]}return a=Go(e,r,n),a},zo=function(e){for(var r=this.cy(),n=this.nodes(),a=dy(e),i={},s=0;s=L?(N=L,L=A,O=k):A>N&&(N=A);for(var I=0;I0?1:0;w[T%a.minIterations*o+B]=$,G+=$}if(G>0&&(T>=a.minIterations-1||T==a.maxIterations-1)){for(var U=0,K=0;K1||D>1)&&(o=!0),c[m]=[],b.outgoers().forEach(function(x){x.isEdge()&&c[m].push(x.id())})}else v[m]=[void 0,b.target().id()]}):s.forEach(function(b){var m=b.id();if(b.isNode()){var E=b.degree(!0);E%2&&(u?l?o=!0:l=m:u=m),c[m]=[],b.connectedEdges().forEach(function(C){return c[m].push(C.id())})}else v[m]=[b.source().id(),b.target().id()]});var h={found:!1,trail:void 0};if(o)return h;if(l&&u)if(i){if(f&&l!=f)return h;f=l}else{if(f&&l!=f&&u!=f)return h;f||(f=l)}else f||(f=s[0].id());var d=function(m){for(var E=m,C=[m],D,w,x;c[E].length;)D=c[E].shift(),w=v[D][0],x=v[D][1],E!=x?(c[x]=c[x].filter(function(T){return T!=D}),E=x):!i&&E!=w&&(c[w]=c[w].filter(function(T){return T!=D}),E=w),C.unshift(D),C.unshift(E);return C},y=[],p=[];for(p=d(f);p.length!=1;)c[p[0]].length==0?(y.unshift(s.getElementById(p.shift())),y.unshift(s.getElementById(p.shift()))):p=d(p.shift()).concat(p);y.unshift(s.getElementById(p.shift()));for(var g in c)if(c[g].length)return h;return h.found=!0,h.trail=this.spawn(y,!0),h}},Ta=function(){var e=this,r={},n=0,a=0,i=[],s=[],o={},u=function(v,h){for(var d=s.length-1,y=[],p=e.spawn();s[d].x!=v||s[d].y!=h;)y.push(s.pop().edge),d--;y.push(s.pop().edge),y.forEach(function(g){var b=g.connectedNodes().intersection(e);p.merge(g),b.forEach(function(m){var E=m.id(),C=m.connectedEdges().intersection(e);p.merge(m),r[E].cutVertex?p.merge(C.filter(function(D){return D.isLoop()})):p.merge(C)})}),i.push(p)},l=function c(v,h,d){v===d&&(a+=1),r[h]={id:n,low:n++,cutVertex:!1};var y=e.getElementById(h).connectedEdges().intersection(e);if(y.size()===0)i.push(e.spawn(e.getElementById(h)));else{var p,g,b,m;y.forEach(function(E){p=E.source().id(),g=E.target().id(),b=p===h?g:p,b!==d&&(m=E.id(),o[m]||(o[m]=!0,s.push({x:h,y:b,edge:E})),b in r?r[h].low=Math.min(r[h].low,r[b].id):(c(v,b,h),r[h].low=Math.min(r[h].low,r[b].low),r[h].id<=r[b].low&&(r[h].cutVertex=!0,u(h,b))))})}};e.forEach(function(c){if(c.isNode()){var v=c.id();v in r||(a=0,l(v,v),r[v].cutVertex=a>1)}});var f=Object.keys(r).filter(function(c){return r[c].cutVertex}).map(function(c){return e.getElementById(c)});return{cut:e.spawn(f),components:i}},xy={hopcroftTarjanBiconnected:Ta,htbc:Ta,htb:Ta,hopcroftTarjanBiconnectedComponents:Ta},Ca=function(){var e=this,r={},n=0,a=[],i=[],s=e.spawn(e),o=function u(l){i.push(l),r[l]={index:n,low:n++,explored:!1};var f=e.getElementById(l).connectedEdges().intersection(e);if(f.forEach(function(y){var p=y.target().id();p!==l&&(p in r||u(p),r[p].explored||(r[l].low=Math.min(r[l].low,r[p].low)))}),r[l].index===r[l].low){for(var c=e.spawn();;){var v=i.pop();if(c.merge(e.getElementById(v)),r[v].low=r[l].index,r[v].explored=!0,v===l)break}var h=c.edgesWith(c),d=c.merge(h);a.push(d),s=s.difference(d)}};return e.forEach(function(u){if(u.isNode()){var l=u.id();l in r||o(l)}}),{cut:s,components:a}},Ty={tarjanStronglyConnected:Ca,tsc:Ca,tscc:Ca,tarjanStronglyConnectedComponents:Ca},Fl={};[Wn,jg,ep,rp,ap,sp,lp,Rp,jr,en,rs,qp,sy,hy,by,Ey,xy,Ty].forEach(function(t){be(Fl,t)});/*! Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable diff --git a/assets/chunks/theme.B7K9K7dh.js b/assets/chunks/theme.BIU4L49Z.js similarity index 99% rename from assets/chunks/theme.B7K9K7dh.js rename to assets/chunks/theme.BIU4L49Z.js index 53a59f4a..d0f4b9b5 100644 --- a/assets/chunks/theme.B7K9K7dh.js +++ b/assets/chunks/theme.BIU4L49Z.js @@ -1,4 +1,4 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/VPLocalSearchBox.6bnhNGDg.js","assets/chunks/framework.DIzwIJpr.js"])))=>i.map(i=>d[i]); -import{d as b,o as s,c as l,r as v,n as H,a as j,t as T,b as y,w as p,e as f,T as ze,_ as g,u as Re,i as jt,f as Ut,g as qe,h as E,j as le,k as L,l as Y,m as u,p as i,q as Z,s as X,v as ie,x as Fe,y as te,z as Ce,A as Ke,B as ut,C as Gt,D as ce,F as A,E as G,G as dt,H as Te,I as _,J as re,K as mt,L as fe,M as we,N as Me,O as Rt,P as xe,Q as qt,R as We,S as vt,U as Kt,V as Wt,W as Yt,X as pt,Y as ht,Z as ft,$ as Zt,a0 as Xt,a1 as Jt,a2 as Qt,a3 as en,a4 as Ve,a5 as tn}from"./framework.DIzwIJpr.js";const nn=b({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(n){return(e,t)=>(s(),l("span",{class:H(["VPBadge",e.type])},[v(e.$slots,"default",{},()=>[j(T(e.text),1)])],2))}}),on={key:0,class:"VPBackdrop"},an=b({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(n){return(e,t)=>(s(),y(ze,{name:"fade"},{default:p(()=>[e.show?(s(),l("div",on)):f("",!0)]),_:1}))}}),sn=g(an,[["__scopeId","data-v-39225c2a"]]),z=Re;function rn(n,e){let t,o=!1;return()=>{t&&clearTimeout(t),o?t=setTimeout(n,e):(n(),(o=!0)&&setTimeout(()=>o=!1,e))}}function je(n){return/^\//.test(n)?n:`/${n}`}function Ye(n){const{pathname:e,search:t,hash:o,protocol:a}=new URL(n,"http://a.com");if(jt(n)||n.startsWith("#")||!a.startsWith("http")||!Ut(e))return n;const{site:r}=z(),c=e.endsWith("/")||e.endsWith(".html")?n:n.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,r.value.cleanUrls?"":".html")}${t}${o}`);return qe(c)}const Ze=E(le?location.hash:"");le&&window.addEventListener("hashchange",()=>{Ze.value=location.hash});function _e({removeCurrent:n=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:o,page:a,theme:r}=z(),c=L(()=>{var m,k;return{label:(m=t.value.locales[o.value])==null?void 0:m.label,link:((k=t.value.locales[o.value])==null?void 0:k.link)||(o.value==="root"?"/":`/${o.value}/`)}});return{localeLinks:L(()=>Object.entries(t.value.locales).flatMap(([m,k])=>n&&c.value.label===k.label?[]:{text:k.label,link:ln(k.link||(m==="root"?"/":`/${m}/`),r.value.i18nRouting!==!1&&e,a.value.relativePath.slice(c.value.link.length-1),!t.value.cleanUrls)+Ze.value})),currentLang:c}}function ln(n,e,t,o){return e?n.replace(/\/$/,"")+je(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,o?".html":"")):n}const cn=n=>(Z("data-v-b4d69a0b"),n=n(),X(),n),un={class:"NotFound"},dn={class:"code"},mn={class:"title"},vn=cn(()=>u("div",{class:"divider"},null,-1)),pn={class:"quote"},hn={class:"action"},fn=["href","aria-label"],_n=b({__name:"NotFound",setup(n){const{site:e,theme:t}=z(),{localeLinks:o}=_e({removeCurrent:!1}),a=E("/");return Y(()=>{var c;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");o.value.length&&(a.value=((c=o.value.find(({link:d})=>d.startsWith(r)))==null?void 0:c.link)||o.value[0].link)}),(r,c)=>{var d,m,k,$,w;return s(),l("div",un,[u("p",dn,T(((d=i(t).notFound)==null?void 0:d.code)??"404"),1),u("h1",mn,T(((m=i(t).notFound)==null?void 0:m.title)??"PAGE NOT FOUND"),1),vn,u("blockquote",pn,T(((k=i(t).notFound)==null?void 0:k.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),u("div",hn,[u("a",{class:"link",href:i(qe)(a.value),"aria-label":(($=i(t).notFound)==null?void 0:$.linkLabel)??"go to home"},T(((w=i(t).notFound)==null?void 0:w.linkText)??"Take me home"),9,fn)])])}}}),gn=g(_n,[["__scopeId","data-v-b4d69a0b"]]);function _t(n,e){if(Array.isArray(n))return Le(n);if(n==null)return[];e=je(e);const t=Object.keys(n).sort((a,r)=>r.split("/").length-a.split("/").length).find(a=>e.startsWith(je(a))),o=t?n[t]:[];return Array.isArray(o)?Le(o):Le(o.items,o.base)}function bn(n){const e=[];let t=0;for(const o in n){const a=n[o];if(a.items){t=e.push(a);continue}e[t]||e.push({items:[]}),e[t].items.push(a)}return e}function kn(n){const e=[];function t(o){for(const a of o)a.text&&a.link&&e.push({text:a.text,link:a.link,docFooterText:a.docFooterText}),a.items&&t(a.items)}return t(n),e}function Ue(n,e){return Array.isArray(e)?e.some(t=>Ue(n,t)):ie(n,e.link)?!0:e.items?Ue(n,e.items):!1}function Le(n,e){return[...n].map(t=>{const o={...t},a=o.base||e;return a&&o.link&&(o.link=a+o.link),o.items&&(o.items=Le(o.items,a)),o})}function ne(){const{frontmatter:n,page:e,theme:t}=z(),o=Fe("(min-width: 960px)"),a=E(!1),r=L(()=>{const I=t.value.sidebar,N=e.value.relativePath;return I?_t(I,N):[]}),c=E(r.value);te(r,(I,N)=>{JSON.stringify(I)!==JSON.stringify(N)&&(c.value=r.value)});const d=L(()=>n.value.sidebar!==!1&&c.value.length>0&&n.value.layout!=="home"),m=L(()=>k?n.value.aside==null?t.value.aside==="left":n.value.aside==="left":!1),k=L(()=>n.value.layout==="home"?!1:n.value.aside!=null?!!n.value.aside:t.value.aside!==!1),$=L(()=>d.value&&o.value),w=L(()=>d.value?bn(c.value):[]);function S(){a.value=!0}function B(){a.value=!1}function V(){a.value?B():S()}return{isOpen:a,sidebar:c,sidebarGroups:w,hasSidebar:d,hasAside:k,leftAside:m,isSidebarEnabled:$,open:S,close:B,toggle:V}}function $n(n,e){let t;Ce(()=>{t=n.value?document.activeElement:void 0}),Y(()=>{window.addEventListener("keyup",o)}),Ke(()=>{window.removeEventListener("keyup",o)});function o(a){a.key==="Escape"&&n.value&&(e(),t==null||t.focus())}}function yn(n){const{page:e}=z(),t=E(!1),o=L(()=>n.value.collapsed!=null),a=L(()=>!!n.value.link),r=E(!1),c=()=>{r.value=ie(e.value.relativePath,n.value.link)};te([e,n,Ze],c),Y(c);const d=L(()=>r.value?!0:n.value.items?Ue(e.value.relativePath,n.value.items):!1),m=L(()=>!!(n.value.items&&n.value.items.length));Ce(()=>{t.value=!!(o.value&&n.value.collapsed)}),ut(()=>{(r.value||d.value)&&(t.value=!1)});function k(){o.value&&(t.value=!t.value)}return{collapsed:t,collapsible:o,isLink:a,isActiveLink:r,hasActiveLink:d,hasChildren:m,toggle:k}}function wn(){const{hasSidebar:n}=ne(),e=Fe("(min-width: 960px)"),t=Fe("(min-width: 1280px)");return{isAsideEnabled:L(()=>!t.value&&!e.value?!1:n.value?t.value:e.value)}}const Ge=[];function gt(n){return typeof n.outline=="object"&&!Array.isArray(n.outline)&&n.outline.label||n.outlineTitle||"On this page"}function Xe(n){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const o=Number(t.tagName[1]);return{element:t,title:Ln(t),link:"#"+t.id,level:o}});return Pn(e,n)}function Ln(n){let e="";for(const t of n.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Pn(n,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[o,a]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;n=n.filter(c=>c.level>=o&&c.level<=a),Ge.length=0;for(const{element:c,link:d}of n)Ge.push({element:c,link:d});const r=[];e:for(let c=0;c=0;m--){const k=n[m];if(k.level{requestAnimationFrame(r),window.addEventListener("scroll",o)}),Gt(()=>{c(location.hash)}),Ke(()=>{window.removeEventListener("scroll",o)});function r(){if(!t.value)return;const d=(()=>{var I;const V=(I=document.querySelector("#VPContent .VPDoc"))==null?void 0:I.firstElementChild;return V?ot(V):78})(),m=window.scrollY,k=window.innerHeight,$=document.body.offsetHeight,w=Math.abs(m+k-$)<1,S=Ge.map(({element:V,link:I})=>({link:I,top:ot(V)})).filter(({top:V})=>!Number.isNaN(V)).sort((V,I)=>V.top-I.top);if(!S.length){c(null);return}if(m<1){c(null);return}if(w){c(S[S.length-1].link);return}let B=null;for(const{link:V,top:I}of S){if(I>m+d)break;B=V}c(B)}function c(d){a&&a.classList.remove("active"),d==null?a=null:a=n.value.querySelector(`a[href="${decodeURIComponent(d)}"]`);const m=a;m?(m.classList.add("active"),e.value.style.top=m.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function ot(n){let e=0;for(;n!==document.body;){if(n===null)return NaN;e+=n.offsetTop,n=n.offsetParent}return e}const Sn=["href","title"],zn=b({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(n){function e({target:t}){const o=t.href.split("#")[1],a=document.getElementById(decodeURIComponent(o));a==null||a.focus({preventScroll:!0})}return(t,o)=>{const a=ce("VPDocOutlineItem",!0);return s(),l("ul",{class:H(["VPDocOutlineItem",t.root?"root":"nested"])},[(s(!0),l(A,null,G(t.headers,({children:r,link:c,title:d})=>(s(),l("li",null,[u("a",{class:"outline-link",href:c,onClick:e,title:d},T(d),9,Sn),r!=null&&r.length?(s(),y(a,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}}),bt=g(zn,[["__scopeId","data-v-f4ef067b"]]),Cn=n=>(Z("data-v-f1d5f0bc"),n=n(),X(),n),Tn={class:"content"},Mn={class:"outline-title",role:"heading","aria-level":"2"},In={"aria-labelledby":"doc-outline-aria-label"},En=Cn(()=>u("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Nn=b({__name:"VPDocAsideOutline",setup(n){const{frontmatter:e,theme:t}=z(),o=dt([]);Te(()=>{o.value=Xe(e.value.outline??t.value.outline)});const a=E(),r=E();return Vn(a,r),(c,d)=>(s(),l("div",{class:H(["VPDocAsideOutline",{"has-outline":o.value.length>0}]),ref_key:"container",ref:a,role:"navigation"},[u("div",Tn,[u("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),u("div",Mn,T(i(gt)(i(t))),1),u("nav",In,[En,_(bt,{headers:o.value,root:!0},null,8,["headers"])])])],2))}}),Hn=g(Nn,[["__scopeId","data-v-f1d5f0bc"]]),An={class:"VPDocAsideCarbonAds"},Bn=b({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(n){const e=()=>null;return(t,o)=>(s(),l("div",An,[_(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),On=n=>(Z("data-v-5207b98e"),n=n(),X(),n),Dn={class:"VPDocAside"},Fn=On(()=>u("div",{class:"spacer"},null,-1)),xn=b({__name:"VPDocAside",setup(n){const{theme:e}=z();return(t,o)=>(s(),l("div",Dn,[v(t.$slots,"aside-top",{},void 0,!0),v(t.$slots,"aside-outline-before",{},void 0,!0),_(Hn),v(t.$slots,"aside-outline-after",{},void 0,!0),Fn,v(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(s(),y(Bn,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):f("",!0),v(t.$slots,"aside-ads-after",{},void 0,!0),v(t.$slots,"aside-bottom",{},void 0,!0)]))}}),jn=g(xn,[["__scopeId","data-v-5207b98e"]]);function Un(){const{theme:n,page:e}=z();return L(()=>{const{text:t="Edit this page",pattern:o=""}=n.value.editLink||{};let a;return typeof o=="function"?a=o(e.value):a=o.replace(/:path/g,e.value.filePath),{url:a,text:t}})}function Gn(){const{page:n,theme:e,frontmatter:t}=z();return L(()=>{var m,k,$,w,S,B,V,I;const o=_t(e.value.sidebar,n.value.relativePath),a=kn(o),r=a.findIndex(N=>ie(n.value.relativePath,N.link)),c=((m=e.value.docFooter)==null?void 0:m.prev)===!1&&!t.value.prev||t.value.prev===!1,d=((k=e.value.docFooter)==null?void 0:k.next)===!1&&!t.value.next||t.value.next===!1;return{prev:c?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??(($=a[r-1])==null?void 0:$.docFooterText)??((w=a[r-1])==null?void 0:w.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((S=a[r-1])==null?void 0:S.link)},next:d?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((B=a[r+1])==null?void 0:B.docFooterText)??((V=a[r+1])==null?void 0:V.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((I=a[r+1])==null?void 0:I.link)}}})}const Rn={},qn={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Kn=u("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),Wn=u("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),Yn=[Kn,Wn];function Zn(n,e){return s(),l("svg",qn,Yn)}const Xn=g(Rn,[["render",Zn]]),K=b({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(n){const e=n,t=L(()=>e.tag??(e.href?"a":"span")),o=L(()=>e.href&&mt.test(e.href));return(a,r)=>(s(),y(re(t.value),{class:H(["VPLink",{link:a.href,"vp-external-link-icon":o.value,"no-icon":a.noIcon}]),href:a.href?i(Ye)(a.href):void 0,target:a.target??(o.value?"_blank":void 0),rel:a.rel??(o.value?"noreferrer":void 0)},{default:p(()=>[v(a.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Jn={class:"VPLastUpdated"},Qn=["datetime"],eo=b({__name:"VPDocFooterLastUpdated",setup(n){const{theme:e,page:t,frontmatter:o,lang:a}=z(),r=L(()=>new Date(o.value.lastUpdated??t.value.lastUpdated)),c=L(()=>r.value.toISOString()),d=E("");return Y(()=>{Ce(()=>{var m,k,$;d.value=new Intl.DateTimeFormat((k=(m=e.value.lastUpdated)==null?void 0:m.formatOptions)!=null&&k.forceLocale?a.value:void 0,(($=e.value.lastUpdated)==null?void 0:$.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(m,k)=>{var $;return s(),l("p",Jn,[j(T((($=i(e).lastUpdated)==null?void 0:$.text)||i(e).lastUpdatedText||"Last updated")+": ",1),u("time",{datetime:c.value},T(d.value),9,Qn)])}}}),to=g(eo,[["__scopeId","data-v-e6d29f27"]]),no={key:0,class:"VPDocFooter"},oo={key:0,class:"edit-info"},ao={key:0,class:"edit-link"},so={key:1,class:"last-updated"},ro={key:1,class:"prev-next"},io={class:"pager"},lo=["innerHTML"],co=["innerHTML"],uo={class:"pager"},mo=["innerHTML"],vo=["innerHTML"],po=b({__name:"VPDocFooter",setup(n){const{theme:e,page:t,frontmatter:o}=z(),a=Un(),r=Gn(),c=L(()=>e.value.editLink&&o.value.editLink!==!1),d=L(()=>t.value.lastUpdated&&o.value.lastUpdated!==!1),m=L(()=>c.value||d.value||r.value.prev||r.value.next);return(k,$)=>{var w,S,B,V;return m.value?(s(),l("footer",no,[v(k.$slots,"doc-footer-before",{},void 0,!0),c.value||d.value?(s(),l("div",oo,[c.value?(s(),l("div",ao,[_(K,{class:"edit-link-button",href:i(a).url,"no-icon":!0},{default:p(()=>[_(Xn,{class:"edit-link-icon","aria-label":"edit icon"}),j(" "+T(i(a).text),1)]),_:1},8,["href"])])):f("",!0),d.value?(s(),l("div",so,[_(to)])):f("",!0)])):f("",!0),(w=i(r).prev)!=null&&w.link||(S=i(r).next)!=null&&S.link?(s(),l("nav",ro,[u("div",io,[(B=i(r).prev)!=null&&B.link?(s(),y(K,{key:0,class:"pager-link prev",href:i(r).prev.link},{default:p(()=>{var I;return[u("span",{class:"desc",innerHTML:((I=i(e).docFooter)==null?void 0:I.prev)||"Previous page"},null,8,lo),u("span",{class:"title",innerHTML:i(r).prev.text},null,8,co)]}),_:1},8,["href"])):f("",!0)]),u("div",uo,[(V=i(r).next)!=null&&V.link?(s(),y(K,{key:0,class:"pager-link next",href:i(r).next.link},{default:p(()=>{var I;return[u("span",{class:"desc",innerHTML:((I=i(e).docFooter)==null?void 0:I.next)||"Next page"},null,8,mo),u("span",{class:"title",innerHTML:i(r).next.text},null,8,vo)]}),_:1},8,["href"])):f("",!0)])])):f("",!0)])):f("",!0)}}}),ho=g(po,[["__scopeId","data-v-da9bd828"]]),fo=n=>(Z("data-v-e5aed501"),n=n(),X(),n),_o={class:"container"},go=fo(()=>u("div",{class:"aside-curtain"},null,-1)),bo={class:"aside-container"},ko={class:"aside-content"},$o={class:"content"},yo={class:"content-container"},wo={class:"main"},Lo=b({__name:"VPDoc",setup(n){const{theme:e}=z(),t=fe(),{hasSidebar:o,hasAside:a,leftAside:r}=ne(),c=L(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(d,m)=>{const k=ce("Content");return s(),l("div",{class:H(["VPDoc",{"has-sidebar":i(o),"has-aside":i(a)}])},[v(d.$slots,"doc-top",{},void 0,!0),u("div",_o,[i(a)?(s(),l("div",{key:0,class:H(["aside",{"left-aside":i(r)}])},[go,u("div",bo,[u("div",ko,[_(jn,null,{"aside-top":p(()=>[v(d.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[v(d.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[v(d.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(d.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(d.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(d.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),u("div",$o,[u("div",yo,[v(d.$slots,"doc-before",{},void 0,!0),u("main",wo,[_(k,{class:H(["vp-doc",[c.value,i(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),_(ho,null,{"doc-footer-before":p(()=>[v(d.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),v(d.$slots,"doc-after",{},void 0,!0)])])]),v(d.$slots,"doc-bottom",{},void 0,!0)],2)}}}),Po=g(Lo,[["__scopeId","data-v-e5aed501"]]),Vo=b({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{}},setup(n){const e=n,t=L(()=>e.href&&mt.test(e.href)),o=L(()=>e.tag||e.href?"a":"button");return(a,r)=>(s(),y(re(o.value),{class:H(["VPButton",[a.size,a.theme]]),href:a.href?i(Ye)(a.href):void 0,target:t.value?"_blank":void 0,rel:t.value?"noreferrer":void 0},{default:p(()=>[j(T(a.text),1)]),_:1},8,["class","href","target","rel"]))}}),So=g(Vo,[["__scopeId","data-v-70b4c594"]]),zo=["src","alt"],Co=b({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(n){return(e,t)=>{const o=ce("VPImage",!0);return e.image?(s(),l(A,{key:0},[typeof e.image=="string"||"src"in e.image?(s(),l("img",we({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(qe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,zo)):(s(),l(A,{key:1},[_(o,we({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),_(o,we({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}}),Se=g(Co,[["__scopeId","data-v-a3c772fb"]]),To=n=>(Z("data-v-22db75ec"),n=n(),X(),n),Mo={class:"container"},Io={class:"main"},Eo={key:0,class:"name"},No=["innerHTML"],Ho=["innerHTML"],Ao=["innerHTML"],Bo={key:0,class:"actions"},Oo={key:0,class:"image"},Do={class:"image-container"},Fo=To(()=>u("div",{class:"image-bg"},null,-1)),xo=b({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(n){const e=Me("hero-image-slot-exists");return(t,o)=>(s(),l("div",{class:H(["VPHero",{"has-image":t.image||i(e)}])},[u("div",Mo,[u("div",Io,[v(t.$slots,"home-hero-info",{},()=>[t.name?(s(),l("h1",Eo,[u("span",{innerHTML:t.name,class:"clip"},null,8,No)])):f("",!0),t.text?(s(),l("p",{key:1,innerHTML:t.text,class:"text"},null,8,Ho)):f("",!0),t.tagline?(s(),l("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Ao)):f("",!0)],!0),t.actions?(s(),l("div",Bo,[(s(!0),l(A,null,G(t.actions,a=>(s(),l("div",{key:a.link,class:"action"},[_(So,{tag:"a",size:"medium",theme:a.theme,text:a.text,href:a.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||i(e)?(s(),l("div",Oo,[u("div",Do,[Fo,v(t.$slots,"home-hero-image",{},()=>[t.image?(s(),y(Se,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}}),jo=g(xo,[["__scopeId","data-v-22db75ec"]]),Uo=b({__name:"VPHomeHero",setup(n){const{frontmatter:e}=z();return(t,o)=>i(e).hero?(s(),y(jo,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info":p(()=>[v(t.$slots,"home-hero-info")]),"home-hero-image":p(()=>[v(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Go={},Ro={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},qo=u("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Ko=[qo];function Wo(n,e){return s(),l("svg",Ro,Ko)}const Yo=g(Go,[["render",Wo]]),Zo={class:"box"},Xo={key:0,class:"icon"},Jo=["innerHTML"],Qo=["innerHTML"],ea=["innerHTML"],ta={key:4,class:"link-text"},na={class:"link-text-value"},oa=b({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(n){return(e,t)=>(s(),y(K,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:p(()=>[u("article",Zo,[typeof e.icon=="object"&&e.icon.wrap?(s(),l("div",Xo,[_(Se,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(s(),y(Se,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(s(),l("div",{key:2,class:"icon",innerHTML:e.icon},null,8,Jo)):f("",!0),u("h2",{class:"title",innerHTML:e.title},null,8,Qo),e.details?(s(),l("p",{key:3,class:"details",innerHTML:e.details},null,8,ea)):f("",!0),e.linkText?(s(),l("div",ta,[u("p",na,[j(T(e.linkText)+" ",1),_(Yo,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),aa=g(oa,[["__scopeId","data-v-2908087c"]]),sa={key:0,class:"VPFeatures"},ra={class:"container"},ia={class:"items"},la=b({__name:"VPFeatures",props:{features:{}},setup(n){const e=n,t=L(()=>{const o=e.features.length;if(o){if(o===2)return"grid-2";if(o===3)return"grid-3";if(o%3===0)return"grid-6";if(o>3)return"grid-4"}else return});return(o,a)=>o.features?(s(),l("div",sa,[u("div",ra,[u("div",ia,[(s(!0),l(A,null,G(o.features,r=>(s(),l("div",{key:r.title,class:H(["item",[t.value]])},[_(aa,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}}),ca=g(la,[["__scopeId","data-v-25d4ed06"]]),ua=b({__name:"VPHomeFeatures",setup(n){const{frontmatter:e}=z();return(t,o)=>i(e).features?(s(),y(ca,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):f("",!0)}}),da={class:"VPHome"},ma=b({__name:"VPHome",setup(n){return(e,t)=>{const o=ce("Content");return s(),l("div",da,[v(e.$slots,"home-hero-before",{},void 0,!0),_(Uo,null,{"home-hero-info":p(()=>[v(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),v(e.$slots,"home-hero-after",{},void 0,!0),v(e.$slots,"home-features-before",{},void 0,!0),_(ua),v(e.$slots,"home-features-after",{},void 0,!0),_(o)])}}}),va=g(ma,[["__scopeId","data-v-5629135b"]]),pa={},ha={class:"VPPage"};function fa(n,e){const t=ce("Content");return s(),l("div",ha,[v(n.$slots,"page-top"),_(t),v(n.$slots,"page-bottom")])}const _a=g(pa,[["render",fa]]),ga=b({__name:"VPContent",setup(n){const{page:e,frontmatter:t}=z(),{hasSidebar:o}=ne();return(a,r)=>(s(),l("div",{class:H(["VPContent",{"has-sidebar":i(o),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?v(a.$slots,"not-found",{key:0},()=>[_(gn)],!0):i(t).layout==="page"?(s(),y(_a,{key:1},{"page-top":p(()=>[v(a.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[v(a.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(s(),y(va,{key:2},{"home-hero-before":p(()=>[v(a.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":p(()=>[v(a.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(a.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[v(a.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[v(a.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[v(a.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(t).layout&&i(t).layout!=="doc"?(s(),y(re(i(t).layout),{key:3})):(s(),y(Po,{key:4},{"doc-top":p(()=>[v(a.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[v(a.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":p(()=>[v(a.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[v(a.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[v(a.$slots,"doc-after",{},void 0,!0)]),"aside-top":p(()=>[v(a.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":p(()=>[v(a.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(a.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(a.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(a.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":p(()=>[v(a.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),ba=g(ga,[["__scopeId","data-v-6274197d"]]),ka={class:"container"},$a=["innerHTML"],ya=["innerHTML"],wa=b({__name:"VPFooter",setup(n){const{theme:e,frontmatter:t}=z(),{hasSidebar:o}=ne();return(a,r)=>i(e).footer&&i(t).footer!==!1?(s(),l("footer",{key:0,class:H(["VPFooter",{"has-sidebar":i(o)}])},[u("div",ka,[i(e).footer.message?(s(),l("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,$a)):f("",!0),i(e).footer.copyright?(s(),l("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,ya)):f("",!0)])],2)):f("",!0)}}),La=g(wa,[["__scopeId","data-v-48fac9ef"]]);function kt(){const{theme:n,frontmatter:e}=z(),t=dt([]),o=L(()=>t.value.length>0);return Te(()=>{t.value=Xe(e.value.outline??n.value.outline)}),{headers:t,hasLocalNav:o}}const Pa={},Va={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Sa=u("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),za=[Sa];function Ca(n,e){return s(),l("svg",Va,za)}const $t=g(Pa,[["render",Ca]]),Ta={class:"header"},Ma={class:"outline"},Ia=b({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(n){const e=n,{theme:t}=z(),o=E(!1),a=E(0),r=E(),c=E();Rt(r,()=>{o.value=!1}),xe("Escape",()=>{o.value=!1}),Te(()=>{o.value=!1});function d(){o.value=!o.value,a.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function m($){$.target.classList.contains("outline-link")&&(c.value&&(c.value.style.transition="none"),We(()=>{o.value=!1}))}function k(){o.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return($,w)=>(s(),l("div",{class:"VPLocalNavOutlineDropdown",style:qt({"--vp-vh":a.value+"px"}),ref_key:"main",ref:r},[$.headers.length>0?(s(),l("button",{key:0,onClick:d,class:H({open:o.value})},[j(T(i(gt)(i(t)))+" ",1),_($t,{class:"icon"})],2)):(s(),l("button",{key:1,onClick:k},T(i(t).returnToTopLabel||"Return to top"),1)),_(ze,{name:"flyout"},{default:p(()=>[o.value?(s(),l("div",{key:0,ref_key:"items",ref:c,class:"items",onClick:m},[u("div",Ta,[u("a",{class:"top-link",href:"#",onClick:k},T(i(t).returnToTopLabel||"Return to top"),1)]),u("div",Ma,[_(bt,{headers:$.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}}),Ea=g(Ia,[["__scopeId","data-v-57a7b996"]]),Na={},Ha={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Aa=u("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Ba=u("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),Oa=u("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Da=u("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Fa=[Aa,Ba,Oa,Da];function xa(n,e){return s(),l("svg",Ha,Fa)}const ja=g(Na,[["render",xa]]),Ua={class:"container"},Ga=["aria-expanded"],Ra={class:"menu-text"},qa=b({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(n){const{theme:e,frontmatter:t}=z(),{hasSidebar:o}=ne(),{headers:a}=kt(),{y:r}=vt(),c=E(0);Y(()=>{c.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Te(()=>{a.value=Xe(t.value.outline??e.value.outline)});const d=L(()=>a.value.length===0),m=L(()=>d.value&&!o.value),k=L(()=>({VPLocalNav:!0,"has-sidebar":o.value,empty:d.value,fixed:m.value}));return($,w)=>i(t).layout!=="home"&&(!m.value||i(r)>=c.value)?(s(),l("div",{key:0,class:H(k.value)},[u("div",Ua,[i(o)?(s(),l("button",{key:0,class:"menu","aria-expanded":$.open,"aria-controls":"VPSidebarNav",onClick:w[0]||(w[0]=S=>$.$emit("open-menu"))},[_(ja,{class:"menu-icon"}),u("span",Ra,T(i(e).sidebarMenuLabel||"Menu"),1)],8,Ga)):f("",!0),_(Ea,{headers:i(a),navHeight:c.value},null,8,["headers","navHeight"])])],2)):f("",!0)}}),Ka=g(qa,[["__scopeId","data-v-9df9ee96"]]);function Wa(){const n=E(!1);function e(){n.value=!0,window.addEventListener("resize",a)}function t(){n.value=!1,window.removeEventListener("resize",a)}function o(){n.value?t():e()}function a(){window.outerWidth>=768&&t()}const r=fe();return te(()=>r.path,t),{isScreenOpen:n,openScreen:e,closeScreen:t,toggleScreen:o}}const Ya={},Za={class:"VPSwitch",type:"button",role:"switch"},Xa={class:"check"},Ja={key:0,class:"icon"};function Qa(n,e){return s(),l("button",Za,[u("span",Xa,[n.$slots.default?(s(),l("span",Ja,[v(n.$slots,"default",{},void 0,!0)])):f("",!0)])])}const es=g(Ya,[["render",Qa],["__scopeId","data-v-c5ec0895"]]),ts={},ns={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},os=u("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),as=[os];function ss(n,e){return s(),l("svg",ns,as)}const rs=g(ts,[["render",ss]]),is={},ls={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},cs=Kt('',9),us=[cs];function ds(n,e){return s(),l("svg",ls,us)}const ms=g(is,[["render",ds]]),vs=b({__name:"VPSwitchAppearance",setup(n){const{isDark:e,theme:t}=z(),o=Me("toggle-appearance",()=>{e.value=!e.value}),a=L(()=>e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme");return(r,c)=>(s(),y(es,{title:a.value,class:"VPSwitchAppearance","aria-checked":i(e),onClick:i(o)},{default:p(()=>[_(ms,{class:"sun"}),_(rs,{class:"moon"})]),_:1},8,["title","aria-checked","onClick"]))}}),Je=g(vs,[["__scopeId","data-v-fcacf28d"]]),ps={key:0,class:"VPNavBarAppearance"},hs=b({__name:"VPNavBarAppearance",setup(n){const{site:e}=z();return(t,o)=>i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",ps,[_(Je)])):f("",!0)}}),fs=g(hs,[["__scopeId","data-v-b2119317"]]),Qe=E();let yt=!1,Oe=0;function _s(n){const e=E(!1);if(le){!yt&&gs(),Oe++;const t=te(Qe,o=>{var a,r,c;o===n.el.value||(a=n.el.value)!=null&&a.contains(o)?(e.value=!0,(r=n.onFocus)==null||r.call(n)):(e.value=!1,(c=n.onBlur)==null||c.call(n))});Ke(()=>{t(),Oe--,Oe||bs()})}return Wt(e)}function gs(){document.addEventListener("focusin",wt),yt=!0,Qe.value=document.activeElement}function bs(){document.removeEventListener("focusin",wt)}function wt(){Qe.value=document.activeElement}const ks={},$s={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ys=u("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),ws=[ys];function Ls(n,e){return s(),l("svg",$s,ws)}const Lt=g(ks,[["render",Ls]]),Ps={},Vs={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ss=u("circle",{cx:"12",cy:"12",r:"2"},null,-1),zs=u("circle",{cx:"19",cy:"12",r:"2"},null,-1),Cs=u("circle",{cx:"5",cy:"12",r:"2"},null,-1),Ts=[Ss,zs,Cs];function Ms(n,e){return s(),l("svg",Vs,Ts)}const Is=g(Ps,[["render",Ms]]),Es={class:"VPMenuLink"},Ns=b({__name:"VPMenuLink",props:{item:{}},setup(n){const{page:e}=z();return(t,o)=>(s(),l("div",Es,[_(K,{class:H({active:i(ie)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),Ie=g(Ns,[["__scopeId","data-v-c0982df3"]]),Hs={class:"VPMenuGroup"},As={key:0,class:"title"},Bs=b({__name:"VPMenuGroup",props:{text:{},items:{}},setup(n){return(e,t)=>(s(),l("div",Hs,[e.text?(s(),l("p",As,T(e.text),1)):f("",!0),(s(!0),l(A,null,G(e.items,o=>(s(),l(A,null,["link"in o?(s(),y(Ie,{key:0,item:o},null,8,["item"])):f("",!0)],64))),256))]))}}),Os=g(Bs,[["__scopeId","data-v-23ee77ae"]]),Ds={class:"VPMenu"},Fs={key:0,class:"items"},xs=b({__name:"VPMenu",props:{items:{}},setup(n){return(e,t)=>(s(),l("div",Ds,[e.items?(s(),l("div",Fs,[(s(!0),l(A,null,G(e.items,o=>(s(),l(A,{key:o.text},["link"in o?(s(),y(Ie,{key:0,item:o},null,8,["item"])):(s(),y(Os,{key:1,text:o.text,items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0),v(e.$slots,"default",{},void 0,!0)]))}}),js=g(xs,[["__scopeId","data-v-87095e00"]]),Us=["aria-expanded","aria-label"],Gs={key:0,class:"text"},Rs=["innerHTML"],qs={class:"menu"},Ks=b({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(n){const e=E(!1),t=E();_s({el:t,onBlur:o});function o(){e.value=!1}return(a,r)=>(s(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=c=>e.value=!0),onMouseleave:r[2]||(r[2]=c=>e.value=!1)},[u("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":a.label,onClick:r[0]||(r[0]=c=>e.value=!e.value)},[a.button||a.icon?(s(),l("span",Gs,[a.icon?(s(),y(re(a.icon),{key:0,class:"option-icon"})):f("",!0),a.button?(s(),l("span",{key:1,innerHTML:a.button},null,8,Rs)):f("",!0),_(Lt,{class:"text-icon"})])):(s(),y(Is,{key:1,class:"icon"}))],8,Us),u("div",qs,[_(js,{items:a.items},{default:p(()=>[v(a.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),et=g(Ks,[["__scopeId","data-v-f5a36f1b"]]),Ws={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},Ys=["href","aria-label","innerHTML"],Zs=b({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(n){const e=n,t=L(()=>typeof e.icon=="object"?e.icon.svg:Ws[e.icon]);return(o,a)=>(s(),l("a",{class:"VPSocialLink no-icon",href:o.link,"aria-label":o.ariaLabel??(typeof o.icon=="string"?o.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,Ys))}}),Xs=g(Zs,[["__scopeId","data-v-405b7737"]]),Js={class:"VPSocialLinks"},Qs=b({__name:"VPSocialLinks",props:{links:{}},setup(n){return(e,t)=>(s(),l("div",Js,[(s(!0),l(A,null,G(e.links,({link:o,icon:a,ariaLabel:r})=>(s(),y(Xs,{key:o,icon:a,link:o,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}}),Ee=g(Qs,[["__scopeId","data-v-c9800f80"]]),er={key:0,class:"group translations"},tr={class:"trans-title"},nr={key:1,class:"group"},or={class:"item appearance"},ar={class:"label"},sr={class:"appearance-action"},rr={key:2,class:"group"},ir={class:"item social-links"},lr=b({__name:"VPNavBarExtra",setup(n){const{site:e,theme:t}=z(),{localeLinks:o,currentLang:a}=_e({correspondingLink:!0}),r=L(()=>o.value.length&&a.value.label||e.value.appearance||t.value.socialLinks);return(c,d)=>r.value?(s(),y(et,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:p(()=>[i(o).length&&i(a).label?(s(),l("div",er,[u("p",tr,T(i(a).label),1),(s(!0),l(A,null,G(i(o),m=>(s(),y(Ie,{key:m.link,item:m},null,8,["item"]))),128))])):f("",!0),i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",nr,[u("div",or,[u("p",ar,T(i(t).darkModeSwitchLabel||"Appearance"),1),u("div",sr,[_(Je)])])])):f("",!0),i(t).socialLinks?(s(),l("div",rr,[u("div",ir,[_(Ee,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}}),cr=g(lr,[["__scopeId","data-v-8a171de0"]]),ur=n=>(Z("data-v-f746d7e0"),n=n(),X(),n),dr=["aria-expanded"],mr=ur(()=>u("span",{class:"container"},[u("span",{class:"top"}),u("span",{class:"middle"}),u("span",{class:"bottom"})],-1)),vr=[mr],pr=b({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(n){return(e,t)=>(s(),l("button",{type:"button",class:H(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=o=>e.$emit("click"))},vr,10,dr))}}),hr=g(pr,[["__scopeId","data-v-f746d7e0"]]),fr=["innerHTML"],_r=b({__name:"VPNavBarMenuLink",props:{item:{}},setup(n){const{page:e}=z();return(t,o)=>(s(),y(K,{class:H({VPNavBarMenuLink:!0,active:i(ie)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:p(()=>[u("span",{innerHTML:t.item.text},null,8,fr)]),_:1},8,["class","href","target","rel"]))}}),gr=g(_r,[["__scopeId","data-v-ef9c2bfa"]]),br=b({__name:"VPNavBarMenuGroup",props:{item:{}},setup(n){const e=n,{page:t}=z(),o=r=>"link"in r?ie(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(o),a=L(()=>o(e.item));return(r,c)=>(s(),y(et,{class:H({VPNavBarMenuGroup:!0,active:i(ie)(i(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||a.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),kr=n=>(Z("data-v-ca39d846"),n=n(),X(),n),$r={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},yr=kr(()=>u("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),wr=b({__name:"VPNavBarMenu",setup(n){const{theme:e}=z();return(t,o)=>i(e).nav?(s(),l("nav",$r,[yr,(s(!0),l(A,null,G(i(e).nav,a=>(s(),l(A,{key:a.text},["link"in a?(s(),y(gr,{key:0,item:a},null,8,["item"])):(s(),y(br,{key:1,item:a},null,8,["item"]))],64))),128))])):f("",!0)}}),Lr=g(wr,[["__scopeId","data-v-ca39d846"]]);function Pr(n){const{localeIndex:e,theme:t}=z();function o(a){var V,I,N;const r=a.split("."),c=(V=t.value.search)==null?void 0:V.options,d=c&&typeof c=="object",m=d&&((N=(I=c.locales)==null?void 0:I[e.value])==null?void 0:N.translations)||null,k=d&&c.translations||null;let $=m,w=k,S=n;const B=r.pop();for(const ue of r){let J=null;const F=S==null?void 0:S[ue];F&&(J=S=F);const oe=w==null?void 0:w[ue];oe&&(J=w=oe);const Q=$==null?void 0:$[ue];Q&&(J=$=Q),F||(S=J),oe||(w=J),Q||($=J)}return($==null?void 0:$[B])??(w==null?void 0:w[B])??(S==null?void 0:S[B])??""}return o}const Vr=["aria-label"],Sr={class:"DocSearch-Button-Container"},zr=u("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[u("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Cr={class:"DocSearch-Button-Placeholder"},Tr=u("span",{class:"DocSearch-Button-Keys"},[u("kbd",{class:"DocSearch-Button-Key"}),u("kbd",{class:"DocSearch-Button-Key"},"K")],-1),at=b({__name:"VPNavBarSearchButton",setup(n){const t=Pr({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(o,a)=>(s(),l("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":i(t)("button.buttonAriaLabel")},[u("span",Sr,[zr,u("span",Cr,T(i(t)("button.buttonText")),1)]),Tr],8,Vr))}}),Mr={class:"VPNavBarSearch"},Ir={id:"local-search"},Er={key:1,id:"docsearch"},Nr=b({__name:"VPNavBarSearch",setup(n){const e=Yt(()=>pt(()=>import("./VPLocalSearchBox.6bnhNGDg.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:o}=z(),a=E(!1),r=E(!1);Y(()=>{});function c(){a.value||(a.value=!0,setTimeout(d,16))}function d(){const w=new Event("keydown");w.key="k",w.metaKey=!0,window.dispatchEvent(w),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||d()},16)}function m(w){const S=w.target,B=S.tagName;return S.isContentEditable||B==="INPUT"||B==="SELECT"||B==="TEXTAREA"}const k=E(!1);xe("k",w=>{(w.ctrlKey||w.metaKey)&&(w.preventDefault(),k.value=!0)}),xe("/",w=>{m(w)||(w.preventDefault(),k.value=!0)});const $="local";return(w,S)=>{var B;return s(),l("div",Mr,[i($)==="local"?(s(),l(A,{key:0},[k.value?(s(),y(i(e),{key:0,onClose:S[0]||(S[0]=V=>k.value=!1)})):f("",!0),u("div",Ir,[_(at,{onClick:S[1]||(S[1]=V=>k.value=!0)})])],64)):i($)==="algolia"?(s(),l(A,{key:1},[a.value?(s(),y(i(t),{key:0,algolia:((B=i(o).search)==null?void 0:B.options)??i(o).algolia,onVnodeBeforeMount:S[2]||(S[2]=V=>r.value=!0)},null,8,["algolia"])):f("",!0),r.value?f("",!0):(s(),l("div",Er,[_(at,{onClick:c})]))],64)):f("",!0)])}}}),Hr=b({__name:"VPNavBarSocialLinks",setup(n){const{theme:e}=z();return(t,o)=>i(e).socialLinks?(s(),y(Ee,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Ar=g(Hr,[["__scopeId","data-v-fe082610"]]),Br=["href","rel","target"],Or=b({__name:"VPNavBarTitle",setup(n){const{site:e,theme:t}=z(),{hasSidebar:o}=ne(),{currentLang:a}=_e(),r=L(()=>{var m;return typeof t.value.logoLink=="string"?t.value.logoLink:(m=t.value.logoLink)==null?void 0:m.link}),c=L(()=>{var m;return typeof t.value.logoLink=="string"||(m=t.value.logoLink)==null?void 0:m.rel}),d=L(()=>{var m;return typeof t.value.logoLink=="string"||(m=t.value.logoLink)==null?void 0:m.target});return(m,k)=>(s(),l("div",{class:H(["VPNavBarTitle",{"has-sidebar":i(o)}])},[u("a",{class:"title",href:r.value??i(Ye)(i(a).link),rel:c.value,target:d.value},[v(m.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(s(),y(Se,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):f("",!0),i(t).siteTitle?(s(),l(A,{key:1},[j(T(i(t).siteTitle),1)],64)):i(t).siteTitle===void 0?(s(),l(A,{key:2},[j(T(i(e).title),1)],64)):f("",!0),v(m.$slots,"nav-bar-title-after",{},void 0,!0)],8,Br)],2))}}),Dr=g(Or,[["__scopeId","data-v-15df090c"]]),Fr={},xr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},jr=u("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),Ur=u("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),Gr=[jr,Ur];function Rr(n,e){return s(),l("svg",xr,Gr)}const Pt=g(Fr,[["render",Rr]]),qr={class:"items"},Kr={class:"title"},Wr=b({__name:"VPNavBarTranslations",setup(n){const{theme:e}=z(),{localeLinks:t,currentLang:o}=_e({correspondingLink:!0});return(a,r)=>i(t).length&&i(o).label?(s(),y(et,{key:0,class:"VPNavBarTranslations",icon:Pt,label:i(e).langMenuLabel||"Change language"},{default:p(()=>[u("div",qr,[u("p",Kr,T(i(o).label),1),(s(!0),l(A,null,G(i(t),c=>(s(),y(Ie,{key:c.link,item:c},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}}),Yr=g(Wr,[["__scopeId","data-v-cf938b1a"]]),Zr=n=>(Z("data-v-293f3bf8"),n=n(),X(),n),Xr={class:"wrapper"},Jr={class:"container"},Qr={class:"title"},ei={class:"content"},ti={class:"content-body"},ni=Zr(()=>u("div",{class:"divider"},[u("div",{class:"divider-line"})],-1)),oi=b({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(n){const{y:e}=vt(),{hasSidebar:t}=ne(),{hasLocalNav:o}=kt(),{frontmatter:a}=z(),r=E({});return ut(()=>{r.value={"has-sidebar":t.value,"has-local-nav":o.value,top:a.value.layout==="home"&&e.value===0}}),(c,d)=>(s(),l("div",{class:H(["VPNavBar",r.value])},[u("div",Xr,[u("div",Jr,[u("div",Qr,[_(Dr,null,{"nav-bar-title-before":p(()=>[v(c.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(c.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),u("div",ei,[u("div",ti,[v(c.$slots,"nav-bar-content-before",{},void 0,!0),_(Nr,{class:"search"}),_(Lr,{class:"menu"}),_(Yr,{class:"translations"}),_(fs,{class:"appearance"}),_(Ar,{class:"social-links"}),_(cr,{class:"extra"}),v(c.$slots,"nav-bar-content-after",{},void 0,!0),_(hr,{class:"hamburger",active:c.isScreenOpen,onClick:d[0]||(d[0]=m=>c.$emit("toggle-screen"))},null,8,["active"])])])])]),ni],2))}}),ai=g(oi,[["__scopeId","data-v-293f3bf8"]]),si={key:0,class:"VPNavScreenAppearance"},ri={class:"text"},ii=b({__name:"VPNavScreenAppearance",setup(n){const{site:e,theme:t}=z();return(o,a)=>i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",si,[u("p",ri,T(i(t).darkModeSwitchLabel||"Appearance"),1),_(Je)])):f("",!0)}}),li=g(ii,[["__scopeId","data-v-46f82938"]]),ci=b({__name:"VPNavScreenMenuLink",props:{item:{}},setup(n){const e=Me("close-screen");return(t,o)=>(s(),y(K,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),ui=g(ci,[["__scopeId","data-v-55da9136"]]),di={},mi={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},vi=u("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),pi=[vi];function hi(n,e){return s(),l("svg",mi,pi)}const fi=g(di,[["render",hi]]),_i=b({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(n){const e=Me("close-screen");return(t,o)=>(s(),y(K,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Vt=g(_i,[["__scopeId","data-v-c1cc298a"]]),gi={class:"VPNavScreenMenuGroupSection"},bi={key:0,class:"title"},ki=b({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(n){return(e,t)=>(s(),l("div",gi,[e.text?(s(),l("p",bi,T(e.text),1)):f("",!0),(s(!0),l(A,null,G(e.items,o=>(s(),y(Vt,{key:o.text,item:o},null,8,["item"]))),128))]))}}),$i=g(ki,[["__scopeId","data-v-b00c649a"]]),yi=["aria-controls","aria-expanded"],wi=["innerHTML"],Li=["id"],Pi={key:1,class:"group"},Vi=b({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(n){const e=n,t=E(!1),o=L(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function a(){t.value=!t.value}return(r,c)=>(s(),l("div",{class:H(["VPNavScreenMenuGroup",{open:t.value}])},[u("button",{class:"button","aria-controls":o.value,"aria-expanded":t.value,onClick:a},[u("span",{class:"button-text",innerHTML:r.text},null,8,wi),_(fi,{class:"button-icon"})],8,yi),u("div",{id:o.value,class:"items"},[(s(!0),l(A,null,G(r.items,d=>(s(),l(A,{key:d.text},["link"in d?(s(),l("div",{key:d.text,class:"item"},[_(Vt,{item:d},null,8,["item"])])):(s(),l("div",Pi,[_($i,{text:d.text,items:d.items},null,8,["text","items"])]))],64))),128))],8,Li)],2))}}),Si=g(Vi,[["__scopeId","data-v-31391d93"]]),zi={key:0,class:"VPNavScreenMenu"},Ci=b({__name:"VPNavScreenMenu",setup(n){const{theme:e}=z();return(t,o)=>i(e).nav?(s(),l("nav",zi,[(s(!0),l(A,null,G(i(e).nav,a=>(s(),l(A,{key:a.text},["link"in a?(s(),y(ui,{key:0,item:a},null,8,["item"])):(s(),y(Si,{key:1,text:a.text||"",items:a.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Ti=b({__name:"VPNavScreenSocialLinks",setup(n){const{theme:e}=z();return(t,o)=>i(e).socialLinks?(s(),y(Ee,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Mi={class:"list"},Ii=b({__name:"VPNavScreenTranslations",setup(n){const{localeLinks:e,currentLang:t}=_e({correspondingLink:!0}),o=E(!1);function a(){o.value=!o.value}return(r,c)=>i(e).length&&i(t).label?(s(),l("div",{key:0,class:H(["VPNavScreenTranslations",{open:o.value}])},[u("button",{class:"title",onClick:a},[_(Pt,{class:"icon lang"}),j(" "+T(i(t).label)+" ",1),_(Lt,{class:"icon chevron"})]),u("ul",Mi,[(s(!0),l(A,null,G(i(e),d=>(s(),l("li",{key:d.link,class:"item"},[_(K,{class:"link",href:d.link},{default:p(()=>[j(T(d.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}}),Ei=g(Ii,[["__scopeId","data-v-b6d43e7d"]]),Ni={class:"container"},Hi=b({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(n){const e=E(null),t=ht(le?document.body:null);return(o,a)=>(s(),y(ze,{name:"fade",onEnter:a[0]||(a[0]=r=>t.value=!0),onAfterLeave:a[1]||(a[1]=r=>t.value=!1)},{default:p(()=>[o.open?(s(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[u("div",Ni,[v(o.$slots,"nav-screen-content-before",{},void 0,!0),_(Ci,{class:"menu"}),_(Ei,{class:"translations"}),_(li,{class:"appearance"}),_(Ti,{class:"social-links"}),v(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}}),Ai=g(Hi,[["__scopeId","data-v-3dd6f37e"]]),Bi={key:0,class:"VPNav"},Oi=b({__name:"VPNav",setup(n){const{isScreenOpen:e,closeScreen:t,toggleScreen:o}=Wa(),{frontmatter:a}=z(),r=L(()=>a.value.navbar!==!1);return ft("close-screen",t),Ce(()=>{le&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(c,d)=>r.value?(s(),l("header",Bi,[_(ai,{"is-screen-open":i(e),onToggleScreen:i(o)},{"nav-bar-title-before":p(()=>[v(c.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(c.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[v(c.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[v(c.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),_(Ai,{open:i(e)},{"nav-screen-content-before":p(()=>[v(c.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[v(c.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}}),Di=g(Oi,[["__scopeId","data-v-9ac35370"]]),Fi=n=>(Z("data-v-e216f58b"),n=n(),X(),n),xi=["role","tabindex"],ji=Fi(()=>u("div",{class:"indicator"},null,-1)),Ui={key:1,class:"items"},Gi=b({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(n){const e=n,{collapsed:t,collapsible:o,isLink:a,isActiveLink:r,hasActiveLink:c,hasChildren:d,toggle:m}=yn(L(()=>e.item)),k=L(()=>d.value?"section":"div"),$=L(()=>a.value?"a":"div"),w=L(()=>d.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),S=L(()=>a.value?void 0:"button"),B=L(()=>[[`level-${e.depth}`],{collapsible:o.value},{collapsed:t.value},{"is-link":a.value},{"is-active":r.value},{"has-active":c.value}]);function V(N){"key"in N&&N.key!=="Enter"||!e.item.link&&m()}function I(){e.item.link&&m()}return(N,ue)=>{const J=ce("VPSidebarItem",!0);return s(),y(re(k.value),{class:H(["VPSidebarItem",B.value])},{default:p(()=>[N.item.text?(s(),l("div",we({key:0,class:"item",role:S.value},Zt(N.item.items?{click:V,keydown:V}:{},!0),{tabindex:N.item.items&&0}),[ji,N.item.link?(s(),y(K,{key:0,tag:$.value,class:"link",href:N.item.link,rel:N.item.rel,target:N.item.target},{default:p(()=>[(s(),y(re(w.value),{class:"text",innerHTML:N.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(s(),y(re(w.value),{key:1,class:"text",innerHTML:N.item.text},null,8,["innerHTML"])),N.item.collapsed!=null?(s(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:I,onKeydown:Xt(I,["enter"]),tabindex:"0"},[_($t,{class:"caret-icon"})],32)):f("",!0)],16,xi)):f("",!0),N.item.items&&N.item.items.length?(s(),l("div",Ui,[N.depth<5?(s(!0),l(A,{key:0},G(N.item.items,F=>(s(),y(J,{key:F.text,item:F,depth:N.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}}),Ri=g(Gi,[["__scopeId","data-v-e216f58b"]]),St=n=>(Z("data-v-71cefa04"),n=n(),X(),n),qi=St(()=>u("div",{class:"curtain"},null,-1)),Ki={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Wi=St(()=>u("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Yi=b({__name:"VPSidebar",props:{open:{type:Boolean}},setup(n){const{sidebarGroups:e,hasSidebar:t}=ne(),o=n,a=E(null),r=ht(le?document.body:null);return te([o,a],()=>{var c;o.open?(r.value=!0,(c=a.value)==null||c.focus()):r.value=!1},{immediate:!0,flush:"post"}),(c,d)=>i(t)?(s(),l("aside",{key:0,class:H(["VPSidebar",{open:c.open}]),ref_key:"navEl",ref:a,onClick:d[0]||(d[0]=Jt(()=>{},["stop"]))},[qi,u("nav",Ki,[Wi,v(c.$slots,"sidebar-nav-before",{},void 0,!0),(s(!0),l(A,null,G(i(e),m=>(s(),l("div",{key:m.text,class:"group"},[_(Ri,{item:m,depth:0},null,8,["item"])]))),128)),v(c.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}}),Zi=g(Yi,[["__scopeId","data-v-71cefa04"]]),Xi=b({__name:"VPSkipLink",setup(n){const e=fe(),t=E();te(()=>e.path,()=>t.value.focus());function o({target:a}){const r=document.getElementById(decodeURIComponent(a.hash).slice(1));if(r){const c=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",c)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",c),r.focus(),window.scrollTo(0,0)}}return(a,r)=>(s(),l(A,null,[u("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),u("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:o}," Skip to content ")],64))}}),Ji=g(Xi,[["__scopeId","data-v-db2dcaee"]]),Qi=b({__name:"Layout",setup(n){const{isOpen:e,open:t,close:o}=ne(),a=fe();te(()=>a.path,o),$n(e,o);const{frontmatter:r}=z(),c=Qt(),d=L(()=>!!c["home-hero-image"]);return ft("hero-image-slot-exists",d),(m,k)=>{const $=ce("Content");return i(r).layout!==!1?(s(),l("div",{key:0,class:H(["Layout",i(r).pageClass])},[v(m.$slots,"layout-top",{},void 0,!0),_(Ji),_(sn,{class:"backdrop",show:i(e),onClick:i(o)},null,8,["show","onClick"]),_(Di,null,{"nav-bar-title-before":p(()=>[v(m.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(m.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[v(m.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[v(m.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":p(()=>[v(m.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[v(m.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),_(Ka,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),_(Zi,{open:i(e)},{"sidebar-nav-before":p(()=>[v(m.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":p(()=>[v(m.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),_(ba,null,{"page-top":p(()=>[v(m.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[v(m.$slots,"page-bottom",{},void 0,!0)]),"not-found":p(()=>[v(m.$slots,"not-found",{},void 0,!0)]),"home-hero-before":p(()=>[v(m.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":p(()=>[v(m.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(m.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[v(m.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[v(m.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[v(m.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":p(()=>[v(m.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[v(m.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[v(m.$slots,"doc-after",{},void 0,!0)]),"doc-top":p(()=>[v(m.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[v(m.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":p(()=>[v(m.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[v(m.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[v(m.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(m.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(m.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(m.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),_(La),v(m.$slots,"layout-bottom",{},void 0,!0)],2)):(s(),y($,{key:1}))}}}),el=g(Qi,[["__scopeId","data-v-c9d4f922"]]),tl={},nl={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},ol=u("path",{d:"M12,22.2c-0.3,0-0.5-0.1-0.7-0.3l-8.8-8.8c-2.5-2.5-2.5-6.7,0-9.2c2.5-2.5,6.7-2.5,9.2,0L12,4.3l0.4-0.4c0,0,0,0,0,0C13.6,2.7,15.2,2,16.9,2c0,0,0,0,0,0c1.7,0,3.4,0.7,4.6,1.9l0,0c1.2,1.2,1.9,2.9,1.9,4.6c0,1.7-0.7,3.4-1.9,4.6l-8.8,8.8C12.5,22.1,12.3,22.2,12,22.2zM7,4C5.9,4,4.7,4.4,3.9,5.3c-1.8,1.8-1.8,4.6,0,6.4l8.1,8.1l8.1-8.1c0.9-0.9,1.3-2,1.3-3.2c0-1.2-0.5-2.3-1.3-3.2l0,0C19.3,4.5,18.2,4,17,4c0,0,0,0,0,0c-1.2,0-2.3,0.5-3.2,1.3c0,0,0,0,0,0l-1.1,1.1c-0.4,0.4-1,0.4-1.4,0l-1.1-1.1C9.4,4.4,8.2,4,7,4z"},null,-1),al=[ol];function sl(n,e){return s(),l("svg",nl,al)}const rl=g(tl,[["render",sl]]),il={},ll={class:"VPTeamPage"};function cl(n,e){return s(),l("div",ll,[v(n.$slots,"default")])}const oc=g(il,[["render",cl],["__scopeId","data-v-c649c573"]]),ul={},dl={class:"VPTeamPageTitle"},ml={key:0,class:"title"},vl={key:1,class:"lead"};function pl(n,e){return s(),l("div",dl,[n.$slots.title?(s(),l("h1",ml,[v(n.$slots,"title",{},void 0,!0)])):f("",!0),n.$slots.lead?(s(),l("p",vl,[v(n.$slots,"lead",{},void 0,!0)])):f("",!0)])}const ac=g(ul,[["render",pl],["__scopeId","data-v-ba2c7188"]]),hl={class:"profile"},fl={class:"avatar"},_l=["src","alt"],gl={class:"data"},bl={class:"name"},kl={key:0,class:"affiliation"},$l={key:0,class:"title"},yl={key:1,class:"at"},wl=["innerHTML"],Ll={key:2,class:"links"},Pl={key:0,class:"sp"},Vl=b({__name:"VPTeamMembersItem",props:{size:{default:"medium"},member:{}},setup(n){return(e,t)=>(s(),l("article",{class:H(["VPTeamMembersItem",[e.size]])},[u("div",hl,[u("figure",fl,[u("img",{class:"avatar-img",src:e.member.avatar,alt:e.member.name},null,8,_l)]),u("div",gl,[u("h1",bl,T(e.member.name),1),e.member.title||e.member.org?(s(),l("p",kl,[e.member.title?(s(),l("span",$l,T(e.member.title),1)):f("",!0),e.member.title&&e.member.org?(s(),l("span",yl," @ ")):f("",!0),e.member.org?(s(),y(K,{key:2,class:H(["org",{link:e.member.orgLink}]),href:e.member.orgLink,"no-icon":""},{default:p(()=>[j(T(e.member.org),1)]),_:1},8,["class","href"])):f("",!0)])):f("",!0),e.member.desc?(s(),l("p",{key:1,class:"desc",innerHTML:e.member.desc},null,8,wl)):f("",!0),e.member.links?(s(),l("div",Ll,[_(Ee,{links:e.member.links},null,8,["links"])])):f("",!0)])]),e.member.sponsor?(s(),l("div",Pl,[_(K,{class:"sp-link",href:e.member.sponsor,"no-icon":""},{default:p(()=>[_(rl,{class:"sp-icon"}),j(" "+T(e.member.actionText||"Sponsor"),1)]),_:1},8,["href"])])):f("",!0)],2))}}),Sl=g(Vl,[["__scopeId","data-v-13ff0bb7"]]),zl={class:"container"},Cl=b({__name:"VPTeamMembers",props:{size:{default:"medium"},members:{}},setup(n){const e=n,t=L(()=>[e.size,`count-${e.members.length}`]);return(o,a)=>(s(),l("div",{class:H(["VPTeamMembers",t.value])},[u("div",zl,[(s(!0),l(A,null,G(o.members,r=>(s(),l("div",{key:r.name,class:"item"},[_(Sl,{size:o.size,member:r},null,8,["size","member"])]))),128))])],2))}}),sc=g(Cl,[["__scopeId","data-v-9c4594aa"]]),st={Layout:el,enhanceApp:({app:n})=>{n.component("Badge",nn)}},Tl=["id","host","repo","repoid","category","categoryid","mapping","term","strict","reactionsenabled","emitmetadata","inputposition","theme","lang","loading"],Ml=b({__name:"Giscus",props:{id:{},host:{},repo:{},repoId:{},category:{},categoryId:{},mapping:{},term:{},theme:{},strict:{},reactionsEnabled:{},emitMetadata:{},inputPosition:{},lang:{},loading:{}},setup(n){const e=E(!1);return Y(()=>{e.value=!0,pt(()=>import("./giscus-aTimukGI.CKTvSCx2.js"),[])}),(t,o)=>e.value?(s(),l("giscus-widget",{key:0,id:t.id,host:t.host,repo:t.repo,repoid:t.repoId,category:t.category,categoryid:t.categoryId,mapping:t.mapping,term:t.term,strict:t.strict,reactionsenabled:t.reactionsEnabled,emitmetadata:t.emitMetadata,inputposition:t.inputPosition,theme:t.theme,lang:t.lang,loading:t.loading},null,8,Tl)):f("",!0)}}),rt=(n,e,t=!0)=>{var k;const o={id:"comment",host:"https://giscus.app",category:"General",mapping:"pathname",term:"Welcome to giscus!",reactionsEnabled:"1",inputPosition:"top",lang:"zh-CN",loading:"lazy",repo:"xxx/xxx",repoId:"",homePageShowComment:!1};if(n.locales){const w=document.querySelector("html").getAttribute("lang");w&&n.locales[w]&&(n.lang=n.locales[w])}const a=n.lightTheme||"light",r=n.darkTheme||"transparent_dark";let c=document.getElementById("giscus");if(c&&c.parentNode.removeChild(c),(e==null?void 0:e.value.comment)!==void 0){if(!(e!=null&&e.value.comment))return}else if(!t)return;if(!n.homePageShowComment&&(!location.pathname||location.pathname==="/"))return;const d=((k=document.querySelector("html"))==null?void 0:k.className.indexOf("dark"))!==-1,m=document.getElementsByClassName("content-container")[0];if(m){const $=document.createElement("div");$.setAttribute("id","giscus"),$.style.height="auto",$.style.marginTop="40px",$.style.borderTop="1px solid var(--vp-c-divider)",$.style.paddingTop="20px",m.append($),en({render:()=>Ve(Ml,{...o,theme:d?r:a,...n})}).mount("#giscus")}},Il=n=>{const e=document.querySelector("html"),t=n.lightTheme||"light",o=n.darkTheme||"transparent_dark";new MutationObserver(r=>{r.forEach(c=>{if(c.type=="attributes"){let d=document.getElementById("comment");d==null||d.setAttribute("theme",e.className.indexOf("dark")!==-1?o:t)}})}).observe(e,{attributeFilter:["class"]})},El=(n,e,t=!0)=>{Y(()=>{rt(n,e.frontmatter,t),Il(n)}),te(()=>e.route.path,()=>We(()=>{rt(n,e.frontmatter,t)}))};/*! medium-zoom 1.1.0 | MIT License | https://github.com/francoischalifour/medium-zoom */var se=Object.assign||function(n){for(var e=1;ei.map(i=>d[i]); +import{d as b,o as s,c as l,r as v,n as H,a as j,t as T,b as y,w as p,e as f,T as ze,_ as g,u as Re,i as jt,f as Ut,g as qe,h as E,j as le,k as L,l as Y,m as u,p as i,q as Z,s as X,v as ie,x as Fe,y as te,z as Ce,A as Ke,B as ut,C as Gt,D as ce,F as A,E as G,G as dt,H as Te,I as _,J as re,K as mt,L as fe,M as we,N as Me,O as Rt,P as xe,Q as qt,R as We,S as vt,U as Kt,V as Wt,W as Yt,X as pt,Y as ht,Z as ft,$ as Zt,a0 as Xt,a1 as Jt,a2 as Qt,a3 as en,a4 as Ve,a5 as tn}from"./framework.DIzwIJpr.js";const nn=b({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(n){return(e,t)=>(s(),l("span",{class:H(["VPBadge",e.type])},[v(e.$slots,"default",{},()=>[j(T(e.text),1)])],2))}}),on={key:0,class:"VPBackdrop"},an=b({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(n){return(e,t)=>(s(),y(ze,{name:"fade"},{default:p(()=>[e.show?(s(),l("div",on)):f("",!0)]),_:1}))}}),sn=g(an,[["__scopeId","data-v-39225c2a"]]),z=Re;function rn(n,e){let t,o=!1;return()=>{t&&clearTimeout(t),o?t=setTimeout(n,e):(n(),(o=!0)&&setTimeout(()=>o=!1,e))}}function je(n){return/^\//.test(n)?n:`/${n}`}function Ye(n){const{pathname:e,search:t,hash:o,protocol:a}=new URL(n,"http://a.com");if(jt(n)||n.startsWith("#")||!a.startsWith("http")||!Ut(e))return n;const{site:r}=z(),c=e.endsWith("/")||e.endsWith(".html")?n:n.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,r.value.cleanUrls?"":".html")}${t}${o}`);return qe(c)}const Ze=E(le?location.hash:"");le&&window.addEventListener("hashchange",()=>{Ze.value=location.hash});function _e({removeCurrent:n=!0,correspondingLink:e=!1}={}){const{site:t,localeIndex:o,page:a,theme:r}=z(),c=L(()=>{var m,k;return{label:(m=t.value.locales[o.value])==null?void 0:m.label,link:((k=t.value.locales[o.value])==null?void 0:k.link)||(o.value==="root"?"/":`/${o.value}/`)}});return{localeLinks:L(()=>Object.entries(t.value.locales).flatMap(([m,k])=>n&&c.value.label===k.label?[]:{text:k.label,link:ln(k.link||(m==="root"?"/":`/${m}/`),r.value.i18nRouting!==!1&&e,a.value.relativePath.slice(c.value.link.length-1),!t.value.cleanUrls)+Ze.value})),currentLang:c}}function ln(n,e,t,o){return e?n.replace(/\/$/,"")+je(t.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,o?".html":"")):n}const cn=n=>(Z("data-v-b4d69a0b"),n=n(),X(),n),un={class:"NotFound"},dn={class:"code"},mn={class:"title"},vn=cn(()=>u("div",{class:"divider"},null,-1)),pn={class:"quote"},hn={class:"action"},fn=["href","aria-label"],_n=b({__name:"NotFound",setup(n){const{site:e,theme:t}=z(),{localeLinks:o}=_e({removeCurrent:!1}),a=E("/");return Y(()=>{var c;const r=window.location.pathname.replace(e.value.base,"").replace(/(^.*?\/).*$/,"/$1");o.value.length&&(a.value=((c=o.value.find(({link:d})=>d.startsWith(r)))==null?void 0:c.link)||o.value[0].link)}),(r,c)=>{var d,m,k,$,w;return s(),l("div",un,[u("p",dn,T(((d=i(t).notFound)==null?void 0:d.code)??"404"),1),u("h1",mn,T(((m=i(t).notFound)==null?void 0:m.title)??"PAGE NOT FOUND"),1),vn,u("blockquote",pn,T(((k=i(t).notFound)==null?void 0:k.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),u("div",hn,[u("a",{class:"link",href:i(qe)(a.value),"aria-label":(($=i(t).notFound)==null?void 0:$.linkLabel)??"go to home"},T(((w=i(t).notFound)==null?void 0:w.linkText)??"Take me home"),9,fn)])])}}}),gn=g(_n,[["__scopeId","data-v-b4d69a0b"]]);function _t(n,e){if(Array.isArray(n))return Le(n);if(n==null)return[];e=je(e);const t=Object.keys(n).sort((a,r)=>r.split("/").length-a.split("/").length).find(a=>e.startsWith(je(a))),o=t?n[t]:[];return Array.isArray(o)?Le(o):Le(o.items,o.base)}function bn(n){const e=[];let t=0;for(const o in n){const a=n[o];if(a.items){t=e.push(a);continue}e[t]||e.push({items:[]}),e[t].items.push(a)}return e}function kn(n){const e=[];function t(o){for(const a of o)a.text&&a.link&&e.push({text:a.text,link:a.link,docFooterText:a.docFooterText}),a.items&&t(a.items)}return t(n),e}function Ue(n,e){return Array.isArray(e)?e.some(t=>Ue(n,t)):ie(n,e.link)?!0:e.items?Ue(n,e.items):!1}function Le(n,e){return[...n].map(t=>{const o={...t},a=o.base||e;return a&&o.link&&(o.link=a+o.link),o.items&&(o.items=Le(o.items,a)),o})}function ne(){const{frontmatter:n,page:e,theme:t}=z(),o=Fe("(min-width: 960px)"),a=E(!1),r=L(()=>{const I=t.value.sidebar,N=e.value.relativePath;return I?_t(I,N):[]}),c=E(r.value);te(r,(I,N)=>{JSON.stringify(I)!==JSON.stringify(N)&&(c.value=r.value)});const d=L(()=>n.value.sidebar!==!1&&c.value.length>0&&n.value.layout!=="home"),m=L(()=>k?n.value.aside==null?t.value.aside==="left":n.value.aside==="left":!1),k=L(()=>n.value.layout==="home"?!1:n.value.aside!=null?!!n.value.aside:t.value.aside!==!1),$=L(()=>d.value&&o.value),w=L(()=>d.value?bn(c.value):[]);function S(){a.value=!0}function B(){a.value=!1}function V(){a.value?B():S()}return{isOpen:a,sidebar:c,sidebarGroups:w,hasSidebar:d,hasAside:k,leftAside:m,isSidebarEnabled:$,open:S,close:B,toggle:V}}function $n(n,e){let t;Ce(()=>{t=n.value?document.activeElement:void 0}),Y(()=>{window.addEventListener("keyup",o)}),Ke(()=>{window.removeEventListener("keyup",o)});function o(a){a.key==="Escape"&&n.value&&(e(),t==null||t.focus())}}function yn(n){const{page:e}=z(),t=E(!1),o=L(()=>n.value.collapsed!=null),a=L(()=>!!n.value.link),r=E(!1),c=()=>{r.value=ie(e.value.relativePath,n.value.link)};te([e,n,Ze],c),Y(c);const d=L(()=>r.value?!0:n.value.items?Ue(e.value.relativePath,n.value.items):!1),m=L(()=>!!(n.value.items&&n.value.items.length));Ce(()=>{t.value=!!(o.value&&n.value.collapsed)}),ut(()=>{(r.value||d.value)&&(t.value=!1)});function k(){o.value&&(t.value=!t.value)}return{collapsed:t,collapsible:o,isLink:a,isActiveLink:r,hasActiveLink:d,hasChildren:m,toggle:k}}function wn(){const{hasSidebar:n}=ne(),e=Fe("(min-width: 960px)"),t=Fe("(min-width: 1280px)");return{isAsideEnabled:L(()=>!t.value&&!e.value?!1:n.value?t.value:e.value)}}const Ge=[];function gt(n){return typeof n.outline=="object"&&!Array.isArray(n.outline)&&n.outline.label||n.outlineTitle||"On this page"}function Xe(n){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(t=>t.id&&t.hasChildNodes()).map(t=>{const o=Number(t.tagName[1]);return{element:t,title:Ln(t),link:"#"+t.id,level:o}});return Pn(e,n)}function Ln(n){let e="";for(const t of n.childNodes)if(t.nodeType===1){if(t.classList.contains("VPBadge")||t.classList.contains("header-anchor")||t.classList.contains("ignore-header"))continue;e+=t.textContent}else t.nodeType===3&&(e+=t.textContent);return e.trim()}function Pn(n,e){if(e===!1)return[];const t=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[o,a]=typeof t=="number"?[t,t]:t==="deep"?[2,6]:t;n=n.filter(c=>c.level>=o&&c.level<=a),Ge.length=0;for(const{element:c,link:d}of n)Ge.push({element:c,link:d});const r=[];e:for(let c=0;c=0;m--){const k=n[m];if(k.level{requestAnimationFrame(r),window.addEventListener("scroll",o)}),Gt(()=>{c(location.hash)}),Ke(()=>{window.removeEventListener("scroll",o)});function r(){if(!t.value)return;const d=(()=>{var I;const V=(I=document.querySelector("#VPContent .VPDoc"))==null?void 0:I.firstElementChild;return V?ot(V):78})(),m=window.scrollY,k=window.innerHeight,$=document.body.offsetHeight,w=Math.abs(m+k-$)<1,S=Ge.map(({element:V,link:I})=>({link:I,top:ot(V)})).filter(({top:V})=>!Number.isNaN(V)).sort((V,I)=>V.top-I.top);if(!S.length){c(null);return}if(m<1){c(null);return}if(w){c(S[S.length-1].link);return}let B=null;for(const{link:V,top:I}of S){if(I>m+d)break;B=V}c(B)}function c(d){a&&a.classList.remove("active"),d==null?a=null:a=n.value.querySelector(`a[href="${decodeURIComponent(d)}"]`);const m=a;m?(m.classList.add("active"),e.value.style.top=m.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function ot(n){let e=0;for(;n!==document.body;){if(n===null)return NaN;e+=n.offsetTop,n=n.offsetParent}return e}const Sn=["href","title"],zn=b({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(n){function e({target:t}){const o=t.href.split("#")[1],a=document.getElementById(decodeURIComponent(o));a==null||a.focus({preventScroll:!0})}return(t,o)=>{const a=ce("VPDocOutlineItem",!0);return s(),l("ul",{class:H(["VPDocOutlineItem",t.root?"root":"nested"])},[(s(!0),l(A,null,G(t.headers,({children:r,link:c,title:d})=>(s(),l("li",null,[u("a",{class:"outline-link",href:c,onClick:e,title:d},T(d),9,Sn),r!=null&&r.length?(s(),y(a,{key:0,headers:r},null,8,["headers"])):f("",!0)]))),256))],2)}}}),bt=g(zn,[["__scopeId","data-v-f4ef067b"]]),Cn=n=>(Z("data-v-f1d5f0bc"),n=n(),X(),n),Tn={class:"content"},Mn={class:"outline-title",role:"heading","aria-level":"2"},In={"aria-labelledby":"doc-outline-aria-label"},En=Cn(()=>u("span",{class:"visually-hidden",id:"doc-outline-aria-label"}," Table of Contents for current page ",-1)),Nn=b({__name:"VPDocAsideOutline",setup(n){const{frontmatter:e,theme:t}=z(),o=dt([]);Te(()=>{o.value=Xe(e.value.outline??t.value.outline)});const a=E(),r=E();return Vn(a,r),(c,d)=>(s(),l("div",{class:H(["VPDocAsideOutline",{"has-outline":o.value.length>0}]),ref_key:"container",ref:a,role:"navigation"},[u("div",Tn,[u("div",{class:"outline-marker",ref_key:"marker",ref:r},null,512),u("div",Mn,T(i(gt)(i(t))),1),u("nav",In,[En,_(bt,{headers:o.value,root:!0},null,8,["headers"])])])],2))}}),Hn=g(Nn,[["__scopeId","data-v-f1d5f0bc"]]),An={class:"VPDocAsideCarbonAds"},Bn=b({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(n){const e=()=>null;return(t,o)=>(s(),l("div",An,[_(i(e),{"carbon-ads":t.carbonAds},null,8,["carbon-ads"])]))}}),On=n=>(Z("data-v-5207b98e"),n=n(),X(),n),Dn={class:"VPDocAside"},Fn=On(()=>u("div",{class:"spacer"},null,-1)),xn=b({__name:"VPDocAside",setup(n){const{theme:e}=z();return(t,o)=>(s(),l("div",Dn,[v(t.$slots,"aside-top",{},void 0,!0),v(t.$slots,"aside-outline-before",{},void 0,!0),_(Hn),v(t.$slots,"aside-outline-after",{},void 0,!0),Fn,v(t.$slots,"aside-ads-before",{},void 0,!0),i(e).carbonAds?(s(),y(Bn,{key:0,"carbon-ads":i(e).carbonAds},null,8,["carbon-ads"])):f("",!0),v(t.$slots,"aside-ads-after",{},void 0,!0),v(t.$slots,"aside-bottom",{},void 0,!0)]))}}),jn=g(xn,[["__scopeId","data-v-5207b98e"]]);function Un(){const{theme:n,page:e}=z();return L(()=>{const{text:t="Edit this page",pattern:o=""}=n.value.editLink||{};let a;return typeof o=="function"?a=o(e.value):a=o.replace(/:path/g,e.value.filePath),{url:a,text:t}})}function Gn(){const{page:n,theme:e,frontmatter:t}=z();return L(()=>{var m,k,$,w,S,B,V,I;const o=_t(e.value.sidebar,n.value.relativePath),a=kn(o),r=a.findIndex(N=>ie(n.value.relativePath,N.link)),c=((m=e.value.docFooter)==null?void 0:m.prev)===!1&&!t.value.prev||t.value.prev===!1,d=((k=e.value.docFooter)==null?void 0:k.next)===!1&&!t.value.next||t.value.next===!1;return{prev:c?void 0:{text:(typeof t.value.prev=="string"?t.value.prev:typeof t.value.prev=="object"?t.value.prev.text:void 0)??(($=a[r-1])==null?void 0:$.docFooterText)??((w=a[r-1])==null?void 0:w.text),link:(typeof t.value.prev=="object"?t.value.prev.link:void 0)??((S=a[r-1])==null?void 0:S.link)},next:d?void 0:{text:(typeof t.value.next=="string"?t.value.next:typeof t.value.next=="object"?t.value.next.text:void 0)??((B=a[r+1])==null?void 0:B.docFooterText)??((V=a[r+1])==null?void 0:V.text),link:(typeof t.value.next=="object"?t.value.next.link:void 0)??((I=a[r+1])==null?void 0:I.link)}}})}const Rn={},qn={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Kn=u("path",{d:"M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"},null,-1),Wn=u("path",{d:"M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"},null,-1),Yn=[Kn,Wn];function Zn(n,e){return s(),l("svg",qn,Yn)}const Xn=g(Rn,[["render",Zn]]),K=b({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(n){const e=n,t=L(()=>e.tag??(e.href?"a":"span")),o=L(()=>e.href&&mt.test(e.href));return(a,r)=>(s(),y(re(t.value),{class:H(["VPLink",{link:a.href,"vp-external-link-icon":o.value,"no-icon":a.noIcon}]),href:a.href?i(Ye)(a.href):void 0,target:a.target??(o.value?"_blank":void 0),rel:a.rel??(o.value?"noreferrer":void 0)},{default:p(()=>[v(a.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),Jn={class:"VPLastUpdated"},Qn=["datetime"],eo=b({__name:"VPDocFooterLastUpdated",setup(n){const{theme:e,page:t,frontmatter:o,lang:a}=z(),r=L(()=>new Date(o.value.lastUpdated??t.value.lastUpdated)),c=L(()=>r.value.toISOString()),d=E("");return Y(()=>{Ce(()=>{var m,k,$;d.value=new Intl.DateTimeFormat((k=(m=e.value.lastUpdated)==null?void 0:m.formatOptions)!=null&&k.forceLocale?a.value:void 0,(($=e.value.lastUpdated)==null?void 0:$.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(r.value)})}),(m,k)=>{var $;return s(),l("p",Jn,[j(T((($=i(e).lastUpdated)==null?void 0:$.text)||i(e).lastUpdatedText||"Last updated")+": ",1),u("time",{datetime:c.value},T(d.value),9,Qn)])}}}),to=g(eo,[["__scopeId","data-v-e6d29f27"]]),no={key:0,class:"VPDocFooter"},oo={key:0,class:"edit-info"},ao={key:0,class:"edit-link"},so={key:1,class:"last-updated"},ro={key:1,class:"prev-next"},io={class:"pager"},lo=["innerHTML"],co=["innerHTML"],uo={class:"pager"},mo=["innerHTML"],vo=["innerHTML"],po=b({__name:"VPDocFooter",setup(n){const{theme:e,page:t,frontmatter:o}=z(),a=Un(),r=Gn(),c=L(()=>e.value.editLink&&o.value.editLink!==!1),d=L(()=>t.value.lastUpdated&&o.value.lastUpdated!==!1),m=L(()=>c.value||d.value||r.value.prev||r.value.next);return(k,$)=>{var w,S,B,V;return m.value?(s(),l("footer",no,[v(k.$slots,"doc-footer-before",{},void 0,!0),c.value||d.value?(s(),l("div",oo,[c.value?(s(),l("div",ao,[_(K,{class:"edit-link-button",href:i(a).url,"no-icon":!0},{default:p(()=>[_(Xn,{class:"edit-link-icon","aria-label":"edit icon"}),j(" "+T(i(a).text),1)]),_:1},8,["href"])])):f("",!0),d.value?(s(),l("div",so,[_(to)])):f("",!0)])):f("",!0),(w=i(r).prev)!=null&&w.link||(S=i(r).next)!=null&&S.link?(s(),l("nav",ro,[u("div",io,[(B=i(r).prev)!=null&&B.link?(s(),y(K,{key:0,class:"pager-link prev",href:i(r).prev.link},{default:p(()=>{var I;return[u("span",{class:"desc",innerHTML:((I=i(e).docFooter)==null?void 0:I.prev)||"Previous page"},null,8,lo),u("span",{class:"title",innerHTML:i(r).prev.text},null,8,co)]}),_:1},8,["href"])):f("",!0)]),u("div",uo,[(V=i(r).next)!=null&&V.link?(s(),y(K,{key:0,class:"pager-link next",href:i(r).next.link},{default:p(()=>{var I;return[u("span",{class:"desc",innerHTML:((I=i(e).docFooter)==null?void 0:I.next)||"Next page"},null,8,mo),u("span",{class:"title",innerHTML:i(r).next.text},null,8,vo)]}),_:1},8,["href"])):f("",!0)])])):f("",!0)])):f("",!0)}}}),ho=g(po,[["__scopeId","data-v-da9bd828"]]),fo=n=>(Z("data-v-e5aed501"),n=n(),X(),n),_o={class:"container"},go=fo(()=>u("div",{class:"aside-curtain"},null,-1)),bo={class:"aside-container"},ko={class:"aside-content"},$o={class:"content"},yo={class:"content-container"},wo={class:"main"},Lo=b({__name:"VPDoc",setup(n){const{theme:e}=z(),t=fe(),{hasSidebar:o,hasAside:a,leftAside:r}=ne(),c=L(()=>t.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(d,m)=>{const k=ce("Content");return s(),l("div",{class:H(["VPDoc",{"has-sidebar":i(o),"has-aside":i(a)}])},[v(d.$slots,"doc-top",{},void 0,!0),u("div",_o,[i(a)?(s(),l("div",{key:0,class:H(["aside",{"left-aside":i(r)}])},[go,u("div",bo,[u("div",ko,[_(jn,null,{"aside-top":p(()=>[v(d.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[v(d.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[v(d.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(d.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(d.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(d.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):f("",!0),u("div",$o,[u("div",yo,[v(d.$slots,"doc-before",{},void 0,!0),u("main",wo,[_(k,{class:H(["vp-doc",[c.value,i(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),_(ho,null,{"doc-footer-before":p(()=>[v(d.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),v(d.$slots,"doc-after",{},void 0,!0)])])]),v(d.$slots,"doc-bottom",{},void 0,!0)],2)}}}),Po=g(Lo,[["__scopeId","data-v-e5aed501"]]),Vo=b({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{}},setup(n){const e=n,t=L(()=>e.href&&mt.test(e.href)),o=L(()=>e.tag||e.href?"a":"button");return(a,r)=>(s(),y(re(o.value),{class:H(["VPButton",[a.size,a.theme]]),href:a.href?i(Ye)(a.href):void 0,target:t.value?"_blank":void 0,rel:t.value?"noreferrer":void 0},{default:p(()=>[j(T(a.text),1)]),_:1},8,["class","href","target","rel"]))}}),So=g(Vo,[["__scopeId","data-v-70b4c594"]]),zo=["src","alt"],Co=b({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(n){return(e,t)=>{const o=ce("VPImage",!0);return e.image?(s(),l(A,{key:0},[typeof e.image=="string"||"src"in e.image?(s(),l("img",we({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:i(qe)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,zo)):(s(),l(A,{key:1},[_(o,we({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),_(o,we({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):f("",!0)}}}),Se=g(Co,[["__scopeId","data-v-a3c772fb"]]),To=n=>(Z("data-v-22db75ec"),n=n(),X(),n),Mo={class:"container"},Io={class:"main"},Eo={key:0,class:"name"},No=["innerHTML"],Ho=["innerHTML"],Ao=["innerHTML"],Bo={key:0,class:"actions"},Oo={key:0,class:"image"},Do={class:"image-container"},Fo=To(()=>u("div",{class:"image-bg"},null,-1)),xo=b({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(n){const e=Me("hero-image-slot-exists");return(t,o)=>(s(),l("div",{class:H(["VPHero",{"has-image":t.image||i(e)}])},[u("div",Mo,[u("div",Io,[v(t.$slots,"home-hero-info",{},()=>[t.name?(s(),l("h1",Eo,[u("span",{innerHTML:t.name,class:"clip"},null,8,No)])):f("",!0),t.text?(s(),l("p",{key:1,innerHTML:t.text,class:"text"},null,8,Ho)):f("",!0),t.tagline?(s(),l("p",{key:2,innerHTML:t.tagline,class:"tagline"},null,8,Ao)):f("",!0)],!0),t.actions?(s(),l("div",Bo,[(s(!0),l(A,null,G(t.actions,a=>(s(),l("div",{key:a.link,class:"action"},[_(So,{tag:"a",size:"medium",theme:a.theme,text:a.text,href:a.link},null,8,["theme","text","href"])]))),128))])):f("",!0)]),t.image||i(e)?(s(),l("div",Oo,[u("div",Do,[Fo,v(t.$slots,"home-hero-image",{},()=>[t.image?(s(),y(Se,{key:0,class:"image-src",image:t.image},null,8,["image"])):f("",!0)],!0)])])):f("",!0)])],2))}}),jo=g(xo,[["__scopeId","data-v-22db75ec"]]),Uo=b({__name:"VPHomeHero",setup(n){const{frontmatter:e}=z();return(t,o)=>i(e).hero?(s(),y(jo,{key:0,class:"VPHomeHero",name:i(e).hero.name,text:i(e).hero.text,tagline:i(e).hero.tagline,image:i(e).hero.image,actions:i(e).hero.actions},{"home-hero-info":p(()=>[v(t.$slots,"home-hero-info")]),"home-hero-image":p(()=>[v(t.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):f("",!0)}}),Go={},Ro={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},qo=u("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Ko=[qo];function Wo(n,e){return s(),l("svg",Ro,Ko)}const Yo=g(Go,[["render",Wo]]),Zo={class:"box"},Xo={key:0,class:"icon"},Jo=["innerHTML"],Qo=["innerHTML"],ea=["innerHTML"],ta={key:4,class:"link-text"},na={class:"link-text-value"},oa=b({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(n){return(e,t)=>(s(),y(K,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:p(()=>[u("article",Zo,[typeof e.icon=="object"&&e.icon.wrap?(s(),l("div",Xo,[_(Se,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(s(),y(Se,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(s(),l("div",{key:2,class:"icon",innerHTML:e.icon},null,8,Jo)):f("",!0),u("h2",{class:"title",innerHTML:e.title},null,8,Qo),e.details?(s(),l("p",{key:3,class:"details",innerHTML:e.details},null,8,ea)):f("",!0),e.linkText?(s(),l("div",ta,[u("p",na,[j(T(e.linkText)+" ",1),_(Yo,{class:"link-text-icon"})])])):f("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),aa=g(oa,[["__scopeId","data-v-2908087c"]]),sa={key:0,class:"VPFeatures"},ra={class:"container"},ia={class:"items"},la=b({__name:"VPFeatures",props:{features:{}},setup(n){const e=n,t=L(()=>{const o=e.features.length;if(o){if(o===2)return"grid-2";if(o===3)return"grid-3";if(o%3===0)return"grid-6";if(o>3)return"grid-4"}else return});return(o,a)=>o.features?(s(),l("div",sa,[u("div",ra,[u("div",ia,[(s(!0),l(A,null,G(o.features,r=>(s(),l("div",{key:r.title,class:H(["item",[t.value]])},[_(aa,{icon:r.icon,title:r.title,details:r.details,link:r.link,"link-text":r.linkText,rel:r.rel,target:r.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):f("",!0)}}),ca=g(la,[["__scopeId","data-v-25d4ed06"]]),ua=b({__name:"VPHomeFeatures",setup(n){const{frontmatter:e}=z();return(t,o)=>i(e).features?(s(),y(ca,{key:0,class:"VPHomeFeatures",features:i(e).features},null,8,["features"])):f("",!0)}}),da={class:"VPHome"},ma=b({__name:"VPHome",setup(n){return(e,t)=>{const o=ce("Content");return s(),l("div",da,[v(e.$slots,"home-hero-before",{},void 0,!0),_(Uo,null,{"home-hero-info":p(()=>[v(e.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(e.$slots,"home-hero-image",{},void 0,!0)]),_:3}),v(e.$slots,"home-hero-after",{},void 0,!0),v(e.$slots,"home-features-before",{},void 0,!0),_(ua),v(e.$slots,"home-features-after",{},void 0,!0),_(o)])}}}),va=g(ma,[["__scopeId","data-v-5629135b"]]),pa={},ha={class:"VPPage"};function fa(n,e){const t=ce("Content");return s(),l("div",ha,[v(n.$slots,"page-top"),_(t),v(n.$slots,"page-bottom")])}const _a=g(pa,[["render",fa]]),ga=b({__name:"VPContent",setup(n){const{page:e,frontmatter:t}=z(),{hasSidebar:o}=ne();return(a,r)=>(s(),l("div",{class:H(["VPContent",{"has-sidebar":i(o),"is-home":i(t).layout==="home"}]),id:"VPContent"},[i(e).isNotFound?v(a.$slots,"not-found",{key:0},()=>[_(gn)],!0):i(t).layout==="page"?(s(),y(_a,{key:1},{"page-top":p(()=>[v(a.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[v(a.$slots,"page-bottom",{},void 0,!0)]),_:3})):i(t).layout==="home"?(s(),y(va,{key:2},{"home-hero-before":p(()=>[v(a.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":p(()=>[v(a.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(a.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[v(a.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[v(a.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[v(a.$slots,"home-features-after",{},void 0,!0)]),_:3})):i(t).layout&&i(t).layout!=="doc"?(s(),y(re(i(t).layout),{key:3})):(s(),y(Po,{key:4},{"doc-top":p(()=>[v(a.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[v(a.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":p(()=>[v(a.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[v(a.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[v(a.$slots,"doc-after",{},void 0,!0)]),"aside-top":p(()=>[v(a.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":p(()=>[v(a.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(a.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(a.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(a.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":p(()=>[v(a.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),ba=g(ga,[["__scopeId","data-v-6274197d"]]),ka={class:"container"},$a=["innerHTML"],ya=["innerHTML"],wa=b({__name:"VPFooter",setup(n){const{theme:e,frontmatter:t}=z(),{hasSidebar:o}=ne();return(a,r)=>i(e).footer&&i(t).footer!==!1?(s(),l("footer",{key:0,class:H(["VPFooter",{"has-sidebar":i(o)}])},[u("div",ka,[i(e).footer.message?(s(),l("p",{key:0,class:"message",innerHTML:i(e).footer.message},null,8,$a)):f("",!0),i(e).footer.copyright?(s(),l("p",{key:1,class:"copyright",innerHTML:i(e).footer.copyright},null,8,ya)):f("",!0)])],2)):f("",!0)}}),La=g(wa,[["__scopeId","data-v-48fac9ef"]]);function kt(){const{theme:n,frontmatter:e}=z(),t=dt([]),o=L(()=>t.value.length>0);return Te(()=>{t.value=Xe(e.value.outline??n.value.outline)}),{headers:t,hasLocalNav:o}}const Pa={},Va={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Sa=u("path",{d:"M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"},null,-1),za=[Sa];function Ca(n,e){return s(),l("svg",Va,za)}const $t=g(Pa,[["render",Ca]]),Ta={class:"header"},Ma={class:"outline"},Ia=b({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(n){const e=n,{theme:t}=z(),o=E(!1),a=E(0),r=E(),c=E();Rt(r,()=>{o.value=!1}),xe("Escape",()=>{o.value=!1}),Te(()=>{o.value=!1});function d(){o.value=!o.value,a.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function m($){$.target.classList.contains("outline-link")&&(c.value&&(c.value.style.transition="none"),We(()=>{o.value=!1}))}function k(){o.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return($,w)=>(s(),l("div",{class:"VPLocalNavOutlineDropdown",style:qt({"--vp-vh":a.value+"px"}),ref_key:"main",ref:r},[$.headers.length>0?(s(),l("button",{key:0,onClick:d,class:H({open:o.value})},[j(T(i(gt)(i(t)))+" ",1),_($t,{class:"icon"})],2)):(s(),l("button",{key:1,onClick:k},T(i(t).returnToTopLabel||"Return to top"),1)),_(ze,{name:"flyout"},{default:p(()=>[o.value?(s(),l("div",{key:0,ref_key:"items",ref:c,class:"items",onClick:m},[u("div",Ta,[u("a",{class:"top-link",href:"#",onClick:k},T(i(t).returnToTopLabel||"Return to top"),1)]),u("div",Ma,[_(bt,{headers:$.headers},null,8,["headers"])])],512)):f("",!0)]),_:1})],4))}}),Ea=g(Ia,[["__scopeId","data-v-57a7b996"]]),Na={},Ha={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Aa=u("path",{d:"M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"},null,-1),Ba=u("path",{d:"M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"},null,-1),Oa=u("path",{d:"M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"},null,-1),Da=u("path",{d:"M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"},null,-1),Fa=[Aa,Ba,Oa,Da];function xa(n,e){return s(),l("svg",Ha,Fa)}const ja=g(Na,[["render",xa]]),Ua={class:"container"},Ga=["aria-expanded"],Ra={class:"menu-text"},qa=b({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(n){const{theme:e,frontmatter:t}=z(),{hasSidebar:o}=ne(),{headers:a}=kt(),{y:r}=vt(),c=E(0);Y(()=>{c.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),Te(()=>{a.value=Xe(t.value.outline??e.value.outline)});const d=L(()=>a.value.length===0),m=L(()=>d.value&&!o.value),k=L(()=>({VPLocalNav:!0,"has-sidebar":o.value,empty:d.value,fixed:m.value}));return($,w)=>i(t).layout!=="home"&&(!m.value||i(r)>=c.value)?(s(),l("div",{key:0,class:H(k.value)},[u("div",Ua,[i(o)?(s(),l("button",{key:0,class:"menu","aria-expanded":$.open,"aria-controls":"VPSidebarNav",onClick:w[0]||(w[0]=S=>$.$emit("open-menu"))},[_(ja,{class:"menu-icon"}),u("span",Ra,T(i(e).sidebarMenuLabel||"Menu"),1)],8,Ga)):f("",!0),_(Ea,{headers:i(a),navHeight:c.value},null,8,["headers","navHeight"])])],2)):f("",!0)}}),Ka=g(qa,[["__scopeId","data-v-9df9ee96"]]);function Wa(){const n=E(!1);function e(){n.value=!0,window.addEventListener("resize",a)}function t(){n.value=!1,window.removeEventListener("resize",a)}function o(){n.value?t():e()}function a(){window.outerWidth>=768&&t()}const r=fe();return te(()=>r.path,t),{isScreenOpen:n,openScreen:e,closeScreen:t,toggleScreen:o}}const Ya={},Za={class:"VPSwitch",type:"button",role:"switch"},Xa={class:"check"},Ja={key:0,class:"icon"};function Qa(n,e){return s(),l("button",Za,[u("span",Xa,[n.$slots.default?(s(),l("span",Ja,[v(n.$slots,"default",{},void 0,!0)])):f("",!0)])])}const es=g(Ya,[["render",Qa],["__scopeId","data-v-c5ec0895"]]),ts={},ns={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},os=u("path",{d:"M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"},null,-1),as=[os];function ss(n,e){return s(),l("svg",ns,as)}const rs=g(ts,[["render",ss]]),is={},ls={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},cs=Kt('',9),us=[cs];function ds(n,e){return s(),l("svg",ls,us)}const ms=g(is,[["render",ds]]),vs=b({__name:"VPSwitchAppearance",setup(n){const{isDark:e,theme:t}=z(),o=Me("toggle-appearance",()=>{e.value=!e.value}),a=L(()=>e.value?t.value.lightModeSwitchTitle||"Switch to light theme":t.value.darkModeSwitchTitle||"Switch to dark theme");return(r,c)=>(s(),y(es,{title:a.value,class:"VPSwitchAppearance","aria-checked":i(e),onClick:i(o)},{default:p(()=>[_(ms,{class:"sun"}),_(rs,{class:"moon"})]),_:1},8,["title","aria-checked","onClick"]))}}),Je=g(vs,[["__scopeId","data-v-fcacf28d"]]),ps={key:0,class:"VPNavBarAppearance"},hs=b({__name:"VPNavBarAppearance",setup(n){const{site:e}=z();return(t,o)=>i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",ps,[_(Je)])):f("",!0)}}),fs=g(hs,[["__scopeId","data-v-b2119317"]]),Qe=E();let yt=!1,Oe=0;function _s(n){const e=E(!1);if(le){!yt&&gs(),Oe++;const t=te(Qe,o=>{var a,r,c;o===n.el.value||(a=n.el.value)!=null&&a.contains(o)?(e.value=!0,(r=n.onFocus)==null||r.call(n)):(e.value=!1,(c=n.onBlur)==null||c.call(n))});Ke(()=>{t(),Oe--,Oe||bs()})}return Wt(e)}function gs(){document.addEventListener("focusin",wt),yt=!0,Qe.value=document.activeElement}function bs(){document.removeEventListener("focusin",wt)}function wt(){Qe.value=document.activeElement}const ks={},$s={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},ys=u("path",{d:"M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"},null,-1),ws=[ys];function Ls(n,e){return s(),l("svg",$s,ws)}const Lt=g(ks,[["render",Ls]]),Ps={},Vs={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},Ss=u("circle",{cx:"12",cy:"12",r:"2"},null,-1),zs=u("circle",{cx:"19",cy:"12",r:"2"},null,-1),Cs=u("circle",{cx:"5",cy:"12",r:"2"},null,-1),Ts=[Ss,zs,Cs];function Ms(n,e){return s(),l("svg",Vs,Ts)}const Is=g(Ps,[["render",Ms]]),Es={class:"VPMenuLink"},Ns=b({__name:"VPMenuLink",props:{item:{}},setup(n){const{page:e}=z();return(t,o)=>(s(),l("div",Es,[_(K,{class:H({active:i(ie)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),Ie=g(Ns,[["__scopeId","data-v-c0982df3"]]),Hs={class:"VPMenuGroup"},As={key:0,class:"title"},Bs=b({__name:"VPMenuGroup",props:{text:{},items:{}},setup(n){return(e,t)=>(s(),l("div",Hs,[e.text?(s(),l("p",As,T(e.text),1)):f("",!0),(s(!0),l(A,null,G(e.items,o=>(s(),l(A,null,["link"in o?(s(),y(Ie,{key:0,item:o},null,8,["item"])):f("",!0)],64))),256))]))}}),Os=g(Bs,[["__scopeId","data-v-23ee77ae"]]),Ds={class:"VPMenu"},Fs={key:0,class:"items"},xs=b({__name:"VPMenu",props:{items:{}},setup(n){return(e,t)=>(s(),l("div",Ds,[e.items?(s(),l("div",Fs,[(s(!0),l(A,null,G(e.items,o=>(s(),l(A,{key:o.text},["link"in o?(s(),y(Ie,{key:0,item:o},null,8,["item"])):(s(),y(Os,{key:1,text:o.text,items:o.items},null,8,["text","items"]))],64))),128))])):f("",!0),v(e.$slots,"default",{},void 0,!0)]))}}),js=g(xs,[["__scopeId","data-v-87095e00"]]),Us=["aria-expanded","aria-label"],Gs={key:0,class:"text"},Rs=["innerHTML"],qs={class:"menu"},Ks=b({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(n){const e=E(!1),t=E();_s({el:t,onBlur:o});function o(){e.value=!1}return(a,r)=>(s(),l("div",{class:"VPFlyout",ref_key:"el",ref:t,onMouseenter:r[1]||(r[1]=c=>e.value=!0),onMouseleave:r[2]||(r[2]=c=>e.value=!1)},[u("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":a.label,onClick:r[0]||(r[0]=c=>e.value=!e.value)},[a.button||a.icon?(s(),l("span",Gs,[a.icon?(s(),y(re(a.icon),{key:0,class:"option-icon"})):f("",!0),a.button?(s(),l("span",{key:1,innerHTML:a.button},null,8,Rs)):f("",!0),_(Lt,{class:"text-icon"})])):(s(),y(Is,{key:1,class:"icon"}))],8,Us),u("div",qs,[_(js,{items:a.items},{default:p(()=>[v(a.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),et=g(Ks,[["__scopeId","data-v-f5a36f1b"]]),Ws={discord:'Discord',facebook:'Facebook',github:'GitHub',instagram:'Instagram',linkedin:'LinkedIn',mastodon:'Mastodon',slack:'Slack',twitter:'Twitter',x:'X',youtube:'YouTube'},Ys=["href","aria-label","innerHTML"],Zs=b({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(n){const e=n,t=L(()=>typeof e.icon=="object"?e.icon.svg:Ws[e.icon]);return(o,a)=>(s(),l("a",{class:"VPSocialLink no-icon",href:o.link,"aria-label":o.ariaLabel??(typeof o.icon=="string"?o.icon:""),target:"_blank",rel:"noopener",innerHTML:t.value},null,8,Ys))}}),Xs=g(Zs,[["__scopeId","data-v-405b7737"]]),Js={class:"VPSocialLinks"},Qs=b({__name:"VPSocialLinks",props:{links:{}},setup(n){return(e,t)=>(s(),l("div",Js,[(s(!0),l(A,null,G(e.links,({link:o,icon:a,ariaLabel:r})=>(s(),y(Xs,{key:o,icon:a,link:o,ariaLabel:r},null,8,["icon","link","ariaLabel"]))),128))]))}}),Ee=g(Qs,[["__scopeId","data-v-c9800f80"]]),er={key:0,class:"group translations"},tr={class:"trans-title"},nr={key:1,class:"group"},or={class:"item appearance"},ar={class:"label"},sr={class:"appearance-action"},rr={key:2,class:"group"},ir={class:"item social-links"},lr=b({__name:"VPNavBarExtra",setup(n){const{site:e,theme:t}=z(),{localeLinks:o,currentLang:a}=_e({correspondingLink:!0}),r=L(()=>o.value.length&&a.value.label||e.value.appearance||t.value.socialLinks);return(c,d)=>r.value?(s(),y(et,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:p(()=>[i(o).length&&i(a).label?(s(),l("div",er,[u("p",tr,T(i(a).label),1),(s(!0),l(A,null,G(i(o),m=>(s(),y(Ie,{key:m.link,item:m},null,8,["item"]))),128))])):f("",!0),i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",nr,[u("div",or,[u("p",ar,T(i(t).darkModeSwitchLabel||"Appearance"),1),u("div",sr,[_(Je)])])])):f("",!0),i(t).socialLinks?(s(),l("div",rr,[u("div",ir,[_(Ee,{class:"social-links-list",links:i(t).socialLinks},null,8,["links"])])])):f("",!0)]),_:1})):f("",!0)}}),cr=g(lr,[["__scopeId","data-v-8a171de0"]]),ur=n=>(Z("data-v-f746d7e0"),n=n(),X(),n),dr=["aria-expanded"],mr=ur(()=>u("span",{class:"container"},[u("span",{class:"top"}),u("span",{class:"middle"}),u("span",{class:"bottom"})],-1)),vr=[mr],pr=b({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(n){return(e,t)=>(s(),l("button",{type:"button",class:H(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:t[0]||(t[0]=o=>e.$emit("click"))},vr,10,dr))}}),hr=g(pr,[["__scopeId","data-v-f746d7e0"]]),fr=["innerHTML"],_r=b({__name:"VPNavBarMenuLink",props:{item:{}},setup(n){const{page:e}=z();return(t,o)=>(s(),y(K,{class:H({VPNavBarMenuLink:!0,active:i(ie)(i(e).relativePath,t.item.activeMatch||t.item.link,!!t.item.activeMatch)}),href:t.item.link,target:t.item.target,rel:t.item.rel,tabindex:"0"},{default:p(()=>[u("span",{innerHTML:t.item.text},null,8,fr)]),_:1},8,["class","href","target","rel"]))}}),gr=g(_r,[["__scopeId","data-v-ef9c2bfa"]]),br=b({__name:"VPNavBarMenuGroup",props:{item:{}},setup(n){const e=n,{page:t}=z(),o=r=>"link"in r?ie(t.value.relativePath,r.link,!!e.item.activeMatch):r.items.some(o),a=L(()=>o(e.item));return(r,c)=>(s(),y(et,{class:H({VPNavBarMenuGroup:!0,active:i(ie)(i(t).relativePath,r.item.activeMatch,!!r.item.activeMatch)||a.value}),button:r.item.text,items:r.item.items},null,8,["class","button","items"]))}}),kr=n=>(Z("data-v-ca39d846"),n=n(),X(),n),$r={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},yr=kr(()=>u("span",{id:"main-nav-aria-label",class:"visually-hidden"},"Main Navigation",-1)),wr=b({__name:"VPNavBarMenu",setup(n){const{theme:e}=z();return(t,o)=>i(e).nav?(s(),l("nav",$r,[yr,(s(!0),l(A,null,G(i(e).nav,a=>(s(),l(A,{key:a.text},["link"in a?(s(),y(gr,{key:0,item:a},null,8,["item"])):(s(),y(br,{key:1,item:a},null,8,["item"]))],64))),128))])):f("",!0)}}),Lr=g(wr,[["__scopeId","data-v-ca39d846"]]);function Pr(n){const{localeIndex:e,theme:t}=z();function o(a){var V,I,N;const r=a.split("."),c=(V=t.value.search)==null?void 0:V.options,d=c&&typeof c=="object",m=d&&((N=(I=c.locales)==null?void 0:I[e.value])==null?void 0:N.translations)||null,k=d&&c.translations||null;let $=m,w=k,S=n;const B=r.pop();for(const ue of r){let J=null;const F=S==null?void 0:S[ue];F&&(J=S=F);const oe=w==null?void 0:w[ue];oe&&(J=w=oe);const Q=$==null?void 0:$[ue];Q&&(J=$=Q),F||(S=J),oe||(w=J),Q||($=J)}return($==null?void 0:$[B])??(w==null?void 0:w[B])??(S==null?void 0:S[B])??""}return o}const Vr=["aria-label"],Sr={class:"DocSearch-Button-Container"},zr=u("svg",{class:"DocSearch-Search-Icon",width:"20",height:"20",viewBox:"0 0 20 20","aria-label":"search icon"},[u("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})],-1),Cr={class:"DocSearch-Button-Placeholder"},Tr=u("span",{class:"DocSearch-Button-Keys"},[u("kbd",{class:"DocSearch-Button-Key"}),u("kbd",{class:"DocSearch-Button-Key"},"K")],-1),at=b({__name:"VPNavBarSearchButton",setup(n){const t=Pr({button:{buttonText:"Search",buttonAriaLabel:"Search"}});return(o,a)=>(s(),l("button",{type:"button",class:"DocSearch DocSearch-Button","aria-label":i(t)("button.buttonAriaLabel")},[u("span",Sr,[zr,u("span",Cr,T(i(t)("button.buttonText")),1)]),Tr],8,Vr))}}),Mr={class:"VPNavBarSearch"},Ir={id:"local-search"},Er={key:1,id:"docsearch"},Nr=b({__name:"VPNavBarSearch",setup(n){const e=Yt(()=>pt(()=>import("./VPLocalSearchBox.DH5uDbJr.js"),__vite__mapDeps([0,1]))),t=()=>null,{theme:o}=z(),a=E(!1),r=E(!1);Y(()=>{});function c(){a.value||(a.value=!0,setTimeout(d,16))}function d(){const w=new Event("keydown");w.key="k",w.metaKey=!0,window.dispatchEvent(w),setTimeout(()=>{document.querySelector(".DocSearch-Modal")||d()},16)}function m(w){const S=w.target,B=S.tagName;return S.isContentEditable||B==="INPUT"||B==="SELECT"||B==="TEXTAREA"}const k=E(!1);xe("k",w=>{(w.ctrlKey||w.metaKey)&&(w.preventDefault(),k.value=!0)}),xe("/",w=>{m(w)||(w.preventDefault(),k.value=!0)});const $="local";return(w,S)=>{var B;return s(),l("div",Mr,[i($)==="local"?(s(),l(A,{key:0},[k.value?(s(),y(i(e),{key:0,onClose:S[0]||(S[0]=V=>k.value=!1)})):f("",!0),u("div",Ir,[_(at,{onClick:S[1]||(S[1]=V=>k.value=!0)})])],64)):i($)==="algolia"?(s(),l(A,{key:1},[a.value?(s(),y(i(t),{key:0,algolia:((B=i(o).search)==null?void 0:B.options)??i(o).algolia,onVnodeBeforeMount:S[2]||(S[2]=V=>r.value=!0)},null,8,["algolia"])):f("",!0),r.value?f("",!0):(s(),l("div",Er,[_(at,{onClick:c})]))],64)):f("",!0)])}}}),Hr=b({__name:"VPNavBarSocialLinks",setup(n){const{theme:e}=z();return(t,o)=>i(e).socialLinks?(s(),y(Ee,{key:0,class:"VPNavBarSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Ar=g(Hr,[["__scopeId","data-v-fe082610"]]),Br=["href","rel","target"],Or=b({__name:"VPNavBarTitle",setup(n){const{site:e,theme:t}=z(),{hasSidebar:o}=ne(),{currentLang:a}=_e(),r=L(()=>{var m;return typeof t.value.logoLink=="string"?t.value.logoLink:(m=t.value.logoLink)==null?void 0:m.link}),c=L(()=>{var m;return typeof t.value.logoLink=="string"||(m=t.value.logoLink)==null?void 0:m.rel}),d=L(()=>{var m;return typeof t.value.logoLink=="string"||(m=t.value.logoLink)==null?void 0:m.target});return(m,k)=>(s(),l("div",{class:H(["VPNavBarTitle",{"has-sidebar":i(o)}])},[u("a",{class:"title",href:r.value??i(Ye)(i(a).link),rel:c.value,target:d.value},[v(m.$slots,"nav-bar-title-before",{},void 0,!0),i(t).logo?(s(),y(Se,{key:0,class:"logo",image:i(t).logo},null,8,["image"])):f("",!0),i(t).siteTitle?(s(),l(A,{key:1},[j(T(i(t).siteTitle),1)],64)):i(t).siteTitle===void 0?(s(),l(A,{key:2},[j(T(i(e).title),1)],64)):f("",!0),v(m.$slots,"nav-bar-title-after",{},void 0,!0)],8,Br)],2))}}),Dr=g(Or,[["__scopeId","data-v-15df090c"]]),Fr={},xr={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},jr=u("path",{d:"M0 0h24v24H0z",fill:"none"},null,-1),Ur=u("path",{d:" M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z ",class:"css-c4d79v"},null,-1),Gr=[jr,Ur];function Rr(n,e){return s(),l("svg",xr,Gr)}const Pt=g(Fr,[["render",Rr]]),qr={class:"items"},Kr={class:"title"},Wr=b({__name:"VPNavBarTranslations",setup(n){const{theme:e}=z(),{localeLinks:t,currentLang:o}=_e({correspondingLink:!0});return(a,r)=>i(t).length&&i(o).label?(s(),y(et,{key:0,class:"VPNavBarTranslations",icon:Pt,label:i(e).langMenuLabel||"Change language"},{default:p(()=>[u("div",qr,[u("p",Kr,T(i(o).label),1),(s(!0),l(A,null,G(i(t),c=>(s(),y(Ie,{key:c.link,item:c},null,8,["item"]))),128))])]),_:1},8,["label"])):f("",!0)}}),Yr=g(Wr,[["__scopeId","data-v-cf938b1a"]]),Zr=n=>(Z("data-v-293f3bf8"),n=n(),X(),n),Xr={class:"wrapper"},Jr={class:"container"},Qr={class:"title"},ei={class:"content"},ti={class:"content-body"},ni=Zr(()=>u("div",{class:"divider"},[u("div",{class:"divider-line"})],-1)),oi=b({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(n){const{y:e}=vt(),{hasSidebar:t}=ne(),{hasLocalNav:o}=kt(),{frontmatter:a}=z(),r=E({});return ut(()=>{r.value={"has-sidebar":t.value,"has-local-nav":o.value,top:a.value.layout==="home"&&e.value===0}}),(c,d)=>(s(),l("div",{class:H(["VPNavBar",r.value])},[u("div",Xr,[u("div",Jr,[u("div",Qr,[_(Dr,null,{"nav-bar-title-before":p(()=>[v(c.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(c.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),u("div",ei,[u("div",ti,[v(c.$slots,"nav-bar-content-before",{},void 0,!0),_(Nr,{class:"search"}),_(Lr,{class:"menu"}),_(Yr,{class:"translations"}),_(fs,{class:"appearance"}),_(Ar,{class:"social-links"}),_(cr,{class:"extra"}),v(c.$slots,"nav-bar-content-after",{},void 0,!0),_(hr,{class:"hamburger",active:c.isScreenOpen,onClick:d[0]||(d[0]=m=>c.$emit("toggle-screen"))},null,8,["active"])])])])]),ni],2))}}),ai=g(oi,[["__scopeId","data-v-293f3bf8"]]),si={key:0,class:"VPNavScreenAppearance"},ri={class:"text"},ii=b({__name:"VPNavScreenAppearance",setup(n){const{site:e,theme:t}=z();return(o,a)=>i(e).appearance&&i(e).appearance!=="force-dark"?(s(),l("div",si,[u("p",ri,T(i(t).darkModeSwitchLabel||"Appearance"),1),_(Je)])):f("",!0)}}),li=g(ii,[["__scopeId","data-v-46f82938"]]),ci=b({__name:"VPNavScreenMenuLink",props:{item:{}},setup(n){const e=Me("close-screen");return(t,o)=>(s(),y(K,{class:"VPNavScreenMenuLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),ui=g(ci,[["__scopeId","data-v-55da9136"]]),di={},mi={xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",viewBox:"0 0 24 24"},vi=u("path",{d:"M18.9,10.9h-6v-6c0-0.6-0.4-1-1-1s-1,0.4-1,1v6h-6c-0.6,0-1,0.4-1,1s0.4,1,1,1h6v6c0,0.6,0.4,1,1,1s1-0.4,1-1v-6h6c0.6,0,1-0.4,1-1S19.5,10.9,18.9,10.9z"},null,-1),pi=[vi];function hi(n,e){return s(),l("svg",mi,pi)}const fi=g(di,[["render",hi]]),_i=b({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(n){const e=Me("close-screen");return(t,o)=>(s(),y(K,{class:"VPNavScreenMenuGroupLink",href:t.item.link,target:t.item.target,rel:t.item.rel,onClick:i(e)},{default:p(()=>[j(T(t.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),Vt=g(_i,[["__scopeId","data-v-c1cc298a"]]),gi={class:"VPNavScreenMenuGroupSection"},bi={key:0,class:"title"},ki=b({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(n){return(e,t)=>(s(),l("div",gi,[e.text?(s(),l("p",bi,T(e.text),1)):f("",!0),(s(!0),l(A,null,G(e.items,o=>(s(),y(Vt,{key:o.text,item:o},null,8,["item"]))),128))]))}}),$i=g(ki,[["__scopeId","data-v-b00c649a"]]),yi=["aria-controls","aria-expanded"],wi=["innerHTML"],Li=["id"],Pi={key:1,class:"group"},Vi=b({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(n){const e=n,t=E(!1),o=L(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function a(){t.value=!t.value}return(r,c)=>(s(),l("div",{class:H(["VPNavScreenMenuGroup",{open:t.value}])},[u("button",{class:"button","aria-controls":o.value,"aria-expanded":t.value,onClick:a},[u("span",{class:"button-text",innerHTML:r.text},null,8,wi),_(fi,{class:"button-icon"})],8,yi),u("div",{id:o.value,class:"items"},[(s(!0),l(A,null,G(r.items,d=>(s(),l(A,{key:d.text},["link"in d?(s(),l("div",{key:d.text,class:"item"},[_(Vt,{item:d},null,8,["item"])])):(s(),l("div",Pi,[_($i,{text:d.text,items:d.items},null,8,["text","items"])]))],64))),128))],8,Li)],2))}}),Si=g(Vi,[["__scopeId","data-v-31391d93"]]),zi={key:0,class:"VPNavScreenMenu"},Ci=b({__name:"VPNavScreenMenu",setup(n){const{theme:e}=z();return(t,o)=>i(e).nav?(s(),l("nav",zi,[(s(!0),l(A,null,G(i(e).nav,a=>(s(),l(A,{key:a.text},["link"in a?(s(),y(ui,{key:0,item:a},null,8,["item"])):(s(),y(Si,{key:1,text:a.text||"",items:a.items},null,8,["text","items"]))],64))),128))])):f("",!0)}}),Ti=b({__name:"VPNavScreenSocialLinks",setup(n){const{theme:e}=z();return(t,o)=>i(e).socialLinks?(s(),y(Ee,{key:0,class:"VPNavScreenSocialLinks",links:i(e).socialLinks},null,8,["links"])):f("",!0)}}),Mi={class:"list"},Ii=b({__name:"VPNavScreenTranslations",setup(n){const{localeLinks:e,currentLang:t}=_e({correspondingLink:!0}),o=E(!1);function a(){o.value=!o.value}return(r,c)=>i(e).length&&i(t).label?(s(),l("div",{key:0,class:H(["VPNavScreenTranslations",{open:o.value}])},[u("button",{class:"title",onClick:a},[_(Pt,{class:"icon lang"}),j(" "+T(i(t).label)+" ",1),_(Lt,{class:"icon chevron"})]),u("ul",Mi,[(s(!0),l(A,null,G(i(e),d=>(s(),l("li",{key:d.link,class:"item"},[_(K,{class:"link",href:d.link},{default:p(()=>[j(T(d.text),1)]),_:2},1032,["href"])]))),128))])],2)):f("",!0)}}),Ei=g(Ii,[["__scopeId","data-v-b6d43e7d"]]),Ni={class:"container"},Hi=b({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(n){const e=E(null),t=ht(le?document.body:null);return(o,a)=>(s(),y(ze,{name:"fade",onEnter:a[0]||(a[0]=r=>t.value=!0),onAfterLeave:a[1]||(a[1]=r=>t.value=!1)},{default:p(()=>[o.open?(s(),l("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[u("div",Ni,[v(o.$slots,"nav-screen-content-before",{},void 0,!0),_(Ci,{class:"menu"}),_(Ei,{class:"translations"}),_(li,{class:"appearance"}),_(Ti,{class:"social-links"}),v(o.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):f("",!0)]),_:3}))}}),Ai=g(Hi,[["__scopeId","data-v-3dd6f37e"]]),Bi={key:0,class:"VPNav"},Oi=b({__name:"VPNav",setup(n){const{isScreenOpen:e,closeScreen:t,toggleScreen:o}=Wa(),{frontmatter:a}=z(),r=L(()=>a.value.navbar!==!1);return ft("close-screen",t),Ce(()=>{le&&document.documentElement.classList.toggle("hide-nav",!r.value)}),(c,d)=>r.value?(s(),l("header",Bi,[_(ai,{"is-screen-open":i(e),onToggleScreen:i(o)},{"nav-bar-title-before":p(()=>[v(c.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(c.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[v(c.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[v(c.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),_(Ai,{open:i(e)},{"nav-screen-content-before":p(()=>[v(c.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[v(c.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):f("",!0)}}),Di=g(Oi,[["__scopeId","data-v-9ac35370"]]),Fi=n=>(Z("data-v-e216f58b"),n=n(),X(),n),xi=["role","tabindex"],ji=Fi(()=>u("div",{class:"indicator"},null,-1)),Ui={key:1,class:"items"},Gi=b({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(n){const e=n,{collapsed:t,collapsible:o,isLink:a,isActiveLink:r,hasActiveLink:c,hasChildren:d,toggle:m}=yn(L(()=>e.item)),k=L(()=>d.value?"section":"div"),$=L(()=>a.value?"a":"div"),w=L(()=>d.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),S=L(()=>a.value?void 0:"button"),B=L(()=>[[`level-${e.depth}`],{collapsible:o.value},{collapsed:t.value},{"is-link":a.value},{"is-active":r.value},{"has-active":c.value}]);function V(N){"key"in N&&N.key!=="Enter"||!e.item.link&&m()}function I(){e.item.link&&m()}return(N,ue)=>{const J=ce("VPSidebarItem",!0);return s(),y(re(k.value),{class:H(["VPSidebarItem",B.value])},{default:p(()=>[N.item.text?(s(),l("div",we({key:0,class:"item",role:S.value},Zt(N.item.items?{click:V,keydown:V}:{},!0),{tabindex:N.item.items&&0}),[ji,N.item.link?(s(),y(K,{key:0,tag:$.value,class:"link",href:N.item.link,rel:N.item.rel,target:N.item.target},{default:p(()=>[(s(),y(re(w.value),{class:"text",innerHTML:N.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(s(),y(re(w.value),{key:1,class:"text",innerHTML:N.item.text},null,8,["innerHTML"])),N.item.collapsed!=null?(s(),l("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:I,onKeydown:Xt(I,["enter"]),tabindex:"0"},[_($t,{class:"caret-icon"})],32)):f("",!0)],16,xi)):f("",!0),N.item.items&&N.item.items.length?(s(),l("div",Ui,[N.depth<5?(s(!0),l(A,{key:0},G(N.item.items,F=>(s(),y(J,{key:F.text,item:F,depth:N.depth+1},null,8,["item","depth"]))),128)):f("",!0)])):f("",!0)]),_:1},8,["class"])}}}),Ri=g(Gi,[["__scopeId","data-v-e216f58b"]]),St=n=>(Z("data-v-71cefa04"),n=n(),X(),n),qi=St(()=>u("div",{class:"curtain"},null,-1)),Ki={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Wi=St(()=>u("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),Yi=b({__name:"VPSidebar",props:{open:{type:Boolean}},setup(n){const{sidebarGroups:e,hasSidebar:t}=ne(),o=n,a=E(null),r=ht(le?document.body:null);return te([o,a],()=>{var c;o.open?(r.value=!0,(c=a.value)==null||c.focus()):r.value=!1},{immediate:!0,flush:"post"}),(c,d)=>i(t)?(s(),l("aside",{key:0,class:H(["VPSidebar",{open:c.open}]),ref_key:"navEl",ref:a,onClick:d[0]||(d[0]=Jt(()=>{},["stop"]))},[qi,u("nav",Ki,[Wi,v(c.$slots,"sidebar-nav-before",{},void 0,!0),(s(!0),l(A,null,G(i(e),m=>(s(),l("div",{key:m.text,class:"group"},[_(Ri,{item:m,depth:0},null,8,["item"])]))),128)),v(c.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):f("",!0)}}),Zi=g(Yi,[["__scopeId","data-v-71cefa04"]]),Xi=b({__name:"VPSkipLink",setup(n){const e=fe(),t=E();te(()=>e.path,()=>t.value.focus());function o({target:a}){const r=document.getElementById(decodeURIComponent(a.hash).slice(1));if(r){const c=()=>{r.removeAttribute("tabindex"),r.removeEventListener("blur",c)};r.setAttribute("tabindex","-1"),r.addEventListener("blur",c),r.focus(),window.scrollTo(0,0)}}return(a,r)=>(s(),l(A,null,[u("span",{ref_key:"backToTop",ref:t,tabindex:"-1"},null,512),u("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:o}," Skip to content ")],64))}}),Ji=g(Xi,[["__scopeId","data-v-db2dcaee"]]),Qi=b({__name:"Layout",setup(n){const{isOpen:e,open:t,close:o}=ne(),a=fe();te(()=>a.path,o),$n(e,o);const{frontmatter:r}=z(),c=Qt(),d=L(()=>!!c["home-hero-image"]);return ft("hero-image-slot-exists",d),(m,k)=>{const $=ce("Content");return i(r).layout!==!1?(s(),l("div",{key:0,class:H(["Layout",i(r).pageClass])},[v(m.$slots,"layout-top",{},void 0,!0),_(Ji),_(sn,{class:"backdrop",show:i(e),onClick:i(o)},null,8,["show","onClick"]),_(Di,null,{"nav-bar-title-before":p(()=>[v(m.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":p(()=>[v(m.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":p(()=>[v(m.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":p(()=>[v(m.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":p(()=>[v(m.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":p(()=>[v(m.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),_(Ka,{open:i(e),onOpenMenu:i(t)},null,8,["open","onOpenMenu"]),_(Zi,{open:i(e)},{"sidebar-nav-before":p(()=>[v(m.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":p(()=>[v(m.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),_(ba,null,{"page-top":p(()=>[v(m.$slots,"page-top",{},void 0,!0)]),"page-bottom":p(()=>[v(m.$slots,"page-bottom",{},void 0,!0)]),"not-found":p(()=>[v(m.$slots,"not-found",{},void 0,!0)]),"home-hero-before":p(()=>[v(m.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info":p(()=>[v(m.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-image":p(()=>[v(m.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":p(()=>[v(m.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":p(()=>[v(m.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":p(()=>[v(m.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":p(()=>[v(m.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":p(()=>[v(m.$slots,"doc-before",{},void 0,!0)]),"doc-after":p(()=>[v(m.$slots,"doc-after",{},void 0,!0)]),"doc-top":p(()=>[v(m.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":p(()=>[v(m.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":p(()=>[v(m.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":p(()=>[v(m.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":p(()=>[v(m.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":p(()=>[v(m.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":p(()=>[v(m.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":p(()=>[v(m.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),_(La),v(m.$slots,"layout-bottom",{},void 0,!0)],2)):(s(),y($,{key:1}))}}}),el=g(Qi,[["__scopeId","data-v-c9d4f922"]]),tl={},nl={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},ol=u("path",{d:"M12,22.2c-0.3,0-0.5-0.1-0.7-0.3l-8.8-8.8c-2.5-2.5-2.5-6.7,0-9.2c2.5-2.5,6.7-2.5,9.2,0L12,4.3l0.4-0.4c0,0,0,0,0,0C13.6,2.7,15.2,2,16.9,2c0,0,0,0,0,0c1.7,0,3.4,0.7,4.6,1.9l0,0c1.2,1.2,1.9,2.9,1.9,4.6c0,1.7-0.7,3.4-1.9,4.6l-8.8,8.8C12.5,22.1,12.3,22.2,12,22.2zM7,4C5.9,4,4.7,4.4,3.9,5.3c-1.8,1.8-1.8,4.6,0,6.4l8.1,8.1l8.1-8.1c0.9-0.9,1.3-2,1.3-3.2c0-1.2-0.5-2.3-1.3-3.2l0,0C19.3,4.5,18.2,4,17,4c0,0,0,0,0,0c-1.2,0-2.3,0.5-3.2,1.3c0,0,0,0,0,0l-1.1,1.1c-0.4,0.4-1,0.4-1.4,0l-1.1-1.1C9.4,4.4,8.2,4,7,4z"},null,-1),al=[ol];function sl(n,e){return s(),l("svg",nl,al)}const rl=g(tl,[["render",sl]]),il={},ll={class:"VPTeamPage"};function cl(n,e){return s(),l("div",ll,[v(n.$slots,"default")])}const oc=g(il,[["render",cl],["__scopeId","data-v-c649c573"]]),ul={},dl={class:"VPTeamPageTitle"},ml={key:0,class:"title"},vl={key:1,class:"lead"};function pl(n,e){return s(),l("div",dl,[n.$slots.title?(s(),l("h1",ml,[v(n.$slots,"title",{},void 0,!0)])):f("",!0),n.$slots.lead?(s(),l("p",vl,[v(n.$slots,"lead",{},void 0,!0)])):f("",!0)])}const ac=g(ul,[["render",pl],["__scopeId","data-v-ba2c7188"]]),hl={class:"profile"},fl={class:"avatar"},_l=["src","alt"],gl={class:"data"},bl={class:"name"},kl={key:0,class:"affiliation"},$l={key:0,class:"title"},yl={key:1,class:"at"},wl=["innerHTML"],Ll={key:2,class:"links"},Pl={key:0,class:"sp"},Vl=b({__name:"VPTeamMembersItem",props:{size:{default:"medium"},member:{}},setup(n){return(e,t)=>(s(),l("article",{class:H(["VPTeamMembersItem",[e.size]])},[u("div",hl,[u("figure",fl,[u("img",{class:"avatar-img",src:e.member.avatar,alt:e.member.name},null,8,_l)]),u("div",gl,[u("h1",bl,T(e.member.name),1),e.member.title||e.member.org?(s(),l("p",kl,[e.member.title?(s(),l("span",$l,T(e.member.title),1)):f("",!0),e.member.title&&e.member.org?(s(),l("span",yl," @ ")):f("",!0),e.member.org?(s(),y(K,{key:2,class:H(["org",{link:e.member.orgLink}]),href:e.member.orgLink,"no-icon":""},{default:p(()=>[j(T(e.member.org),1)]),_:1},8,["class","href"])):f("",!0)])):f("",!0),e.member.desc?(s(),l("p",{key:1,class:"desc",innerHTML:e.member.desc},null,8,wl)):f("",!0),e.member.links?(s(),l("div",Ll,[_(Ee,{links:e.member.links},null,8,["links"])])):f("",!0)])]),e.member.sponsor?(s(),l("div",Pl,[_(K,{class:"sp-link",href:e.member.sponsor,"no-icon":""},{default:p(()=>[_(rl,{class:"sp-icon"}),j(" "+T(e.member.actionText||"Sponsor"),1)]),_:1},8,["href"])])):f("",!0)],2))}}),Sl=g(Vl,[["__scopeId","data-v-13ff0bb7"]]),zl={class:"container"},Cl=b({__name:"VPTeamMembers",props:{size:{default:"medium"},members:{}},setup(n){const e=n,t=L(()=>[e.size,`count-${e.members.length}`]);return(o,a)=>(s(),l("div",{class:H(["VPTeamMembers",t.value])},[u("div",zl,[(s(!0),l(A,null,G(o.members,r=>(s(),l("div",{key:r.name,class:"item"},[_(Sl,{size:o.size,member:r},null,8,["size","member"])]))),128))])],2))}}),sc=g(Cl,[["__scopeId","data-v-9c4594aa"]]),st={Layout:el,enhanceApp:({app:n})=>{n.component("Badge",nn)}},Tl=["id","host","repo","repoid","category","categoryid","mapping","term","strict","reactionsenabled","emitmetadata","inputposition","theme","lang","loading"],Ml=b({__name:"Giscus",props:{id:{},host:{},repo:{},repoId:{},category:{},categoryId:{},mapping:{},term:{},theme:{},strict:{},reactionsEnabled:{},emitMetadata:{},inputPosition:{},lang:{},loading:{}},setup(n){const e=E(!1);return Y(()=>{e.value=!0,pt(()=>import("./giscus-aTimukGI.CKTvSCx2.js"),[])}),(t,o)=>e.value?(s(),l("giscus-widget",{key:0,id:t.id,host:t.host,repo:t.repo,repoid:t.repoId,category:t.category,categoryid:t.categoryId,mapping:t.mapping,term:t.term,strict:t.strict,reactionsenabled:t.reactionsEnabled,emitmetadata:t.emitMetadata,inputposition:t.inputPosition,theme:t.theme,lang:t.lang,loading:t.loading},null,8,Tl)):f("",!0)}}),rt=(n,e,t=!0)=>{var k;const o={id:"comment",host:"https://giscus.app",category:"General",mapping:"pathname",term:"Welcome to giscus!",reactionsEnabled:"1",inputPosition:"top",lang:"zh-CN",loading:"lazy",repo:"xxx/xxx",repoId:"",homePageShowComment:!1};if(n.locales){const w=document.querySelector("html").getAttribute("lang");w&&n.locales[w]&&(n.lang=n.locales[w])}const a=n.lightTheme||"light",r=n.darkTheme||"transparent_dark";let c=document.getElementById("giscus");if(c&&c.parentNode.removeChild(c),(e==null?void 0:e.value.comment)!==void 0){if(!(e!=null&&e.value.comment))return}else if(!t)return;if(!n.homePageShowComment&&(!location.pathname||location.pathname==="/"))return;const d=((k=document.querySelector("html"))==null?void 0:k.className.indexOf("dark"))!==-1,m=document.getElementsByClassName("content-container")[0];if(m){const $=document.createElement("div");$.setAttribute("id","giscus"),$.style.height="auto",$.style.marginTop="40px",$.style.borderTop="1px solid var(--vp-c-divider)",$.style.paddingTop="20px",m.append($),en({render:()=>Ve(Ml,{...o,theme:d?r:a,...n})}).mount("#giscus")}},Il=n=>{const e=document.querySelector("html"),t=n.lightTheme||"light",o=n.darkTheme||"transparent_dark";new MutationObserver(r=>{r.forEach(c=>{if(c.type=="attributes"){let d=document.getElementById("comment");d==null||d.setAttribute("theme",e.className.indexOf("dark")!==-1?o:t)}})}).observe(e,{attributeFilter:["class"]})},El=(n,e,t=!0)=>{Y(()=>{rt(n,e.frontmatter,t),Il(n)}),te(()=>e.route.path,()=>We(()=>{rt(n,e.frontmatter,t)}))};/*! medium-zoom 1.1.0 | MIT License | https://github.com/francoischalifour/medium-zoom */var se=Object.assign||function(n){for(var e=1;e1&&arguments[1]!==void 0?arguments[1]:{},o=window.Promise||function(P){function C(){}P(C,C)},a=function(P){var C=P.target;if(C===ge){V();return}F.indexOf(C)!==-1&&I({target:C})},r=function(){if(!(Q||!h.original)){var P=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(tt-P)>O.scrollOffset&&setTimeout(V,150)}},c=function(P){var C=P.key||P.keyCode;(C==="Escape"||C==="Esc"||C===27)&&V()},d=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},C=P;if(P.background&&(ge.style.background=P.background),P.container&&P.container instanceof Object&&(C.container=se({},O.container,P.container)),P.template){var D=Pe(P.template)?P.template:document.querySelector(P.template);C.template=D}return O=se({},O,C),F.forEach(function(x){x.dispatchEvent(me("medium-zoom:update",{detail:{zoom:U}}))}),U},m=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return n(se({},O,P))},k=function(){for(var P=arguments.length,C=Array(P),D=0;D0?C.reduce(function(M,q){return[].concat(M,lt(q))},[]):F;return x.forEach(function(M){M.classList.remove("medium-zoom-image"),M.dispatchEvent(me("medium-zoom:detach",{detail:{zoom:U}}))}),F=F.filter(function(M){return x.indexOf(M)===-1}),U},w=function(P,C){var D=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return F.forEach(function(x){x.addEventListener("medium-zoom:"+P,C,D)}),oe.push({type:"medium-zoom:"+P,listener:C,options:D}),U},S=function(P,C){var D=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return F.forEach(function(x){x.removeEventListener("medium-zoom:"+P,C,D)}),oe=oe.filter(function(x){return!(x.type==="medium-zoom:"+P&&x.listener.toString()===C.toString())}),U},B=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},C=P.target,D=function(){var M={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},q=void 0,W=void 0;if(O.container)if(O.container instanceof Object)M=se({},M,O.container),q=M.width-M.left-M.right-O.margin*2,W=M.height-M.top-M.bottom-O.margin*2;else{var de=Pe(O.container)?O.container:document.querySelector(O.container),ae=de.getBoundingClientRect(),Ne=ae.width,Mt=ae.height,It=ae.left,Et=ae.top;M=se({},M,{width:Ne,height:Mt,left:It,top:Et})}q=q||M.width-O.margin*2,W=W||M.height-O.margin*2;var he=h.zoomedHd||h.original,Nt=it(he)?q:he.naturalWidth||q,Ht=it(he)?W:he.naturalHeight||W,be=he.getBoundingClientRect(),At=be.top,Bt=be.left,He=be.width,Ae=be.height,Ot=Math.min(Math.max(He,Nt),q)/He,Dt=Math.min(Math.max(Ae,Ht),W)/Ae,Be=Math.min(Ot,Dt),Ft=(-Bt+(q-He)/2+O.margin+M.left)/Be,xt=(-At+(W-Ae)/2+O.margin+M.top)/Be,nt="scale("+Be+") translate3d("+Ft+"px, "+xt+"px, 0)";h.zoomed.style.transform=nt,h.zoomedHd&&(h.zoomedHd.style.transform=nt)};return new o(function(x){if(C&&F.indexOf(C)===-1){x(U);return}var M=function Ne(){Q=!1,h.zoomed.removeEventListener("transitionend",Ne),h.original.dispatchEvent(me("medium-zoom:opened",{detail:{zoom:U}})),x(U)};if(h.zoomed){x(U);return}if(C)h.original=C;else if(F.length>0){var q=F;h.original=q[0]}else{x(U);return}if(h.original.dispatchEvent(me("medium-zoom:open",{detail:{zoom:U}})),tt=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,Q=!0,h.zoomed=Al(h.original),document.body.appendChild(ge),O.template){var W=Pe(O.template)?O.template:document.querySelector(O.template);h.template=document.createElement("div"),h.template.appendChild(W.content.cloneNode(!0)),document.body.appendChild(h.template)}if(h.original.parentElement&&h.original.parentElement.tagName==="PICTURE"&&h.original.currentSrc&&(h.zoomed.src=h.original.currentSrc),document.body.appendChild(h.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),h.original.classList.add("medium-zoom-image--hidden"),h.zoomed.classList.add("medium-zoom-image--opened"),h.zoomed.addEventListener("click",V),h.zoomed.addEventListener("transitionend",M),h.original.getAttribute("data-zoom-src")){h.zoomedHd=h.zoomed.cloneNode(),h.zoomedHd.removeAttribute("srcset"),h.zoomedHd.removeAttribute("sizes"),h.zoomedHd.removeAttribute("loading"),h.zoomedHd.src=h.zoomed.getAttribute("data-zoom-src"),h.zoomedHd.onerror=function(){clearInterval(de),console.warn("Unable to reach the zoom image target "+h.zoomedHd.src),h.zoomedHd=null,D()};var de=setInterval(function(){h.zoomedHd.complete&&(clearInterval(de),h.zoomedHd.classList.add("medium-zoom-image--opened"),h.zoomedHd.addEventListener("click",V),document.body.appendChild(h.zoomedHd),D())},10)}else if(h.original.hasAttribute("srcset")){h.zoomedHd=h.zoomed.cloneNode(),h.zoomedHd.removeAttribute("sizes"),h.zoomedHd.removeAttribute("loading");var ae=h.zoomedHd.addEventListener("load",function(){h.zoomedHd.removeEventListener("load",ae),h.zoomedHd.classList.add("medium-zoom-image--opened"),h.zoomedHd.addEventListener("click",V),document.body.appendChild(h.zoomedHd),D()})}else D()})},V=function(){return new o(function(P){if(Q||!h.original){P(U);return}var C=function D(){h.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(h.zoomed),h.zoomedHd&&document.body.removeChild(h.zoomedHd),document.body.removeChild(ge),h.zoomed.classList.remove("medium-zoom-image--opened"),h.template&&document.body.removeChild(h.template),Q=!1,h.zoomed.removeEventListener("transitionend",D),h.original.dispatchEvent(me("medium-zoom:closed",{detail:{zoom:U}})),h.original=null,h.zoomed=null,h.zoomedHd=null,h.template=null,P(U)};Q=!0,document.body.classList.remove("medium-zoom--opened"),h.zoomed.style.transform="",h.zoomedHd&&(h.zoomedHd.style.transform=""),h.template&&(h.template.style.transition="opacity 150ms",h.template.style.opacity=0),h.original.dispatchEvent(me("medium-zoom:close",{detail:{zoom:U}})),h.zoomed.addEventListener("transitionend",C)})},I=function(){var P=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},C=P.target;return h.original?V():B({target:C})},N=function(){return O},ue=function(){return F},J=function(){return h.original},F=[],oe=[],Q=!1,tt=0,O=t,h={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(e)==="[object Object]"?O=e:(e||typeof e=="string")&&k(e),O=se({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},O);var ge=Hl(O.background);document.addEventListener("click",a),document.addEventListener("keyup",c),document.addEventListener("scroll",r),window.addEventListener("resize",V);var U={open:B,close:V,toggle:I,update:d,clone:m,attach:k,detach:$,on:w,off:S,getOptions:N,getImages:ue,getZoomedImage:J};return U};function Ol(n,e){e===void 0&&(e={});var t=e.insertAt;if(!(typeof document>"u")){var o=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css",t==="top"&&o.firstChild?o.insertBefore(a,o.firstChild):o.appendChild(a),a.styleSheet?a.styleSheet.cssText=n:a.appendChild(document.createTextNode(n))}}var Dl=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";Ol(Dl);const Fl=n=>(Z("data-v-09295527"),n=n(),X(),n),xl=Fl(()=>u("svg",{class:"icon-top",viewBox:"0 0 48 48",fill:"none",xmlns:"http://www.w3.org/2000/svg",stroke:"currentColor","stroke-width":"4","stroke-linecap":"butt","stroke-linejoin":"miter"},[u("path",{d:"M39.6 30.557 24.043 15 8.487 30.557"})],-1)),jl=[xl],Ul=b({__name:"back-to-top",props:{threshold:{default:300}},setup(n){const e=n,t=E(0),o=L(()=>t.value>e.threshold);Y(()=>{t.value=a(),window.addEventListener("scroll",c(()=>{t.value=a()},100))});function a(){return window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0}function r(){window.scrollTo({top:0,behavior:"smooth"}),t.value=0}function c(d,m=100){let k;return(...$)=>{clearTimeout(k),k=setTimeout(()=>{d.apply(null,$)},m)}}return(d,m)=>(s(),y(ze,{name:"fade"},{default:p(()=>[i(o)?(s(),l("div",{key:0,class:"go-to-top",onClick:r},jl)):f("",!0)]),_:1}))}}),Gl=(n,e)=>{const t=n.__vccOpts||n;for(const[o,a]of e)t[o]=a;return t},Rl=Gl(Ul,[["__scopeId","data-v-09295527"]]),ql=n=>{typeof window>"u"||window.addEventListener("load",()=>{const e=document.createElement("div");document.body.appendChild(e),tn(Ve(Rl,{threshold:n==null?void 0:n.threshold}),e)})};var rc=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Kl(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var zt,pe,ee,Ct,De,ct,ve,$e=!1,ye=[];typeof document<"u"&&(Ct=function(n){return $e||document.readyState==="interactive"||document.readyState==="complete"?n.call(document):ye.push(function(){return n.call(this)}),this},ct=function(){for(var n=0,e=ye.length;n{pe&&pe.hides(),zt.fetch("//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback",function(n){pe.texts(n),pe.shows()})};pe={bszs:["site_pv","page_pv","site_uv"],texts:function(n){this.bszs.map(function(e){var t=document.getElementById("busuanzi_value_"+e);t&&(t.innerHTML=n[e])})},hides:function(){this.bszs.map(function(n){var e=document.getElementById("busuanzi_container_"+n);e&&(e.style.display="none")})},shows:function(){this.bszs.map(function(n){var e=document.getElementById("busuanzi_container_"+n);e&&(e.style.display="inline")})}};typeof document<"u"&&Tt();var Wl={fetch:Tt},Yl=Wl;const Zl=Kl(Yl),Xl={class:"page_info"},Jl={key:0,class:"page_info_item"},Ql={key:1,class:"page_info_item"},ec=u("span",{class:"page_info_item"},[j(" 📔 "),u("span",{id:"busuanzi_container_page_pv"},[j(" 阅读量:"),u("span",{id:"busuanzi_value_page_pv"})])],-1),tc={__name:"PageInfo",setup(n){const{frontmatter:e}=Re();return(t,o)=>(s(),l("div",Xl,[i(e).Author?(s(),l("span",Jl,[j(" 🎨 "),u("span",null,"作者:"+T(i(e).Author),1)])):f("",!0),i(e).date?(s(),l("span",Ql,[j(" 🕐 "),u("span",null,"发表于:"+T(i(e).date?i(e).date.substring(0,10):""),1)])):f("",!0),ec]))}},ic={extends:st,Layout(){return Ve(st.Layout,null,{"doc-before":()=>Ve(tc)})},enhanceApp({app:n,router:e}){le&&(e.onAfterRouteChanged=()=>{Zl.fetch()}),ql({threshold:300})},setup(){const{frontmatter:n}=Re(),e=fe(),t=()=>{Bl(".main img",{background:"var(--vp-c-bg)"})};Y(()=>{t()}),te(()=>e.path,()=>We(()=>t())),El({repo:"linuxdeepin/youqu",repoId:"R_kgDOKDOpHg",category:"Announcements",categoryId:"DIC_kwDOKDOpHs4CcRPx",mapping:"pathname",inputPosition:"top",lang:"zh-CN"},{frontmatter:n,route:e},!0)}};export{ic as R,ac as V,sc as a,oc as b,rc as c,Pr as d,Kl as g,z as u}; diff --git a/assets/index.md.B0Rvt6-g.js b/assets/index.md.DItuxErn.js similarity index 97% rename from assets/index.md.B0Rvt6-g.js rename to assets/index.md.DItuxErn.js index 251c4e05..c3a50b19 100644 --- a/assets/index.md.B0Rvt6-g.js +++ b/assets/index.md.DItuxErn.js @@ -1 +1 @@ -import{V as a,a as o,b as u}from"./chunks/theme.B7K9K7dh.js";import{c as h,I as t,w as i,p as e,o as g,a as n}from"./chunks/framework.DIzwIJpr.js";const w=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"YouQu","text":"使用简单且功能强大的自动化测试框架","tagline":"让 Linux 自动化测试变得简单","actions":[{"theme":"brand","text":"YouQu3 🔥","link":"https://youqu.uniontech.com/v3/"},{"theme":"brand","text":"PyLinuxAuto 🔥","link":"https://youqu.uniontech.com/pylinuxauto/"}],"image":{"src":"/logo.png","alt":"YouQu"}},"features":[{"icon":"💻","title":"Linux 桌面 UI 自动化测试","details":"提升Linux桌面应用品质,确保用户体验的一致性,选择我们的UI自动化测试服务。","link":"/实践/Linux桌面UI自动化测试/初始化项目","linkText":"查看"},{"icon":"🌏","title":"Web UI 自动化测试","details":"Web UI自动化测试,优化用户体验,提升Web应用的稳定性和可靠性。","link":"/实践/WebUI自动化测试/初始化项目","linkText":"查看"},{"icon":"🚌","title":"Linux DBus 接口自动化测试","details":"专业自动化测试D-Bus接口,为Linux桌面应用的稳定性和可靠性保驾护航。","link":"/实践/DBus接口自动化测试/初始化项目","linkText":"查看"},{"icon":"🚀","title":"命令行自动化测试","details":"高效命令行自动化测试,让Linux软件开发和维护更加轻松便捷。","link":"/实践/命令行自动化测试/初始化项目","linkText":"查看"},{"icon":"️🕷️","title":"HTTP 接口自动化测试","details":"保障HTTP接口的响应速度和数据传输安全,我们的自动化测试是您的明智之选。","link":"/实践/HTTP接口自动化测试/初始化项目","linkText":"查看"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1722828555000}'),m={name:"index.md"},x=Object.assign(m,{setup(r){const l=[{avatar:"https://www.github.com/mikigo.png",name:"mikigo",title:"Creator",org:"YouQu",orgLink:"https://github.com/linuxdeepin/youqu",links:[{icon:"github",link:"https://github.com/mikigo"},{icon:"x",link:"https://twitter.com/mikigo_"}]},{avatar:"https://www.github.com/githublitao.png",name:"githublitao",title:"Developer",links:[{icon:"github",link:"https://github.com/githublitao"}]},{avatar:"https://www.github.com/zhao-george.png",name:"zhao-george",title:"Developer",links:[{icon:"github",link:"https://github.com/zhao-george"}]},{avatar:"https://www.github.com/saifeiLee.png",name:"saifeiLee",title:"Developer",links:[{icon:"github",link:"https://github.com/saifeiLee"}]},{avatar:"https://www.github.com/DarkLii.png",name:"DarkLii",title:"Developer",links:[{icon:"github",link:"https://github.com/DarkLii"}]},{avatar:"https://www.github.com/CCrazyPeter.png",name:"CCrazyPeter",title:"Developer",links:[{icon:"github",link:"https://github.com/CCrazyPeter"}]},{avatar:"https://www.github.com/003307.png",name:"003307",title:"Developer",links:[{icon:"github",link:"https://github.com/003307"}]},{avatar:"https://www.github.com/Marszzz1116.png",name:"Marszzz1116",title:"Developer",links:[{icon:"github",link:"https://github.com/Marszzz1116"}]},{avatar:"https://www.github.com/lu-xianseng.png",name:"lu-xianseng",title:"Developer",links:[{icon:"github",link:"https://github.com/lu-xianseng"}]},{avatar:"https://www.github.com/KeyLee123.png",name:"KeyLee123",title:"Developer",links:[{icon:"github",link:"https://github.com/KeyLee123"}]},{avatar:"https://www.github.com/qisijia367.png",name:"qisijia367",title:"Developer",links:[{icon:"github",link:"https://github.com/qisijia367"}]}],s=[{avatar:"https://www.github.com/rb-union.png",name:"rb-union",title:"Helper",links:[{icon:"github",link:"https://github.com/rb-union"}]},{avatar:"https://www.github.com/Jimijun.png",name:"Jimijun",title:"Helper",links:[{icon:"github",link:"https://github.com/Jimijun"}]},{avatar:"https://www.github.com/king123666.png",name:"king123666",title:"Helper",links:[{icon:"github",link:"https://github.com/king123666"}]},{avatar:"https://www.github.com/momiji33.png",name:"momiji33",title:"Helper",links:[{icon:"github",link:"https://github.com/momiji33"}]}];return(p,c)=>(g(),h("div",null,[t(e(u),null,{default:i(()=>[t(e(a),null,{title:i(()=>[n(" Contributors ")]),lead:i(()=>[n(" 感谢以下所有人的贡献与参与 ")]),_:1}),t(e(o),{size:"small",members:l}),t(e(a),null,{title:i(()=>[n(" Helpers ")]),lead:i(()=>[n(" 感谢以下所有人提供的帮助及重要建议 ")]),_:1}),t(e(o),{size:"small",members:s})]),_:1})]))}});export{w as __pageData,x as default}; +import{V as a,a as o,b as u}from"./chunks/theme.BIU4L49Z.js";import{c as h,I as t,w as i,p as e,o as g,a as n}from"./chunks/framework.DIzwIJpr.js";const w=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"YouQu","text":"使用简单且功能强大的自动化测试框架","tagline":"让 Linux 自动化测试变得简单","actions":[{"theme":"brand","text":"YouQu3 🔥","link":"https://youqu.uniontech.com/v3/"},{"theme":"brand","text":"PyLinuxAuto 🔥","link":"https://youqu.uniontech.com/pylinuxauto/"}],"image":{"src":"/logo.png","alt":"YouQu"}},"features":[{"icon":"💻","title":"Linux 桌面 UI 自动化测试","details":"提升Linux桌面应用品质,确保用户体验的一致性,选择我们的UI自动化测试服务。","link":"/实践/Linux桌面UI自动化测试/初始化项目","linkText":"查看"},{"icon":"🌏","title":"Web UI 自动化测试","details":"Web UI自动化测试,优化用户体验,提升Web应用的稳定性和可靠性。","link":"/实践/WebUI自动化测试/初始化项目","linkText":"查看"},{"icon":"🚌","title":"Linux DBus 接口自动化测试","details":"专业自动化测试D-Bus接口,为Linux桌面应用的稳定性和可靠性保驾护航。","link":"/实践/DBus接口自动化测试/初始化项目","linkText":"查看"},{"icon":"🚀","title":"命令行自动化测试","details":"高效命令行自动化测试,让Linux软件开发和维护更加轻松便捷。","link":"/实践/命令行自动化测试/初始化项目","linkText":"查看"},{"icon":"️🕷️","title":"HTTP 接口自动化测试","details":"保障HTTP接口的响应速度和数据传输安全,我们的自动化测试是您的明智之选。","link":"/实践/HTTP接口自动化测试/初始化项目","linkText":"查看"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1722828751000}'),m={name:"index.md"},x=Object.assign(m,{setup(r){const l=[{avatar:"https://www.github.com/mikigo.png",name:"mikigo",title:"Creator",org:"YouQu",orgLink:"https://github.com/linuxdeepin/youqu",links:[{icon:"github",link:"https://github.com/mikigo"},{icon:"x",link:"https://twitter.com/mikigo_"}]},{avatar:"https://www.github.com/githublitao.png",name:"githublitao",title:"Developer",links:[{icon:"github",link:"https://github.com/githublitao"}]},{avatar:"https://www.github.com/zhao-george.png",name:"zhao-george",title:"Developer",links:[{icon:"github",link:"https://github.com/zhao-george"}]},{avatar:"https://www.github.com/saifeiLee.png",name:"saifeiLee",title:"Developer",links:[{icon:"github",link:"https://github.com/saifeiLee"}]},{avatar:"https://www.github.com/DarkLii.png",name:"DarkLii",title:"Developer",links:[{icon:"github",link:"https://github.com/DarkLii"}]},{avatar:"https://www.github.com/CCrazyPeter.png",name:"CCrazyPeter",title:"Developer",links:[{icon:"github",link:"https://github.com/CCrazyPeter"}]},{avatar:"https://www.github.com/003307.png",name:"003307",title:"Developer",links:[{icon:"github",link:"https://github.com/003307"}]},{avatar:"https://www.github.com/Marszzz1116.png",name:"Marszzz1116",title:"Developer",links:[{icon:"github",link:"https://github.com/Marszzz1116"}]},{avatar:"https://www.github.com/lu-xianseng.png",name:"lu-xianseng",title:"Developer",links:[{icon:"github",link:"https://github.com/lu-xianseng"}]},{avatar:"https://www.github.com/KeyLee123.png",name:"KeyLee123",title:"Developer",links:[{icon:"github",link:"https://github.com/KeyLee123"}]},{avatar:"https://www.github.com/qisijia367.png",name:"qisijia367",title:"Developer",links:[{icon:"github",link:"https://github.com/qisijia367"}]}],s=[{avatar:"https://www.github.com/rb-union.png",name:"rb-union",title:"Helper",links:[{icon:"github",link:"https://github.com/rb-union"}]},{avatar:"https://www.github.com/Jimijun.png",name:"Jimijun",title:"Helper",links:[{icon:"github",link:"https://github.com/Jimijun"}]},{avatar:"https://www.github.com/king123666.png",name:"king123666",title:"Helper",links:[{icon:"github",link:"https://github.com/king123666"}]},{avatar:"https://www.github.com/momiji33.png",name:"momiji33",title:"Helper",links:[{icon:"github",link:"https://github.com/momiji33"}]}];return(p,c)=>(g(),h("div",null,[t(e(u),null,{default:i(()=>[t(e(a),null,{title:i(()=>[n(" Contributors ")]),lead:i(()=>[n(" 感谢以下所有人的贡献与参与 ")]),_:1}),t(e(o),{size:"small",members:l}),t(e(a),null,{title:i(()=>[n(" Helpers ")]),lead:i(()=>[n(" 感谢以下所有人提供的帮助及重要建议 ")]),_:1}),t(e(o),{size:"small",members:s})]),_:1})]))}});export{w as __pageData,x as default}; diff --git a/assets/index.md.B0Rvt6-g.lean.js b/assets/index.md.DItuxErn.lean.js similarity index 97% rename from assets/index.md.B0Rvt6-g.lean.js rename to assets/index.md.DItuxErn.lean.js index 251c4e05..c3a50b19 100644 --- a/assets/index.md.B0Rvt6-g.lean.js +++ b/assets/index.md.DItuxErn.lean.js @@ -1 +1 @@ -import{V as a,a as o,b as u}from"./chunks/theme.B7K9K7dh.js";import{c as h,I as t,w as i,p as e,o as g,a as n}from"./chunks/framework.DIzwIJpr.js";const w=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"YouQu","text":"使用简单且功能强大的自动化测试框架","tagline":"让 Linux 自动化测试变得简单","actions":[{"theme":"brand","text":"YouQu3 🔥","link":"https://youqu.uniontech.com/v3/"},{"theme":"brand","text":"PyLinuxAuto 🔥","link":"https://youqu.uniontech.com/pylinuxauto/"}],"image":{"src":"/logo.png","alt":"YouQu"}},"features":[{"icon":"💻","title":"Linux 桌面 UI 自动化测试","details":"提升Linux桌面应用品质,确保用户体验的一致性,选择我们的UI自动化测试服务。","link":"/实践/Linux桌面UI自动化测试/初始化项目","linkText":"查看"},{"icon":"🌏","title":"Web UI 自动化测试","details":"Web UI自动化测试,优化用户体验,提升Web应用的稳定性和可靠性。","link":"/实践/WebUI自动化测试/初始化项目","linkText":"查看"},{"icon":"🚌","title":"Linux DBus 接口自动化测试","details":"专业自动化测试D-Bus接口,为Linux桌面应用的稳定性和可靠性保驾护航。","link":"/实践/DBus接口自动化测试/初始化项目","linkText":"查看"},{"icon":"🚀","title":"命令行自动化测试","details":"高效命令行自动化测试,让Linux软件开发和维护更加轻松便捷。","link":"/实践/命令行自动化测试/初始化项目","linkText":"查看"},{"icon":"️🕷️","title":"HTTP 接口自动化测试","details":"保障HTTP接口的响应速度和数据传输安全,我们的自动化测试是您的明智之选。","link":"/实践/HTTP接口自动化测试/初始化项目","linkText":"查看"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1722828555000}'),m={name:"index.md"},x=Object.assign(m,{setup(r){const l=[{avatar:"https://www.github.com/mikigo.png",name:"mikigo",title:"Creator",org:"YouQu",orgLink:"https://github.com/linuxdeepin/youqu",links:[{icon:"github",link:"https://github.com/mikigo"},{icon:"x",link:"https://twitter.com/mikigo_"}]},{avatar:"https://www.github.com/githublitao.png",name:"githublitao",title:"Developer",links:[{icon:"github",link:"https://github.com/githublitao"}]},{avatar:"https://www.github.com/zhao-george.png",name:"zhao-george",title:"Developer",links:[{icon:"github",link:"https://github.com/zhao-george"}]},{avatar:"https://www.github.com/saifeiLee.png",name:"saifeiLee",title:"Developer",links:[{icon:"github",link:"https://github.com/saifeiLee"}]},{avatar:"https://www.github.com/DarkLii.png",name:"DarkLii",title:"Developer",links:[{icon:"github",link:"https://github.com/DarkLii"}]},{avatar:"https://www.github.com/CCrazyPeter.png",name:"CCrazyPeter",title:"Developer",links:[{icon:"github",link:"https://github.com/CCrazyPeter"}]},{avatar:"https://www.github.com/003307.png",name:"003307",title:"Developer",links:[{icon:"github",link:"https://github.com/003307"}]},{avatar:"https://www.github.com/Marszzz1116.png",name:"Marszzz1116",title:"Developer",links:[{icon:"github",link:"https://github.com/Marszzz1116"}]},{avatar:"https://www.github.com/lu-xianseng.png",name:"lu-xianseng",title:"Developer",links:[{icon:"github",link:"https://github.com/lu-xianseng"}]},{avatar:"https://www.github.com/KeyLee123.png",name:"KeyLee123",title:"Developer",links:[{icon:"github",link:"https://github.com/KeyLee123"}]},{avatar:"https://www.github.com/qisijia367.png",name:"qisijia367",title:"Developer",links:[{icon:"github",link:"https://github.com/qisijia367"}]}],s=[{avatar:"https://www.github.com/rb-union.png",name:"rb-union",title:"Helper",links:[{icon:"github",link:"https://github.com/rb-union"}]},{avatar:"https://www.github.com/Jimijun.png",name:"Jimijun",title:"Helper",links:[{icon:"github",link:"https://github.com/Jimijun"}]},{avatar:"https://www.github.com/king123666.png",name:"king123666",title:"Helper",links:[{icon:"github",link:"https://github.com/king123666"}]},{avatar:"https://www.github.com/momiji33.png",name:"momiji33",title:"Helper",links:[{icon:"github",link:"https://github.com/momiji33"}]}];return(p,c)=>(g(),h("div",null,[t(e(u),null,{default:i(()=>[t(e(a),null,{title:i(()=>[n(" Contributors ")]),lead:i(()=>[n(" 感谢以下所有人的贡献与参与 ")]),_:1}),t(e(o),{size:"small",members:l}),t(e(a),null,{title:i(()=>[n(" Helpers ")]),lead:i(()=>[n(" 感谢以下所有人提供的帮助及重要建议 ")]),_:1}),t(e(o),{size:"small",members:s})]),_:1})]))}});export{w as __pageData,x as default}; +import{V as a,a as o,b as u}from"./chunks/theme.BIU4L49Z.js";import{c as h,I as t,w as i,p as e,o as g,a as n}from"./chunks/framework.DIzwIJpr.js";const w=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"YouQu","text":"使用简单且功能强大的自动化测试框架","tagline":"让 Linux 自动化测试变得简单","actions":[{"theme":"brand","text":"YouQu3 🔥","link":"https://youqu.uniontech.com/v3/"},{"theme":"brand","text":"PyLinuxAuto 🔥","link":"https://youqu.uniontech.com/pylinuxauto/"}],"image":{"src":"/logo.png","alt":"YouQu"}},"features":[{"icon":"💻","title":"Linux 桌面 UI 自动化测试","details":"提升Linux桌面应用品质,确保用户体验的一致性,选择我们的UI自动化测试服务。","link":"/实践/Linux桌面UI自动化测试/初始化项目","linkText":"查看"},{"icon":"🌏","title":"Web UI 自动化测试","details":"Web UI自动化测试,优化用户体验,提升Web应用的稳定性和可靠性。","link":"/实践/WebUI自动化测试/初始化项目","linkText":"查看"},{"icon":"🚌","title":"Linux DBus 接口自动化测试","details":"专业自动化测试D-Bus接口,为Linux桌面应用的稳定性和可靠性保驾护航。","link":"/实践/DBus接口自动化测试/初始化项目","linkText":"查看"},{"icon":"🚀","title":"命令行自动化测试","details":"高效命令行自动化测试,让Linux软件开发和维护更加轻松便捷。","link":"/实践/命令行自动化测试/初始化项目","linkText":"查看"},{"icon":"️🕷️","title":"HTTP 接口自动化测试","details":"保障HTTP接口的响应速度和数据传输安全,我们的自动化测试是您的明智之选。","link":"/实践/HTTP接口自动化测试/初始化项目","linkText":"查看"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1722828751000}'),m={name:"index.md"},x=Object.assign(m,{setup(r){const l=[{avatar:"https://www.github.com/mikigo.png",name:"mikigo",title:"Creator",org:"YouQu",orgLink:"https://github.com/linuxdeepin/youqu",links:[{icon:"github",link:"https://github.com/mikigo"},{icon:"x",link:"https://twitter.com/mikigo_"}]},{avatar:"https://www.github.com/githublitao.png",name:"githublitao",title:"Developer",links:[{icon:"github",link:"https://github.com/githublitao"}]},{avatar:"https://www.github.com/zhao-george.png",name:"zhao-george",title:"Developer",links:[{icon:"github",link:"https://github.com/zhao-george"}]},{avatar:"https://www.github.com/saifeiLee.png",name:"saifeiLee",title:"Developer",links:[{icon:"github",link:"https://github.com/saifeiLee"}]},{avatar:"https://www.github.com/DarkLii.png",name:"DarkLii",title:"Developer",links:[{icon:"github",link:"https://github.com/DarkLii"}]},{avatar:"https://www.github.com/CCrazyPeter.png",name:"CCrazyPeter",title:"Developer",links:[{icon:"github",link:"https://github.com/CCrazyPeter"}]},{avatar:"https://www.github.com/003307.png",name:"003307",title:"Developer",links:[{icon:"github",link:"https://github.com/003307"}]},{avatar:"https://www.github.com/Marszzz1116.png",name:"Marszzz1116",title:"Developer",links:[{icon:"github",link:"https://github.com/Marszzz1116"}]},{avatar:"https://www.github.com/lu-xianseng.png",name:"lu-xianseng",title:"Developer",links:[{icon:"github",link:"https://github.com/lu-xianseng"}]},{avatar:"https://www.github.com/KeyLee123.png",name:"KeyLee123",title:"Developer",links:[{icon:"github",link:"https://github.com/KeyLee123"}]},{avatar:"https://www.github.com/qisijia367.png",name:"qisijia367",title:"Developer",links:[{icon:"github",link:"https://github.com/qisijia367"}]}],s=[{avatar:"https://www.github.com/rb-union.png",name:"rb-union",title:"Helper",links:[{icon:"github",link:"https://github.com/rb-union"}]},{avatar:"https://www.github.com/Jimijun.png",name:"Jimijun",title:"Helper",links:[{icon:"github",link:"https://github.com/Jimijun"}]},{avatar:"https://www.github.com/king123666.png",name:"king123666",title:"Helper",links:[{icon:"github",link:"https://github.com/king123666"}]},{avatar:"https://www.github.com/momiji33.png",name:"momiji33",title:"Helper",links:[{icon:"github",link:"https://github.com/momiji33"}]}];return(p,c)=>(g(),h("div",null,[t(e(u),null,{default:i(()=>[t(e(a),null,{title:i(()=>[n(" Contributors ")]),lead:i(()=>[n(" 感谢以下所有人的贡献与参与 ")]),_:1}),t(e(o),{size:"small",members:l}),t(e(a),null,{title:i(()=>[n(" Helpers ")]),lead:i(()=>[n(" 感谢以下所有人提供的帮助及重要建议 ")]),_:1}),t(e(o),{size:"small",members:s})]),_:1})]))}});export{w as __pageData,x as default}; diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.js" similarity index 99% rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.js" rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.js" index cdaa261e..2d1930ad 100644 --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.js" +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.js" @@ -1,4 +1,4 @@ -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建APP工程.md","filePath":"实践/DBus接口自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建APP工程.md","filePath":"实践/DBus接口自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case  # 用例目录
    diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.lean.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.lean.js"
    rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.lean.js"
    index 274cd30a..a9b34c47 100644
    --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.4O34DUFa.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.hrjrbfya.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建APP工程.md","filePath":"实践/DBus接口自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建APP工程.md","filePath":"实践/DBus接口自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.js"
    rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.js"
    index 1672ddd9..72fb191e 100644
    --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.js"
    +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const t="/youqu/%E5%AE%9E%E8%B7%B5/DBus%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E5%8C%96/d-feet.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","filePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/创建一条完整的用例.md"},e=n(`

    创建一条完整的用例

    判断操作系统的激活状态为激活

    封装用例步骤的方法

    所有的方法都在 widget 目录下;

    方法基类 base_widget.py::BaseWidget 里面定义接口对象。

    python
    # base_widget.py
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const t="/youqu/%E5%AE%9E%E8%B7%B5/DBus%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E5%8C%96/d-feet.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","filePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/创建一条完整的用例.md"},e=n(`

    创建一条完整的用例

    判断操作系统的激活状态为激活

    封装用例步骤的方法

    所有的方法都在 widget 目录下;

    方法基类 base_widget.py::BaseWidget 里面定义接口对象。

    python
    # base_widget.py
     
     from src.dbus_utils import DbusUtils
     
    diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.lean.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.lean.js"
    similarity index 90%
    rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.lean.js"
    rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.lean.js"
    index d2db19c0..822eb425 100644
    --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.C9weuXoI.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.PZ_9GVPL.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const t="/youqu/%E5%AE%9E%E8%B7%B5/DBus%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E5%8C%96/d-feet.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","filePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/创建一条完整的用例.md"},e=n("",17),l=[e];function h(k,d,o,E,r,c){return a(),i("div",null,l)}const u=s(p,[["render",h]]);export{y as __pageData,u as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const t="/youqu/%E5%AE%9E%E8%B7%B5/DBus%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E5%8C%96/d-feet.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","filePath":"实践/DBus接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/创建一条完整的用例.md"},e=n("",17),l=[e];function h(k,d,o,E,r,c){return a(),i("div",null,l)}const u=s(p,[["render",h]]);export{y as __pageData,u as default};
    diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.js"
    similarity index 98%
    rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.js"
    rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.js"
    index a881dc48..e1fb4bf4 100644
    --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.js"
    +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux DBus 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/初始化项目.md","filePath":"实践/DBus接口自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/初始化项目.md"},h=l('

    Linux DBus 接口自动化测试

    DBus 是一个为应用程序间通信的消息总线系统,对操作系统的接口测试通常指的是对 DBus 接口的测试。

    YouQu 提供了对 DBus 接口操作的模块:DbusUtils

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux DBus 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/初始化项目.md","filePath":"实践/DBus接口自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/初始化项目.md"},h=l('

    Linux DBus 接口自动化测试

    DBus 是一个为应用程序间通信的消息总线系统,对操作系统的接口测试通常指的是对 DBus 接口的测试。

    YouQu 提供了对 DBus 接口操作的模块:DbusUtils

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
     ├── apps  # 用于放置APP工程
     ├── conftest.py  # Pytest 插件库
     ├── CURRENT      # 记录YouQu当前的版本
    diff --git "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.lean.js" "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.lean.js"
    rename to "assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.lean.js"
    index edd6ad5f..d4c25dfa 100644
    --- "a/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Cq1ADuHE.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.Qn54NA5E.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux DBus 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/初始化项目.md","filePath":"实践/DBus接口自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/DBus接口自动化测试/初始化项目.md"},h=l("",15),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const B=a(p,[["render",k]]);export{C as __pageData,B as default};
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux DBus 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/DBus接口自动化测试/初始化项目.md","filePath":"实践/DBus接口自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/DBus接口自动化测试/初始化项目.md"},h=l("",15),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const B=a(p,[["render",k]]);export{C as __pageData,B as default};
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.js"
    index de7bb8f6..3ef606a9 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i,c as a,o as h,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建APP工程.md","filePath":"实践/HTTP接口自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),k={name:"实践/HTTP接口自动化测试/创建APP工程.md"},p=n('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i,c as a,o as h,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建APP工程.md","filePath":"实践/HTTP接口自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),k={name:"实践/HTTP接口自动化测试/创建APP工程.md"},p=n('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case  # 用例目录
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.lean.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.lean.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.lean.js"
    index 20707d1b..da3dcf26 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DYG_9u9K.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.BB2SseQ7.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i,c as a,o as h,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建APP工程.md","filePath":"实践/HTTP接口自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),k={name:"实践/HTTP接口自动化测试/创建APP工程.md"},p=n("",12),l=[p];function t(F,e,d,r,y,g){return h(),a("div",null,l)}const c=i(k,[["render",t]]);export{E as __pageData,c as default};
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i,c as a,o as h,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建APP工程.md","filePath":"实践/HTTP接口自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),k={name:"实践/HTTP接口自动化测试/创建APP工程.md"},p=n("",12),l=[p];function t(F,e,d,r,y,g){return h(),a("div",null,l)}const c=i(k,[["render",t]]);export{E as __pageData,c as default};
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.js"
    index c6dbb2c9..186e7a87 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","filePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),h={name:"实践/HTTP接口自动化测试/创建一条完整的用例.md"},p=n(`

    创建一条完整的用例

    以域管服务端平台创建子管理员为例

    封装用例步骤的方法

    所有的方法都在 api 目录下;

    方法基类 _base_api.py::BaseAPI 里面定义登陆接口,获取管理员登陆 WEB 平台 cookietoken 信息。

    python
    # _base_api.py
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","filePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),h={name:"实践/HTTP接口自动化测试/创建一条完整的用例.md"},p=n(`

    创建一条完整的用例

    以域管服务端平台创建子管理员为例

    封装用例步骤的方法

    所有的方法都在 api 目录下;

    方法基类 _base_api.py::BaseAPI 里面定义登陆接口,获取管理员登陆 WEB 平台 cookietoken 信息。

    python
    # _base_api.py
     
     from apps.autotest_udcp.config import config
     from urllib3.exceptions import InsecureRequestWarning
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.lean.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.lean.js"
    similarity index 88%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.lean.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.lean.js"
    index 9a8c3632..bebfddd8 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.CILkfzMi.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJXSzHsE.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","filePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),h={name:"实践/HTTP接口自动化测试/创建一条完整的用例.md"},p=n("",15),k=[p];function l(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",l]]);export{F as __pageData,o as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","filePath":"实践/HTTP接口自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),h={name:"实践/HTTP接口自动化测试/创建一条完整的用例.md"},p=n("",15),k=[p];function l(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",l]]);export{F as __pageData,o as default};
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.js"
    index 46fcf4d3..19fdc1dc 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"HTTP 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/初始化项目.md","filePath":"实践/HTTP接口自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/HTTP接口自动化测试/初始化项目.md"},e=l('

    HTTP 接口自动化测试

    HTTP 接口自动化测试是一个传统测试类型,只要有接口请求能力就能做,YouQu 自带网络接口模块 requestx ,它基于标准库 urllib 封装,能满足对大部分的网络接口处理的需求。

    YouQu 框架的很多网络相关功能都是基于此模块实现,但大多数同学喜欢用三方模块 requests 做网络接口,因为用法上更加简洁。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"HTTP 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/初始化项目.md","filePath":"实践/HTTP接口自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/HTTP接口自动化测试/初始化项目.md"},e=l('

    HTTP 接口自动化测试

    HTTP 接口自动化测试是一个传统测试类型,只要有接口请求能力就能做,YouQu 自带网络接口模块 requestx ,它基于标准库 urllib 封装,能满足对大部分的网络接口处理的需求。

    YouQu 框架的很多网络相关功能都是基于此模块实现,但大多数同学喜欢用三方模块 requests 做网络接口,因为用法上更加简洁。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
     ├── apps  # 用于放置APP工程
     ├── conftest.py  # Pytest 插件库
     ├── CURRENT      # 记录YouQu当前的版本
    diff --git "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.lean.js" "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.lean.js"
    rename to "assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.lean.js"
    index 65eab3b0..9caba884 100644
    --- "a/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DLJQT1pe.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DvTxsOBd.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"HTTP 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/初始化项目.md","filePath":"实践/HTTP接口自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/HTTP接口自动化测试/初始化项目.md"},e=l("",15),h=[e];function k(r,d,o,c,g,F){return t(),n("div",null,h)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"HTTP 接口自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/HTTP接口自动化测试/初始化项目.md","filePath":"实践/HTTP接口自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/HTTP接口自动化测试/初始化项目.md"},e=l("",15),h=[e];function k(r,d,o,c,g,F){return t(),n("div",null,h)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.js"
    index 22c69975..47e25402 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","filePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/Linux桌面UI自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","filePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/Linux桌面UI自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case  # 用例目录
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.lean.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.lean.js"
    similarity index 90%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.lean.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.lean.js"
    index 51d281f0..4ddb208a 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DMVy6riC.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.fMT7s3Dw.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","filePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/Linux桌面UI自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","filePath":"实践/Linux桌面UI自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/Linux桌面UI自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.js"
    index 52e54e28..674bed59 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/sniff.png",t="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/assert.gif",u=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","filePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),l={name:"实践/Linux桌面UI自动化测试/创建一条完整的用例.md"},e=n(`

    创建一条完整的用例

    创建一条通过任务栏打开文件管理器的测试用例;

    用例步骤

    • 点击任务栏上的文件管理器图标;
    • 判断(断言)文件管理器已经启动;

    封装用例步骤的方法

    所有的方法都在 widget 目录下;

    首先这里的主要操作对象是任务栏(dde-dock),因此在方法基类 base_widget.py::BaseWidget 里面需要定义 dde-dock的信息:

    python
    # base_widget.py
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/sniff.png",t="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/assert.gif",u=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","filePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),l={name:"实践/Linux桌面UI自动化测试/创建一条完整的用例.md"},e=n(`

    创建一条完整的用例

    创建一条通过任务栏打开文件管理器的测试用例;

    用例步骤

    • 点击任务栏上的文件管理器图标;
    • 判断(断言)文件管理器已经启动;

    封装用例步骤的方法

    所有的方法都在 widget 目录下;

    首先这里的主要操作对象是任务栏(dde-dock),因此在方法基类 base_widget.py::BaseWidget 里面需要定义 dde-dock的信息:

    python
    # base_widget.py
     
     from src import Src
     
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.lean.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.lean.js"
    similarity index 91%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.lean.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.lean.js"
    index 551a03a0..b5118930 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.39VpWliZ.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Dvhe2fAz.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/sniff.png",t="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/assert.gif",u=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","filePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),l={name:"实践/Linux桌面UI自动化测试/创建一条完整的用例.md"},e=n("",23),h=[e];function k(d,o,r,c,E,g){return a(),i("div",null,h)}const F=s(l,[["render",k]]);export{u as __pageData,F as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/sniff.png",t="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/assert.gif",u=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","filePath":"实践/Linux桌面UI自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),l={name:"实践/Linux桌面UI自动化测试/创建一条完整的用例.md"},e=n("",23),h=[e];function k(d,o,r,c,E,g){return a(),i("div",null,h)}const F=s(l,[["render",k]]);export{u as __pageData,F as default};
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.js"
    index f381b8b7..e90dc939 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux 桌面 UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/初始化项目.md","filePath":"实践/Linux桌面UI自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/Linux桌面UI自动化测试/初始化项目.md"},h=l('

    Linux 桌面 UI 自动化测试

    YouQu 框架从设计之初,就是以桌面 UI 自动化测试为基础,因此 YouQu 真的非常擅长构建 Linux 桌面 UI 自动化项目。

    YouQu 在桌面 UI 自动化测试方向也有非常多的技术突破,例如:兼容 Wayland 显示协议、多样的元素定位方案、用例失败录屏、远程交互式控制等等。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux 桌面 UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/初始化项目.md","filePath":"实践/Linux桌面UI自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/Linux桌面UI自动化测试/初始化项目.md"},h=l('

    Linux 桌面 UI 自动化测试

    YouQu 框架从设计之初,就是以桌面 UI 自动化测试为基础,因此 YouQu 真的非常擅长构建 Linux 桌面 UI 自动化项目。

    YouQu 在桌面 UI 自动化测试方向也有非常多的技术突破,例如:兼容 Wayland 显示协议、多样的元素定位方案、用例失败录屏、远程交互式控制等等。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
     ├── apps  # 用于放置APP工程
     ├── conftest.py  # Pytest 插件库
     ├── CURRENT      # 记录YouQu当前的版本
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.lean.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.lean.js"
    similarity index 90%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.lean.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.lean.js"
    index 7e2ad28f..eedf0145 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.fO_mX3bv.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CZrjCFH_.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux 桌面 UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/初始化项目.md","filePath":"实践/Linux桌面UI自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/Linux桌面UI自动化测试/初始化项目.md"},h=l("",15),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Linux 桌面 UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/初始化项目.md","filePath":"实践/Linux桌面UI自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/Linux桌面UI自动化测试/初始化项目.md"},h=l("",15),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.js"
    index 88d300e1..da7ad32c 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","filePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","lastUpdated":1722828555000}'),h={name:"实践/Linux桌面UI自动化测试/远程交互式控制.md"},p=t('

    远程交互式控制

    远程交互式控制可以在用例步骤中实现对远程机器的交互式控制;

    逻辑示意图

    标识文件

    shell
    autotest_my_project
    +import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","filePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","lastUpdated":1722828751000}'),h={name:"实践/Linux桌面UI自动化测试/远程交互式控制.md"},p=t('

    远程交互式控制

    远程交互式控制可以在用例步骤中实现对远程机器的交互式控制;

    逻辑示意图

    标识文件

    shell
    autotest_my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case
    diff --git "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.lean.js" "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.lean.js"
    rename to "assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.lean.js"
    index 19b6be76..6b24f029 100644
    --- "a/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.C8b2k9nJ.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BItb9rzf.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","filePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","lastUpdated":1722828555000}'),h={name:"实践/Linux桌面UI自动化测试/远程交互式控制.md"},p=t("",12),l=[p];function k(e,d,r,F,E,g){return n(),a("div",null,l)}const C=i(h,[["render",k]]);export{c as __pageData,C as default};
    +import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","filePath":"实践/Linux桌面UI自动化测试/远程交互式控制.md","lastUpdated":1722828751000}'),h={name:"实践/Linux桌面UI自动化测试/远程交互式控制.md"},p=t("",12),l=[p];function k(e,d,r,F,E,g){return n(),a("div",null,l)}const C=i(h,[["render",k]]);export{c as __pageData,C as default};
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.js"
    index 286d42fc..3ac53ed4 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建APP工程.md","filePath":"实践/WebUI自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/WebUI自动化测试/创建APP工程.md"},l=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建APP工程.md","filePath":"实践/WebUI自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/WebUI自动化测试/创建APP工程.md"},l=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case  # 用例目录
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.lean.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.lean.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.lean.js"
    index 3f94cb21..f8cea20d 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.Dbz5gpGS.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.DwmtmtLf.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建APP工程.md","filePath":"实践/WebUI自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/WebUI自动化测试/创建APP工程.md"},l=k("",16),t=[l];function F(e,d,r,y,g,C){return n(),h("div",null,t)}const _=a(p,[["render",F]]);export{o as __pageData,_ as default};
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建APP工程.md","filePath":"实践/WebUI自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/WebUI自动化测试/创建APP工程.md"},l=k("",16),t=[l];function F(e,d,r,y,g,C){return n(),h("div",null,t)}const _=a(p,[["render",F]]);export{o as __pageData,_ as default};
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.js"
    index 599726a0..5a3a3669 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/WebUI%E8%87%AA%E5%8A%A8%E5%8C%96/web_assert.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建一条完整的用例.md","filePath":"实践/WebUI自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),t={name:"实践/WebUI自动化测试/创建一条完整的用例.md"},l=n(`

    创建一条完整的用例

    创建一条在百度首页搜索 YouQu 的用例;

    用例步骤

    • 在浏览器访问百度首页;
    • 搜索框输入YouQu;

    封装用例步骤的方法

    方法基类 base_page.py:: BasePage

    python
    from src.webui import WebUI
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/WebUI%E8%87%AA%E5%8A%A8%E5%8C%96/web_assert.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建一条完整的用例.md","filePath":"实践/WebUI自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),t={name:"实践/WebUI自动化测试/创建一条完整的用例.md"},l=n(`

    创建一条完整的用例

    创建一条在百度首页搜索 YouQu 的用例;

    用例步骤

    • 在浏览器访问百度首页;
    • 搜索框输入YouQu;

    封装用例步骤的方法

    方法基类 base_page.py:: BasePage

    python
    from src.webui import WebUI
     
     class BasePage(WebUI):
     
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.lean.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.lean.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.lean.js"
    index 6149c855..92cde2a4 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.DNwaUUy6.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BkBUwUkc.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/WebUI%E8%87%AA%E5%8A%A8%E5%8C%96/web_assert.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建一条完整的用例.md","filePath":"实践/WebUI自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),t={name:"实践/WebUI自动化测试/创建一条完整的用例.md"},l=n("",20),e=[l];function h(k,r,d,o,E,c){return a(),i("div",null,e)}const u=s(t,[["render",h]]);export{y as __pageData,u as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const p="/youqu/%E5%AE%9E%E8%B7%B5/WebUI%E8%87%AA%E5%8A%A8%E5%8C%96/web_assert.png",y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/创建一条完整的用例.md","filePath":"实践/WebUI自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),t={name:"实践/WebUI自动化测试/创建一条完整的用例.md"},l=n("",20),e=[l];function h(k,r,d,o,E,c){return a(),i("div",null,e)}const u=s(t,[["render",h]]);export{y as __pageData,u as default};
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.js"
    index d13051d0..29e1e0c4 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as e,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Web UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/初始化项目.md","filePath":"实践/WebUI自动化测试/初始化项目.md","lastUpdated":1722828555000}'),l={name:"实践/WebUI自动化测试/初始化项目.md"},p=t('

    Web UI 自动化测试

    Web UI 自动化测试是一种通用的自动化测试类型,只要是基于浏览器的项目都适用。

    YouQu 基于 Playwright 构建了一整套通用的 Web UI 自动化测试方案。

    YouQu 框架提供灵活可配置的浏览器对象。

    • 提供一个全局默认的对象:page,默认使用系统自带的浏览器进行测试,如果需要指定其他第三方的浏览器,提供配置项可以指定浏览器对应的路径。
    • 还需要提供一个对象:native_page,它使用 Playwright 最新的 Chromium 浏览器进行测试。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as e,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Web UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/初始化项目.md","filePath":"实践/WebUI自动化测试/初始化项目.md","lastUpdated":1722828751000}'),l={name:"实践/WebUI自动化测试/初始化项目.md"},p=t('

    Web UI 自动化测试

    Web UI 自动化测试是一种通用的自动化测试类型,只要是基于浏览器的项目都适用。

    YouQu 基于 Playwright 构建了一整套通用的 Web UI 自动化测试方案。

    YouQu 框架提供灵活可配置的浏览器对象。

    • 提供一个全局默认的对象:page,默认使用系统自带的浏览器进行测试,如果需要指定其他第三方的浏览器,提供配置项可以指定浏览器对应的路径。
    • 还需要提供一个对象:native_page,它使用 Playwright 最新的 Chromium 浏览器进行测试。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
     ├── apps  # 用于放置APP工程
     ├── conftest.py  # Pytest 插件库
     ├── CURRENT      # 记录YouQu当前的版本
    diff --git "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.lean.js" "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.lean.js"
    rename to "assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.lean.js"
    index d3304e02..dd2563fc 100644
    --- "a/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.BwYOOjva.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.C-wa8EP9.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as e,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Web UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/初始化项目.md","filePath":"实践/WebUI自动化测试/初始化项目.md","lastUpdated":1722828555000}'),l={name:"实践/WebUI自动化测试/初始化项目.md"},p=t("",17),h=[p];function k(d,r,o,c,g,F){return e(),n("div",null,h)}const b=a(l,[["render",k]]);export{C as __pageData,b as default};
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as e,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"Web UI 自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/WebUI自动化测试/初始化项目.md","filePath":"实践/WebUI自动化测试/初始化项目.md","lastUpdated":1722828751000}'),l={name:"实践/WebUI自动化测试/初始化项目.md"},p=t("",17),h=[p];function k(d,r,o,c,g,F){return e(),n("div",null,h)}const b=a(l,[["render",k]]);export{C as __pageData,b as default};
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.js"
    index 85dee7b9..b131ba4a 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建APP工程.md","filePath":"实践/命令行自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建APP工程.md","filePath":"实践/命令行自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/创建APP工程.md"},t=k('

    创建一个 APP 工程

    使用 startapp 创建一个 APP 工程:

    shell
    youqu manage.py startapp autotest_my_app

    自动创建 APP 工程,并生成大量模板代码:

    shell
    my_project
     ├── apps
     │   ├── autotest_my_app  # 创建的APP工程
     │   │   ├── case  # 用例目录
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.lean.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.lean.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.lean.js"
    index da19659b..0d862e09 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CSmxxJk8.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272APP\345\267\245\347\250\213.md.CD7HnebK.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建APP工程.md","filePath":"实践/命令行自动化测试/创建APP工程.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    +import{_ as s}from"./chunks/startapp.TDFOhrgm.js";import{_ as i}from"./chunks/pc_open.BbQ9q2gR.js";import{_ as a,c as h,o as n,U as k}from"./chunks/framework.DIzwIJpr.js";const _=JSON.parse('{"title":"创建一个 APP 工程","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建APP工程.md","filePath":"实践/命令行自动化测试/创建APP工程.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/创建APP工程.md"},t=k("",9),l=[t];function F(e,r,d,y,g,C){return n(),h("div",null,l)}const o=a(p,[["render",F]]);export{_ as __pageData,o as default};
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.js"
    similarity index 99%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.js"
    index ea53acb8..64a10c56 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建一条完整的用例.md","filePath":"实践/命令行自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/创建一条完整的用例.md"},t=n(`

    创建一条完整的用例

    使用 dd 命令创建文件

    封装用例步骤的方法

    方法主文件里面:cmd_widget.py

    python
    # cmd_widget.py
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建一条完整的用例.md","filePath":"实践/命令行自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/创建一条完整的用例.md"},t=n(`

    创建一条完整的用例

    使用 dd 命令创建文件

    封装用例步骤的方法

    方法主文件里面:cmd_widget.py

    python
    # cmd_widget.py
     
     from setting import conf
     from src import Src
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.lean.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.lean.js"
    similarity index 88%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.lean.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.lean.js"
    index 69207ecd..32d9cd54 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.Db9d6q36.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.md.BJNQoDlt.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建一条完整的用例.md","filePath":"实践/命令行自动化测试/创建一条完整的用例.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/创建一条完整的用例.md"},t=n("",11),h=[t];function l(e,k,d,r,E,o){return a(),i("div",null,h)}const g=s(p,[["render",l]]);export{y as __pageData,g as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"创建一条完整的用例","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/创建一条完整的用例.md","filePath":"实践/命令行自动化测试/创建一条完整的用例.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/创建一条完整的用例.md"},t=n("",11),h=[t];function l(e,k,d,r,E,o){return a(),i("div",null,h)}const g=s(p,[["render",l]]);export{y as __pageData,g as default};
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.js"
    similarity index 98%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.js"
    index f3bc73dd..0ced4cce 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"命令行自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/初始化项目.md","filePath":"实践/命令行自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/初始化项目.md"},h=l('

    命令行自动化测试

    命令行自动化测试是 Linux 平台自动化测试的老演员了,与命令行的交互也是相对容易的,这类自动化测试也比较简单。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"命令行自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/初始化项目.md","filePath":"实践/命令行自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/初始化项目.md"},h=l('

    命令行自动化测试

    命令行自动化测试是 Linux 平台自动化测试的老演员了,与命令行的交互也是相对容易的,这类自动化测试也比较简单。

    安装

    安装 YouQu:

    shell
    sudo pip3 install youqu

    创建一个项目

    创建一个项目:

    shell
    youqu-startproject my_project

    shell
    my_project
     ├── apps  # 用于放置APP工程
     ├── conftest.py  # Pytest 插件库
     ├── CURRENT      # 记录YouQu当前的版本
    diff --git "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.lean.js" "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.lean.js"
    similarity index 89%
    rename from "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.lean.js"
    rename to "assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.lean.js"
    index 71a32984..b166c2ba 100644
    --- "a/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.DmoXx_zB.lean.js"
    +++ "b/assets/\345\256\236\350\267\265_\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225_\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.md.CFJCMo4S.lean.js"
    @@ -1 +1 @@
    -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"命令行自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/初始化项目.md","filePath":"实践/命令行自动化测试/初始化项目.md","lastUpdated":1722828555000}'),p={name:"实践/命令行自动化测试/初始化项目.md"},h=l("",14),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i}from"./chunks/env.CqxpnoXB.js";import{_ as a,c as n,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"命令行自动化测试","description":"","frontmatter":{},"headers":[],"relativePath":"实践/命令行自动化测试/初始化项目.md","filePath":"实践/命令行自动化测试/初始化项目.md","lastUpdated":1722828751000}'),p={name:"实践/命令行自动化测试/初始化项目.md"},h=l("",14),e=[h];function k(r,d,o,c,g,F){return t(),n("div",null,e)}const m=a(p,[["render",k]]);export{C as __pageData,m as default};
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.js"
    index d66c9c78..9e4411b4 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E5%85%83%E7%B4%A0%E5%AE%9A%E4%BD%8D/youqu-ocr.png",o=JSON.parse('{"title":"OCR识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/OCR识别.md","filePath":"指南/元素定位/OCR识别.md","lastUpdated":1722828555000}'),p={name:"指南/元素定位/OCR识别.md"},l=n(`

    OCR识别

    背景

    传统的 OCR 方案大多采用谷歌 OCR(Tesseract)方案,但是它对于中文的识别非常差,经过大量的调研,我们使用 PaddleOCR,它是一个开源的基于深度学习的 OCR 识别工具,也是 PaddlePaddle 最有名的一个开源项目,感兴趣的可以点这里了解,多的不说了,你只需要知道它就是中文识别的天花板。

    实现原理

    安装它是个很麻烦的事情,虽然操作很简单,但其实安装包有点大,这并不符合我们对框架依赖治理的理解,我们并不希望直接在 env.sh 中加入它,这会让整个自动化环境变得非常臃肿;

    因此,我们想到将它做成一个 RPC 服务在其他机器上部署,测试机通过远程调用 RPC 服务的方式使用它;

    RPC 的调用逻辑:

    这样我们只需要在服务端部署好 OCR 识别的服务,然后通过 RPC 服务将功能提供出来,框架里面只需要调用对应的 RPC 接口就行了。

    使用说明

    框架代码示意(Client):

    python
    from src import OCR
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E5%85%83%E7%B4%A0%E5%AE%9A%E4%BD%8D/youqu-ocr.png",o=JSON.parse('{"title":"OCR识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/OCR识别.md","filePath":"指南/元素定位/OCR识别.md","lastUpdated":1722828751000}'),p={name:"指南/元素定位/OCR识别.md"},l=n(`

    OCR识别

    背景

    传统的 OCR 方案大多采用谷歌 OCR(Tesseract)方案,但是它对于中文的识别非常差,经过大量的调研,我们使用 PaddleOCR,它是一个开源的基于深度学习的 OCR 识别工具,也是 PaddlePaddle 最有名的一个开源项目,感兴趣的可以点这里了解,多的不说了,你只需要知道它就是中文识别的天花板。

    实现原理

    安装它是个很麻烦的事情,虽然操作很简单,但其实安装包有点大,这并不符合我们对框架依赖治理的理解,我们并不希望直接在 env.sh 中加入它,这会让整个自动化环境变得非常臃肿;

    因此,我们想到将它做成一个 RPC 服务在其他机器上部署,测试机通过远程调用 RPC 服务的方式使用它;

    RPC 的调用逻辑:

    这样我们只需要在服务端部署好 OCR 识别的服务,然后通过 RPC 服务将功能提供出来,框架里面只需要调用对应的 RPC 接口就行了。

    使用说明

    框架代码示意(Client):

    python
    from src import OCR
     
     OCR.ocr(*target_strings, picture_abspath=None, similarity=0.6, return_default=False, return_first=False, lang="ch"):
     # 通过 OCR 进行识别。
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.lean.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.lean.js"
    similarity index 88%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.lean.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.lean.js"
    index 58d7d628..e1dd60b6 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.DK2R5D7p.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_OCR\350\257\206\345\210\253.md.CXrPXR6J.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E5%85%83%E7%B4%A0%E5%AE%9A%E4%BD%8D/youqu-ocr.png",o=JSON.parse('{"title":"OCR识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/OCR识别.md","filePath":"指南/元素定位/OCR识别.md","lastUpdated":1722828555000}'),p={name:"指南/元素定位/OCR识别.md"},l=n("",32),k=[l];function t(e,r,E,d,g,y){return a(),i("div",null,k)}const c=s(p,[["render",t]]);export{o as __pageData,c as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E5%85%83%E7%B4%A0%E5%AE%9A%E4%BD%8D/youqu-ocr.png",o=JSON.parse('{"title":"OCR识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/OCR识别.md","filePath":"指南/元素定位/OCR识别.md","lastUpdated":1722828751000}'),p={name:"指南/元素定位/OCR识别.md"},l=n("",32),k=[l];function t(e,r,E,d,g,y){return a(),i("div",null,k)}const c=s(p,[["render",t]]);export{o as __pageData,c as default};
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.js"
    index 114fa3f2..8e0323cb 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as a,o as i,U as p}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"去干扰识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/去干扰识别.md","filePath":"指南/元素定位/去干扰识别.md","lastUpdated":1722828555000}'),e={name:"指南/元素定位/去干扰识别.md"},t=p(`

    去干扰识别

    以右键菜单来讲解此方案;

    现有右键菜单定位的方案及问题

    右键菜单的元素定位是一个难点,过去我们调研和使用过的元素定位操作方法有 4 种:

    1. 步长操作法

    在右键菜单呼出来之后,通过键盘的 updown 按键,进行选择菜单选择,选中目标之后 enter 即可;比如:在桌面点击右键菜单之后,按 1 次 down ,会出现下图:

    继续再按 2 次 down,会出现这样:

    再按 enter,会出现这样:

    如此,“排序方式”的步长为 3;通过使用键盘上下键,就实现了对右键菜单的操作;

    但是,这种方式有个很烦人的问题,就是右键菜单的选项位置不可能一直不变,在需求迭代的过程中,菜单选项的变化是很大的,甚至有些应用支持自定义菜单,比如文管右键菜单可以自定义;

    也就是说你得经常去维护菜单选项的步长,一个选项现在的步长是 3,下个迭代可能就是 4 或者 5。

    2. 常规图像识别法

    把每个菜单选项单独截图保存,图片中仅包含一个菜单选项,如下图所示:

    这样,每个菜单选项就可以通过图像识别的方式进行元素定位;

    这种方式不用担心菜单选项的顺序或位置,但是需要保存大量的图片,且容易受到字体 UI 变更类需求的影响,比如:字体大小、字体间距等等需求变更都会影响,每次变更之后就需要进行大量图片资源的重新截图替换,是个比较麻烦的事情;

    3. 相对位移法

    鼠标点击右键的时候,鼠标的当前坐标是可以获取到的,菜单选项的宽( w )一般是固定的,变化的是菜单的长度( h ),可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标,如下图所示:

    通过维护菜单选项(相对位置)相对于鼠标位置的距离,即可轻松计算出菜单选项在屏幕中的坐标。

    从理论上此方案是可行的,但是这里仍然存在两个严重的问题:

    • 菜单顺序改变,导致相对距离改变,而且距离是通过像素(px)来表示的,不想步长那么只管,每次需要去量一下,维护起来有点麻烦;
    • 鼠标在桌面不同位置点击右键,右键菜单出现的位置是不同的,上图的菜单是在鼠标的左下方,如果你移动鼠标到屏幕四边,你会发现,右键菜单可能出现在鼠标的四个方向,也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向,而不同的方向上计算方法是不同的,比如:右键菜单在鼠标的左上,菜单选项的坐标计算方法为(x - w / 2, y - h),这样维护起来可以说非常复杂;

    基于以上两个原因,我们并不推荐这种操作方案。

    4. 属性定位

    有同学说干嘛不通过属性定位呢,其实,我们最开始想到的方案就是通过属性定位,但是在属性的 DOM 树里怎么也找不到,无法定位到,我们也联合研发同学一起解决此问题,但最终还是没能解决,非常遗憾;

    去干扰识别

    由于右键菜单选项几乎都是文本,那么通过 OCR 识别,几乎是最优的方案:

    • 不用保存大量的图片;
    • 不会受到菜单选项顺序改变的影响;
    • 不会受到字体 UI 变化的影响;

    关于 OCR 识别我们在前面已经讲到,本章节主要讲基于 OCR 识别,我们在右键菜单识别上的突破和创新;

    使用 OCR 识别右键菜单虽然已经很完美了,但是在一些情况下仍然存在一点问题,就是屏幕中出现多个和菜单选项文字相同的文字时,比如下面这种情况:

    屏幕恰好出现了两个“复制”,此时要定位到菜单中的 “复制”,就需要进一步做数据处理,比如:OCR 返回 2 个“复制”的坐标,用例里面来判断用哪个,从业务上将处理起来比较麻烦,因为你得明确知道菜单在左边还是右边,然后这本身就是不确定的;

    怎么解决这个问题呢,这就要说到本章的主题:去干扰图像识别

    【原理】

    在点击右键菜单之前截一张图,点击右键菜单之后再截取一张图,两张图唯一变化的就是右键菜单,将其他相同的地方都屏蔽掉,只留下菜单界面,如此即可消除干扰,如下图所示:

    将两种图做前后对比提取可以得到这样的图:

    你看,通过前后图片的对比,将相同的部分给消除掉,再进行 OCR 识别,这样就不会有干扰了;

    代码实现请查看 src/filter_image.py

    代码示例:

    python
    def filter_image(action):
    +import{_ as s,c as a,o as i,U as p}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"去干扰识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/去干扰识别.md","filePath":"指南/元素定位/去干扰识别.md","lastUpdated":1722828751000}'),e={name:"指南/元素定位/去干扰识别.md"},t=p(`

    去干扰识别

    以右键菜单来讲解此方案;

    现有右键菜单定位的方案及问题

    右键菜单的元素定位是一个难点,过去我们调研和使用过的元素定位操作方法有 4 种:

    1. 步长操作法

    在右键菜单呼出来之后,通过键盘的 updown 按键,进行选择菜单选择,选中目标之后 enter 即可;比如:在桌面点击右键菜单之后,按 1 次 down ,会出现下图:

    继续再按 2 次 down,会出现这样:

    再按 enter,会出现这样:

    如此,“排序方式”的步长为 3;通过使用键盘上下键,就实现了对右键菜单的操作;

    但是,这种方式有个很烦人的问题,就是右键菜单的选项位置不可能一直不变,在需求迭代的过程中,菜单选项的变化是很大的,甚至有些应用支持自定义菜单,比如文管右键菜单可以自定义;

    也就是说你得经常去维护菜单选项的步长,一个选项现在的步长是 3,下个迭代可能就是 4 或者 5。

    2. 常规图像识别法

    把每个菜单选项单独截图保存,图片中仅包含一个菜单选项,如下图所示:

    这样,每个菜单选项就可以通过图像识别的方式进行元素定位;

    这种方式不用担心菜单选项的顺序或位置,但是需要保存大量的图片,且容易受到字体 UI 变更类需求的影响,比如:字体大小、字体间距等等需求变更都会影响,每次变更之后就需要进行大量图片资源的重新截图替换,是个比较麻烦的事情;

    3. 相对位移法

    鼠标点击右键的时候,鼠标的当前坐标是可以获取到的,菜单选项的宽( w )一般是固定的,变化的是菜单的长度( h ),可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标,如下图所示:

    通过维护菜单选项(相对位置)相对于鼠标位置的距离,即可轻松计算出菜单选项在屏幕中的坐标。

    从理论上此方案是可行的,但是这里仍然存在两个严重的问题:

    • 菜单顺序改变,导致相对距离改变,而且距离是通过像素(px)来表示的,不想步长那么只管,每次需要去量一下,维护起来有点麻烦;
    • 鼠标在桌面不同位置点击右键,右键菜单出现的位置是不同的,上图的菜单是在鼠标的左下方,如果你移动鼠标到屏幕四边,你会发现,右键菜单可能出现在鼠标的四个方向,也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向,而不同的方向上计算方法是不同的,比如:右键菜单在鼠标的左上,菜单选项的坐标计算方法为(x - w / 2, y - h),这样维护起来可以说非常复杂;

    基于以上两个原因,我们并不推荐这种操作方案。

    4. 属性定位

    有同学说干嘛不通过属性定位呢,其实,我们最开始想到的方案就是通过属性定位,但是在属性的 DOM 树里怎么也找不到,无法定位到,我们也联合研发同学一起解决此问题,但最终还是没能解决,非常遗憾;

    去干扰识别

    由于右键菜单选项几乎都是文本,那么通过 OCR 识别,几乎是最优的方案:

    • 不用保存大量的图片;
    • 不会受到菜单选项顺序改变的影响;
    • 不会受到字体 UI 变化的影响;

    关于 OCR 识别我们在前面已经讲到,本章节主要讲基于 OCR 识别,我们在右键菜单识别上的突破和创新;

    使用 OCR 识别右键菜单虽然已经很完美了,但是在一些情况下仍然存在一点问题,就是屏幕中出现多个和菜单选项文字相同的文字时,比如下面这种情况:

    屏幕恰好出现了两个“复制”,此时要定位到菜单中的 “复制”,就需要进一步做数据处理,比如:OCR 返回 2 个“复制”的坐标,用例里面来判断用哪个,从业务上将处理起来比较麻烦,因为你得明确知道菜单在左边还是右边,然后这本身就是不确定的;

    怎么解决这个问题呢,这就要说到本章的主题:去干扰图像识别

    【原理】

    在点击右键菜单之前截一张图,点击右键菜单之后再截取一张图,两张图唯一变化的就是右键菜单,将其他相同的地方都屏蔽掉,只留下菜单界面,如此即可消除干扰,如下图所示:

    将两种图做前后对比提取可以得到这样的图:

    你看,通过前后图片的对比,将相同的部分给消除掉,再进行 OCR 识别,这样就不会有干扰了;

    代码实现请查看 src/filter_image.py

    代码示例:

    python
    def filter_image(action):
         """
         对比动作前后两张图片,提取不同的部分生成一张新的图片,并返回新图片的路径
         :param action: 动作函数的函数对象
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.lean.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.lean.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.lean.js"
    index 8932fe71..21dd32fd 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.BIpooK_Y.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.md.DiZ2-d5A.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as a,o as i,U as p}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"去干扰识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/去干扰识别.md","filePath":"指南/元素定位/去干扰识别.md","lastUpdated":1722828555000}'),e={name:"指南/元素定位/去干扰识别.md"},t=p("",48),n=[t];function l(c,h,o,r,d,k){return i(),a("div",null,n)}const u=s(e,[["render",l]]);export{m as __pageData,u as default};
    +import{_ as s,c as a,o as i,U as p}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"去干扰识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/去干扰识别.md","filePath":"指南/元素定位/去干扰识别.md","lastUpdated":1722828751000}'),e={name:"指南/元素定位/去干扰识别.md"},t=p("",48),n=[t];function l(c,h,o,r,d,k){return i(),a("div",null,n)}const u=s(e,[["render",l]]);export{m as __pageData,u as default};
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.js"
    index 6a3f6210..8c2b5b0d 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"图像识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/图像识别.md","filePath":"指南/元素定位/图像识别.md","lastUpdated":1722828555000}'),p={name:"指南/元素定位/图像识别.md"},h=n(`

    图像识别

    图像识别在 UI 自动化中是不可缺少的,市面上甚至有完全基于图像识别的自动化测试框架,比如 AirtestSikuli 等,在游戏等特定领域也有不错的效果,这些工具实际上也是用的 OpenCV 进行了封装,YouQu 框架基于 OpenCV 开发了自己的图像识别功能,它可以方便的用于界面元素的定位和断言;

    YouQu 的图像识别功能几乎满足了你的所有要求,我们在长时间的思考和摸索中,针对常规场景及一些特殊场景探索出了一些实用且有效的方案,且听我慢慢道来。

    常规识别

    【背景】

    常规识别很好理解,一句话讲就是,要获取到目标元素在屏幕中的位置。

    【原理实现】

    在测试过程中需要获取的坐标是相对于整个屏幕的坐标,我们可以截取到整个屏幕的图片(screen);

    在元素识别的过程中,我们需要截取某个元素的小图进行识别,比如截取播放按钮:

    那么实际上,元素定位的问题就转换为,将截图的小图(play_btn)拿到整个屏幕的大图(screen)中去做匹配,如果匹配成功,返回小图在大图中的坐标( x, y )即可。

    为了方便描述,以下我将整个屏幕的截图称为:大图,某个元素图片的截图称为:小图。

    基于 OpenCV 的模板匹配 cv.matchTemplate() 功能,我们实现了图像定位的功能,框架提供了一个图像识别的底层接口(一般不对上层提供调用):

    python
    def _match_image_by_opencv(
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"图像识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/图像识别.md","filePath":"指南/元素定位/图像识别.md","lastUpdated":1722828751000}'),p={name:"指南/元素定位/图像识别.md"},h=n(`

    图像识别

    图像识别在 UI 自动化中是不可缺少的,市面上甚至有完全基于图像识别的自动化测试框架,比如 AirtestSikuli 等,在游戏等特定领域也有不错的效果,这些工具实际上也是用的 OpenCV 进行了封装,YouQu 框架基于 OpenCV 开发了自己的图像识别功能,它可以方便的用于界面元素的定位和断言;

    YouQu 的图像识别功能几乎满足了你的所有要求,我们在长时间的思考和摸索中,针对常规场景及一些特殊场景探索出了一些实用且有效的方案,且听我慢慢道来。

    常规识别

    【背景】

    常规识别很好理解,一句话讲就是,要获取到目标元素在屏幕中的位置。

    【原理实现】

    在测试过程中需要获取的坐标是相对于整个屏幕的坐标,我们可以截取到整个屏幕的图片(screen);

    在元素识别的过程中,我们需要截取某个元素的小图进行识别,比如截取播放按钮:

    那么实际上,元素定位的问题就转换为,将截图的小图(play_btn)拿到整个屏幕的大图(screen)中去做匹配,如果匹配成功,返回小图在大图中的坐标( x, y )即可。

    为了方便描述,以下我将整个屏幕的截图称为:大图,某个元素图片的截图称为:小图。

    基于 OpenCV 的模板匹配 cv.matchTemplate() 功能,我们实现了图像定位的功能,框架提供了一个图像识别的底层接口(一般不对上层提供调用):

    python
    def _match_image_by_opencv(
         image_path: str, 
         rate: float = None, 
         multiple: bool = False, 
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.lean.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.lean.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.lean.js"
    index 3375c510..be684480 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.cYhyqO_w.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\233\276\345\203\217\350\257\206\345\210\253.md.DNFlkZ4K.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"图像识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/图像识别.md","filePath":"指南/元素定位/图像识别.md","lastUpdated":1722828555000}'),p={name:"指南/元素定位/图像识别.md"},h=n("",106),l=[h];function t(k,e,r,E,d,g){return a(),i("div",null,l)}const y=s(p,[["render",t]]);export{F as __pageData,y as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"图像识别","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/图像识别.md","filePath":"指南/元素定位/图像识别.md","lastUpdated":1722828751000}'),p={name:"指南/元素定位/图像识别.md"},h=n("",106),l=[h];function t(k,e,r,E,d,g){return a(),i("div",null,l)}const y=s(p,[["render",t]]);export{F as __pageData,y as default};
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.js"
    index 0e501176..f5e6d4dc 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"属性定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/属性定位.md","filePath":"指南/元素定位/属性定位.md","lastUpdated":1722828555000}'),h={name:"指南/元素定位/属性定位.md"},l=n(`

    属性定位

    背景

    传统的 UI 自动化大多都是基于浏览器的,核心是在网页的 DOM 树上查找元素,并对其进行定位操作;

    Linux 桌面应用大多是采用 Qt 编写的,在 Qt 中也是从最顶层的 MainWindow 开始构建应用,所以逻辑也是一样的,Qt 应用的自动化测试同样可以通过 DOM 树(属性树)进行元素定位,我们称之为属性定位

    借助开源工具 dogtail 我们可以对元素进行获取,从而进行定位操作。dogtail 的项目介绍可以猛戳这里

    sniff(嗅探器)使用

    在终端输入 sniff 启动 AT-SPI Browser

    shell
    mikigo@mikigo-PC:~$ sniff

    查看应用的标签

    在 sniff 里面可以看到系统中已启动的应用,点击应用名称前面的三角形图标,可以展开应用的标签,所有标签以 tree 的形式展示,对应应用里面的父窗口和子窗口。

    获取元素控件的标签名称

    首先,为了方便查看元素控件对应的位置,建议现在上方工具栏点击 Actions,然后勾选 Hightlight Items,这样在 sniff 中鼠标选中元素标签的时候,应用中会有相应的光标锁定。

    在 sniff 里面点击进入应用的标签 tree 中后,点击相应的元素控件,在工具下方,会展示元素控件的 Name,这个就是标签名称。

    在 tree 中有些地方是空白的或者是 Form,是因为开发人员在添加标签的时候没有添加,或者有些父窗口不需要添加,这种在实际业务中是不影响的,我们只要保证自动化测试用例中,要用到的元素都添加了标签即可。

    元素操作

    获取应用对象

    dogtail 获取应用对象的时候,使用的是 tree 库里面的 application() 方法:

    python
    from dogtail.tree import root
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"属性定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/属性定位.md","filePath":"指南/元素定位/属性定位.md","lastUpdated":1722828751000}'),h={name:"指南/元素定位/属性定位.md"},l=n(`

    属性定位

    背景

    传统的 UI 自动化大多都是基于浏览器的,核心是在网页的 DOM 树上查找元素,并对其进行定位操作;

    Linux 桌面应用大多是采用 Qt 编写的,在 Qt 中也是从最顶层的 MainWindow 开始构建应用,所以逻辑也是一样的,Qt 应用的自动化测试同样可以通过 DOM 树(属性树)进行元素定位,我们称之为属性定位

    借助开源工具 dogtail 我们可以对元素进行获取,从而进行定位操作。dogtail 的项目介绍可以猛戳这里

    sniff(嗅探器)使用

    在终端输入 sniff 启动 AT-SPI Browser

    shell
    mikigo@mikigo-PC:~$ sniff

    查看应用的标签

    在 sniff 里面可以看到系统中已启动的应用,点击应用名称前面的三角形图标,可以展开应用的标签,所有标签以 tree 的形式展示,对应应用里面的父窗口和子窗口。

    获取元素控件的标签名称

    首先,为了方便查看元素控件对应的位置,建议现在上方工具栏点击 Actions,然后勾选 Hightlight Items,这样在 sniff 中鼠标选中元素标签的时候,应用中会有相应的光标锁定。

    在 sniff 里面点击进入应用的标签 tree 中后,点击相应的元素控件,在工具下方,会展示元素控件的 Name,这个就是标签名称。

    在 tree 中有些地方是空白的或者是 Form,是因为开发人员在添加标签的时候没有添加,或者有些父窗口不需要添加,这种在实际业务中是不影响的,我们只要保证自动化测试用例中,要用到的元素都添加了标签即可。

    元素操作

    获取应用对象

    dogtail 获取应用对象的时候,使用的是 tree 库里面的 application() 方法:

    python
    from dogtail.tree import root
     app_obj = root.application('deepin-music')

    app_obj就是应用的对象。

    • 获取元素对象

    获取元素对象,是应用对象使用child()方法:

    python
    element = app_obj.child('element_name')

    我们可以通过传入元素的 Name,获取到相应元素的对象。Name 可以通过 sniff 查看。

    • 获取元素对象列表:
    python
    element_list = element.children

    获取到这个元素下面所有的元素列表。

    这个方法适用于有些标签没有添加,但是位置是固定的,我们通过索引可以取得元素。

    python
    element_list[0]
    • 对元素的操作

    在获取到元素之后,我们就可以对元素进行相应的操作。

    • 单击
    python
    element.click(button=1)

    button 1 —>左键,2 —>滚轮,3 —>右键,默认为 1

    • 双击
    python
    element.doubleClick(button=1)
    • 鼠标悬停
    python
    element.point()

    鼠标移动到元素中心位置

    • 文本输入
    python
    element.typeText(string)

    向元素对象输入字符串 ,比如输入框

    • 组合键
    python
    element.keyCombo(comboString)

    框架封装

    代码示例:

    python
    # 详细代码请查看 src/dogtail_utils.py
     class DogtailUtils:
     
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.lean.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.lean.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.lean.js"
    index b5b9af79..eaacbac1 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BhtbdZ6I.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\345\261\236\346\200\247\345\256\232\344\275\215.md.BsFtkb-s.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"属性定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/属性定位.md","filePath":"指南/元素定位/属性定位.md","lastUpdated":1722828555000}'),h={name:"指南/元素定位/属性定位.md"},l=n("",56),k=[l];function p(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",p]]);export{F as __pageData,o as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"属性定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/属性定位.md","filePath":"指南/元素定位/属性定位.md","lastUpdated":1722828751000}'),h={name:"指南/元素定位/属性定位.md"},l=n("",56),k=[l];function p(t,e,E,r,d,g){return a(),i("div",null,k)}const o=s(h,[["render",p]]);export{F as __pageData,o as default};
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.js"
    index 7f85aaa6..29ffe1e1 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"相对坐标定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/相对坐标定位.md","filePath":"指南/元素定位/相对坐标定位.md","lastUpdated":1722828555000}'),h={name:"指南/元素定位/相对坐标定位.md"},k=n(`

    相对坐标定位

    背景

    相对坐标定位方案是是一种基于 UI 的元素定位方案,是我们自研的一个使用简单,且效率极高、稳定性好的元素定位方案,基于元素按钮在应用中的相对位置,动态获取元素在当前屏幕中的位置,适用于各种屏幕分辨率(包括高分屏、宽屏、带鱼屏),当元素按钮位置相对于应用界面位置发生修改之后,只需要根据 UI 设计图上的源数据修改对应坐标数据就好,维护非常的方便。

    此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用,比如音乐(99% 的元素定位采用这种,效果非常好),不适用于界面不固定的应用,比如截图录屏,很明显不适用于这类元素定位方案。这种全新的元素定位方案有它的适用条件,如果你发现使用常规的(属性定位、图像定位)不好做时,不妨考虑使用这种,其效果一定能惊讶到你,并且迅速爱上他。

    实现原理

    在 UI 设计图中我们是可以获取到元素按钮相对于应用边框的距离的,然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小,示意图如下:

    (x1, y1)为应用左上角相对于屏幕左上角(0, 0)的位置;(x2, y2)是按钮【播放所有】的左上角相对于应用窗口左上角(x1, y1)的坐标,那么实际上【播放所有】左上角相对于屏幕左上角(0, 0)的位置为:( x1 + x2, y1 + y2 )

    是按钮【播放所有】的大小(w2, h2),可以从 UI 设计图上获取;

    在 UI 设计稿上点击【播放所有】图标,然后移动鼠标就就可以看到上图的参考线及数据;

    所以,我们可以轻松的获取到按钮【播放所有】的中心坐标为:( x1 + x2 + (w2 / 2), y1 + y2 + ( h2 / 2) )

    详细源代码请查看 AT 基础框架: src/button_center.py

    • 获取应用窗口的信息

    使用 xdotoolxwininfo 获取到应用窗口在当前屏幕中的位置(左上角)及大小。

    代码示例:

    python
    app_id = CmdCtl.run_cmd(f"xdotool search --classname --onlyvisible {self.app_name}"
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"相对坐标定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/相对坐标定位.md","filePath":"指南/元素定位/相对坐标定位.md","lastUpdated":1722828751000}'),h={name:"指南/元素定位/相对坐标定位.md"},k=n(`

    相对坐标定位

    背景

    相对坐标定位方案是是一种基于 UI 的元素定位方案,是我们自研的一个使用简单,且效率极高、稳定性好的元素定位方案,基于元素按钮在应用中的相对位置,动态获取元素在当前屏幕中的位置,适用于各种屏幕分辨率(包括高分屏、宽屏、带鱼屏),当元素按钮位置相对于应用界面位置发生修改之后,只需要根据 UI 设计图上的源数据修改对应坐标数据就好,维护非常的方便。

    此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用,比如音乐(99% 的元素定位采用这种,效果非常好),不适用于界面不固定的应用,比如截图录屏,很明显不适用于这类元素定位方案。这种全新的元素定位方案有它的适用条件,如果你发现使用常规的(属性定位、图像定位)不好做时,不妨考虑使用这种,其效果一定能惊讶到你,并且迅速爱上他。

    实现原理

    在 UI 设计图中我们是可以获取到元素按钮相对于应用边框的距离的,然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小,示意图如下:

    (x1, y1)为应用左上角相对于屏幕左上角(0, 0)的位置;(x2, y2)是按钮【播放所有】的左上角相对于应用窗口左上角(x1, y1)的坐标,那么实际上【播放所有】左上角相对于屏幕左上角(0, 0)的位置为:( x1 + x2, y1 + y2 )

    是按钮【播放所有】的大小(w2, h2),可以从 UI 设计图上获取;

    在 UI 设计稿上点击【播放所有】图标,然后移动鼠标就就可以看到上图的参考线及数据;

    所以,我们可以轻松的获取到按钮【播放所有】的中心坐标为:( x1 + x2 + (w2 / 2), y1 + y2 + ( h2 / 2) )

    详细源代码请查看 AT 基础框架: src/button_center.py

    • 获取应用窗口的信息

    使用 xdotoolxwininfo 获取到应用窗口在当前屏幕中的位置(左上角)及大小。

    代码示例:

    python
    app_id = CmdCtl.run_cmd(f"xdotool search --classname --onlyvisible {self.app_name}"
     ).split("\\n")
     app_id_list = [int(_id) for _id in app_id if _id]
     return CmdCtl.run_cmd(f"xwininfo -id {app_id_list[self.number]}")

    使用正则获取窗口的位置及大小。

    • 获取配置

    ini 配置文件,获取元素按钮相对与应用窗口边界的位置及大小。

    代码示例:

    python
    conf = ConfigParser()
    diff --git "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.lean.js" "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.lean.js"
    similarity index 87%
    rename from "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.lean.js"
    rename to "assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.lean.js"
    index 853ef6b1..f5253725 100644
    --- "a/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.o2JL1JQc.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\345\205\203\347\264\240\345\256\232\344\275\215_\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.md.mSzYAd7F.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"相对坐标定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/相对坐标定位.md","filePath":"指南/元素定位/相对坐标定位.md","lastUpdated":1722828555000}'),h={name:"指南/元素定位/相对坐标定位.md"},k=n("",36),l=[k];function p(t,E,e,r,d,g){return a(),i("div",null,l)}const o=s(h,[["render",p]]);export{y as __pageData,o as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"相对坐标定位","description":"","frontmatter":{},"headers":[],"relativePath":"指南/元素定位/相对坐标定位.md","filePath":"指南/元素定位/相对坐标定位.md","lastUpdated":1722828751000}'),h={name:"指南/元素定位/相对坐标定位.md"},k=n("",36),l=[k];function p(t,E,e,r,d,g){return a(),i("div",null,l)}const o=s(h,[["render",p]]);export{y as __pageData,o as default};
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.js"
    index 43254f5c..c266760b 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-1.png",t="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-2.png",p="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-3.png",h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-4.png",q=JSON.parse('{"title":"Ruff","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/Ruff代码检查.md","filePath":"指南/框架必备/Ruff代码检查.md","lastUpdated":1722828555000}'),e={name:"指南/框架必备/Ruff代码检查.md"},k=n('

    Ruff

    YouQu 默认使用 Python 最强代码检查&格式化工具——Ruff。

    安装

    shell
    pip3 install ruff

    代码检查

    代码检查是扫描代码中存在的问题。

    shell
    ruff check .

    表示扫描当前目录下所有的代码,当然你可以指定一个具体的目录或文件。

    在扫描日志最后可以看到一个 fixable,意思是可以通过 --fix 参数直接给你修复掉。

    shell
    ruff check setting/ --fix

    对比下文件前后:

    你看,直接修复了对吧。

    代码格式化

    经过前面代码检查并修复之后,说明我们代码中没有“问题”了,接下来就可以进行代码格式化。

    shell
    ruff format setting/

    效果很不错对吧。

    格式化这块 Ruff 官方表示是可以直接替代 Black 的。

    配置

    前面代码检查的时候报了一个问题,是说在 __init__.py 文件里面写了一个导入,但没有被使用。

    但是这是我特意这样写的,是一种名称空间的设计,可以在 setting 名称空间下直接导入,不需要 Ruff 处理这个问题,这也不是个问题。

    因此,我们需要对 Ruff 进行配置。

    在根目录下 ruff.toml 的文件:

    toml
    # Exclude a variety of commonly ignored directories.
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-1.png",t="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-2.png",p="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-3.png",h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-4.png",q=JSON.parse('{"title":"Ruff","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/Ruff代码检查.md","filePath":"指南/框架必备/Ruff代码检查.md","lastUpdated":1722828751000}'),e={name:"指南/框架必备/Ruff代码检查.md"},k=n('

    Ruff

    YouQu 默认使用 Python 最强代码检查&格式化工具——Ruff。

    安装

    shell
    pip3 install ruff

    代码检查

    代码检查是扫描代码中存在的问题。

    shell
    ruff check .

    表示扫描当前目录下所有的代码,当然你可以指定一个具体的目录或文件。

    在扫描日志最后可以看到一个 fixable,意思是可以通过 --fix 参数直接给你修复掉。

    shell
    ruff check setting/ --fix

    对比下文件前后:

    你看,直接修复了对吧。

    代码格式化

    经过前面代码检查并修复之后,说明我们代码中没有“问题”了,接下来就可以进行代码格式化。

    shell
    ruff format setting/

    效果很不错对吧。

    格式化这块 Ruff 官方表示是可以直接替代 Black 的。

    配置

    前面代码检查的时候报了一个问题,是说在 __init__.py 文件里面写了一个导入,但没有被使用。

    但是这是我特意这样写的,是一种名称空间的设计,可以在 setting 名称空间下直接导入,不需要 Ruff 处理这个问题,这也不是个问题。

    因此,我们需要对 Ruff 进行配置。

    在根目录下 ruff.toml 的文件:

    toml
    # Exclude a variety of commonly ignored directories.
     exclude = [
         ".bzr",
         ".direnv",
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.lean.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.lean.js"
    similarity index 91%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.lean.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.lean.js"
    index e15f0bc9..54bf50ad 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.yrpKeZ2W.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_Ruff\344\273\243\347\240\201\346\243\200\346\237\245.md.CJKmN6E7.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-1.png",t="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-2.png",p="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-3.png",h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-4.png",q=JSON.parse('{"title":"Ruff","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/Ruff代码检查.md","filePath":"指南/框架必备/Ruff代码检查.md","lastUpdated":1722828555000}'),e={name:"指南/框架必备/Ruff代码检查.md"},k=n("",31),E=[k];function d(r,o,c,g,u,F){return a(),i("div",null,E)}const C=s(e,[["render",d]]);export{q as __pageData,C as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-1.png",t="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-2.png",p="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-3.png",h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/ruff-4.png",q=JSON.parse('{"title":"Ruff","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/Ruff代码检查.md","filePath":"指南/框架必备/Ruff代码检查.md","lastUpdated":1722828751000}'),e={name:"指南/框架必备/Ruff代码检查.md"},k=n("",31),E=[k];function d(r,o,c,g,u,F){return a(),i("div",null,E)}const C=s(e,[["render",d]]);export{q as __pageData,C as default};
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.js"
    index 31be5298..d015dd8e 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as h}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"执行管理器 - manage.py","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/执行管理器.md","filePath":"指南/框架必备/执行管理器.md","lastUpdated":1722828555000}'),n={name:"指南/框架必备/执行管理器.md"},p=h(`

    执行管理器 - manage.py

    YouQu 的执行管理器 manage.py 提供了丰富的配置和命令行参数,可用于本地用例驱动执行、远程用例驱动执行、CSV 文件管理、PMS 与本地 CSV 文件标签关联管理、脚手架等功能;

    如何使用

    【命令行使用】

    所有功能的驱动执行都是通过 manage.py 进行的,它是全局的入口文件,后面提到的一些命令行参数也都默认是在 manage.py 之后添加使用;

    你可以使用 -h--help 查看它的帮助:

    shell
    $ youqu manage.py -h

    这样可以查看它支持的子命令;

    然后再通过子命令 -h--help 查看子命令的帮助,以子命令 run 举例:

    shell
    $ youqu manage.py run -h

    这样可以查看到子命令支持的各项参数及参数使用说明。

    【配置文件】

    配置文件在 setting 目录下,绝大部分的配置项均在 globalconfig.ini 文件中,为了方便描述后面经常提到的“配置文件”、“配置项”几乎都是指的 setting/globalconfig.ini

    你可以在配置文件中每一个配置项上面看到该配置项的使用说明;

    在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明,并没有再补充其对应的命令行参数,但是几乎所有的命令行参数都对应提供了配置文件配置项;

    注意

    命令行参数的优先级高于配置文件配置,也就是说通过命令行参数指定了对应的参数,配置文件中不管是否配置均不生效。

    下面介绍两个常用的用例执行的功能:

    本地执行

    本地执行子命令为:run

    shell
    $ youqu manage.py run

    1. 命令行参数

    通过命令行参数配置参数

    以下为 youqu manage.py run 提供的一些常用的参数选项:

    coffeescript
      -h, --help            show this help message and exit
    +import{_ as s,c as i,o as a,U as h}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"执行管理器 - manage.py","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/执行管理器.md","filePath":"指南/框架必备/执行管理器.md","lastUpdated":1722828751000}'),n={name:"指南/框架必备/执行管理器.md"},p=h(`

    执行管理器 - manage.py

    YouQu 的执行管理器 manage.py 提供了丰富的配置和命令行参数,可用于本地用例驱动执行、远程用例驱动执行、CSV 文件管理、PMS 与本地 CSV 文件标签关联管理、脚手架等功能;

    如何使用

    【命令行使用】

    所有功能的驱动执行都是通过 manage.py 进行的,它是全局的入口文件,后面提到的一些命令行参数也都默认是在 manage.py 之后添加使用;

    你可以使用 -h--help 查看它的帮助:

    shell
    $ youqu manage.py -h

    这样可以查看它支持的子命令;

    然后再通过子命令 -h--help 查看子命令的帮助,以子命令 run 举例:

    shell
    $ youqu manage.py run -h

    这样可以查看到子命令支持的各项参数及参数使用说明。

    【配置文件】

    配置文件在 setting 目录下,绝大部分的配置项均在 globalconfig.ini 文件中,为了方便描述后面经常提到的“配置文件”、“配置项”几乎都是指的 setting/globalconfig.ini

    你可以在配置文件中每一个配置项上面看到该配置项的使用说明;

    在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明,并没有再补充其对应的命令行参数,但是几乎所有的命令行参数都对应提供了配置文件配置项;

    注意

    命令行参数的优先级高于配置文件配置,也就是说通过命令行参数指定了对应的参数,配置文件中不管是否配置均不生效。

    下面介绍两个常用的用例执行的功能:

    本地执行

    本地执行子命令为:run

    shell
    $ youqu manage.py run

    1. 命令行参数

    通过命令行参数配置参数

    以下为 youqu manage.py run 提供的一些常用的参数选项:

    coffeescript
      -h, --help            show this help message and exit
       -a APP, --app APP     应用名称:apps/autotest_deepin_music
                             autotest_deepin_music
       -k KEYWORDS, --keywords KEYWORDS
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.lean.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.lean.js"
    similarity index 87%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.lean.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.lean.js"
    index 53abb327..00731157 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.C6nNtXOh.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.md.CJ6rimlS.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as h}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"执行管理器 - manage.py","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/执行管理器.md","filePath":"指南/框架必备/执行管理器.md","lastUpdated":1722828555000}'),n={name:"指南/框架必备/执行管理器.md"},p=h("",96),t=[p];function l(k,e,d,r,F,g){return a(),i("div",null,t)}const E=s(n,[["render",l]]);export{o as __pageData,E as default};
    +import{_ as s,c as i,o as a,U as h}from"./chunks/framework.DIzwIJpr.js";const o=JSON.parse('{"title":"执行管理器 - manage.py","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/执行管理器.md","filePath":"指南/框架必备/执行管理器.md","lastUpdated":1722828751000}'),n={name:"指南/框架必备/执行管理器.md"},p=h("",96),t=[p];function l(k,e,d,r,F,g){return a(),i("div",null,t)}const E=s(n,[["render",l]]);export{o as __pageData,E as default};
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.js"
    index 0e21ffed..664e5cc3 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/assert.png",C=JSON.parse('{"title":"断言","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/断言.md","filePath":"指南/框架必备/断言.md","lastUpdated":1722828555000}'),k={name:"指南/框架必备/断言.md"},p=n(`

    断言

    YouQu 自带多种断言语句,几乎满足了所有的断言场景;

    用例中使用方法

    APP 工程自有断言模块:my_app_assert.py,它继承了 YouQu 框架的断言库:

    python
    # my_app_assert.py
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/assert.png",C=JSON.parse('{"title":"断言","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/断言.md","filePath":"指南/框架必备/断言.md","lastUpdated":1722828751000}'),k={name:"指南/框架必备/断言.md"},p=n(`

    断言

    YouQu 自带多种断言语句,几乎满足了所有的断言场景;

    用例中使用方法

    APP 工程自有断言模块:my_app_assert.py,它继承了 YouQu 框架的断言库:

    python
    # my_app_assert.py
     
     from src.assert_common import AssertCommon
     
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.lean.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.lean.js"
    similarity index 87%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.lean.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.lean.js"
    index d5eb84ff..fb46e94e 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.B3p9qKhI.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\226\255\350\250\200.md.ZVbSVmrj.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/assert.png",C=JSON.parse('{"title":"断言","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/断言.md","filePath":"指南/框架必备/断言.md","lastUpdated":1722828555000}'),k={name:"指南/框架必备/断言.md"},p=n("",12),l=[p];function t(e,E,r,F,d,g){return a(),i("div",null,l)}const o=s(k,[["render",t]]);export{C as __pageData,o as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const h="/youqu/%E6%8C%87%E5%8D%97/%E6%A1%86%E6%9E%B6%E5%BF%85%E5%A4%87/assert.png",C=JSON.parse('{"title":"断言","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/断言.md","filePath":"指南/框架必备/断言.md","lastUpdated":1722828751000}'),k={name:"指南/框架必备/断言.md"},p=n("",12),l=[p];function t(e,E,r,F,d,g){return a(),i("div",null,l)}const o=s(k,[["render",t]]);export{C as __pageData,o as default};
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.js"
    index 5f342ed9..0eec348b 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as l}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"测试报告","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/测试报告.md","filePath":"指南/框架必备/测试报告.md","lastUpdated":1722828555000}'),n={name:"指南/框架必备/测试报告.md"},h=l(`

    测试报告

    目录结构

    执行时会在根目录下动态生成 report 目录,所有的报告相关的文件会统一存放在里面,示例:

    shell
    /report
    +import{_ as s,c as i,o as a,U as l}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"测试报告","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/测试报告.md","filePath":"指南/框架必备/测试报告.md","lastUpdated":1722828751000}'),n={name:"指南/框架必备/测试报告.md"},h=l(`

    测试报告

    目录结构

    执行时会在根目录下动态生成 report 目录,所有的报告相关的文件会统一存放在里面,示例:

    shell
    /report
         ├── allure  # allure报告
         │   ├── ...
         │   └── ffb324f3-2199-4eea-8a6f-2d7e77ce1718-container.json
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.lean.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.lean.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.lean.js"
    index ce28ca9b..c1a7b14b 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.BTX0dRwU.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\346\265\213\350\257\225\346\212\245\345\221\212.md.C0M3WFUQ.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as l}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"测试报告","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/测试报告.md","filePath":"指南/框架必备/测试报告.md","lastUpdated":1722828555000}'),n={name:"指南/框架必备/测试报告.md"},h=l("",19),t=[h];function p(e,k,F,d,r,c){return a(),i("div",null,t)}const y=s(n,[["render",p]]);export{g as __pageData,y as default};
    +import{_ as s,c as i,o as a,U as l}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"测试报告","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/测试报告.md","filePath":"指南/框架必备/测试报告.md","lastUpdated":1722828751000}'),n={name:"指南/框架必备/测试报告.md"},h=l("",19),t=[h];function p(e,k,F,d,r,c){return a(),i("div",null,t)}const y=s(n,[["render",p]]);export{g as __pageData,y as default};
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.js"
    index 9daa48b0..7c1632fa 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"键鼠操作","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/键鼠操作.md","filePath":"指南/框架必备/键鼠操作.md","lastUpdated":1722828555000}'),h={name:"指南/框架必备/键鼠操作.md"},l=n(`

    键鼠操作

    YouQu 键鼠操作模块集成了多个键鼠操作的方案:PyAutoGUIXdotoolwayland_autotool

    有同学肯定要问,我之前就只用 PyAutoGUI 也都挺好的,好像用不到这么多键鼠操作的东西吧;

    任何模块当然是希望越简洁通用越好,但问题是没有一种方案是通用的,它们都有自己存在的问题或者说不适用的场景,如果你还没有遇到,只能说使用的场景还不够多。

    常规键鼠操作

    YouQu 的键鼠操作模块主要有两个:MouseKeyShortCut

    分别是 键鼠的基本操作模块快捷键模块,基本上你能用到的键鼠操作,这里都包含了,在用例里面只需要通过方法层的类对象直接调用即可,比如:

    python
    from apps.autotest_deepin_music.widget.deepin_music_widget import DeepinMusicWidget
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"键鼠操作","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/键鼠操作.md","filePath":"指南/框架必备/键鼠操作.md","lastUpdated":1722828751000}'),h={name:"指南/框架必备/键鼠操作.md"},l=n(`

    键鼠操作

    YouQu 键鼠操作模块集成了多个键鼠操作的方案:PyAutoGUIXdotoolwayland_autotool

    有同学肯定要问,我之前就只用 PyAutoGUI 也都挺好的,好像用不到这么多键鼠操作的东西吧;

    任何模块当然是希望越简洁通用越好,但问题是没有一种方案是通用的,它们都有自己存在的问题或者说不适用的场景,如果你还没有遇到,只能说使用的场景还不够多。

    常规键鼠操作

    YouQu 的键鼠操作模块主要有两个:MouseKeyShortCut

    分别是 键鼠的基本操作模块快捷键模块,基本上你能用到的键鼠操作,这里都包含了,在用例里面只需要通过方法层的类对象直接调用即可,比如:

    python
    from apps.autotest_deepin_music.widget.deepin_music_widget import DeepinMusicWidget
     
     DeepinMusicWidget.click()
     DeepinMusicWidget.ctrl_c()

    当然你也可以直接通过 src 导入使用:

    python
    from src import Src
    diff --git "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.lean.js" "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.lean.js"
    rename to "assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.lean.js"
    index d726bbba..648024b0 100644
    --- "a/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.ES7BlKM1.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\346\241\206\346\236\266\345\277\205\345\244\207_\351\224\256\351\274\240\346\223\215\344\275\234.md.CrfCBGgm.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"键鼠操作","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/键鼠操作.md","filePath":"指南/框架必备/键鼠操作.md","lastUpdated":1722828555000}'),h={name:"指南/框架必备/键鼠操作.md"},l=n("",19),k=[l];function p(t,e,E,r,F,d){return a(),i("div",null,k)}const C=s(h,[["render",p]]);export{y as __pageData,C as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"键鼠操作","description":"","frontmatter":{},"headers":[],"relativePath":"指南/框架必备/键鼠操作.md","filePath":"指南/框架必备/键鼠操作.md","lastUpdated":1722828751000}'),h={name:"指南/框架必备/键鼠操作.md"},l=n("",19),k=[l];function p(t,e,E,r,F,d){return a(),i("div",null,k)}const C=s(h,[["render",p]]);export{y as __pageData,C as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.js"
    similarity index 98%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.js"
    index 56307ee7..f983352f 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as a,o as i,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"Wayland 适配","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/Wayland适配.md","filePath":"指南/特色功能/Wayland适配.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/Wayland适配.md"},l=n(`

    Wayland 适配

    Wayland 下自动化主要问题是 X11 下的键鼠操作方法无法使用,比如 XdotoolPyAutoGUIXwininfo 等等;

    YouQu 在 Wayland 下兼容适配,env.shWayland 下执行时会安装自研的键鼠操作服务(可能存在一些依赖报错,按照注释解决即可),框架核心库也针对性的做了适配,上层用例完全不用关心机器是Wayland 还是 X11,框架会根据执行时状态自动判断走不同的逻辑;

    简单讲就是,应用库只需要维护一套用例脚本即可。

    【用例兼容】

    因为 Wayland 下有些应用的界面显示和功能本身存在一些差异,用例层可能需要对这部分用例做逻辑判断,使用全局配置里面的常量进行逻辑编写即可:

    python
    from setting import conf
    +import{_ as s,c as a,o as i,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"Wayland 适配","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/Wayland适配.md","filePath":"指南/特色功能/Wayland适配.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/Wayland适配.md"},l=n(`

    Wayland 适配

    Wayland 下自动化主要问题是 X11 下的键鼠操作方法无法使用,比如 XdotoolPyAutoGUIXwininfo 等等;

    YouQu 在 Wayland 下兼容适配,env.shWayland 下执行时会安装自研的键鼠操作服务(可能存在一些依赖报错,按照注释解决即可),框架核心库也针对性的做了适配,上层用例完全不用关心机器是Wayland 还是 X11,框架会根据执行时状态自动判断走不同的逻辑;

    简单讲就是,应用库只需要维护一套用例脚本即可。

    【用例兼容】

    因为 Wayland 下有些应用的界面显示和功能本身存在一些差异,用例层可能需要对这部分用例做逻辑判断,使用全局配置里面的常量进行逻辑编写即可:

    python
    from setting import conf
     
     # GlobalConfig.IS_WAYLAND 获取到当前的显示服务器(bool)
     # 应用库 Config 继承 GlobalConfig
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.lean.js"
    index d2465e85..b4942146 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.SxIWeBCE.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_Wayland\351\200\202\351\205\215.md.6ZbXmWyh.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as a,o as i,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"Wayland 适配","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/Wayland适配.md","filePath":"指南/特色功能/Wayland适配.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/Wayland适配.md"},l=n("",10),t=[l];function p(h,d,k,o,c,r){return i(),a("div",null,t)}const g=s(e,[["render",p]]);export{E as __pageData,g as default};
    +import{_ as s,c as a,o as i,U as n}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"Wayland 适配","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/Wayland适配.md","filePath":"指南/特色功能/Wayland适配.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/Wayland适配.md"},l=n("",10),t=[l];function p(h,d,k,o,c,r){return i(),a("div",null,t)}const g=s(e,[["render",p]]);export{E as __pageData,g as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.js"
    similarity index 98%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.js"
    index e72856eb..fd63a79a 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.js"
    @@ -1,4 +1,4 @@
    -import{_ as t,c as e,o as s,U as a}from"./chunks/framework.DIzwIJpr.js";const k=JSON.parse('{"title":"WebUI","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/WebUI.md","filePath":"指南/特色功能/WebUI.md","lastUpdated":1722828555000}'),i={name:"指南/特色功能/WebUI.md"},l=a(`

    WebUI

    YouQu 基于 Playwright 驱动浏览器实现 WebUI 自动化测试。

    市面上耳熟能详的可用于 Web UI 自动化测试工具:SeleniumCypressPuppeteerPlaywright

    咱们先初步排除掉一些明显不用的:

    • Cypress,只支持 JavaScript,而我们自动化人员大多使用 PythonJavaScript 不熟悉,排除。
    • Puppeteer,只支持谷歌浏览器,格局没打开,官方不支持 Python,排除。

    剩下 SeleniumPlaywright,我们从一些方面做对比:

    对比指标SeleniumPlaywright
    环境安装难度
    运行速度
    元素等待
    智能定位
    稳定性
    文档
    接口测试

    总结:

    Playwright 作为一个比较新的工具,在文档方便确实没有老牌的 Selenium 完善,特别是一些示例、方法的使用说明,都还不够好,甚至有些就没有说明,但基本的使用该有的都有。

    除了文档方面,Playwright 几乎在各方面碾压 Selenium,很明显 Playwright 以绝对优势获胜。

    实践方法

    参考章节 【Web UI 自动化测试】

    断言方法

    YouQu 框架统一提供断言语句,以保持统一的断言语句风格。

    python
    # src/webui.py
    +import{_ as t,c as e,o as s,U as a}from"./chunks/framework.DIzwIJpr.js";const k=JSON.parse('{"title":"WebUI","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/WebUI.md","filePath":"指南/特色功能/WebUI.md","lastUpdated":1722828751000}'),i={name:"指南/特色功能/WebUI.md"},l=a(`

    WebUI

    YouQu 基于 Playwright 驱动浏览器实现 WebUI 自动化测试。

    市面上耳熟能详的可用于 Web UI 自动化测试工具:SeleniumCypressPuppeteerPlaywright

    咱们先初步排除掉一些明显不用的:

    • Cypress,只支持 JavaScript,而我们自动化人员大多使用 PythonJavaScript 不熟悉,排除。
    • Puppeteer,只支持谷歌浏览器,格局没打开,官方不支持 Python,排除。

    剩下 SeleniumPlaywright,我们从一些方面做对比:

    对比指标SeleniumPlaywright
    环境安装难度
    运行速度
    元素等待
    智能定位
    稳定性
    文档
    接口测试

    总结:

    Playwright 作为一个比较新的工具,在文档方便确实没有老牌的 Selenium 完善,特别是一些示例、方法的使用说明,都还不够好,甚至有些就没有说明,但基本的使用该有的都有。

    除了文档方面,Playwright 几乎在各方面碾压 Selenium,很明显 Playwright 以绝对优势获胜。

    实践方法

    参考章节 【Web UI 自动化测试】

    断言方法

    YouQu 框架统一提供断言语句,以保持统一的断言语句风格。

    python
    # src/webui.py
     
     class WebAssert:
         
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.lean.js"
    similarity index 85%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.lean.js"
    index 8fbebf1f..3e5ffbda 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.BrN7FjYV.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_WebUI.md.CHSHkZOg.lean.js"
    @@ -1 +1 @@
    -import{_ as t,c as e,o as s,U as a}from"./chunks/framework.DIzwIJpr.js";const k=JSON.parse('{"title":"WebUI","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/WebUI.md","filePath":"指南/特色功能/WebUI.md","lastUpdated":1722828555000}'),i={name:"指南/特色功能/WebUI.md"},l=a("",15),n=[l];function d(r,o,c,p,h,y){return s(),e("div",null,n)}const E=t(i,[["render",d]]);export{k as __pageData,E as default};
    +import{_ as t,c as e,o as s,U as a}from"./chunks/framework.DIzwIJpr.js";const k=JSON.parse('{"title":"WebUI","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/WebUI.md","filePath":"指南/特色功能/WebUI.md","lastUpdated":1722828751000}'),i={name:"指南/特色功能/WebUI.md"},l=a("",15),n=[l];function d(r,o,c,p,h,y){return s(),e("div",null,n)}const E=t(i,[["render",d]]);export{k as __pageData,E as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.js"
    index c50eaf01..fa484595 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.js"
    @@ -1,4 +1,4 @@
    -import{_ as n,c as l,m as s,a as i,t,U as p,o as h}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"全自动日志——funnylog","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/全自动日志.md","filePath":"指南/特色功能/全自动日志.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/全自动日志.md"},k=p(`

    全自动日志——funnylog

    背景

    基于 YouQu 自动化测试框架操作方法封装写法,通常是这样的:类里面一个函数只包含一个操作或多次调用的一系列可合并的操作;

    传统的日志输出方式,需要在每个函数里面主动编写日志输出代码 ,例如:

    python
    class XXXWidget:
    +import{_ as n,c as l,m as s,a as i,t,U as p,o as h}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"全自动日志——funnylog","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/全自动日志.md","filePath":"指南/特色功能/全自动日志.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/全自动日志.md"},k=p(`

    全自动日志——funnylog

    背景

    基于 YouQu 自动化测试框架操作方法封装写法,通常是这样的:类里面一个函数只包含一个操作或多次调用的一系列可合并的操作;

    传统的日志输出方式,需要在每个函数里面主动编写日志输出代码 ,例如:

    python
    class XXXWidget:
         
         def click_xxx(self):
             """点击某个元素"""
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.lean.js"
    similarity index 94%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.lean.js"
    index aed602be..8e463f0e 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.CTmh7ANk.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.md.DTvi86m3.lean.js"
    @@ -1 +1 @@
    -import{_ as n,c as l,m as s,a as i,t,U as p,o as h}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"全自动日志——funnylog","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/全自动日志.md","filePath":"指南/特色功能/全自动日志.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/全自动日志.md"},k=p("",28),d=s("p",null,[i("没错,这就是我们参考"),s("code",null,"Django"),i(" 和 "),s("code",null,"jinja2"),i(" 的模板语法设计出的"),s("strong",null,"日志模板语法"),i(",使用方法很简单,"),s("strong",null,"用两对大括号把函数的参数括起来"),i(",这样在日志输出的时候就能把调用函数时参数的值输出出来。")],-1);function r(a,o,g,E,c,y){return h(),l("div",null,[k,s("p",null,[i("通过观察前面的例子,细心的同学可能还发现了一个小细节:函数功能说明中,两对大括号中的内容 "),s("code",null,t(a.elements),1),i(" 作为变量输出出来了;")]),d])}const C=n(e,[["render",r]]);export{u as __pageData,C as default};
    +import{_ as n,c as l,m as s,a as i,t,U as p,o as h}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"全自动日志——funnylog","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/全自动日志.md","filePath":"指南/特色功能/全自动日志.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/全自动日志.md"},k=p("",28),d=s("p",null,[i("没错,这就是我们参考"),s("code",null,"Django"),i(" 和 "),s("code",null,"jinja2"),i(" 的模板语法设计出的"),s("strong",null,"日志模板语法"),i(",使用方法很简单,"),s("strong",null,"用两对大括号把函数的参数括起来"),i(",这样在日志输出的时候就能把调用函数时参数的值输出出来。")],-1);function r(a,o,g,E,c,y){return h(),l("div",null,[k,s("p",null,[i("通过观察前面的例子,细心的同学可能还发现了一个小细节:函数功能说明中,两对大括号中的内容 "),s("code",null,t(a.elements),1),i(" 作为变量输出出来了;")]),d])}const C=n(e,[["render",r]]);export{u as __pageData,C as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.js"
    similarity index 97%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.js"
    index 8194c849..bf4bd754 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"失败录屏","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/失败录屏.md","filePath":"指南/特色功能/失败录屏.md","lastUpdated":1722828555000}'),n={name:"指南/特色功能/失败录屏.md"},p=e(`

    失败录屏

    录屏其实是一种视频形式的日志,因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因,因此用例的录屏能让我们看到用例在执行过程;

    【使用方法】

    globalconfig.ini 里面配置关注 2 个参数;

    ini
    ;失败用例重跑次数
    +import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"失败录屏","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/失败录屏.md","filePath":"指南/特色功能/失败录屏.md","lastUpdated":1722828751000}'),n={name:"指南/特色功能/失败录屏.md"},p=e(`

    失败录屏

    录屏其实是一种视频形式的日志,因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因,因此用例的录屏能让我们看到用例在执行过程;

    【使用方法】

    globalconfig.ini 里面配置关注 2 个参数;

    ini
    ;失败用例重跑次数
     RERUN = 1
     
     ;失败录屏从第几次开始录制视频。
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.lean.js"
    index b1a871a8..e782b8b1 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.Cacn-PJ6.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\345\244\261\350\264\245\345\275\225\345\261\217.md.DmEAhRmW.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"失败录屏","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/失败录屏.md","filePath":"指南/特色功能/失败录屏.md","lastUpdated":1722828555000}'),n={name:"指南/特色功能/失败录屏.md"},p=e("",10),t=[p];function l(o,c,d,h,_,r){return i(),a("div",null,t)}const A=s(n,[["render",l]]);export{E as __pageData,A as default};
    +import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const E=JSON.parse('{"title":"失败录屏","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/失败录屏.md","filePath":"指南/特色功能/失败录屏.md","lastUpdated":1722828751000}'),n={name:"指南/特色功能/失败录屏.md"},p=e("",10),t=[p];function l(o,c,d,h,_,r){return i(),a("div",null,t)}const A=s(n,[["render",l]]);export{E as __pageData,A as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.js"
    index 7b165a31..bce48024 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as p}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"PMS数据回填","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/数据回填.md","filePath":"指南/特色功能/数据回填.md","lastUpdated":1722828555000}'),n={name:"指南/特色功能/数据回填.md"},t=p(`

    PMS数据回填

    测试单关联的用例,自动化测试对应的去跑这些关联的用例,并且将执行的结果回填的测试用例的状态里面。

    本机执行时回填

    PMS 数据回填主要有三种方式:

    (1)异步回填

    在用例执行的过程中,采用异步的方式去进行数据回填,直白的讲就是,第二条用例开始跑的时候,通过子线程去做第一条用例的数据回填,如此循环,直到所有用例执行结束;

    这种方案的时间效率最高的,因为理论上用例的执行时间是大于数据回填的接口请求时间的,也就是说,当用例执行完之后,数据回填也完成了。

    【方法一】配置文件

    使用方法,在 globalconfig.ini 里面配置以下参数:(以下涉及到的参数配置都是在配置文件里面进行配置)

    ini
    PMS_USER = PMS账号
    +import{_ as s,c as i,o as a,U as p}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"PMS数据回填","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/数据回填.md","filePath":"指南/特色功能/数据回填.md","lastUpdated":1722828751000}'),n={name:"指南/特色功能/数据回填.md"},t=p(`

    PMS数据回填

    测试单关联的用例,自动化测试对应的去跑这些关联的用例,并且将执行的结果回填的测试用例的状态里面。

    本机执行时回填

    PMS 数据回填主要有三种方式:

    (1)异步回填

    在用例执行的过程中,采用异步的方式去进行数据回填,直白的讲就是,第二条用例开始跑的时候,通过子线程去做第一条用例的数据回填,如此循环,直到所有用例执行结束;

    这种方案的时间效率最高的,因为理论上用例的执行时间是大于数据回填的接口请求时间的,也就是说,当用例执行完之后,数据回填也完成了。

    【方法一】配置文件

    使用方法,在 globalconfig.ini 里面配置以下参数:(以下涉及到的参数配置都是在配置文件里面进行配置)

    ini
    PMS_USER = PMS账号
     PMS_PASSWORD = PMS密码
     SEND_PMS = async
     TASK_ID = 测试单ID
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.lean.js"
    index 50b8ef70..0946002c 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.CQ3MKS-E.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\225\260\346\215\256\345\233\236\345\241\253.md.oYvfIg_g.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as p}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"PMS数据回填","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/数据回填.md","filePath":"指南/特色功能/数据回填.md","lastUpdated":1722828555000}'),n={name:"指南/特色功能/数据回填.md"},t=p("",35),h=[t];function l(e,k,d,r,o,g){return a(),i("div",null,h)}const E=s(n,[["render",l]]);export{F as __pageData,E as default};
    +import{_ as s,c as i,o as a,U as p}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"PMS数据回填","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/数据回填.md","filePath":"指南/特色功能/数据回填.md","lastUpdated":1722828751000}'),n={name:"指南/特色功能/数据回填.md"},t=p("",35),h=[t];function l(e,k,d,r,o,g){return a(),i("div",null,h)}const E=s(n,[["render",l]]);export{F as __pageData,E as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.js"
    index ccf31b42..b154f03f 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"标签化管理","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签化管理.md","filePath":"指南/特色功能/标签化管理.md","lastUpdated":1722828555000}'),t={name:"指南/特色功能/标签化管理.md"},e=n(`

    标签化管理

    标签说明

    根据现有业务需要,用例需要添加的标签有:

    • 脚本 ID :自动化用例脚本/函数 ID
    • *PMS用例ID :PMS 上对应的用例 ID(用例库 ID)
    • 用例级别 :对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示
    • 用例类型 :FUNC(功能)、PERF(性能)、STR(压力)、SEC(安全)、CTS(兼容性)、API(接口)、BASELINE(基线-预留)
    • *设备类型 :PPL(依赖外设的用例)、COL(依赖主控机的用例)
    • 一二级bug自动化 :BUG(由 Bug 转的用例)
    • *上线对象 :CICD,表示上线到 CICD 流水线的用例
    • 跳过原因 :skip-XXX,用于控制用例是否执行
    • 确认修复 :fixed-XXX,用于标记用例的修复状态
    • 废弃用例 :removed-已废弃,用于标记已经废弃的用例,此用例标签不会被添加,也不会被执行

    示例:

    脚本ID*PMS用例ID用例级别用例类型*设备类型一二级bug自动化*上线对象跳过原因确认修复废弃用例...
    679537679537L1FUNCPPLBUGCICDskip-XXXfixed-XXXremoved-已废弃...

    操作步骤

    1. 在子项目目录下新建 csv 文件,用于保存用例标签,以 用例脚本的 py 文件去掉首字符串 "test_" ,去掉用例序号后的字符串,取中间的名称作为 csv 文件的文件名 。

      例如: 相册的用例文件为 test_album_xxx.py,xxx 表示用例的ID(也可以是自定义的数字代表用例序号),此时 csv 文件名就应为 album.csv

      对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,所有 csv 文件建议放在一个 tags 目录下。

      是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

    2. 第一列为脚本 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;用例标签可以无序。

    跳过用例

    传统跳过用例的方式是在用例脚本里面给用例添加装饰器(@pytest.mark.skip),解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多;

    将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;

    1. 固定跳过

    示例:

    脚本ID...(各种用例标签)跳过原因
    679537...skip-受到某新需求影响
    • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标签开头为 “skip-XXX”;
    • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标签,存在跳过标签则用例也不会被执行,最终的用例状态会被标签为 SKIPED

    2. 条件判断跳过

    示例:

    脚本ID...(各种用例标签)跳过原因
    001...skipif_platform-aarch64&mips64
    • 某些用例会因为不同的环境判断用例是否执行,常见的场景为在不同架构上判断是否执行,跳过的原因标签为 “skipif_platform-” 加架构名,多个架构之间使用 “&” 拼接;
    • 以上例子为用例执行时,判断当前架构是否为 arrch64 或者 mips64,若是,则跳过用例不执行,若否则执行用例;

    在项目目录路径下存在文件 setting/skipif.py,所有条件判断跳过的函数写在此文件中。

    python
    #!/usr/bin/env python3
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"标签化管理","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签化管理.md","filePath":"指南/特色功能/标签化管理.md","lastUpdated":1722828751000}'),t={name:"指南/特色功能/标签化管理.md"},e=n(`

    标签化管理

    标签说明

    根据现有业务需要,用例需要添加的标签有:

    • 脚本 ID :自动化用例脚本/函数 ID
    • *PMS用例ID :PMS 上对应的用例 ID(用例库 ID)
    • 用例级别 :对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示
    • 用例类型 :FUNC(功能)、PERF(性能)、STR(压力)、SEC(安全)、CTS(兼容性)、API(接口)、BASELINE(基线-预留)
    • *设备类型 :PPL(依赖外设的用例)、COL(依赖主控机的用例)
    • 一二级bug自动化 :BUG(由 Bug 转的用例)
    • *上线对象 :CICD,表示上线到 CICD 流水线的用例
    • 跳过原因 :skip-XXX,用于控制用例是否执行
    • 确认修复 :fixed-XXX,用于标记用例的修复状态
    • 废弃用例 :removed-已废弃,用于标记已经废弃的用例,此用例标签不会被添加,也不会被执行

    示例:

    脚本ID*PMS用例ID用例级别用例类型*设备类型一二级bug自动化*上线对象跳过原因确认修复废弃用例...
    679537679537L1FUNCPPLBUGCICDskip-XXXfixed-XXXremoved-已废弃...

    操作步骤

    1. 在子项目目录下新建 csv 文件,用于保存用例标签,以 用例脚本的 py 文件去掉首字符串 "test_" ,去掉用例序号后的字符串,取中间的名称作为 csv 文件的文件名 。

      例如: 相册的用例文件为 test_album_xxx.py,xxx 表示用例的ID(也可以是自定义的数字代表用例序号),此时 csv 文件名就应为 album.csv

      对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,所有 csv 文件建议放在一个 tags 目录下。

      是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

    2. 第一列为脚本 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;用例标签可以无序。

    跳过用例

    传统跳过用例的方式是在用例脚本里面给用例添加装饰器(@pytest.mark.skip),解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多;

    将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;

    1. 固定跳过

    示例:

    脚本ID...(各种用例标签)跳过原因
    679537...skip-受到某新需求影响
    • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标签开头为 “skip-XXX”;
    • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标签,存在跳过标签则用例也不会被执行,最终的用例状态会被标签为 SKIPED

    2. 条件判断跳过

    示例:

    脚本ID...(各种用例标签)跳过原因
    001...skipif_platform-aarch64&mips64
    • 某些用例会因为不同的环境判断用例是否执行,常见的场景为在不同架构上判断是否执行,跳过的原因标签为 “skipif_platform-” 加架构名,多个架构之间使用 “&” 拼接;
    • 以上例子为用例执行时,判断当前架构是否为 arrch64 或者 mips64,若是,则跳过用例不执行,若否则执行用例;

    在项目目录路径下存在文件 setting/skipif.py,所有条件判断跳过的函数写在此文件中。

    python
    #!/usr/bin/env python3
     # _*_ coding:utf-8 _*_
     # SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
     # SPDX-License-Identifier: GPL-2.0-only
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.lean.js"
    similarity index 86%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.lean.js"
    index ec03417f..3776413d 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.DWlTruxg.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.md.lI_bb-4N.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"标签化管理","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签化管理.md","filePath":"指南/特色功能/标签化管理.md","lastUpdated":1722828555000}'),t={name:"指南/特色功能/标签化管理.md"},e=n("",48),l=[e];function p(h,k,d,r,c,o){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default};
    +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"标签化管理","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签化管理.md","filePath":"指南/特色功能/标签化管理.md","lastUpdated":1722828751000}'),t={name:"指南/特色功能/标签化管理.md"},e=n("",48),l=[e];function p(h,k,d,r,c,o){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.js"
    similarity index 98%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.js"
    index 469dfd37..a3c982df 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.js"
    @@ -1,4 +1,4 @@
    -import{_ as s,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"导出CSV文件","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签导出.md","filePath":"指南/特色功能/标签导出.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/标签导出.md"},p=t(`

    导出CSV文件

    【使用方法一】

    框架提供导出指定标签用例的功能:

    shell
    youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD -ec case_list.csv

    表示导出 deepin-album 的用例中标记了 CICD 标签的用例,导出 CSV 文件的字段格式已经适配了 CICD 的要求。

    【使用方法二】

    也可以使用配置文件选项:

    ini
    ;导出的csv文件名称,比如:case_list.csv
    +import{_ as s,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"导出CSV文件","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签导出.md","filePath":"指南/特色功能/标签导出.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/标签导出.md"},p=t(`

    导出CSV文件

    【使用方法一】

    框架提供导出指定标签用例的功能:

    shell
    youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD -ec case_list.csv

    表示导出 deepin-album 的用例中标记了 CICD 标签的用例,导出 CSV 文件的字段格式已经适配了 CICD 的要求。

    【使用方法二】

    也可以使用配置文件选项:

    ini
    ;导出的csv文件名称,比如:case_list.csv
     EXPORT_CSV_FILE =

    命令行执行:

    shell
    youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD

    参数说明:

    ini
    -a 如果不给就是apps目录下所有的;
     -t 要导出用例的标签;
     case_list.csv 文件名称可以自定义,在report目录下会自动生成;
    `,13),n=[p];function l(h,d,c,k,o,r){return a(),i("div",null,n)}const F=s(e,[["render",l]]);export{C as __pageData,F as default}; diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.lean.js" similarity index 86% rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.lean.js" rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.lean.js" index 3a9895d6..92899844 100644 --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.rmeW3DeT.lean.js" +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\345\257\274\345\207\272.md.BKDYq-Ay.lean.js" @@ -1 +1 @@ -import{_ as s,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"导出CSV文件","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签导出.md","filePath":"指南/特色功能/标签导出.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/标签导出.md"},p=t("",13),n=[p];function l(h,d,c,k,o,r){return a(),i("div",null,n)}const F=s(e,[["render",l]]);export{C as __pageData,F as default}; +import{_ as s,c as i,o as a,U as t}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"导出CSV文件","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签导出.md","filePath":"指南/特色功能/标签导出.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/标签导出.md"},p=t("",13),n=[p];function l(h,d,c,k,o,r){return a(),i("div",null,n)}const F=s(e,[["render",l]]);export{C as __pageData,F as default}; diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.js" similarity index 99% rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.js" rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.js" index 8665455d..5ebebae5 100644 --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.js" +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.js" @@ -1,4 +1,4 @@ -import{_ as s,c as i,o as a,U as e}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"标签自动同步","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签自动同步.md","filePath":"指南/特色功能/标签自动同步.md","lastUpdated":1722828555000}'),p={name:"指南/特色功能/标签自动同步.md"},n=e(`

    标签自动同步

    自动同步脚本 ID 到 CSV 文件

    支持自动同步脚本 ID(用例 py 文件的 ID)到 CSV 文件;

    【使用方法一】

    配置文件方式,通过一下几个配置来控制:

    ini
    [csvctl]
    +import{_ as s,c as i,o as a,U as e}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"标签自动同步","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签自动同步.md","filePath":"指南/特色功能/标签自动同步.md","lastUpdated":1722828751000}'),p={name:"指南/特色功能/标签自动同步.md"},n=e(`

    标签自动同步

    自动同步脚本 ID 到 CSV 文件

    支持自动同步脚本 ID(用例 py 文件的 ID)到 CSV 文件;

    【使用方法一】

    配置文件方式,通过一下几个配置来控制:

    ini
    [csvctl]
     ;将py文件的case id同步到csv文件
     ;yes, 开启同步
     ;no, 关闭同步
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.lean.js"
    similarity index 87%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.lean.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.lean.js"
    index 8fd6b977..195b1d97 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.B7luhQFj.lean.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.md.DuruozvS.lean.js"
    @@ -1 +1 @@
    -import{_ as s,c as i,o as a,U as e}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"标签自动同步","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签自动同步.md","filePath":"指南/特色功能/标签自动同步.md","lastUpdated":1722828555000}'),p={name:"指南/特色功能/标签自动同步.md"},n=e("",28),t=[n];function l(h,c,d,o,k,r){return a(),i("div",null,t)}const u=s(p,[["render",l]]);export{y as __pageData,u as default};
    +import{_ as s,c as i,o as a,U as e}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"标签自动同步","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/标签自动同步.md","filePath":"指南/特色功能/标签自动同步.md","lastUpdated":1722828751000}'),p={name:"指南/特色功能/标签自动同步.md"},n=e("",28),t=[n];function l(h,c,d,o,k,r){return a(),i("div",null,t)}const u=s(p,[["render",l]]);export{y as __pageData,u as default};
    diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.js"
    similarity index 99%
    rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.js"
    rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.js"
    index 3eb583fd..6fe3f258 100644
    --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.js"
    +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.js"
    @@ -1,4 +1,4 @@
    -import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/rdog.png",p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/remote_complete.gif",m=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/远程交互式控制.md","filePath":"指南/特色功能/远程交互式控制.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/远程交互式控制.md"},h=t('

    远程交互式控制

    在用例执行过程中控制远程机器执行复杂的 UI 操作或命令行操作。

    在远程测试机上部署一个完整的 YouQu 环境以提供 UI 交互的基础能力,然后将这些基础能力通过 RPC 服务的方式提供出来,在服务端通过调用 RPC 接口从而控制远程机器执行用例步骤。

    slaves对象提供远程机器信息

    slaves 是 YouQu 提供的一个全局对象,它保存了远程测试机的信息列表;

    机器信息有 2 种方式传入:

    • 命令行

      shell
      youqu manage.py run --slaves root@192.168.1.1:password1

      多个机器信息用 / 分割:root@192.168.1.1:password1/root@192.168.1.2:password2

    • 配置文件

      setting/globalconfig.ini 里面:

      ini
      ;=============================== SLAVE CONFIG ===================================
      +import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/rdog.png",p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/remote_complete.gif",m=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/远程交互式控制.md","filePath":"指南/特色功能/远程交互式控制.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/远程交互式控制.md"},h=t('

      远程交互式控制

      在用例执行过程中控制远程机器执行复杂的 UI 操作或命令行操作。

      在远程测试机上部署一个完整的 YouQu 环境以提供 UI 交互的基础能力,然后将这些基础能力通过 RPC 服务的方式提供出来,在服务端通过调用 RPC 接口从而控制远程机器执行用例步骤。

      slaves对象提供远程机器信息

      slaves 是 YouQu 提供的一个全局对象,它保存了远程测试机的信息列表;

      机器信息有 2 种方式传入:

      • 命令行

        shell
        youqu manage.py run --slaves root@192.168.1.1:password1

        多个机器信息用 / 分割:root@192.168.1.1:password1/root@192.168.1.2:password2

      • 配置文件

        setting/globalconfig.ini 里面:

        ini
        ;=============================== SLAVE CONFIG ===================================
         ;附属的测试机,用例步骤中与其他机器进行交互
         ;        ┌─ slave \${user}@\${ip}:\${password}
         ; master ┼─ slave mikigo@192.168.8.11:admin123
        diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.lean.js"
        similarity index 91%
        rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.lean.js"
        rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.lean.js"
        index 5b774cc0..11457d8e 100644
        --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.DDAD1-63.lean.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.md.BKsVD6-h.lean.js"
        @@ -1 +1 @@
        -import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/rdog.png",p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/remote_complete.gif",m=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/远程交互式控制.md","filePath":"指南/特色功能/远程交互式控制.md","lastUpdated":1722828555000}'),e={name:"指南/特色功能/远程交互式控制.md"},h=t("",33),k=[h];function r(d,E,o,g,c,y){return n(),a("div",null,k)}const _=i(e,[["render",r]]);export{m as __pageData,_ as default};
        +import{_ as s}from"./chunks/remote_control.DQQd2WAg.js";import{_ as i,c as a,o as n,U as t}from"./chunks/framework.DIzwIJpr.js";const l="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/rdog.png",p="/youqu/%E5%AE%9E%E8%B7%B5/%E6%A1%8C%E9%9D%A2UI%E8%87%AA%E5%8A%A8%E5%8C%96/remote_complete.gif",m=JSON.parse('{"title":"远程交互式控制","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/远程交互式控制.md","filePath":"指南/特色功能/远程交互式控制.md","lastUpdated":1722828751000}'),e={name:"指南/特色功能/远程交互式控制.md"},h=t("",33),k=[h];function r(d,E,o,g,c,y){return n(),a("div",null,k)}const _=i(e,[["render",r]]);export{m as __pageData,_ as default};
        diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.js"
        similarity index 99%
        rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.js"
        rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.js"
        index f1c5b83b..2e43abf6 100644
        --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.js"
        @@ -1,4 +1,4 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"重启类场景","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/重启类场景.md","filePath":"指南/特色功能/重启类场景.md","lastUpdated":1722828555000}'),t={name:"指南/特色功能/重启类场景.md"},e=n(`

        重启类场景

        对于重启类场景的用例需要解决的核心问题是,重启之后如何让用例能继续重启前的步骤继续执行,YouQu 集成了自研的 letmego 技术方案;

        详细技术方案、实现细节、Demo可以看 letmego 官方在线文档;

        使用方法

        使用方法很简单,只需要给应用方法层的唯一出口类加一个装饰器(@letmego.mark)即可:

        python
        import letmego
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"重启类场景","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/重启类场景.md","filePath":"指南/特色功能/重启类场景.md","lastUpdated":1722828751000}'),t={name:"指南/特色功能/重启类场景.md"},e=n(`

        重启类场景

        对于重启类场景的用例需要解决的核心问题是,重启之后如何让用例能继续重启前的步骤继续执行,YouQu 集成了自研的 letmego 技术方案;

        详细技术方案、实现细节、Demo可以看 letmego 官方在线文档;

        使用方法

        使用方法很简单,只需要给应用方法层的唯一出口类加一个装饰器(@letmego.mark)即可:

        python
        import letmego
         
         @letmego.mark
         class DeepinMusicWidget(WindowWidget, TitleWidget, PopWidget):
        diff --git "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.lean.js" "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.lean.js"
        similarity index 86%
        rename from "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.lean.js"
        rename to "assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.lean.js"
        index e1c90459..c5b863a5 100644
        --- "a/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.12pN6UD1.lean.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\211\271\350\211\262\345\212\237\350\203\275_\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.md.CuJzqqgq.lean.js"
        @@ -1 +1 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"重启类场景","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/重启类场景.md","filePath":"指南/特色功能/重启类场景.md","lastUpdated":1722828555000}'),t={name:"指南/特色功能/重启类场景.md"},e=n("",18),l=[e];function p(h,k,d,r,o,c){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default};
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"重启类场景","description":"","frontmatter":{},"headers":[],"relativePath":"指南/特色功能/重启类场景.md","filePath":"指南/特色功能/重启类场景.md","lastUpdated":1722828751000}'),t={name:"指南/特色功能/重启类场景.md"},e=n("",18),l=[e];function p(h,k,d,r,o,c){return a(),i("div",null,l)}const y=s(t,[["render",p]]);export{g as __pageData,y as default};
        diff --git "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.js" "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.js"
        similarity index 99%
        rename from "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.js"
        rename to "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.js"
        index 8cb94f5f..1c76f2e5 100644
        --- "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.js"
        @@ -1,4 +1,4 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const D=JSON.parse('{"title":"全局配置 - setting.conf","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/全局配置.md","filePath":"指南/环境/全局配置.md","lastUpdated":1722828555000}'),p={name:"指南/环境/全局配置.md"},l=n(`

        全局配置 - setting.conf

        配置文件

        全局配置模块 setting 包含了以下配置文件:

        (1)ini 配置文件

        主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

        (2)py 配置文件

        主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

        一些支持人工修改或自定义的配置项都在 ini 配置文件里面,py 文件是不需要人工去修改的;

        配置对象获取

        导入全局配置对象

        py
        from setting import conf

        通过 conf 对象能获取到所有可获取的配置项的值,比如:

        py
        conf.PASSWORD

        这样可以获取到 globalconfig.ini 配置文件中 PASSWORD 配置的值。

        除了上面这种导入方式,还可以这样导入:

        py
        from setting.globalconfig import GlobalConfig

        GlobalConfig 也是全局配置对象,实际上 confGlobalConfig 的别名,你可以根据自己喜欢选择用哪个;

        APP工程配置对象

        所有应用库配置对象都是继承框架的全局配置类的:

        python
        from setting.globalconfig import _GlobalConfig
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const D=JSON.parse('{"title":"全局配置 - setting.conf","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/全局配置.md","filePath":"指南/环境/全局配置.md","lastUpdated":1722828751000}'),p={name:"指南/环境/全局配置.md"},l=n(`

        全局配置 - setting.conf

        配置文件

        全局配置模块 setting 包含了以下配置文件:

        (1)ini 配置文件

        主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

        (2)py 配置文件

        主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

        一些支持人工修改或自定义的配置项都在 ini 配置文件里面,py 文件是不需要人工去修改的;

        配置对象获取

        导入全局配置对象

        py
        from setting import conf

        通过 conf 对象能获取到所有可获取的配置项的值,比如:

        py
        conf.PASSWORD

        这样可以获取到 globalconfig.ini 配置文件中 PASSWORD 配置的值。

        除了上面这种导入方式,还可以这样导入:

        py
        from setting.globalconfig import GlobalConfig

        GlobalConfig 也是全局配置对象,实际上 confGlobalConfig 的别名,你可以根据自己喜欢选择用哪个;

        APP工程配置对象

        所有应用库配置对象都是继承框架的全局配置类的:

        python
        from setting.globalconfig import _GlobalConfig
         
         class _Config(_GlobalConfig):
             pass
        diff --git "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.lean.js" "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.lean.js"
        similarity index 86%
        rename from "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.lean.js"
        rename to "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.lean.js"
        index a47532d0..b7928cdb 100644
        --- "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.D7iWqOwm.lean.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\345\205\250\345\261\200\351\205\215\347\275\256.md.C4BtOvZP.lean.js"
        @@ -1 +1 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const D=JSON.parse('{"title":"全局配置 - setting.conf","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/全局配置.md","filePath":"指南/环境/全局配置.md","lastUpdated":1722828555000}'),p={name:"指南/环境/全局配置.md"},l=n("",24),h=[l];function k(e,t,A,c,d,r){return a(),i("div",null,h)}const g=s(p,[["render",k]]);export{D as __pageData,g as default};
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const D=JSON.parse('{"title":"全局配置 - setting.conf","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/全局配置.md","filePath":"指南/环境/全局配置.md","lastUpdated":1722828751000}'),p={name:"指南/环境/全局配置.md"},l=n("",24),h=[l];function k(e,t,A,c,d,r){return a(),i("div",null,h)}const g=s(p,[["render",k]]);export{D as __pageData,g as default};
        diff --git "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.js" "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.js"
        similarity index 99%
        rename from "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.js"
        rename to "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.js"
        index b586d239..3900f072 100644
        --- "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.js"
        @@ -1,4 +1,4 @@
        -import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"环境部署 - env.sh","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/环境部署.md","filePath":"指南/环境/环境部署.md","lastUpdated":1722828555000}'),t={name:"指南/环境/环境部署.md"},l=e(`

        环境部署 - env.sh

        安装

        项目根目录下运行 env.sh 即可。

        shell
        $ bash env.sh

        密码问题

        使用的默认密码是 1

        您可以使用 -p 选项传入密码:bash env.sh -p \${my_password}

        也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

        定制依赖

        1. 新增依赖

        如果应用库还需要其他 Python 依赖库,只需要在应用库根目录下保存一个 requirement.txt 文件;

        shell
        autotest_xxx
        +import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"环境部署 - env.sh","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/环境部署.md","filePath":"指南/环境/环境部署.md","lastUpdated":1722828751000}'),t={name:"指南/环境/环境部署.md"},l=e(`

        环境部署 - env.sh

        安装

        项目根目录下运行 env.sh 即可。

        shell
        $ bash env.sh

        密码问题

        使用的默认密码是 1

        您可以使用 -p 选项传入密码:bash env.sh -p \${my_password}

        也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

        定制依赖

        1. 新增依赖

        如果应用库还需要其他 Python 依赖库,只需要在应用库根目录下保存一个 requirement.txt 文件;

        shell
        autotest_xxx
         ├── requirement.txt
         ├── case	
         ...

        里面写入需要安装的三方依赖,比如像这样:

        shell
        PyYAML==6.0  # 指定安装某个版本
        diff --git "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.lean.js" "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.lean.js"
        similarity index 86%
        rename from "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.lean.js"
        rename to "assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.lean.js"
        index 7910b92e..e3a56c51 100644
        --- "a/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.BKazqIKb.lean.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\216\257\345\242\203_\347\216\257\345\242\203\351\203\250\347\275\262.md.CsGL0y3b.lean.js"
        @@ -1 +1 @@
        -import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"环境部署 - env.sh","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/环境部署.md","filePath":"指南/环境/环境部署.md","lastUpdated":1722828555000}'),t={name:"指南/环境/环境部署.md"},l=e("",49),n=[l];function p(h,d,o,c,r,k){return i(),a("div",null,n)}const b=s(t,[["render",p]]);export{u as __pageData,b as default};
        +import{_ as s,c as a,o as i,U as e}from"./chunks/framework.DIzwIJpr.js";const u=JSON.parse('{"title":"环境部署 - env.sh","description":"","frontmatter":{},"headers":[],"relativePath":"指南/环境/环境部署.md","filePath":"指南/环境/环境部署.md","lastUpdated":1722828751000}'),t={name:"指南/环境/环境部署.md"},l=e("",49),n=[l];function p(h,d,o,c,r,k){return i(),a("div",null,n)}const b=s(t,[["render",p]]);export{u as __pageData,b as default};
        diff --git "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.js" "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.js"
        similarity index 99%
        rename from "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.js"
        rename to "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.js"
        index 9a6710a0..3fa6a30f 100644
        --- "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.js"
        @@ -1 +1 @@
        -import{_ as e,c as t,o as a,U as i}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"YouQu 是什么?","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/YouQu是什么.md","filePath":"指南/简介/YouQu是什么.md","lastUpdated":1722828555000}'),l={name:"指南/简介/YouQu是什么.md"},r=i('
        Flag

        众所周知,操作系统领域长期被国外占领,恰逢国产操作系统百年一遇之大变局,我辈正站在一个新的历史起点上,不再只是跟随者,而要成为引领者。

        自动化测试框架,是提升国产操作系统质量的关键一环,这不仅是一项技术的革新,更是一次精神的磨砺。我们要以坚定的决心,攻克一个又一个难题,让我们的操作系统在稳定性和易用性上,达到世界顶尖水平。

        YouQu 是什么?

        YouQu(有趣)是统信公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。🔥

        YouQu 能做什么?

        ☑ 💻 Linux 桌面应用 UI 自动化测试

        ☑ 🌏 Web UI 自动化测试

        ☑ 🚌 Linux DBus 接口自动化测试

        ☑ 🚀 命令行自动化测试

        ☑ 🕷️ HTTP 接口自动化测试

        爱上 YouQu 的 N 个理由

        • 无处不在的代码补全

          让编写自动化测试用例成为一种享受。

        • 提供统一的接口

          编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;

        • 多种元素定位方案

          除了常用的属性定位、图像识别、OCR识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你。

        • 用例标签化管理

          提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情。

        • 功能强大的执行管理器

          让你可以方便的在本地执行、远程执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想。

        • 远程交互式控制

          用例步骤过程中控制远程机器。

        • 自动输出日志

          你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》。

        • 一键部署环境

          让你再也不用为环境部署而烦恼。

        • 自动生成多种报告

          你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能。

        • 自定义断言

          对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效。

        • 用例超时控制

          不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行。

        • 软硬件兼容

          完美兼容 WaylandX11 显示协议,硬件兼容 x86_64aarch64loongarch64sw64,真正做到一套代码,随处执行。

        开源许可证

        YouQu 在 GPL-2.0 下发布。

        ',13),o=[r];function d(n,b,c,p,u,k){return a(),t("div",null,o)}const f=e(l,[["render",d]]);export{g as __pageData,f as default}; +import{_ as e,c as t,o as a,U as i}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"YouQu 是什么?","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/YouQu是什么.md","filePath":"指南/简介/YouQu是什么.md","lastUpdated":1722828751000}'),l={name:"指南/简介/YouQu是什么.md"},r=i('
        Flag

        众所周知,操作系统领域长期被国外占领,恰逢国产操作系统百年一遇之大变局,我辈正站在一个新的历史起点上,不再只是跟随者,而要成为引领者。

        自动化测试框架,是提升国产操作系统质量的关键一环,这不仅是一项技术的革新,更是一次精神的磨砺。我们要以坚定的决心,攻克一个又一个难题,让我们的操作系统在稳定性和易用性上,达到世界顶尖水平。

        YouQu 是什么?

        YouQu(有趣)是统信公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。🔥

        YouQu 能做什么?

        ☑ 💻 Linux 桌面应用 UI 自动化测试

        ☑ 🌏 Web UI 自动化测试

        ☑ 🚌 Linux DBus 接口自动化测试

        ☑ 🚀 命令行自动化测试

        ☑ 🕷️ HTTP 接口自动化测试

        爱上 YouQu 的 N 个理由

        • 无处不在的代码补全

          让编写自动化测试用例成为一种享受。

        • 提供统一的接口

          编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;

        • 多种元素定位方案

          除了常用的属性定位、图像识别、OCR识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你。

        • 用例标签化管理

          提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情。

        • 功能强大的执行管理器

          让你可以方便的在本地执行、远程执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想。

        • 远程交互式控制

          用例步骤过程中控制远程机器。

        • 自动输出日志

          你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》。

        • 一键部署环境

          让你再也不用为环境部署而烦恼。

        • 自动生成多种报告

          你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能。

        • 自定义断言

          对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效。

        • 用例超时控制

          不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行。

        • 软硬件兼容

          完美兼容 WaylandX11 显示协议,硬件兼容 x86_64aarch64loongarch64sw64,真正做到一套代码,随处执行。

        开源许可证

        YouQu 在 GPL-2.0 下发布。

        ',13),o=[r];function d(n,b,c,p,u,k){return a(),t("div",null,o)}const f=e(l,[["render",d]]);export{g as __pageData,f as default}; diff --git "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.lean.js" "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.lean.js" similarity index 86% rename from "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.lean.js" rename to "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.lean.js" index 3d82a5c1..79d15c19 100644 --- "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.CH30t2w9.lean.js" +++ "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_YouQu\346\230\257\344\273\200\344\271\210.md.BDSnfo1D.lean.js" @@ -1 +1 @@ -import{_ as e,c as t,o as a,U as i}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"YouQu 是什么?","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/YouQu是什么.md","filePath":"指南/简介/YouQu是什么.md","lastUpdated":1722828555000}'),l={name:"指南/简介/YouQu是什么.md"},r=i("",13),o=[r];function d(n,b,c,p,u,k){return a(),t("div",null,o)}const f=e(l,[["render",d]]);export{g as __pageData,f as default}; +import{_ as e,c as t,o as a,U as i}from"./chunks/framework.DIzwIJpr.js";const g=JSON.parse('{"title":"YouQu 是什么?","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/YouQu是什么.md","filePath":"指南/简介/YouQu是什么.md","lastUpdated":1722828751000}'),l={name:"指南/简介/YouQu是什么.md"},r=i("",13),o=[r];function d(n,b,c,p,u,k){return a(),t("div",null,o)}const f=e(l,[["render",d]]);export{g as __pageData,f as default}; diff --git "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.js" "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.js" similarity index 99% rename from "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.js" rename to "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.js" index db9c3c6c..bb36dd48 100644 --- "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.js" +++ "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.js" @@ -1,4 +1,4 @@ -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i,c as a,o as n,U as h}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"快速开始","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/快速开始.md","filePath":"指南/简介/快速开始.md","lastUpdated":1722828555000}'),p={name:"指南/简介/快速开始.md"},l=h('

        快速开始

        安装

        从 PyPI 安装:

        shell
        $ sudo pip3 install youqu
        不加 sudo ?

        不加 sudo 也可以:

        shell
        pip3 install youqu

        但可能出现 youqu-startproject 命令无法使用;

        这是因为不加 sudo 时,youqu-startproject 命令会生成在 $HOME/.local/bin 下,

        而此路径可能不在环境变量(PATH)中,因此您需要添加环境变量:

        shell
        export PATH=$PATH:$HOME/.local/bin

        创建项目

        您可以在任意目录下,使用 youqu-startproject 命令创建一个项目:

        shell
        $ youqu-startproject my_project

        注意

        不要以 root 用户执行命令!

        如果 youqu-startproject 后面不加参数,默认的项目名称为:youqu

        安装依赖

        进入项目根目录:

        shell
        $ cd my_project

        安装部署 YouQu 执行所需环境:

        shell
        $ bash env.sh
        shell
        $ bash env.sh -D
        密码问题

        使用的默认密码是 1

        您可以使用 -p 选项传入密码:bash env.sh -p \${my_password}

        也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

        创建 APP 工程

        使用 startapp 命令自动创建 APP 工程:

        shell
        $ youqu manage.py startapp autotest_deepin_some

        APP 工程名称命名规范

        APP 工程名称需要符合 Python 文件命名规范(字母、数字、下划线)。

        自动创建的 APP 工程遵循完整的 PO 设计模式,让你可以专注于用例和方法的编写维护。

        这样在 apps 目录下会创建一个子项目工程: autotest_deepin_some,同时新建好工程模板目录和模板文件:

        shell
        my_project
        +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i,c as a,o as n,U as h}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"快速开始","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/快速开始.md","filePath":"指南/简介/快速开始.md","lastUpdated":1722828751000}'),p={name:"指南/简介/快速开始.md"},l=h('

        快速开始

        安装

        从 PyPI 安装:

        shell
        $ sudo pip3 install youqu
        不加 sudo ?

        不加 sudo 也可以:

        shell
        pip3 install youqu

        但可能出现 youqu-startproject 命令无法使用;

        这是因为不加 sudo 时,youqu-startproject 命令会生成在 $HOME/.local/bin 下,

        而此路径可能不在环境变量(PATH)中,因此您需要添加环境变量:

        shell
        export PATH=$PATH:$HOME/.local/bin

        创建项目

        您可以在任意目录下,使用 youqu-startproject 命令创建一个项目:

        shell
        $ youqu-startproject my_project

        注意

        不要以 root 用户执行命令!

        如果 youqu-startproject 后面不加参数,默认的项目名称为:youqu

        安装依赖

        进入项目根目录:

        shell
        $ cd my_project

        安装部署 YouQu 执行所需环境:

        shell
        $ bash env.sh
        shell
        $ bash env.sh -D
        密码问题

        使用的默认密码是 1

        您可以使用 -p 选项传入密码:bash env.sh -p \${my_password}

        也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

        创建 APP 工程

        使用 startapp 命令自动创建 APP 工程:

        shell
        $ youqu manage.py startapp autotest_deepin_some

        APP 工程名称命名规范

        APP 工程名称需要符合 Python 文件命名规范(字母、数字、下划线)。

        自动创建的 APP 工程遵循完整的 PO 设计模式,让你可以专注于用例和方法的编写维护。

        这样在 apps 目录下会创建一个子项目工程: autotest_deepin_some,同时新建好工程模板目录和模板文件:

        shell
        my_project
         ├── apps
            ├── autotest_deepin_some  # <----- APP工程
         .   .   ├── case  # 用例目录
        diff --git "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.lean.js" "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.lean.js"
        similarity index 87%
        rename from "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.lean.js"
        rename to "assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.lean.js"
        index ed7eb154..8a5593dc 100644
        --- "a/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.QrZkL8xq.lean.js"
        +++ "b/assets/\346\214\207\345\215\227_\347\256\200\344\273\213_\345\277\253\351\200\237\345\274\200\345\247\213.md.VpRzDue3.lean.js"
        @@ -1 +1 @@
        -import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i,c as a,o as n,U as h}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"快速开始","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/快速开始.md","filePath":"指南/简介/快速开始.md","lastUpdated":1722828555000}'),p={name:"指南/简介/快速开始.md"},l=h("",71),t=[l];function k(e,F,d,r,g,y){return n(),a("div",null,t)}const E=i(p,[["render",k]]);export{C as __pageData,E as default};
        +import{_ as s}from"./chunks/install.DYY69KT3.js";import{_ as i,c as a,o as n,U as h}from"./chunks/framework.DIzwIJpr.js";const C=JSON.parse('{"title":"快速开始","description":"","frontmatter":{},"headers":[],"relativePath":"指南/简介/快速开始.md","filePath":"指南/简介/快速开始.md","lastUpdated":1722828751000}'),p={name:"指南/简介/快速开始.md"},l=h("",71),t=[l];function k(e,F,d,r,g,y){return n(),a("div",null,t)}const E=i(p,[["render",k]]);export{C as __pageData,E as default};
        diff --git "a/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.js" "b/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.js"
        similarity index 97%
        rename from "assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.js"
        rename to "assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.js"
        index b8caf178..c37eab33 100644
        --- "a/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.js"
        +++ "b/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.js"
        @@ -1 +1 @@
        -import{_ as a,c as e,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"未来规划","description":"","frontmatter":{},"headers":[],"relativePath":"规划/未来规划.md","filePath":"规划/未来规划.md","lastUpdated":1722828555000}'),i={name:"规划/未来规划.md"},r=l('

        未来规划

        💡 桌面应用性能自动化测试

        需优化解决的性能自动化问题

        1、环境问题,测试人员在本地编写代码,环境不好搭建,框架只提供 Docker 环境部署,适合在生产环境运行,但是对测试人员本地编写代码安装环境很不友好,因为代码编辑器调试代码只能通过入口文件执行,不能在编辑器中直接执行单个用例脚本;

        2、在 Docker 里面执行,代码报错看不到报错信息,不好定位问题;

        3、强制依赖串口线,不插串口线,环境也无法部署,给想要尝试或者愿意尝试的人员造成了一些困扰,还依赖较多设备(服务端-测试机),一些团队并不能找到那么多机器;

        4、那些好不容易尝试用起来的人员,使用一段时间后会痛恨 1 和 2 的问题,让他们觉得难度有点大,团队中普遍人员代码能力不强,尝试人员都觉得难搞,其他人员也就可想而知;

        方案

        性能自动化支持以下功能

        1、因地制宜(手上有什么设备就用什么方案)

        【低配版】只有一台机器

        • 本机执行方案;

        • 本机执行,本机同步解析;

        • 本机执行,外部机器异步解析;

        【中配版】有两台机器,有网络,但是没有串口线

        • 服务端-客户端,通过远程网络连接控制。

        【高配版】有两台机器,并且有串口线,有没有网络无所谓

        • 服务端-客户端,通过串口线连接控制。

        【顶配版】高配 + 继电器

        • 最完美的方案。

        2、环境安装、代码调试环境、执行环境要对编码人员更加友好;

        ',19),o=[r];function p(_,n,s,c,d,h){return t(),e("div",null,o)}const f=a(i,[["render",p]]);export{m as __pageData,f as default}; +import{_ as a,c as e,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"未来规划","description":"","frontmatter":{},"headers":[],"relativePath":"规划/未来规划.md","filePath":"规划/未来规划.md","lastUpdated":1722828751000}'),i={name:"规划/未来规划.md"},r=l('

        未来规划

        💡 桌面应用性能自动化测试

        需优化解决的性能自动化问题

        1、环境问题,测试人员在本地编写代码,环境不好搭建,框架只提供 Docker 环境部署,适合在生产环境运行,但是对测试人员本地编写代码安装环境很不友好,因为代码编辑器调试代码只能通过入口文件执行,不能在编辑器中直接执行单个用例脚本;

        2、在 Docker 里面执行,代码报错看不到报错信息,不好定位问题;

        3、强制依赖串口线,不插串口线,环境也无法部署,给想要尝试或者愿意尝试的人员造成了一些困扰,还依赖较多设备(服务端-测试机),一些团队并不能找到那么多机器;

        4、那些好不容易尝试用起来的人员,使用一段时间后会痛恨 1 和 2 的问题,让他们觉得难度有点大,团队中普遍人员代码能力不强,尝试人员都觉得难搞,其他人员也就可想而知;

        方案

        性能自动化支持以下功能

        1、因地制宜(手上有什么设备就用什么方案)

        【低配版】只有一台机器

        • 本机执行方案;

        • 本机执行,本机同步解析;

        • 本机执行,外部机器异步解析;

        【中配版】有两台机器,有网络,但是没有串口线

        • 服务端-客户端,通过远程网络连接控制。

        【高配版】有两台机器,并且有串口线,有没有网络无所谓

        • 服务端-客户端,通过串口线连接控制。

        【顶配版】高配 + 继电器

        • 最完美的方案。

        2、环境安装、代码调试环境、执行环境要对编码人员更加友好;

        ',19),o=[r];function p(_,n,s,c,d,h){return t(),e("div",null,o)}const f=a(i,[["render",p]]);export{m as __pageData,f as default}; diff --git "a/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.lean.js" "b/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.lean.js" similarity index 85% rename from "assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.lean.js" rename to "assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.lean.js" index 112147e2..27610096 100644 --- "a/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.DtiEED4P.lean.js" +++ "b/assets/\350\247\204\345\210\222_\346\234\252\346\235\245\350\247\204\345\210\222.md.CbFrL51H.lean.js" @@ -1 +1 @@ -import{_ as a,c as e,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"未来规划","description":"","frontmatter":{},"headers":[],"relativePath":"规划/未来规划.md","filePath":"规划/未来规划.md","lastUpdated":1722828555000}'),i={name:"规划/未来规划.md"},r=l("",19),o=[r];function p(_,n,s,c,d,h){return t(),e("div",null,o)}const f=a(i,[["render",p]]);export{m as __pageData,f as default}; +import{_ as a,c as e,o as t,U as l}from"./chunks/framework.DIzwIJpr.js";const m=JSON.parse('{"title":"未来规划","description":"","frontmatter":{},"headers":[],"relativePath":"规划/未来规划.md","filePath":"规划/未来规划.md","lastUpdated":1722828751000}'),i={name:"规划/未来规划.md"},r=l("",19),o=[r];function p(_,n,s,c,d,h){return t(),e("div",null,o)}const f=a(i,[["render",p]]);export{m as __pageData,f as default}; diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.js" similarity index 99% rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.js" rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.js" index eac3b43a..4474f3f1 100644 --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.js" +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.js" @@ -1,4 +1,4 @@ -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"AT 基础框架设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT基础框架设计方案.md","filePath":"规划/框架设计/AT基础框架设计方案.md","lastUpdated":1722828555000}'),h={name:"规划/框架设计/AT基础框架设计方案.md"},p=n(`

        AT 基础框架设计方案

        一、目标

        做一个简单、好用、功能强大的自动化测试框架。

        • 作为自动化测试的一个基础框架,任何应用都能很方便的接入进来;
        • 提供所有自动化测试所需要的底层功能,并对外提供唯一的接口,方便应用库使用;
        • 整合公共库,减少应用库代码量和方法维护。

        二、设计方案

        1、统一概念

        • 基础框架

          本项目是一个自动化测试的基础框架(AutoTest Basic Frame),全称为“自动化测试基础框架(AT 基础框架)”。

          AT 基础框架是做为一个自动化测试的基础框架来设计的,它提供了自动化测试所要用的基础功能,任何应用接入进来都能快速方便的进行方法和用例编写,同时在用例标签化管理、批量跳过、标签化执行、分布式执行、多种报告输出、优美的执行日志、失败自动录屏和截图、自动环境清理等等,它都提供了完善的解决方案,更重要的是这一切使用起来都非常简单。

          基础框架中包含应用库(apps)、核心库(src)、公共方法库(public)。

        • 应用库(apps

          各个应用自己的仓库,里面主要包含的是用例、方法及一些测试资源,比如文件管理器叫 autotest_dde_file_manager

        • 核心库(src

          核心库自动化测试所要用的到所有底层核心功能,这是最重要的一个部分,灵魂。具体功能模块及说明会在下面第四个章节详细描述。

        • 公共方法库(public

          多个应用都要用到的一些操作方法,按照应用划分存放,主要是为了减少代码量,消除应用间的耦合关系。

        2、架构图

        整体的框架设计在《自动化测试架构设计》文档里面已经有详细描述了,这里贴一下整体的架构图:

        架构图

        为了突显本文的重点,抽取其中重要功能模块,如下图:

        核心模块

        3、目录结构

        shell
        youqu  # 自动化测试基础框架
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"AT 基础框架设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT基础框架设计方案.md","filePath":"规划/框架设计/AT基础框架设计方案.md","lastUpdated":1722828751000}'),h={name:"规划/框架设计/AT基础框架设计方案.md"},p=n(`

        AT 基础框架设计方案

        一、目标

        做一个简单、好用、功能强大的自动化测试框架。

        • 作为自动化测试的一个基础框架,任何应用都能很方便的接入进来;
        • 提供所有自动化测试所需要的底层功能,并对外提供唯一的接口,方便应用库使用;
        • 整合公共库,减少应用库代码量和方法维护。

        二、设计方案

        1、统一概念

        • 基础框架

          本项目是一个自动化测试的基础框架(AutoTest Basic Frame),全称为“自动化测试基础框架(AT 基础框架)”。

          AT 基础框架是做为一个自动化测试的基础框架来设计的,它提供了自动化测试所要用的基础功能,任何应用接入进来都能快速方便的进行方法和用例编写,同时在用例标签化管理、批量跳过、标签化执行、分布式执行、多种报告输出、优美的执行日志、失败自动录屏和截图、自动环境清理等等,它都提供了完善的解决方案,更重要的是这一切使用起来都非常简单。

          基础框架中包含应用库(apps)、核心库(src)、公共方法库(public)。

        • 应用库(apps

          各个应用自己的仓库,里面主要包含的是用例、方法及一些测试资源,比如文件管理器叫 autotest_dde_file_manager

        • 核心库(src

          核心库自动化测试所要用的到所有底层核心功能,这是最重要的一个部分,灵魂。具体功能模块及说明会在下面第四个章节详细描述。

        • 公共方法库(public

          多个应用都要用到的一些操作方法,按照应用划分存放,主要是为了减少代码量,消除应用间的耦合关系。

        2、架构图

        整体的框架设计在《自动化测试架构设计》文档里面已经有详细描述了,这里贴一下整体的架构图:

        架构图

        为了突显本文的重点,抽取其中重要功能模块,如下图:

        核心模块

        3、目录结构

        shell
        youqu  # 自动化测试基础框架
         ├── apps  # 应用库
         │   ├── autotest_dde_file_manager  # 单独的应用仓库(应用库详细目录结构请看应用库设计方案)
         │   │   ├── case  # 用例
        diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.lean.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.lean.js"
        similarity index 88%
        rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.lean.js"
        rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.lean.js"
        index a348a549..3b029ac7 100644
        --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dg54uPBM.lean.js"
        +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.md.Dkc6fJ0S.lean.js"
        @@ -1 +1 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"AT 基础框架设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT基础框架设计方案.md","filePath":"规划/框架设计/AT基础框架设计方案.md","lastUpdated":1722828555000}'),h={name:"规划/框架设计/AT基础框架设计方案.md"},p=n("",42),k=[p];function l(t,e,F,d,r,g){return a(),i("div",null,k)}const c=s(h,[["render",l]]);export{y as __pageData,c as default};
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const y=JSON.parse('{"title":"AT 基础框架设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT基础框架设计方案.md","filePath":"规划/框架设计/AT基础框架设计方案.md","lastUpdated":1722828751000}'),h={name:"规划/框架设计/AT基础框架设计方案.md"},p=n("",42),k=[p];function l(t,e,F,d,r,g){return a(),i("div",null,k)}const c=s(h,[["render",l]]);export{y as __pageData,c as default};
        diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.js"
        similarity index 99%
        rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.js"
        rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.js"
        index e75a4eec..23bc4d7f 100644
        --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.js"
        +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.js"
        @@ -1,4 +1,4 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"AT 应用库设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT应用库设计方案.md","filePath":"规划/框架设计/AT应用库设计方案.md","lastUpdated":1722828555000}'),h={name:"规划/框架设计/AT应用库设计方案.md"},l=n(`

        AT 应用库设计方案

        一、目标

        AT 应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计,以实现应用库高效的编写、维护用例及其方法。

        二、方案设计

        文件管理器从业务复杂度和用例量来讲,在系统所有应用中,是很有代表性的,难度也是最大的,因此我们选取文件管理器作为应用库改造的实验应用,给后续其他应用改造提供切实可行的思路和方案。

        1、分层设计图

        整体仍然遵循 PO 设计理念,根据业务需要,将文管业务层进行 3 层划分:

        应用库架构图(文件管理器)

        2、目录结构

        shell
        autotest_dde_file_manager  # 应用仓库
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"AT 应用库设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT应用库设计方案.md","filePath":"规划/框架设计/AT应用库设计方案.md","lastUpdated":1722828751000}'),h={name:"规划/框架设计/AT应用库设计方案.md"},l=n(`

        AT 应用库设计方案

        一、目标

        AT 应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计,以实现应用库高效的编写、维护用例及其方法。

        二、方案设计

        文件管理器从业务复杂度和用例量来讲,在系统所有应用中,是很有代表性的,难度也是最大的,因此我们选取文件管理器作为应用库改造的实验应用,给后续其他应用改造提供切实可行的思路和方案。

        1、分层设计图

        整体仍然遵循 PO 设计理念,根据业务需要,将文管业务层进行 3 层划分:

        应用库架构图(文件管理器)

        2、目录结构

        shell
        autotest_dde_file_manager  # 应用仓库
         ├── case  # 用例
         │   ├── assert_res  # 断言的图片资源目录
         │   ├── test_xxx_001.py
        diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.lean.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.lean.js"
        similarity index 88%
        rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.lean.js"
        rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.lean.js"
        index bc38c517..6a8470fb 100644
        --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.Bk8-xKu1.lean.js"
        +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.md.DZ_Y8UE1.lean.js"
        @@ -1 +1 @@
        -import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"AT 应用库设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT应用库设计方案.md","filePath":"规划/框架设计/AT应用库设计方案.md","lastUpdated":1722828555000}'),h={name:"规划/框架设计/AT应用库设计方案.md"},l=n("",51),p=[l];function t(k,e,d,r,g,E){return a(),i("div",null,p)}const F=s(h,[["render",t]]);export{c as __pageData,F as default};
        +import{_ as s,c as i,o as a,U as n}from"./chunks/framework.DIzwIJpr.js";const c=JSON.parse('{"title":"AT 应用库设计方案","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/AT应用库设计方案.md","filePath":"规划/框架设计/AT应用库设计方案.md","lastUpdated":1722828751000}'),h={name:"规划/框架设计/AT应用库设计方案.md"},l=n("",51),p=[l];function t(k,e,d,r,g,E){return a(),i("div",null,p)}const F=s(h,[["render",t]]);export{c as __pageData,F as default};
        diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.js"
        similarity index 99%
        rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.js"
        rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.js"
        index 688e908f..2a1d6c12 100644
        --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.js"
        +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.js"
        @@ -1,4 +1,4 @@
        -import{_ as i,c as t,o as s,U as e}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"自动化测试架构设计规划","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/自动化测试架构设计v1.0.md","filePath":"规划/框架设计/自动化测试架构设计v1.0.md","lastUpdated":1722828555000}'),l={name:"规划/框架设计/自动化测试架构设计v1.0.md"},a=e(`

        自动化测试架构设计规划

        • 目标:
          • 应用 AT 架构工程化,参考性能自动化工程完成工程化改造。
          • 应用间用例解耦,解除所有交叉调用的方法,各应用能跟随自身迭代周期独立维护 AT 用例。
          • 完成公共方法的抽取整合,形成一套独立于应用间的公共方法库,各应用方法里面不存在被多个应用调用的情况。
          • 用例实现标签化管理,为将来适配更多的 AT 运用场景提供支撑,原则上可实现无限扩展,在每日构建和持续集成流程落地使用。
          • 代码规范问题清零,符合 Shell CheckPylint、系统部相关编码规范要求。
        • 意义:
          • 统一成研 AT 架构设计思路,消除 AT 代码实现和维护上可能出现的分歧,改善历史 AT 无工程化设计的缺陷,提高架构专业性。
          • 各应用 AT 代码相互独立,契合应用独立发布特性,可支持迭代期间独立新增、维护和执行。
          • 方法调用逻辑得到简化,编写和维护更高效;公共库抽取,减少方法重复编写,提高代码利用率;平均编写一条用例从 40 分钟降低至 30 分钟,日产出用例从 12 条/天提升至 16 条/天。
          • 可灵活支撑不同的自动化运用场景,如 CI、冒烟测试、集成测试、回归测试、专项测试等。

        一、背景介绍

        提示

        这里介绍以前的AT框架情况以及存在的一些问题;

        1、原有架构介绍

        原AT框架架构图

        原有自动化测试架构整体分为三层:用例层(业务逻辑层)、中间层(元素定位和操作方法层)、核心层(底层功能库层)。

        • 用例层:即应用的用例,专注于业务功能逻辑,不关心元素的定位和操作;
        • 中间层:元素的定位和操作方法层,每个方法均对应一个元素的一个具体操作,也可以是多个操作的组合操作,中间层主要服务于用例层,具有可扩展性和复用性;
        • 核心层:主要封装的底层功能实现,此层在框架中提供一些通用的接口能力,功能模块相对独立,核心层主要服务于操作层,比如:通过图像识别的元素定位模块、通过 UI 坐标的元素定位模块、通过属性定位的元素定位模块、键鼠操作的基础方操作模块、Dbus 接口操作模块、文件的增删改查操作模块等。

        2、自动化的应用

        • CI 流程

          • 每日构建流水线:是对研发每日提交的代码进行测试,AT 的大致流程:每日下班之后会将各应用进行打包,然后在测试机上安装更新 deb 包,最后进行自动化测试。

          • 持续集成流水线:是对应用提交集成的版本进行测试,AT 的大致流程:每日下载最新的 ISO 进行 PXE 部署,然后测试机安装最新的镜像,最后进行自动化测试。

        • 验收测试

          • 在各验收节点进行自动化验收,目前的策略是全用例覆盖全架构。
        • 回归测试

          • 回归测试今年规划建设中,旨在回归测试时执行自动化测试用例,减少功能测试的重复劳动力。

        3、存在的问题

        • 各应用之间存在耦合

          在自动化测试项目初期,所有应用是整体发布,我们是将所有应用看成是一个整体,各应用作为其中的一个模块,所以存在应用间方法交叉调用的问题,这样从最初的设计来讲确实能够减少重复代码的编写。

          但是,现在应用走独立发布,各应用都有自己的迭代节奏,在新需求快速变化的过程中,自动化维护变得异常困难,原因就是自动化项目里面各个应用的有比较多的耦合关系,因此我们需要进行解耦,以适应应用不同的迭代周期。

        • 无法精准的划分用例范围

          用例执行的范围不够精准,目前自动化用例执行时,主要通过用例的关键词 core(核心)来区分用例是否为核心用例,但是这样的区分太宽泛了,不能适应自动化测试在多场景下的应用。很多场景下我们还需要根据用例的等级、用例的类型、用例来源等等,不同的维度来挑选要执行的用例。在用例脚本中添加关键字需要人工一条条的改,费时费力,而且不好维护。

        • 受新需求影响跳过的用例不好维护

          目前需要跳过的用例都需要在对应的用例脚本里面,添加跳过用例的代码,后续解除跳过的时候又需要找到这条脚本,删掉跳过用例的代码。在跳过用例较多的情况下,维护起来有难度。

        • 编写用例时逻辑比较复杂,需要调用多个应用的方法模块。

        • 框架扩展性不足,无法整合性能自动化、压测自动化、安全自动化等专项测试。

        二、方案设计

        为解决以上问题,适应不断丰富的测试场景,更好的发挥自动化测试的作用,需要对自动化架构及各功能模块进行重新设计规划。

        1、架构设计

        现AT框架架构图

        2、设计思路

        框架的运行逻辑:

        通过核心层提供一个基础能力,业务层根据实际业务需求(测试用例)动态加载核心层,执行入口加载相应的用例集并控制执行,应用层根据实际测试需求,通过相应的配置项进行配置,从而触发自动化测试任务。

        • 核心层:

          基本保持不变,部分模块会涉及到新功能开发,核心层各功能模块保持独立性,提供通用的接口能力,供上层调用;底层核心模块包括:

          • 图像识别模块
          • UI 定位模块
          • Dbus 接口操作模块
          • 属性定位模块
          • 日志模块
          • 键鼠操作模块
          • 文件操作模块
          • 录屏模块
          • 自定义断言模块
          • 用例执行模块
          • PXE 装机模块
          • 键鼠信号模拟模块
          • OCR 模块
        • 业务层:

          以应用为维度划分,应用内包含多个测试类型,如功能测试、性能测试、漏洞扫描等,后续可以根据需要嫁接进来。其中功能测试设计思路:

          • 以应用为维度划分,并将测试数据和测试资源整合进来,增加用例标签 csv 文件,用于给每条用例打标签。

            各标签所使用对应的字段名称,使用 csv 文件维护用例与标签的对应关系,对用例实现标签化管理,可以组合其中的标签而从驱动对应的自动化用例执行,兼容现有用例标签,且支持用例标签可扩展;

            为什么使用csv格式

            使用 csv 格式文件可以方便的使用 Excel 表格打开进行编辑,同时由于 csv 文件实际是以都好分隔的文本文件,代码中可以在不依赖三方库的情况下方便快速的解析它,可操作性和可维护性较高。

          • 各个应用之间,用例、方法、标签和资源都是相互独立的,编写和维护用例时只需要自己应用下的方法和公共库即可。

          • 结构举例:

            shell
            .
            +import{_ as i,c as t,o as s,U as e}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"自动化测试架构设计规划","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/自动化测试架构设计v1.0.md","filePath":"规划/框架设计/自动化测试架构设计v1.0.md","lastUpdated":1722828751000}'),l={name:"规划/框架设计/自动化测试架构设计v1.0.md"},a=e(`

            自动化测试架构设计规划

            • 目标:
              • 应用 AT 架构工程化,参考性能自动化工程完成工程化改造。
              • 应用间用例解耦,解除所有交叉调用的方法,各应用能跟随自身迭代周期独立维护 AT 用例。
              • 完成公共方法的抽取整合,形成一套独立于应用间的公共方法库,各应用方法里面不存在被多个应用调用的情况。
              • 用例实现标签化管理,为将来适配更多的 AT 运用场景提供支撑,原则上可实现无限扩展,在每日构建和持续集成流程落地使用。
              • 代码规范问题清零,符合 Shell CheckPylint、系统部相关编码规范要求。
            • 意义:
              • 统一成研 AT 架构设计思路,消除 AT 代码实现和维护上可能出现的分歧,改善历史 AT 无工程化设计的缺陷,提高架构专业性。
              • 各应用 AT 代码相互独立,契合应用独立发布特性,可支持迭代期间独立新增、维护和执行。
              • 方法调用逻辑得到简化,编写和维护更高效;公共库抽取,减少方法重复编写,提高代码利用率;平均编写一条用例从 40 分钟降低至 30 分钟,日产出用例从 12 条/天提升至 16 条/天。
              • 可灵活支撑不同的自动化运用场景,如 CI、冒烟测试、集成测试、回归测试、专项测试等。

            一、背景介绍

            提示

            这里介绍以前的AT框架情况以及存在的一些问题;

            1、原有架构介绍

            原AT框架架构图

            原有自动化测试架构整体分为三层:用例层(业务逻辑层)、中间层(元素定位和操作方法层)、核心层(底层功能库层)。

            • 用例层:即应用的用例,专注于业务功能逻辑,不关心元素的定位和操作;
            • 中间层:元素的定位和操作方法层,每个方法均对应一个元素的一个具体操作,也可以是多个操作的组合操作,中间层主要服务于用例层,具有可扩展性和复用性;
            • 核心层:主要封装的底层功能实现,此层在框架中提供一些通用的接口能力,功能模块相对独立,核心层主要服务于操作层,比如:通过图像识别的元素定位模块、通过 UI 坐标的元素定位模块、通过属性定位的元素定位模块、键鼠操作的基础方操作模块、Dbus 接口操作模块、文件的增删改查操作模块等。

            2、自动化的应用

            • CI 流程

              • 每日构建流水线:是对研发每日提交的代码进行测试,AT 的大致流程:每日下班之后会将各应用进行打包,然后在测试机上安装更新 deb 包,最后进行自动化测试。

              • 持续集成流水线:是对应用提交集成的版本进行测试,AT 的大致流程:每日下载最新的 ISO 进行 PXE 部署,然后测试机安装最新的镜像,最后进行自动化测试。

            • 验收测试

              • 在各验收节点进行自动化验收,目前的策略是全用例覆盖全架构。
            • 回归测试

              • 回归测试今年规划建设中,旨在回归测试时执行自动化测试用例,减少功能测试的重复劳动力。

            3、存在的问题

            • 各应用之间存在耦合

              在自动化测试项目初期,所有应用是整体发布,我们是将所有应用看成是一个整体,各应用作为其中的一个模块,所以存在应用间方法交叉调用的问题,这样从最初的设计来讲确实能够减少重复代码的编写。

              但是,现在应用走独立发布,各应用都有自己的迭代节奏,在新需求快速变化的过程中,自动化维护变得异常困难,原因就是自动化项目里面各个应用的有比较多的耦合关系,因此我们需要进行解耦,以适应应用不同的迭代周期。

            • 无法精准的划分用例范围

              用例执行的范围不够精准,目前自动化用例执行时,主要通过用例的关键词 core(核心)来区分用例是否为核心用例,但是这样的区分太宽泛了,不能适应自动化测试在多场景下的应用。很多场景下我们还需要根据用例的等级、用例的类型、用例来源等等,不同的维度来挑选要执行的用例。在用例脚本中添加关键字需要人工一条条的改,费时费力,而且不好维护。

            • 受新需求影响跳过的用例不好维护

              目前需要跳过的用例都需要在对应的用例脚本里面,添加跳过用例的代码,后续解除跳过的时候又需要找到这条脚本,删掉跳过用例的代码。在跳过用例较多的情况下,维护起来有难度。

            • 编写用例时逻辑比较复杂,需要调用多个应用的方法模块。

            • 框架扩展性不足,无法整合性能自动化、压测自动化、安全自动化等专项测试。

            二、方案设计

            为解决以上问题,适应不断丰富的测试场景,更好的发挥自动化测试的作用,需要对自动化架构及各功能模块进行重新设计规划。

            1、架构设计

            现AT框架架构图

            2、设计思路

            框架的运行逻辑:

            通过核心层提供一个基础能力,业务层根据实际业务需求(测试用例)动态加载核心层,执行入口加载相应的用例集并控制执行,应用层根据实际测试需求,通过相应的配置项进行配置,从而触发自动化测试任务。

            • 核心层:

              基本保持不变,部分模块会涉及到新功能开发,核心层各功能模块保持独立性,提供通用的接口能力,供上层调用;底层核心模块包括:

              • 图像识别模块
              • UI 定位模块
              • Dbus 接口操作模块
              • 属性定位模块
              • 日志模块
              • 键鼠操作模块
              • 文件操作模块
              • 录屏模块
              • 自定义断言模块
              • 用例执行模块
              • PXE 装机模块
              • 键鼠信号模拟模块
              • OCR 模块
            • 业务层:

              以应用为维度划分,应用内包含多个测试类型,如功能测试、性能测试、漏洞扫描等,后续可以根据需要嫁接进来。其中功能测试设计思路:

              • 以应用为维度划分,并将测试数据和测试资源整合进来,增加用例标签 csv 文件,用于给每条用例打标签。

                各标签所使用对应的字段名称,使用 csv 文件维护用例与标签的对应关系,对用例实现标签化管理,可以组合其中的标签而从驱动对应的自动化用例执行,兼容现有用例标签,且支持用例标签可扩展;

                为什么使用csv格式

                使用 csv 格式文件可以方便的使用 Excel 表格打开进行编辑,同时由于 csv 文件实际是以都好分隔的文本文件,代码中可以在不依赖三方库的情况下方便快速的解析它,可操作性和可维护性较高。

              • 各个应用之间,用例、方法、标签和资源都是相互独立的,编写和维护用例时只需要自己应用下的方法和公共库即可。

              • 结构举例:

                shell
                .
                 ├── apps
                    ├── deepin_album  # 应用名 (用下划线连接是 Python 编码规范)
                    ├── album_assert  # 断言库
                diff --git "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.lean.js" "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.lean.js"
                similarity index 88%
                rename from "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.lean.js"
                rename to "assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.lean.js"
                index 74066eb6..1133d0fe 100644
                --- "a/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.DNMXnlWg.lean.js"
                +++ "b/assets/\350\247\204\345\210\222_\346\241\206\346\236\266\350\256\276\350\256\241_\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.md.CFdw_Jh4.lean.js"
                @@ -1 +1 @@
                -import{_ as i,c as t,o as s,U as e}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"自动化测试架构设计规划","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/自动化测试架构设计v1.0.md","filePath":"规划/框架设计/自动化测试架构设计v1.0.md","lastUpdated":1722828555000}'),l={name:"规划/框架设计/自动化测试架构设计v1.0.md"},a=e("",63),n=[a];function p(d,h,c,k,o,r){return s(),t("div",null,n)}const y=i(l,[["render",p]]);export{F as __pageData,y as default};
                +import{_ as i,c as t,o as s,U as e}from"./chunks/framework.DIzwIJpr.js";const F=JSON.parse('{"title":"自动化测试架构设计规划","description":"","frontmatter":{"Author":"mikigo"},"headers":[],"relativePath":"规划/框架设计/自动化测试架构设计v1.0.md","filePath":"规划/框架设计/自动化测试架构设计v1.0.md","lastUpdated":1722828751000}'),l={name:"规划/框架设计/自动化测试架构设计v1.0.md"},a=e("",63),n=[a];function p(d,h,c,k,o,r){return s(),t("div",null,n)}const y=i(l,[["render",p]]);export{F as __pageData,y as default};
                diff --git a/hashmap.json b/hashmap.json
                index 804ca4c8..edb8663b 100644
                --- a/hashmap.json
                +++ b/hashmap.json
                @@ -1 +1 @@
                -{"contributing.md":"BE80_gXx","实践_dbus接口自动化测试_创建一条完整的用例.md":"C9weuXoI","index.md":"B0Rvt6-g","实践_http接口自动化测试_初始化项目.md":"DLJQT1pe","实践_命令行自动化测试_创建一条完整的用例.md":"Db9d6q36","指南_元素定位_ocr识别.md":"DK2R5D7p","实践_http接口自动化测试_创建一条完整的用例.md":"CILkfzMi","实践_dbus接口自动化测试_初始化项目.md":"Cq1ADuHE","实践_webui自动化测试_初始化项目.md":"BwYOOjva","实践_http接口自动化测试_创建app工程.md":"DYG_9u9K","实践_webui自动化测试_创建一条完整的用例.md":"DNwaUUy6","实践_linux桌面ui自动化测试_创建一条完整的用例.md":"39VpWliZ","实践_linux桌面ui自动化测试_远程交互式控制.md":"C8b2k9nJ","实践_命令行自动化测试_初始化项目.md":"DmoXx_zB","sig.md":"Bh8YEa0v","实践_命令行自动化测试_创建app工程.md":"CSmxxJk8","实践_webui自动化测试_创建app工程.md":"Dbz5gpGS","实践_linux桌面ui自动化测试_创建app工程.md":"DMVy6riC","指南_框架必备_测试报告.md":"BTX0dRwU","指南_元素定位_图像识别.md":"cYhyqO_w","实践_dbus接口自动化测试_创建app工程.md":"4O34DUFa","指南_框架必备_执行管理器.md":"C6nNtXOh","release.md":"DEam-HSA","指南_元素定位_去干扰识别.md":"BIpooK_Y","指南_元素定位_属性定位.md":"BhtbdZ6I","指南_框架必备_ruff代码检查.md":"yrpKeZ2W","实践_linux桌面ui自动化测试_初始化项目.md":"fO_mX3bv","指南_元素定位_相对坐标定位.md":"o2JL1JQc","指南_环境_环境部署.md":"BKazqIKb","规划_框架设计_at应用库设计方案.md":"Bk8-xKu1","指南_框架必备_断言.md":"B3p9qKhI","指南_特色功能_标签自动同步.md":"B7luhQFj","指南_简介_youqu是什么.md":"CH30t2w9","指南_特色功能_重启类场景.md":"12pN6UD1","规划_未来规划.md":"DtiEED4P","指南_特色功能_wayland适配.md":"SxIWeBCE","指南_特色功能_失败录屏.md":"Cacn-PJ6","规划_框架设计_自动化测试架构设计v1.0.md":"DNMXnlWg","指南_特色功能_标签化管理.md":"DWlTruxg","指南_特色功能_远程交互式控制.md":"DDAD1-63","指南_特色功能_全自动日志.md":"CTmh7ANk","指南_简介_快速开始.md":"QrZkL8xq","规划_框架设计_at基础框架设计方案.md":"Dg54uPBM","指南_特色功能_webui.md":"BrN7FjYV","指南_框架必备_键鼠操作.md":"ES7BlKM1","指南_特色功能_标签导出.md":"rmeW3DeT","指南_特色功能_数据回填.md":"CQ3MKS-E","指南_环境_全局配置.md":"D7iWqOwm"}
                +{"指南_元素定位_图像识别.md":"DNFlkZ4K","指南_框架必备_测试报告.md":"C0M3WFUQ","规划_框架设计_at基础框架设计方案.md":"Dkc6fJ0S","规划_未来规划.md":"CbFrL51H","规划_框架设计_自动化测试架构设计v1.0.md":"CFdw_Jh4","实践_http接口自动化测试_创建app工程.md":"BB2SseQ7","实践_http接口自动化测试_初始化项目.md":"DvTxsOBd","实践_linux桌面ui自动化测试_创建一条完整的用例.md":"Dvhe2fAz","实践_dbus接口自动化测试_创建app工程.md":"hrjrbfya","指南_框架必备_执行管理器.md":"CJ6rimlS","实践_dbus接口自动化测试_创建一条完整的用例.md":"PZ_9GVPL","指南_框架必备_ruff代码检查.md":"CJKmN6E7","实践_命令行自动化测试_创建一条完整的用例.md":"BJNQoDlt","实践_webui自动化测试_创建app工程.md":"DwmtmtLf","实践_webui自动化测试_初始化项目.md":"C-wa8EP9","实践_linux桌面ui自动化测试_初始化项目.md":"CZrjCFH_","指南_特色功能_全自动日志.md":"DTvi86m3","指南_特色功能_webui.md":"CHSHkZOg","指南_特色功能_失败录屏.md":"DmEAhRmW","指南_元素定位_ocr识别.md":"CXrPXR6J","指南_特色功能_远程交互式控制.md":"BKsVD6-h","指南_特色功能_wayland适配.md":"6ZbXmWyh","指南_元素定位_去干扰识别.md":"DiZ2-d5A","实践_dbus接口自动化测试_初始化项目.md":"Qn54NA5E","指南_特色功能_标签化管理.md":"lI_bb-4N","实践_linux桌面ui自动化测试_远程交互式控制.md":"BItb9rzf","指南_特色功能_数据回填.md":"oYvfIg_g","规划_框架设计_at应用库设计方案.md":"DZ_Y8UE1","实践_linux桌面ui自动化测试_创建app工程.md":"fMT7s3Dw","contributing.md":"HEIFCxPI","实践_命令行自动化测试_初始化项目.md":"CFJCMo4S","指南_特色功能_标签自动同步.md":"DuruozvS","指南_元素定位_属性定位.md":"BsFtkb-s","指南_特色功能_标签导出.md":"BKDYq-Ay","指南_特色功能_重启类场景.md":"CuJzqqgq","实践_http接口自动化测试_创建一条完整的用例.md":"BJXSzHsE","实践_命令行自动化测试_创建app工程.md":"CD7HnebK","指南_环境_全局配置.md":"C4BtOvZP","实践_webui自动化测试_创建一条完整的用例.md":"BkBUwUkc","sig.md":"DLmEvgGN","release.md":"DRw-SwT2","index.md":"DItuxErn","指南_简介_youqu是什么.md":"BDSnfo1D","指南_框架必备_键鼠操作.md":"CrfCBGgm","指南_元素定位_相对坐标定位.md":"mSzYAd7F","指南_环境_环境部署.md":"CsGL0y3b","指南_简介_快速开始.md":"VpRzDue3","指南_框架必备_断言.md":"ZVbSVmrj"}
                diff --git a/index.html b/index.html
                index 08a697de..c6c53bd2 100644
                --- a/index.html
                +++ b/index.html
                @@ -8,20 +8,20 @@
                     
                     
                     
                -    
                +    
                     
                     
                -    
                -    
                -    
                +    
                +    
                +    
                     
                     
                     
                     
                   
                   
                -    
                Skip to content
                - +
                Skip to content
                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" index 967df876..bd1fdf5b 100644 --- "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" +++ "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case  # 用例目录
                @@ -49,8 +49,8 @@
                 │   │       ├── other_widget.py   # 其他方法类
                 │   │       ├── pic_res  # 图像识别方法所需要的资源
                 │   │       │   └── readme
                -│   │       └── ui.ini  # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                - +│   │   └── ui.ini # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" index 8f4c52d0..8b132ef3 100644 --- "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" +++ "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                判断操作系统的激活状态为激活

                封装用例步骤的方法

                所有的方法都在 widget 目录下;

                方法基类 base_widget.py::BaseWidget 里面定义接口对象。

                python
                # base_widget.py
                +    
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                判断操作系统的激活状态为激活

                封装用例步骤的方法

                所有的方法都在 widget 目录下;

                方法基类 base_widget.py::BaseWidget 里面定义接口对象。

                python
                # base_widget.py
                 
                 from src.dbus_utils import DbusUtils
                 
                @@ -61,8 +61,8 @@
                         
                         widget = DbusWidget()
                         authorization_state = widget.get_authorization_state()
                -        self.assert_equal(authorization_state, 1)

                这样就完成了一个简单的 DBus 用例编写。

                - + self.assert_equal(authorization_state, 1)

                这样就完成了一个简单的 DBus 用例编写。

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" index 52e1b70d..c8fac00a 100644 --- "a/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" +++ "b/\345\256\236\350\267\265/DBus\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                Linux DBus 接口自动化测试

                DBus 是一个为应用程序间通信的消息总线系统,对操作系统的接口测试通常指的是对 DBus 接口的测试。

                YouQu 提供了对 DBus 接口操作的模块:DbusUtils

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                Linux DBus 接口自动化测试

                DBus 是一个为应用程序间通信的消息总线系统,对操作系统的接口测试通常指的是对 DBus 接口的测试。

                YouQu 提供了对 DBus 接口操作的模块:DbusUtils

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                 ├── apps  # 用于放置APP工程
                 ├── conftest.py  # Pytest 插件库
                 ├── CURRENT      # 记录YouQu当前的版本
                @@ -35,8 +35,8 @@
                 bash env.sh
                 # 使用的默认密码是 1;
                 # 您可以使用 -p 选项传入密码:bash env.sh -p ${my_password};
                -# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                - +# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" index 0386c52c..31a25d86 100644 --- "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" +++ "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" @@ -8,20 +8,20 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case  # 用例目录
                @@ -71,8 +71,8 @@
                 │   │       │   └── readme
                 │   │       ├── __init__.py
                 │   │       └── my_app_api.py  # 方法唯一出口类

                再次执行 env.sh

                shell
                cd my_project
                -bash env.sh
                - +bash env.sh
                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" index 2f97ec23..bba32973 100644 --- "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" +++ "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                以域管服务端平台创建子管理员为例

                封装用例步骤的方法

                所有的方法都在 api 目录下;

                方法基类 _base_api.py::BaseAPI 里面定义登陆接口,获取管理员登陆 WEB 平台 cookietoken 信息。

                python
                # _base_api.py
                +    
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                以域管服务端平台创建子管理员为例

                封装用例步骤的方法

                所有的方法都在 api 目录下;

                方法基类 _base_api.py::BaseAPI 里面定义登陆接口,获取管理员登陆 WEB 平台 cookietoken 信息。

                python
                # _base_api.py
                 
                 from apps.autotest_udcp.config import config
                 from urllib3.exceptions import InsecureRequestWarning
                @@ -165,8 +165,8 @@
                         )
                 
                     def teardown_method(self):
                -        self.api.delete_admin_by_admin_api([self.name])

                这样就完成了一个简单的 HTTP 用例编写。

                - + self.api.delete_admin_by_admin_api([self.name])

                这样就完成了一个简单的 HTTP 用例编写。

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" index 27944fc2..9581eaeb 100644 --- "a/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" +++ "b/\345\256\236\350\267\265/HTTP\346\216\245\345\217\243\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                HTTP 接口自动化测试

                HTTP 接口自动化测试是一个传统测试类型,只要有接口请求能力就能做,YouQu 自带网络接口模块 requestx ,它基于标准库 urllib 封装,能满足对大部分的网络接口处理的需求。

                YouQu 框架的很多网络相关功能都是基于此模块实现,但大多数同学喜欢用三方模块 requests 做网络接口,因为用法上更加简洁。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                HTTP 接口自动化测试

                HTTP 接口自动化测试是一个传统测试类型,只要有接口请求能力就能做,YouQu 自带网络接口模块 requestx ,它基于标准库 urllib 封装,能满足对大部分的网络接口处理的需求。

                YouQu 框架的很多网络相关功能都是基于此模块实现,但大多数同学喜欢用三方模块 requests 做网络接口,因为用法上更加简洁。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                 ├── apps  # 用于放置APP工程
                 ├── conftest.py  # Pytest 插件库
                 ├── CURRENT      # 记录YouQu当前的版本
                @@ -35,8 +35,8 @@
                 bash env.sh
                 # 使用的默认密码是 1;
                 # 您可以使用 -p 选项传入密码:bash env.sh -p ${my_password};
                -# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                - +# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" index 42831888..560b7cd4 100644 --- "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" +++ "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case  # 用例目录
                @@ -49,8 +49,8 @@
                 │   │       ├── other_widget.py   # 其他方法类
                 │   │       ├── pic_res  # 图像识别方法所需要的资源
                 │   │       │   └── readme
                -│   │       └── ui.ini  # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                - +│   │   └── ui.ini # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" index a8fc105b..cf63a01f 100644 --- "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" +++ "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                创建一条通过任务栏打开文件管理器的测试用例;

                用例步骤

                • 点击任务栏上的文件管理器图标;
                • 判断(断言)文件管理器已经启动;

                封装用例步骤的方法

                所有的方法都在 widget 目录下;

                首先这里的主要操作对象是任务栏(dde-dock),因此在方法基类 base_widget.py::BaseWidget 里面需要定义 dde-dock的信息:

                python
                # base_widget.py
                +    
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                创建一条通过任务栏打开文件管理器的测试用例;

                用例步骤

                • 点击任务栏上的文件管理器图标;
                • 判断(断言)文件管理器已经启动;

                封装用例步骤的方法

                所有的方法都在 widget 目录下;

                首先这里的主要操作对象是任务栏(dde-dock),因此在方法基类 base_widget.py::BaseWidget 里面需要定义 dde-dock的信息:

                python
                # base_widget.py
                 
                 from src import Src
                 
                @@ -69,8 +69,8 @@
                 
                 class BaseCase(MyAppAssert):
                     """用例基类"""
                -    APP_NAME = "my-app"

                用例基类用于继承断言模块,这样所有的断言语句都是通过 self.assert_ 调用,由于内建了非常多的断言语句,几乎满足了所有的断言场景:

                这样就完成了一个简单的用例编写。

                - + APP_NAME = "my-app"

                用例基类用于继承断言模块,这样所有的断言语句都是通过 self.assert_ 调用,由于内建了非常多的断言语句,几乎满足了所有的断言场景:

                这样就完成了一个简单的用例编写。

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" index fe064ec3..fffef2d4 100644 --- "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" +++ "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                Linux 桌面 UI 自动化测试

                YouQu 框架从设计之初,就是以桌面 UI 自动化测试为基础,因此 YouQu 真的非常擅长构建 Linux 桌面 UI 自动化项目。

                YouQu 在桌面 UI 自动化测试方向也有非常多的技术突破,例如:兼容 Wayland 显示协议、多样的元素定位方案、用例失败录屏、远程交互式控制等等。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                Linux 桌面 UI 自动化测试

                YouQu 框架从设计之初,就是以桌面 UI 自动化测试为基础,因此 YouQu 真的非常擅长构建 Linux 桌面 UI 自动化项目。

                YouQu 在桌面 UI 自动化测试方向也有非常多的技术突破,例如:兼容 Wayland 显示协议、多样的元素定位方案、用例失败录屏、远程交互式控制等等。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                 ├── apps  # 用于放置APP工程
                 ├── conftest.py  # Pytest 插件库
                 ├── CURRENT      # 记录YouQu当前的版本
                @@ -35,8 +35,8 @@
                 bash env.sh
                 # 使用的默认密码是 1;
                 # 您可以使用 -p 选项传入密码:bash env.sh -p ${my_password};
                -# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                - +# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" index 2b145727..9820ed11 100644 --- "a/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" +++ "b/\345\256\236\350\267\265/Linux\346\241\214\351\235\242UI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" @@ -8,20 +8,20 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                远程交互式控制

                远程交互式控制可以在用例步骤中实现对远程机器的交互式控制;

                逻辑示意图

                标识文件

                shell
                autotest_my_project
                +    
                Skip to content
                📔 阅读量:

                远程交互式控制

                远程交互式控制可以在用例步骤中实现对远程机器的交互式控制;

                逻辑示意图

                标识文件

                shell
                autotest_my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case
                @@ -63,8 +63,8 @@
                         """my case 003"""
                         kwargs = slaves[0]
                         remote = RemoteWidget(**kwargs)
                -        remote.click_deepin_music_on_dock_by_attr()
                - + remote.click_deepin_music_on_dock_by_attr()
                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" index 7bd8c521..ec3ce573 100644 --- "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" +++ "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case  # 用例目录
                @@ -74,8 +74,8 @@
                 │   │       │   └── readme
                 │   │       ├── __init__.py
                 │   │       └── my_app_page.py  # 方法唯一出口类

                再次执行 env.sh

                shell
                cd my_project
                -bash env.sh

                这样 Web UI 相关环境就准备好了。

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                - +bash env.sh

                这样 Web UI 相关环境就准备好了。

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" index 929c0909..cae2e1cb 100644 --- "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" +++ "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                创建一条在百度首页搜索 YouQu 的用例;

                用例步骤

                • 在浏览器访问百度首页;
                • 搜索框输入YouQu;

                封装用例步骤的方法

                方法基类 base_page.py:: BasePage

                python
                from src.webui import WebUI
                +    
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                创建一条在百度首页搜索 YouQu 的用例;

                用例步骤

                • 在浏览器访问百度首页;
                • 搜索框输入YouQu;

                封装用例步骤的方法

                方法基类 base_page.py:: BasePage

                python
                from src.webui import WebUI
                 
                 class BasePage(WebUI):
                 
                @@ -79,8 +79,8 @@
                 
                 
                 class BaseCase(MyAppAssert, WebAssert):
                -    """用例基类"""

                self.assert_locator() 是 Web UI 的专用断言语句,返回的 Playwrightexpect 对象,因此它可以使用 expect 的所有方法;

                比如:

                python
                self.assert_locator(page.locator("//nz-table//tbody/tr[1]")).to_have_text("xxx")

                这样我们就完成了一条简单的 Web UI 自动化用例。

                - + """用例基类"""

                self.assert_locator() 是 Web UI 的专用断言语句,返回的 Playwrightexpect 对象,因此它可以使用 expect 的所有方法;

                比如:

                python
                self.assert_locator(page.locator("//nz-table//tbody/tr[1]")).to_have_text("xxx")

                这样我们就完成了一条简单的 Web UI 自动化用例。

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" index 4ba50922..47f13454 100644 --- "a/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" +++ "b/\345\256\236\350\267\265/WebUI\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                Web UI 自动化测试

                Web UI 自动化测试是一种通用的自动化测试类型,只要是基于浏览器的项目都适用。

                YouQu 基于 Playwright 构建了一整套通用的 Web UI 自动化测试方案。

                YouQu 框架提供灵活可配置的浏览器对象。

                • 提供一个全局默认的对象:page,默认使用系统自带的浏览器进行测试,如果需要指定其他第三方的浏览器,提供配置项可以指定浏览器对应的路径。
                • 还需要提供一个对象:native_page,它使用 Playwright 最新的 Chromium 浏览器进行测试。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                Web UI 自动化测试

                Web UI 自动化测试是一种通用的自动化测试类型,只要是基于浏览器的项目都适用。

                YouQu 基于 Playwright 构建了一整套通用的 Web UI 自动化测试方案。

                YouQu 框架提供灵活可配置的浏览器对象。

                • 提供一个全局默认的对象:page,默认使用系统自带的浏览器进行测试,如果需要指定其他第三方的浏览器,提供配置项可以指定浏览器对应的路径。
                • 还需要提供一个对象:native_page,它使用 Playwright 最新的 Chromium 浏览器进行测试。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                 ├── apps  # 用于放置APP工程
                 ├── conftest.py  # Pytest 插件库
                 ├── CURRENT      # 记录YouQu当前的版本
                @@ -35,8 +35,8 @@
                 bash env.sh
                 # 使用的默认密码是 1;
                 # 您可以使用 -p 选项传入密码:bash env.sh -p ${my_password};
                -# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                - +# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" index 5f019c24..83248680 100644 --- "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" +++ "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272APP\345\267\245\347\250\213.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                创建一个 APP 工程

                使用 startapp 创建一个 APP 工程:

                shell
                youqu manage.py startapp autotest_my_app

                自动创建 APP 工程,并生成大量模板代码:

                shell
                my_project
                 ├── apps
                 │   ├── autotest_my_app  # 创建的APP工程
                 │   │   ├── case  # 用例目录
                @@ -49,8 +49,8 @@
                 │   │       ├── other_widget.py   # 其他方法类
                 │   │       ├── pic_res  # 图像识别方法所需要的资源
                 │   │       │   └── readme
                -│   │       └── ui.ini  # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                - +│   │   └── ui.ini # 相对位移元素定位方案的配置文件

                编辑器打开

                推荐使用 Pycharm 打开,并指定虚拟解释器:

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" index e9f66435..de25cc6c 100644 --- "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" +++ "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\233\345\273\272\344\270\200\346\235\241\345\256\214\346\225\264\347\232\204\347\224\250\344\276\213.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                使用 dd 命令创建文件

                封装用例步骤的方法

                方法主文件里面:cmd_widget.py

                python
                # cmd_widget.py
                +    
                Skip to content
                📔 阅读量:

                创建一条完整的用例

                使用 dd 命令创建文件

                封装用例步骤的方法

                方法主文件里面:cmd_widget.py

                python
                # cmd_widget.py
                 
                 from setting import conf
                 from src import Src
                @@ -54,8 +54,8 @@
                         filesize = "1M"
                         cmd = CmdWidget()
                         cmd.create_file_by_dd_cmd(filepath, filesize)
                -        self.assert_file_exist(f"~/{filepath}")

                这样就完成了一个简单的命令行自动化用例编写。

                - + self.assert_file_exist(f"~/{filepath}")

                这样就完成了一个简单的命令行自动化用例编写。

                + \ No newline at end of file diff --git "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" index 3fae050d..eaf762d6 100644 --- "a/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" +++ "b/\345\256\236\350\267\265/\345\221\275\344\273\244\350\241\214\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225/\345\210\235\345\247\213\345\214\226\351\241\271\347\233\256.html" @@ -8,21 +8,21 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                命令行自动化测试

                命令行自动化测试是 Linux 平台自动化测试的老演员了,与命令行的交互也是相对容易的,这类自动化测试也比较简单。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                命令行自动化测试

                命令行自动化测试是 Linux 平台自动化测试的老演员了,与命令行的交互也是相对容易的,这类自动化测试也比较简单。

                安装

                安装 YouQu:

                shell
                sudo pip3 install youqu

                创建一个项目

                创建一个项目:

                shell
                youqu-startproject my_project

                shell
                my_project
                 ├── apps  # 用于放置APP工程
                 ├── conftest.py  # Pytest 插件库
                 ├── CURRENT      # 记录YouQu当前的版本
                @@ -35,8 +35,8 @@
                 bash env.sh
                 # 使用的默认密码是 1;
                 # 您可以使用 -p 选项传入密码:bash env.sh -p ${my_password};
                -# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                - +# 也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/OCR\350\257\206\345\210\253.html" "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/OCR\350\257\206\345\210\253.html" index b4d6ab71..441a8304 100644 --- "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/OCR\350\257\206\345\210\253.html" +++ "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/OCR\350\257\206\345\210\253.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                OCR识别

                背景

                传统的 OCR 方案大多采用谷歌 OCR(Tesseract)方案,但是它对于中文的识别非常差,经过大量的调研,我们使用 PaddleOCR,它是一个开源的基于深度学习的 OCR 识别工具,也是 PaddlePaddle 最有名的一个开源项目,感兴趣的可以点这里了解,多的不说了,你只需要知道它就是中文识别的天花板。

                实现原理

                安装它是个很麻烦的事情,虽然操作很简单,但其实安装包有点大,这并不符合我们对框架依赖治理的理解,我们并不希望直接在 env.sh 中加入它,这会让整个自动化环境变得非常臃肿;

                因此,我们想到将它做成一个 RPC 服务在其他机器上部署,测试机通过远程调用 RPC 服务的方式使用它;

                RPC 的调用逻辑:

                这样我们只需要在服务端部署好 OCR 识别的服务,然后通过 RPC 服务将功能提供出来,框架里面只需要调用对应的 RPC 接口就行了。

                使用说明

                框架代码示意(Client):

                python
                from src import OCR
                +    
                Skip to content
                📔 阅读量:

                OCR识别

                背景

                传统的 OCR 方案大多采用谷歌 OCR(Tesseract)方案,但是它对于中文的识别非常差,经过大量的调研,我们使用 PaddleOCR,它是一个开源的基于深度学习的 OCR 识别工具,也是 PaddlePaddle 最有名的一个开源项目,感兴趣的可以点这里了解,多的不说了,你只需要知道它就是中文识别的天花板。

                实现原理

                安装它是个很麻烦的事情,虽然操作很简单,但其实安装包有点大,这并不符合我们对框架依赖治理的理解,我们并不希望直接在 env.sh 中加入它,这会让整个自动化环境变得非常臃肿;

                因此,我们想到将它做成一个 RPC 服务在其他机器上部署,测试机通过远程调用 RPC 服务的方式使用它;

                RPC 的调用逻辑:

                这样我们只需要在服务端部署好 OCR 识别的服务,然后通过 RPC 服务将功能提供出来,框架里面只需要调用对应的 RPC 接口就行了。

                使用说明

                框架代码示意(Client):

                python
                from src import OCR
                 
                 OCR.ocr(*target_strings, picture_abspath=None, similarity=0.6, return_default=False, return_first=False, lang="ch"):
                 # 通过 OCR 进行识别。
                @@ -102,8 +102,8 @@
                 OCR.ocrx("确定").right_click()
                 OCR.ocrx("确定").double_click()
                 # 原函数接口ocr,返回坐标
                -OCR.ocr("确定")
                - +OCR.ocr("确定")
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.html" "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.html" index 91e6cac9..2a537909 100644 --- "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.html" +++ "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\216\273\345\271\262\346\211\260\350\257\206\345\210\253.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                去干扰识别

                以右键菜单来讲解此方案;

                现有右键菜单定位的方案及问题

                右键菜单的元素定位是一个难点,过去我们调研和使用过的元素定位操作方法有 4 种:

                1. 步长操作法

                在右键菜单呼出来之后,通过键盘的 updown 按键,进行选择菜单选择,选中目标之后 enter 即可;比如:在桌面点击右键菜单之后,按 1 次 down ,会出现下图:

                继续再按 2 次 down,会出现这样:

                再按 enter,会出现这样:

                如此,“排序方式”的步长为 3;通过使用键盘上下键,就实现了对右键菜单的操作;

                但是,这种方式有个很烦人的问题,就是右键菜单的选项位置不可能一直不变,在需求迭代的过程中,菜单选项的变化是很大的,甚至有些应用支持自定义菜单,比如文管右键菜单可以自定义;

                也就是说你得经常去维护菜单选项的步长,一个选项现在的步长是 3,下个迭代可能就是 4 或者 5。

                2. 常规图像识别法

                把每个菜单选项单独截图保存,图片中仅包含一个菜单选项,如下图所示:

                这样,每个菜单选项就可以通过图像识别的方式进行元素定位;

                这种方式不用担心菜单选项的顺序或位置,但是需要保存大量的图片,且容易受到字体 UI 变更类需求的影响,比如:字体大小、字体间距等等需求变更都会影响,每次变更之后就需要进行大量图片资源的重新截图替换,是个比较麻烦的事情;

                3. 相对位移法

                鼠标点击右键的时候,鼠标的当前坐标是可以获取到的,菜单选项的宽( w )一般是固定的,变化的是菜单的长度( h ),可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标,如下图所示:

                通过维护菜单选项(相对位置)相对于鼠标位置的距离,即可轻松计算出菜单选项在屏幕中的坐标。

                从理论上此方案是可行的,但是这里仍然存在两个严重的问题:

                • 菜单顺序改变,导致相对距离改变,而且距离是通过像素(px)来表示的,不想步长那么只管,每次需要去量一下,维护起来有点麻烦;
                • 鼠标在桌面不同位置点击右键,右键菜单出现的位置是不同的,上图的菜单是在鼠标的左下方,如果你移动鼠标到屏幕四边,你会发现,右键菜单可能出现在鼠标的四个方向,也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向,而不同的方向上计算方法是不同的,比如:右键菜单在鼠标的左上,菜单选项的坐标计算方法为(x - w / 2, y - h),这样维护起来可以说非常复杂;

                基于以上两个原因,我们并不推荐这种操作方案。

                4. 属性定位

                有同学说干嘛不通过属性定位呢,其实,我们最开始想到的方案就是通过属性定位,但是在属性的 DOM 树里怎么也找不到,无法定位到,我们也联合研发同学一起解决此问题,但最终还是没能解决,非常遗憾;

                去干扰识别

                由于右键菜单选项几乎都是文本,那么通过 OCR 识别,几乎是最优的方案:

                • 不用保存大量的图片;
                • 不会受到菜单选项顺序改变的影响;
                • 不会受到字体 UI 变化的影响;

                关于 OCR 识别我们在前面已经讲到,本章节主要讲基于 OCR 识别,我们在右键菜单识别上的突破和创新;

                使用 OCR 识别右键菜单虽然已经很完美了,但是在一些情况下仍然存在一点问题,就是屏幕中出现多个和菜单选项文字相同的文字时,比如下面这种情况:

                屏幕恰好出现了两个“复制”,此时要定位到菜单中的 “复制”,就需要进一步做数据处理,比如:OCR 返回 2 个“复制”的坐标,用例里面来判断用哪个,从业务上将处理起来比较麻烦,因为你得明确知道菜单在左边还是右边,然后这本身就是不确定的;

                怎么解决这个问题呢,这就要说到本章的主题:去干扰图像识别

                【原理】

                在点击右键菜单之前截一张图,点击右键菜单之后再截取一张图,两张图唯一变化的就是右键菜单,将其他相同的地方都屏蔽掉,只留下菜单界面,如此即可消除干扰,如下图所示:

                将两种图做前后对比提取可以得到这样的图:

                你看,通过前后图片的对比,将相同的部分给消除掉,再进行 OCR 识别,这样就不会有干扰了;

                代码实现请查看 src/filter_image.py

                代码示例:

                python
                def filter_image(action):
                +    
                Skip to content
                📔 阅读量:

                去干扰识别

                以右键菜单来讲解此方案;

                现有右键菜单定位的方案及问题

                右键菜单的元素定位是一个难点,过去我们调研和使用过的元素定位操作方法有 4 种:

                1. 步长操作法

                在右键菜单呼出来之后,通过键盘的 updown 按键,进行选择菜单选择,选中目标之后 enter 即可;比如:在桌面点击右键菜单之后,按 1 次 down ,会出现下图:

                继续再按 2 次 down,会出现这样:

                再按 enter,会出现这样:

                如此,“排序方式”的步长为 3;通过使用键盘上下键,就实现了对右键菜单的操作;

                但是,这种方式有个很烦人的问题,就是右键菜单的选项位置不可能一直不变,在需求迭代的过程中,菜单选项的变化是很大的,甚至有些应用支持自定义菜单,比如文管右键菜单可以自定义;

                也就是说你得经常去维护菜单选项的步长,一个选项现在的步长是 3,下个迭代可能就是 4 或者 5。

                2. 常规图像识别法

                把每个菜单选项单独截图保存,图片中仅包含一个菜单选项,如下图所示:

                这样,每个菜单选项就可以通过图像识别的方式进行元素定位;

                这种方式不用担心菜单选项的顺序或位置,但是需要保存大量的图片,且容易受到字体 UI 变更类需求的影响,比如:字体大小、字体间距等等需求变更都会影响,每次变更之后就需要进行大量图片资源的重新截图替换,是个比较麻烦的事情;

                3. 相对位移法

                鼠标点击右键的时候,鼠标的当前坐标是可以获取到的,菜单选项的宽( w )一般是固定的,变化的是菜单的长度( h ),可以通过某个选项相对于鼠标的距离在确定菜单选项的坐标,如下图所示:

                通过维护菜单选项(相对位置)相对于鼠标位置的距离,即可轻松计算出菜单选项在屏幕中的坐标。

                从理论上此方案是可行的,但是这里仍然存在两个严重的问题:

                • 菜单顺序改变,导致相对距离改变,而且距离是通过像素(px)来表示的,不想步长那么只管,每次需要去量一下,维护起来有点麻烦;
                • 鼠标在桌面不同位置点击右键,右键菜单出现的位置是不同的,上图的菜单是在鼠标的左下方,如果你移动鼠标到屏幕四边,你会发现,右键菜单可能出现在鼠标的四个方向,也就是说你需要根据鼠标的不同位置来判断右键菜单出现的方向,而不同的方向上计算方法是不同的,比如:右键菜单在鼠标的左上,菜单选项的坐标计算方法为(x - w / 2, y - h),这样维护起来可以说非常复杂;

                基于以上两个原因,我们并不推荐这种操作方案。

                4. 属性定位

                有同学说干嘛不通过属性定位呢,其实,我们最开始想到的方案就是通过属性定位,但是在属性的 DOM 树里怎么也找不到,无法定位到,我们也联合研发同学一起解决此问题,但最终还是没能解决,非常遗憾;

                去干扰识别

                由于右键菜单选项几乎都是文本,那么通过 OCR 识别,几乎是最优的方案:

                • 不用保存大量的图片;
                • 不会受到菜单选项顺序改变的影响;
                • 不会受到字体 UI 变化的影响;

                关于 OCR 识别我们在前面已经讲到,本章节主要讲基于 OCR 识别,我们在右键菜单识别上的突破和创新;

                使用 OCR 识别右键菜单虽然已经很完美了,但是在一些情况下仍然存在一点问题,就是屏幕中出现多个和菜单选项文字相同的文字时,比如下面这种情况:

                屏幕恰好出现了两个“复制”,此时要定位到菜单中的 “复制”,就需要进一步做数据处理,比如:OCR 返回 2 个“复制”的坐标,用例里面来判断用哪个,从业务上将处理起来比较麻烦,因为你得明确知道菜单在左边还是右边,然后这本身就是不确定的;

                怎么解决这个问题呢,这就要说到本章的主题:去干扰图像识别

                【原理】

                在点击右键菜单之前截一张图,点击右键菜单之后再截取一张图,两张图唯一变化的就是右键菜单,将其他相同的地方都屏蔽掉,只留下菜单界面,如此即可消除干扰,如下图所示:

                将两种图做前后对比提取可以得到这样的图:

                你看,通过前后图片的对比,将相同的部分给消除掉,再进行 OCR 识别,这样就不会有干扰了;

                代码实现请查看 src/filter_image.py

                代码示例:

                python
                def filter_image(action):
                     """
                     对比动作前后两张图片,提取不同的部分生成一张新的图片,并返回新图片的路径
                     :param action: 动作函数的函数对象
                @@ -31,8 +31,8 @@
                     MouseKey.right_click,
                     MouseKey.double_click,
                     MouseKey.move_to,
                -)
                - +)
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\233\276\345\203\217\350\257\206\345\210\253.html" "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\233\276\345\203\217\350\257\206\345\210\253.html" index 9003ea32..e1aaff57 100644 --- "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\233\276\345\203\217\350\257\206\345\210\253.html" +++ "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\233\276\345\203\217\350\257\206\345\210\253.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                图像识别

                图像识别在 UI 自动化中是不可缺少的,市面上甚至有完全基于图像识别的自动化测试框架,比如 AirtestSikuli 等,在游戏等特定领域也有不错的效果,这些工具实际上也是用的 OpenCV 进行了封装,YouQu 框架基于 OpenCV 开发了自己的图像识别功能,它可以方便的用于界面元素的定位和断言;

                YouQu 的图像识别功能几乎满足了你的所有要求,我们在长时间的思考和摸索中,针对常规场景及一些特殊场景探索出了一些实用且有效的方案,且听我慢慢道来。

                常规识别

                【背景】

                常规识别很好理解,一句话讲就是,要获取到目标元素在屏幕中的位置。

                【原理实现】

                在测试过程中需要获取的坐标是相对于整个屏幕的坐标,我们可以截取到整个屏幕的图片(screen);

                在元素识别的过程中,我们需要截取某个元素的小图进行识别,比如截取播放按钮:

                那么实际上,元素定位的问题就转换为,将截图的小图(play_btn)拿到整个屏幕的大图(screen)中去做匹配,如果匹配成功,返回小图在大图中的坐标( x, y )即可。

                为了方便描述,以下我将整个屏幕的截图称为:大图,某个元素图片的截图称为:小图。

                基于 OpenCV 的模板匹配 cv.matchTemplate() 功能,我们实现了图像定位的功能,框架提供了一个图像识别的底层接口(一般不对上层提供调用):

                python
                def _match_image_by_opencv(
                +    
                Skip to content
                📔 阅读量:

                图像识别

                图像识别在 UI 自动化中是不可缺少的,市面上甚至有完全基于图像识别的自动化测试框架,比如 AirtestSikuli 等,在游戏等特定领域也有不错的效果,这些工具实际上也是用的 OpenCV 进行了封装,YouQu 框架基于 OpenCV 开发了自己的图像识别功能,它可以方便的用于界面元素的定位和断言;

                YouQu 的图像识别功能几乎满足了你的所有要求,我们在长时间的思考和摸索中,针对常规场景及一些特殊场景探索出了一些实用且有效的方案,且听我慢慢道来。

                常规识别

                【背景】

                常规识别很好理解,一句话讲就是,要获取到目标元素在屏幕中的位置。

                【原理实现】

                在测试过程中需要获取的坐标是相对于整个屏幕的坐标,我们可以截取到整个屏幕的图片(screen);

                在元素识别的过程中,我们需要截取某个元素的小图进行识别,比如截取播放按钮:

                那么实际上,元素定位的问题就转换为,将截图的小图(play_btn)拿到整个屏幕的大图(screen)中去做匹配,如果匹配成功,返回小图在大图中的坐标( x, y )即可。

                为了方便描述,以下我将整个屏幕的截图称为:大图,某个元素图片的截图称为:小图。

                基于 OpenCV 的模板匹配 cv.matchTemplate() 功能,我们实现了图像定位的功能,框架提供了一个图像识别的底层接口(一般不对上层提供调用):

                python
                def _match_image_by_opencv(
                     image_path: str, 
                     rate: float = None, 
                     multiple: bool = False, 
                @@ -179,8 +179,8 @@
                     :param width: 宽度
                     :param height: 高度
                     :return: 图片路径
                -    """

                此函数用于在操作之前截图一张临时图片,返回图片路径,最后在断言的时候再将图片路径作为参数传入断言语句即可;

                代码示例:

                - + """

                此函数用于在操作之前截图一张临时图片,返回图片路径,最后在断言的时候再将图片路径作为参数传入断言语句即可;

                代码示例:

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\261\236\346\200\247\345\256\232\344\275\215.html" "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\261\236\346\200\247\345\256\232\344\275\215.html" index fe59c342..373f6870 100644 --- "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\261\236\346\200\247\345\256\232\344\275\215.html" +++ "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\345\261\236\346\200\247\345\256\232\344\275\215.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                属性定位

                背景

                传统的 UI 自动化大多都是基于浏览器的,核心是在网页的 DOM 树上查找元素,并对其进行定位操作;

                Linux 桌面应用大多是采用 Qt 编写的,在 Qt 中也是从最顶层的 MainWindow 开始构建应用,所以逻辑也是一样的,Qt 应用的自动化测试同样可以通过 DOM 树(属性树)进行元素定位,我们称之为属性定位

                借助开源工具 dogtail 我们可以对元素进行获取,从而进行定位操作。dogtail 的项目介绍可以猛戳这里

                sniff(嗅探器)使用

                在终端输入 sniff 启动 AT-SPI Browser

                shell
                mikigo@mikigo-PC:~$ sniff

                查看应用的标签

                在 sniff 里面可以看到系统中已启动的应用,点击应用名称前面的三角形图标,可以展开应用的标签,所有标签以 tree 的形式展示,对应应用里面的父窗口和子窗口。

                获取元素控件的标签名称

                首先,为了方便查看元素控件对应的位置,建议现在上方工具栏点击 Actions,然后勾选 Hightlight Items,这样在 sniff 中鼠标选中元素标签的时候,应用中会有相应的光标锁定。

                在 sniff 里面点击进入应用的标签 tree 中后,点击相应的元素控件,在工具下方,会展示元素控件的 Name,这个就是标签名称。

                在 tree 中有些地方是空白的或者是 Form,是因为开发人员在添加标签的时候没有添加,或者有些父窗口不需要添加,这种在实际业务中是不影响的,我们只要保证自动化测试用例中,要用到的元素都添加了标签即可。

                元素操作

                获取应用对象

                dogtail 获取应用对象的时候,使用的是 tree 库里面的 application() 方法:

                python
                from dogtail.tree import root
                +    
                Skip to content
                📔 阅读量:

                属性定位

                背景

                传统的 UI 自动化大多都是基于浏览器的,核心是在网页的 DOM 树上查找元素,并对其进行定位操作;

                Linux 桌面应用大多是采用 Qt 编写的,在 Qt 中也是从最顶层的 MainWindow 开始构建应用,所以逻辑也是一样的,Qt 应用的自动化测试同样可以通过 DOM 树(属性树)进行元素定位,我们称之为属性定位

                借助开源工具 dogtail 我们可以对元素进行获取,从而进行定位操作。dogtail 的项目介绍可以猛戳这里

                sniff(嗅探器)使用

                在终端输入 sniff 启动 AT-SPI Browser

                shell
                mikigo@mikigo-PC:~$ sniff

                查看应用的标签

                在 sniff 里面可以看到系统中已启动的应用,点击应用名称前面的三角形图标,可以展开应用的标签,所有标签以 tree 的形式展示,对应应用里面的父窗口和子窗口。

                获取元素控件的标签名称

                首先,为了方便查看元素控件对应的位置,建议现在上方工具栏点击 Actions,然后勾选 Hightlight Items,这样在 sniff 中鼠标选中元素标签的时候,应用中会有相应的光标锁定。

                在 sniff 里面点击进入应用的标签 tree 中后,点击相应的元素控件,在工具下方,会展示元素控件的 Name,这个就是标签名称。

                在 tree 中有些地方是空白的或者是 Form,是因为开发人员在添加标签的时候没有添加,或者有些父窗口不需要添加,这种在实际业务中是不影响的,我们只要保证自动化测试用例中,要用到的元素都添加了标签即可。

                元素操作

                获取应用对象

                dogtail 获取应用对象的时候,使用的是 tree 库里面的 application() 方法:

                python
                from dogtail.tree import root
                 app_obj = root.application('deepin-music')

                app_obj就是应用的对象。

                • 获取元素对象

                获取元素对象,是应用对象使用child()方法:

                python
                element = app_obj.child('element_name')

                我们可以通过传入元素的 Name,获取到相应元素的对象。Name 可以通过 sniff 查看。

                • 获取元素对象列表:
                python
                element_list = element.children

                获取到这个元素下面所有的元素列表。

                这个方法适用于有些标签没有添加,但是位置是固定的,我们通过索引可以取得元素。

                python
                element_list[0]
                • 对元素的操作

                在获取到元素之后,我们就可以对元素进行相应的操作。

                • 单击
                python
                element.click(button=1)

                button 1 —>左键,2 —>滚轮,3 —>右键,默认为 1

                • 双击
                python
                element.doubleClick(button=1)
                • 鼠标悬停
                python
                element.point()

                鼠标移动到元素中心位置

                • 文本输入
                python
                element.typeText(string)

                向元素对象输入字符串 ,比如输入框

                • 组合键
                python
                element.keyCombo(comboString)

                框架封装

                代码示例:

                python
                # 详细代码请查看 src/dogtail_utils.py
                 class DogtailUtils:
                 
                @@ -286,8 +286,8 @@
                                     recur_inter(i)
                 
                         recur_inter()
                -        return eles
                - + return eles
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.html" "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.html" index 2526a18a..4b487d96 100644 --- "a/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.html" +++ "b/\346\214\207\345\215\227/\345\205\203\347\264\240\345\256\232\344\275\215/\347\233\270\345\257\271\345\235\220\346\240\207\345\256\232\344\275\215.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                相对坐标定位

                背景

                相对坐标定位方案是是一种基于 UI 的元素定位方案,是我们自研的一个使用简单,且效率极高、稳定性好的元素定位方案,基于元素按钮在应用中的相对位置,动态获取元素在当前屏幕中的位置,适用于各种屏幕分辨率(包括高分屏、宽屏、带鱼屏),当元素按钮位置相对于应用界面位置发生修改之后,只需要根据 UI 设计图上的源数据修改对应坐标数据就好,维护非常的方便。

                此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用,比如音乐(99% 的元素定位采用这种,效果非常好),不适用于界面不固定的应用,比如截图录屏,很明显不适用于这类元素定位方案。这种全新的元素定位方案有它的适用条件,如果你发现使用常规的(属性定位、图像定位)不好做时,不妨考虑使用这种,其效果一定能惊讶到你,并且迅速爱上他。

                实现原理

                在 UI 设计图中我们是可以获取到元素按钮相对于应用边框的距离的,然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小,示意图如下:

                (x1, y1)为应用左上角相对于屏幕左上角(0, 0)的位置;(x2, y2)是按钮【播放所有】的左上角相对于应用窗口左上角(x1, y1)的坐标,那么实际上【播放所有】左上角相对于屏幕左上角(0, 0)的位置为:( x1 + x2, y1 + y2 )

                是按钮【播放所有】的大小(w2, h2),可以从 UI 设计图上获取;

                在 UI 设计稿上点击【播放所有】图标,然后移动鼠标就就可以看到上图的参考线及数据;

                所以,我们可以轻松的获取到按钮【播放所有】的中心坐标为:( x1 + x2 + (w2 / 2), y1 + y2 + ( h2 / 2) )

                详细源代码请查看 AT 基础框架: src/button_center.py

                • 获取应用窗口的信息

                使用 xdotoolxwininfo 获取到应用窗口在当前屏幕中的位置(左上角)及大小。

                代码示例:

                python
                app_id = CmdCtl.run_cmd(f"xdotool search --classname --onlyvisible {self.app_name}"
                +    
                Skip to content
                📔 阅读量:

                相对坐标定位

                背景

                相对坐标定位方案是是一种基于 UI 的元素定位方案,是我们自研的一个使用简单,且效率极高、稳定性好的元素定位方案,基于元素按钮在应用中的相对位置,动态获取元素在当前屏幕中的位置,适用于各种屏幕分辨率(包括高分屏、宽屏、带鱼屏),当元素按钮位置相对于应用界面位置发生修改之后,只需要根据 UI 设计图上的源数据修改对应坐标数据就好,维护非常的方便。

                此类元素定位方案适用于一些元素位置相对与应用界面比较固定的应用,比如音乐(99% 的元素定位采用这种,效果非常好),不适用于界面不固定的应用,比如截图录屏,很明显不适用于这类元素定位方案。这种全新的元素定位方案有它的适用条件,如果你发现使用常规的(属性定位、图像定位)不好做时,不妨考虑使用这种,其效果一定能惊讶到你,并且迅速爱上他。

                实现原理

                在 UI 设计图中我们是可以获取到元素按钮相对于应用边框的距离的,然后我们可以通过技术手段获取到应用界面在当前屏幕中的位置及应用窗口的大小,示意图如下:

                (x1, y1)为应用左上角相对于屏幕左上角(0, 0)的位置;(x2, y2)是按钮【播放所有】的左上角相对于应用窗口左上角(x1, y1)的坐标,那么实际上【播放所有】左上角相对于屏幕左上角(0, 0)的位置为:( x1 + x2, y1 + y2 )

                是按钮【播放所有】的大小(w2, h2),可以从 UI 设计图上获取;

                在 UI 设计稿上点击【播放所有】图标,然后移动鼠标就就可以看到上图的参考线及数据;

                所以,我们可以轻松的获取到按钮【播放所有】的中心坐标为:( x1 + x2 + (w2 / 2), y1 + y2 + ( h2 / 2) )

                详细源代码请查看 AT 基础框架: src/button_center.py

                • 获取应用窗口的信息

                使用 xdotoolxwininfo 获取到应用窗口在当前屏幕中的位置(左上角)及大小。

                代码示例:

                python
                app_id = CmdCtl.run_cmd(f"xdotool search --classname --onlyvisible {self.app_name}"
                 ).split("\n")
                 app_id_list = [int(_id) for _id in app_id if _id]
                 return CmdCtl.run_cmd(f"xwininfo -id {app_id_list[self.number]}")

                使用正则获取窗口的位置及大小。

                • 获取配置

                ini 配置文件,获取元素按钮相对与应用窗口边界的位置及大小。

                代码示例:

                python
                conf = ConfigParser()
                @@ -685,8 +685,8 @@
                             if isinstance(info, dict):
                                 return info.get("window_id")
                             elif isinstance(info, list):
                -                return info[-1].get("window_id")
                - + return info[-1].get("window_id")
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/Ruff\344\273\243\347\240\201\346\243\200\346\237\245.html" "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/Ruff\344\273\243\347\240\201\346\243\200\346\237\245.html" index 61e9a4b3..5ff565e0 100644 --- "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/Ruff\344\273\243\347\240\201\346\243\200\346\237\245.html" +++ "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/Ruff\344\273\243\347\240\201\346\243\200\346\237\245.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                Ruff

                YouQu 默认使用 Python 最强代码检查&格式化工具——Ruff。

                安装

                shell
                pip3 install ruff

                代码检查

                代码检查是扫描代码中存在的问题。

                shell
                ruff check .

                表示扫描当前目录下所有的代码,当然你可以指定一个具体的目录或文件。

                在扫描日志最后可以看到一个 fixable,意思是可以通过 --fix 参数直接给你修复掉。

                shell
                ruff check setting/ --fix

                对比下文件前后:

                你看,直接修复了对吧。

                代码格式化

                经过前面代码检查并修复之后,说明我们代码中没有“问题”了,接下来就可以进行代码格式化。

                shell
                ruff format setting/

                效果很不错对吧。

                格式化这块 Ruff 官方表示是可以直接替代 Black 的。

                配置

                前面代码检查的时候报了一个问题,是说在 __init__.py 文件里面写了一个导入,但没有被使用。

                但是这是我特意这样写的,是一种名称空间的设计,可以在 setting 名称空间下直接导入,不需要 Ruff 处理这个问题,这也不是个问题。

                因此,我们需要对 Ruff 进行配置。

                在根目录下 ruff.toml 的文件:

                toml
                # Exclude a variety of commonly ignored directories.
                +    
                Skip to content
                📔 阅读量:

                Ruff

                YouQu 默认使用 Python 最强代码检查&格式化工具——Ruff。

                安装

                shell
                pip3 install ruff

                代码检查

                代码检查是扫描代码中存在的问题。

                shell
                ruff check .

                表示扫描当前目录下所有的代码,当然你可以指定一个具体的目录或文件。

                在扫描日志最后可以看到一个 fixable,意思是可以通过 --fix 参数直接给你修复掉。

                shell
                ruff check setting/ --fix

                对比下文件前后:

                你看,直接修复了对吧。

                代码格式化

                经过前面代码检查并修复之后,说明我们代码中没有“问题”了,接下来就可以进行代码格式化。

                shell
                ruff format setting/

                效果很不错对吧。

                格式化这块 Ruff 官方表示是可以直接替代 Black 的。

                配置

                前面代码检查的时候报了一个问题,是说在 __init__.py 文件里面写了一个导入,但没有被使用。

                但是这是我特意这样写的,是一种名称空间的设计,可以在 setting 名称空间下直接导入,不需要 Ruff 处理这个问题,这也不是个问题。

                因此,我们需要对 Ruff 进行配置。

                在根目录下 ruff.toml 的文件:

                toml
                # Exclude a variety of commonly ignored directories.
                 exclude = [
                     ".bzr",
                     ".direnv",
                @@ -109,8 +109,8 @@
                 #
                 # This only has an effect when the `docstring-code-format` setting is
                 # enabled.
                -docstring-code-line-length = "dynamic"

                在上面配置文件中 ignore = [] 写入错误代码:

                toml
                ignore = ["F401"]

                再次扫描就不会再报之前的问题。

                其他的一些配置也可以根据自己的一些需要进行配置。

                - +docstring-code-line-length = "dynamic"

                在上面配置文件中 ignore = [] 写入错误代码:

                toml
                ignore = ["F401"]

                再次扫描就不会再报之前的问题。

                其他的一些配置也可以根据自己的一些需要进行配置。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.html" "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.html" index cd23d5d0..0120e85b 100644 --- "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.html" +++ "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\211\247\350\241\214\347\256\241\347\220\206\345\231\250.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                执行管理器 - manage.py

                YouQu 的执行管理器 manage.py 提供了丰富的配置和命令行参数,可用于本地用例驱动执行、远程用例驱动执行、CSV 文件管理、PMS 与本地 CSV 文件标签关联管理、脚手架等功能;

                如何使用

                【命令行使用】

                所有功能的驱动执行都是通过 manage.py 进行的,它是全局的入口文件,后面提到的一些命令行参数也都默认是在 manage.py 之后添加使用;

                你可以使用 -h--help 查看它的帮助:

                shell
                $ youqu manage.py -h

                这样可以查看它支持的子命令;

                然后再通过子命令 -h--help 查看子命令的帮助,以子命令 run 举例:

                shell
                $ youqu manage.py run -h

                这样可以查看到子命令支持的各项参数及参数使用说明。

                【配置文件】

                配置文件在 setting 目录下,绝大部分的配置项均在 globalconfig.ini 文件中,为了方便描述后面经常提到的“配置文件”、“配置项”几乎都是指的 setting/globalconfig.ini

                你可以在配置文件中每一个配置项上面看到该配置项的使用说明;

                在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明,并没有再补充其对应的命令行参数,但是几乎所有的命令行参数都对应提供了配置文件配置项;

                注意

                命令行参数的优先级高于配置文件配置,也就是说通过命令行参数指定了对应的参数,配置文件中不管是否配置均不生效。

                下面介绍两个常用的用例执行的功能:

                本地执行

                本地执行子命令为:run

                shell
                $ youqu manage.py run

                1. 命令行参数

                通过命令行参数配置参数

                以下为 youqu manage.py run 提供的一些常用的参数选项:

                coffeescript
                  -h, --help            show this help message and exit
                +    
                Skip to content
                📔 阅读量:

                执行管理器 - manage.py

                YouQu 的执行管理器 manage.py 提供了丰富的配置和命令行参数,可用于本地用例驱动执行、远程用例驱动执行、CSV 文件管理、PMS 与本地 CSV 文件标签关联管理、脚手架等功能;

                如何使用

                【命令行使用】

                所有功能的驱动执行都是通过 manage.py 进行的,它是全局的入口文件,后面提到的一些命令行参数也都默认是在 manage.py 之后添加使用;

                你可以使用 -h--help 查看它的帮助:

                shell
                $ youqu manage.py -h

                这样可以查看它支持的子命令;

                然后再通过子命令 -h--help 查看子命令的帮助,以子命令 run 举例:

                shell
                $ youqu manage.py run -h

                这样可以查看到子命令支持的各项参数及参数使用说明。

                【配置文件】

                配置文件在 setting 目录下,绝大部分的配置项均在 globalconfig.ini 文件中,为了方便描述后面经常提到的“配置文件”、“配置项”几乎都是指的 setting/globalconfig.ini

                你可以在配置文件中每一个配置项上面看到该配置项的使用说明;

                在后面的一些功能描述中有些为了方面描述只提到了配置项的使用说明,并没有再补充其对应的命令行参数,但是几乎所有的命令行参数都对应提供了配置文件配置项;

                注意

                命令行参数的优先级高于配置文件配置,也就是说通过命令行参数指定了对应的参数,配置文件中不管是否配置均不生效。

                下面介绍两个常用的用例执行的功能:

                本地执行

                本地执行子命令为:run

                shell
                $ youqu manage.py run

                1. 命令行参数

                通过命令行参数配置参数

                以下为 youqu manage.py run 提供的一些常用的参数选项:

                coffeescript
                  -h, --help            show this help message and exit
                   -a APP, --app APP     应用名称:apps/autotest_deepin_music
                                         autotest_deepin_music
                   -k KEYWORDS, --keywords KEYWORDS
                @@ -95,8 +95,8 @@
                 │  	└── test_mycase_002.py

                驱动执行 smoke 目录下所有用例:

                shehll
                youqu manage.py run -k smoke

                执行某个APP工程的所有用例

                shell
                youqu manage.py run -a apps/autotest_my_app

                根据关键词执行

                执行包含关键词的用例,关键词可以是用例对象中的任意字符,且大小写不敏感

                模块名称、py 文件名称、类名、函数名等等都可以做为关键词

                比如:apps/autotest_deepin_music/case/test_music_001.py::TestMusic::test_music_001

                整个字符串中可以任意截取字符作为关键词。

                关键词驱动支持 and/or/not 表达式。

                shell
                youqu manage.py run -k "music and deepin"

                根据标签执行

                基于 YouQu 特有的 CSV 文件管理的标签,也可以是传统的 Pytest 标签:@pytest.mark.L1

                标签驱动支持 and/or/not 表达式。

                shell
                youqu manage.py run -t "L1 or smoke"

                批量用例ID驱动执行

                shell
                youqu manage.py run -t "id1 or id2 or id3 or id4"

                测试单驱动执行

                shell
                youqu manage.py run -a apps/autotest_xxx -u ut001234 -p my_password --task_id xxxx --send_pms async

                测试套件驱动执行

                shell
                youqu manage.py run -a apps/autotest_xxx -u ut001234 -p my_password --suit_id xxxx --send_pms async

                本地用例文件驱动执行

                shell
                youqu manage.py run -f test_suite.txt

                test_suite.txt 中编写用例所在路径:

                txt
                apps/autotest_deepin_music/case/test_music_001.py::TestMusic::test_music_001
                 apps/autotest_deepin_music/case/test_music_002.py::TestMusic
                 apps/autotest_deepin_music/case/test_music_003.py
                -apps/autotest_deepin_music/case/test_music_004.py
                - +apps/autotest_deepin_music/case/test_music_004.py
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\226\255\350\250\200.html" "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\226\255\350\250\200.html" index d027f7c4..75e23ef5 100644 --- "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\226\255\350\250\200.html" +++ "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\226\255\350\250\200.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                断言

                YouQu 自带多种断言语句,几乎满足了所有的断言场景;

                用例中使用方法

                APP 工程自有断言模块:my_app_assert.py,它继承了 YouQu 框架的断言库:

                python
                # my_app_assert.py
                +    
                Skip to content
                📔 阅读量:

                断言

                YouQu 自带多种断言语句,几乎满足了所有的断言场景;

                用例中使用方法

                APP 工程自有断言模块:my_app_assert.py,它继承了 YouQu 框架的断言库:

                python
                # my_app_assert.py
                 
                 from src.assert_common import AssertCommon
                 
                @@ -639,8 +639,8 @@
                                         f"通过OCR在范围[{resolution}]识别到不应存在的文案:{dict(res)}",
                                         f"{pic if pic else GlobalConfig.SCREEN_CACHE}",
                                     )
                -                )
                - + )
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\265\213\350\257\225\346\212\245\345\221\212.html" "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\265\213\350\257\225\346\212\245\345\221\212.html" index 98a60cfe..0b9c3af6 100644 --- "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\265\213\350\257\225\346\212\245\345\221\212.html" +++ "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\346\265\213\350\257\225\346\212\245\345\221\212.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                测试报告

                目录结构

                执行时会在根目录下动态生成 report 目录,所有的报告相关的文件会统一存放在里面,示例:

                shell
                /report
                +    
                Skip to content
                📔 阅读量:

                测试报告

                目录结构

                执行时会在根目录下动态生成 report 目录,所有的报告相关的文件会统一存放在里面,示例:

                shell
                /report
                     ├── allure  # allure报告
                     │   ├── ...
                     │   └── ffb324f3-2199-4eea-8a6f-2d7e77ce1718-container.json
                @@ -43,8 +43,8 @@
                     │       └── 15时14分09秒_test_music_679537_2_autotest.mp4
                     └── xml  # xml报告
                         └── autotest_deepin_music-20221109134736.xml

                默认情况下同时生成 html、xml、json三种形式的报告。

                定制报告

                我们对 allure 报告进行了一系列的定制:

                • 定制 logotitle、报告默认语言为中文;
                • 加入了用例断言失败时的屏幕截图,以及此时图像对比的模板图片;
                • 加入了失败录屏,你可以在 html 报告中直接看录制的视频;
                • 加入了 IP 地址、系统信息、镜像版本等;

                报告 UI 效果会持续优化;

                查看报告

                • 本地执行

                report/allure 目录下会生成一堆文本文件,这些是 allure 插件生成的报告源数据,我们在 report/allure_html 目录下给你生成了 html 文件,但是你不能直接通过浏览器打开 index.html 文件,因为 allure 的报告都是基于在线的服务。

                可以直接在 Pycharm 里面找到 index.html 文件,然后右键选择浏览器打开;

                或者你可以用一个 http 服务打开。

                shell
                cd report/allure_html
                -python3 -m http.server

                然后在浏览器访问:127.0.0.1:8000

                • 远程执行

                远程执行结束之后,会将所有远程测试机的测试报告都收集到 report/allure 目录下,分别按照机器的 IP 等建了不同的目录,你可以在这些目录里面去查看对应的测试报告,查看方法和前面本地执行查看的方法一样。

                - +python3 -m http.server

                然后在浏览器访问:127.0.0.1:8000

                • 远程执行

                远程执行结束之后,会将所有远程测试机的测试报告都收集到 report/allure 目录下,分别按照机器的 IP 等建了不同的目录,你可以在这些目录里面去查看对应的测试报告,查看方法和前面本地执行查看的方法一样。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\351\224\256\351\274\240\346\223\215\344\275\234.html" "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\351\224\256\351\274\240\346\223\215\344\275\234.html" index 73c14ee0..4d7293a4 100644 --- "a/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\351\224\256\351\274\240\346\223\215\344\275\234.html" +++ "b/\346\214\207\345\215\227/\346\241\206\346\236\266\345\277\205\345\244\207/\351\224\256\351\274\240\346\223\215\344\275\234.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                键鼠操作

                YouQu 键鼠操作模块集成了多个键鼠操作的方案:PyAutoGUIXdotoolwayland_autotool

                有同学肯定要问,我之前就只用 PyAutoGUI 也都挺好的,好像用不到这么多键鼠操作的东西吧;

                任何模块当然是希望越简洁通用越好,但问题是没有一种方案是通用的,它们都有自己存在的问题或者说不适用的场景,如果你还没有遇到,只能说使用的场景还不够多。

                常规键鼠操作

                YouQu 的键鼠操作模块主要有两个:MouseKeyShortCut

                分别是 键鼠的基本操作模块快捷键模块,基本上你能用到的键鼠操作,这里都包含了,在用例里面只需要通过方法层的类对象直接调用即可,比如:

                python
                from apps.autotest_deepin_music.widget.deepin_music_widget import DeepinMusicWidget
                +    
                Skip to content
                📔 阅读量:

                键鼠操作

                YouQu 键鼠操作模块集成了多个键鼠操作的方案:PyAutoGUIXdotoolwayland_autotool

                有同学肯定要问,我之前就只用 PyAutoGUI 也都挺好的,好像用不到这么多键鼠操作的东西吧;

                任何模块当然是希望越简洁通用越好,但问题是没有一种方案是通用的,它们都有自己存在的问题或者说不适用的场景,如果你还没有遇到,只能说使用的场景还不够多。

                常规键鼠操作

                YouQu 的键鼠操作模块主要有两个:MouseKeyShortCut

                分别是 键鼠的基本操作模块快捷键模块,基本上你能用到的键鼠操作,这里都包含了,在用例里面只需要通过方法层的类对象直接调用即可,比如:

                python
                from apps.autotest_deepin_music.widget.deepin_music_widget import DeepinMusicWidget
                 
                 DeepinMusicWidget.click()
                 DeepinMusicWidget.ctrl_c()

                当然你也可以直接通过 src 导入使用:

                python
                from src import Src
                @@ -519,8 +519,8 @@
                         """
                         logger.debug("清空表单")
                         cls.hot_key("ctrl", "a")
                -        cls.press_key("backspace")
                - + cls.press_key("backspace")
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/Wayland\351\200\202\351\205\215.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/Wayland\351\200\202\351\205\215.html" index b8a46723..8ae65a96 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/Wayland\351\200\202\351\205\215.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/Wayland\351\200\202\351\205\215.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                Wayland 适配

                Wayland 下自动化主要问题是 X11 下的键鼠操作方法无法使用,比如 XdotoolPyAutoGUIXwininfo 等等;

                YouQu 在 Wayland 下兼容适配,env.shWayland 下执行时会安装自研的键鼠操作服务(可能存在一些依赖报错,按照注释解决即可),框架核心库也针对性的做了适配,上层用例完全不用关心机器是Wayland 还是 X11,框架会根据执行时状态自动判断走不同的逻辑;

                简单讲就是,应用库只需要维护一套用例脚本即可。

                【用例兼容】

                因为 Wayland 下有些应用的界面显示和功能本身存在一些差异,用例层可能需要对这部分用例做逻辑判断,使用全局配置里面的常量进行逻辑编写即可:

                python
                from setting import conf
                +    
                Skip to content
                📔 阅读量:

                Wayland 适配

                Wayland 下自动化主要问题是 X11 下的键鼠操作方法无法使用,比如 XdotoolPyAutoGUIXwininfo 等等;

                YouQu 在 Wayland 下兼容适配,env.shWayland 下执行时会安装自研的键鼠操作服务(可能存在一些依赖报错,按照注释解决即可),框架核心库也针对性的做了适配,上层用例完全不用关心机器是Wayland 还是 X11,框架会根据执行时状态自动判断走不同的逻辑;

                简单讲就是,应用库只需要维护一套用例脚本即可。

                【用例兼容】

                因为 Wayland 下有些应用的界面显示和功能本身存在一些差异,用例层可能需要对这部分用例做逻辑判断,使用全局配置里面的常量进行逻辑编写即可:

                python
                from setting import conf
                 
                 # GlobalConfig.IS_WAYLAND 获取到当前的显示服务器(bool)
                 # 应用库 Config 继承 GlobalConfig
                @@ -30,8 +30,8 @@
                     pass

                比如用例里面如果断言的图片不同:

                python
                if conf.IS_WAYLAND:
                     self.assert_image_exist("wayland_XXX")
                 else:
                -    self.assert_image_exist("x11_XXX")

                这样这条用例脚本在 WaylandX11 下都可以跑,so easy 是不是?完全没必要专门拉新分支进行 Wayland 适配。

                - + self.assert_image_exist("x11_XXX")

                这样这条用例脚本在 WaylandX11 下都可以跑,so easy 是不是?完全没必要专门拉新分支进行 Wayland 适配。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/WebUI.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/WebUI.html" index 3c902a4c..2748c0e2 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/WebUI.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/WebUI.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                WebUI

                YouQu 基于 Playwright 驱动浏览器实现 WebUI 自动化测试。

                市面上耳熟能详的可用于 Web UI 自动化测试工具:SeleniumCypressPuppeteerPlaywright

                咱们先初步排除掉一些明显不用的:

                • Cypress,只支持 JavaScript,而我们自动化人员大多使用 PythonJavaScript 不熟悉,排除。
                • Puppeteer,只支持谷歌浏览器,格局没打开,官方不支持 Python,排除。

                剩下 SeleniumPlaywright,我们从一些方面做对比:

                对比指标SeleniumPlaywright
                环境安装难度
                运行速度
                元素等待
                智能定位
                稳定性
                文档
                接口测试

                总结:

                Playwright 作为一个比较新的工具,在文档方便确实没有老牌的 Selenium 完善,特别是一些示例、方法的使用说明,都还不够好,甚至有些就没有说明,但基本的使用该有的都有。

                除了文档方面,Playwright 几乎在各方面碾压 Selenium,很明显 Playwright 以绝对优势获胜。

                实践方法

                参考章节 【Web UI 自动化测试】

                断言方法

                YouQu 框架统一提供断言语句,以保持统一的断言语句风格。

                python
                # src/webui.py
                +    
                Skip to content
                📔 阅读量:

                WebUI

                YouQu 基于 Playwright 驱动浏览器实现 WebUI 自动化测试。

                市面上耳熟能详的可用于 Web UI 自动化测试工具:SeleniumCypressPuppeteerPlaywright

                咱们先初步排除掉一些明显不用的:

                • Cypress,只支持 JavaScript,而我们自动化人员大多使用 PythonJavaScript 不熟悉,排除。
                • Puppeteer,只支持谷歌浏览器,格局没打开,官方不支持 Python,排除。

                剩下 SeleniumPlaywright,我们从一些方面做对比:

                对比指标SeleniumPlaywright
                环境安装难度
                运行速度
                元素等待
                智能定位
                稳定性
                文档
                接口测试

                总结:

                Playwright 作为一个比较新的工具,在文档方便确实没有老牌的 Selenium 完善,特别是一些示例、方法的使用说明,都还不够好,甚至有些就没有说明,但基本的使用该有的都有。

                除了文档方面,Playwright 几乎在各方面碾压 Selenium,很明显 Playwright 以绝对优势获胜。

                实践方法

                参考章节 【Web UI 自动化测试】

                断言方法

                YouQu 框架统一提供断言语句,以保持统一的断言语句风格。

                python
                # src/webui.py
                 
                 class WebAssert:
                     
                @@ -28,8 +28,8 @@
                     def assert_locator(
                         locator: Union[Page, Locator, APIResponse],
                     ) -> Union[PageAssertions, LocatorAssertions, APIResponseAssertions]:
                -        return _expect(locator)
                - + return _expect(locator)
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.html" index 02ed7e6a..677492a0 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\205\250\350\207\252\345\212\250\346\227\245\345\277\227.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                全自动日志——funnylog

                背景

                基于 YouQu 自动化测试框架操作方法封装写法,通常是这样的:类里面一个函数只包含一个操作或多次调用的一系列可合并的操作;

                传统的日志输出方式,需要在每个函数里面主动编写日志输出代码 ,例如:

                python
                class XXXWidget:
                +    
                Skip to content
                📔 阅读量:

                全自动日志——funnylog

                背景

                基于 YouQu 自动化测试框架操作方法封装写法,通常是这样的:类里面一个函数只包含一个操作或多次调用的一系列可合并的操作;

                传统的日志输出方式,需要在每个函数里面主动编写日志输出代码 ,例如:

                python
                class XXXWidget:
                     
                     def click_xxx(self):
                         """点击某个元素"""
                @@ -64,8 +64,8 @@
                         :return:
                         """
                         element = tuple(map(lambda x: f"{Config.PIC_RES_PATH}/{x}", elements))
                -        return cls.find_image(*element, multiple=multiple)

                调用方法时:

                python
                DfmWidget.find_dfm_image("dfm_001")

                自动输出的日志:

                shell
                >> x86_64-uos-6: 02/28 17:48:47 | INFO  | logger_utils: [find_dfm_image]: 查找图片 dfm_001.png 在屏幕中相似度大于 0.9 的坐标

                加上装饰器 @log 之后,方法层所有的函数(包括实例方法、类方法、静态方法)都不需要再写日志代码,执行的时候会自动输出,并且所有调用的方法会以 allure.step 的方式,展示在 allure 报告中,在报告中更能一目了然的看到用例执行步骤。

                日志模板语法

                通过观察前面的例子,细心的同学可能还发现了一个小细节:函数功能说明中,两对大括号中的内容 作为变量输出出来了;

                没错,这就是我们参考Djangojinja2 的模板语法设计出的日志模板语法,使用方法很简单,用两对大括号把函数的参数括起来,这样在日志输出的时候就能把调用函数时参数的值输出出来。

                - + return cls.find_image(*element, multiple=multiple)

                调用方法时:

                python
                DfmWidget.find_dfm_image("dfm_001")

                自动输出的日志:

                shell
                >> x86_64-uos-6: 02/28 17:48:47 | INFO  | logger_utils: [find_dfm_image]: 查找图片 dfm_001.png 在屏幕中相似度大于 0.9 的坐标

                加上装饰器 @log 之后,方法层所有的函数(包括实例方法、类方法、静态方法)都不需要再写日志代码,执行的时候会自动输出,并且所有调用的方法会以 allure.step 的方式,展示在 allure 报告中,在报告中更能一目了然的看到用例执行步骤。

                日志模板语法

                通过观察前面的例子,细心的同学可能还发现了一个小细节:函数功能说明中,两对大括号中的内容 作为变量输出出来了;

                没错,这就是我们参考Djangojinja2 的模板语法设计出的日志模板语法,使用方法很简单,用两对大括号把函数的参数括起来,这样在日志输出的时候就能把调用函数时参数的值输出出来。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\244\261\350\264\245\345\275\225\345\261\217.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\244\261\350\264\245\345\275\225\345\261\217.html" index 3eb58675..eddb0152 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\244\261\350\264\245\345\275\225\345\261\217.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\345\244\261\350\264\245\345\275\225\345\261\217.html" @@ -8,26 +8,26 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                失败录屏

                录屏其实是一种视频形式的日志,因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因,因此用例的录屏能让我们看到用例在执行过程;

                【使用方法】

                globalconfig.ini 里面配置关注 2 个参数;

                ini
                ;失败用例重跑次数
                +    
                Skip to content
                📔 阅读量:

                失败录屏

                录屏其实是一种视频形式的日志,因为很多时候我们在查看日志之后仍然无法准确的定位到用例失败的具体原因,因此用例的录屏能让我们看到用例在执行过程;

                【使用方法】

                globalconfig.ini 里面配置关注 2 个参数;

                ini
                ;失败用例重跑次数
                 RERUN = 1
                 
                 ;失败录屏从第几次开始录制视频。
                 ;比如 RECORD_FAILED_CASE = 1 ,表示用例第1次执行失败之后开始录屏。
                 ;注意,用例失败重跑的次数不能小于失败录屏次数,即 RERUN >= RECORD_FAILED_CASE
                -RECORD_FAILED_CASE = 1

                默认失败重跑的次数是 1 次;

                RECORD_FAILED_CASE = 1 表示用例第1次执行失败之后开始录屏;

                RECORD_FAILED_CASE = 0 表示不管用例成功或失败都录屏;

                录屏是要占用系统资源的,特别是在一些配置较低的机器上会很明显,所以你需要考虑是否有必要每条用例都录屏;

                使用 manage.py 执行用例默认读取到 globalconfig.ini 里面的参数,执行完之后会在 report/record 目录下保存失败用例的录屏和断言的那个时间点的截屏,你可以通过视频文件看到失败用例执行过程都发生了什么。

                - +RECORD_FAILED_CASE = 1

                默认失败重跑的次数是 1 次;

                RECORD_FAILED_CASE = 1 表示用例第1次执行失败之后开始录屏;

                RECORD_FAILED_CASE = 0 表示不管用例成功或失败都录屏;

                录屏是要占用系统资源的,特别是在一些配置较低的机器上会很明显,所以你需要考虑是否有必要每条用例都录屏;

                使用 manage.py 执行用例默认读取到 globalconfig.ini 里面的参数,执行完之后会在 report/record 目录下保存失败用例的录屏和断言的那个时间点的截屏,你可以通过视频文件看到失败用例执行过程都发生了什么。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\225\260\346\215\256\345\233\236\345\241\253.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\225\260\346\215\256\345\233\236\345\241\253.html" index db562792..196e66ed 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\225\260\346\215\256\345\233\236\345\241\253.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\225\260\346\215\256\345\233\236\345\241\253.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                PMS数据回填

                测试单关联的用例,自动化测试对应的去跑这些关联的用例,并且将执行的结果回填的测试用例的状态里面。

                本机执行时回填

                PMS 数据回填主要有三种方式:

                (1)异步回填

                在用例执行的过程中,采用异步的方式去进行数据回填,直白的讲就是,第二条用例开始跑的时候,通过子线程去做第一条用例的数据回填,如此循环,直到所有用例执行结束;

                这种方案的时间效率最高的,因为理论上用例的执行时间是大于数据回填的接口请求时间的,也就是说,当用例执行完之后,数据回填也完成了。

                【方法一】配置文件

                使用方法,在 globalconfig.ini 里面配置以下参数:(以下涉及到的参数配置都是在配置文件里面进行配置)

                ini
                PMS_USER = PMS账号
                +    
                Skip to content
                📔 阅读量:

                PMS数据回填

                测试单关联的用例,自动化测试对应的去跑这些关联的用例,并且将执行的结果回填的测试用例的状态里面。

                本机执行时回填

                PMS 数据回填主要有三种方式:

                (1)异步回填

                在用例执行的过程中,采用异步的方式去进行数据回填,直白的讲就是,第二条用例开始跑的时候,通过子线程去做第一条用例的数据回填,如此循环,直到所有用例执行结束;

                这种方案的时间效率最高的,因为理论上用例的执行时间是大于数据回填的接口请求时间的,也就是说,当用例执行完之后,数据回填也完成了。

                【方法一】配置文件

                使用方法,在 globalconfig.ini 里面配置以下参数:(以下涉及到的参数配置都是在配置文件里面进行配置)

                ini
                PMS_USER = PMS账号
                 PMS_PASSWORD = PMS密码
                 SEND_PMS = async
                 TASK_ID = 测试单ID
                @@ -35,8 +35,8 @@
                 SEND_PMS = finish
                 TASK_ID = 测试单ID
                 TRIGGER = hand
                -APP_NAME =

                后续手动回填方法:

                shell
                youqu manage.py pmsctl --send2task yes

                远程执行时回填

                远程执行需要控制多台测试机同时执行用例,也就是说同一条用例会在多台机器上同时执行,但是执行结果可能不一致;

                因此,远程执行的数据回填需要等所有测试机执行结束之后,服务端收集到测试结果,并对测试结果做处理(只要有1个机器上用例失败,那此用例为失败)之后,在进行数据回填;

                使用方法:

                shell
                youqu manage.py remote -c uos@10.8.13.xx/uos@10.8.13.yy -a apps/autotest_xxx -u ut001234 -p my_password --task_id xxxx --send_pms finish

                执行结束之后在 report 目录下会有 pms_xxx 开头的目录,里面保存了所有远程测试机的测试结果,以及汇总的结果;

                可能遇到的“问题”

                有同学可能会发现,怎么回填一次之后,后面想再次回填就不生效了;

                这是因为为了应对前面提到的多种数据回填的方式,在 report 目录下会有 pms_xxx 开头的目录,用于记录了用例的执行结果和回填情况,如果这条用例之前已经回填过了,后续就不会再此触发回填了;

                如果你想重新做回填,你可以把 report/pms_xxx 目录删掉,这样就可以重新做数据回填了;

                - +APP_NAME =

                后续手动回填方法:

                shell
                youqu manage.py pmsctl --send2task yes

                远程执行时回填

                远程执行需要控制多台测试机同时执行用例,也就是说同一条用例会在多台机器上同时执行,但是执行结果可能不一致;

                因此,远程执行的数据回填需要等所有测试机执行结束之后,服务端收集到测试结果,并对测试结果做处理(只要有1个机器上用例失败,那此用例为失败)之后,在进行数据回填;

                使用方法:

                shell
                youqu manage.py remote -c uos@10.8.13.xx/uos@10.8.13.yy -a apps/autotest_xxx -u ut001234 -p my_password --task_id xxxx --send_pms finish

                执行结束之后在 report 目录下会有 pms_xxx 开头的目录,里面保存了所有远程测试机的测试结果,以及汇总的结果;

                可能遇到的“问题”

                有同学可能会发现,怎么回填一次之后,后面想再次回填就不生效了;

                这是因为为了应对前面提到的多种数据回填的方式,在 report 目录下会有 pms_xxx 开头的目录,用于记录了用例的执行结果和回填情况,如果这条用例之前已经回填过了,后续就不会再此触发回填了;

                如果你想重新做回填,你可以把 report/pms_xxx 目录删掉,这样就可以重新做数据回填了;

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.html" index aa4d8689..ea33a726 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\214\226\347\256\241\347\220\206.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                标签化管理

                标签说明

                根据现有业务需要,用例需要添加的标签有:

                • 脚本 ID :自动化用例脚本/函数 ID
                • *PMS用例ID :PMS 上对应的用例 ID(用例库 ID)
                • 用例级别 :对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示
                • 用例类型 :FUNC(功能)、PERF(性能)、STR(压力)、SEC(安全)、CTS(兼容性)、API(接口)、BASELINE(基线-预留)
                • *设备类型 :PPL(依赖外设的用例)、COL(依赖主控机的用例)
                • 一二级bug自动化 :BUG(由 Bug 转的用例)
                • *上线对象 :CICD,表示上线到 CICD 流水线的用例
                • 跳过原因 :skip-XXX,用于控制用例是否执行
                • 确认修复 :fixed-XXX,用于标记用例的修复状态
                • 废弃用例 :removed-已废弃,用于标记已经废弃的用例,此用例标签不会被添加,也不会被执行

                示例:

                脚本ID*PMS用例ID用例级别用例类型*设备类型一二级bug自动化*上线对象跳过原因确认修复废弃用例...
                679537679537L1FUNCPPLBUGCICDskip-XXXfixed-XXXremoved-已废弃...

                操作步骤

                1. 在子项目目录下新建 csv 文件,用于保存用例标签,以 用例脚本的 py 文件去掉首字符串 "test_" ,去掉用例序号后的字符串,取中间的名称作为 csv 文件的文件名 。

                  例如: 相册的用例文件为 test_album_xxx.py,xxx 表示用例的ID(也可以是自定义的数字代表用例序号),此时 csv 文件名就应为 album.csv

                  对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,所有 csv 文件建议放在一个 tags 目录下。

                  是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

                2. 第一列为脚本 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;用例标签可以无序。

                跳过用例

                传统跳过用例的方式是在用例脚本里面给用例添加装饰器(@pytest.mark.skip),解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多;

                将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;

                1. 固定跳过

                示例:

                脚本ID...(各种用例标签)跳过原因
                679537...skip-受到某新需求影响
                • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标签开头为 “skip-XXX”;
                • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标签,存在跳过标签则用例也不会被执行,最终的用例状态会被标签为 SKIPED

                2. 条件判断跳过

                示例:

                脚本ID...(各种用例标签)跳过原因
                001...skipif_platform-aarch64&mips64
                • 某些用例会因为不同的环境判断用例是否执行,常见的场景为在不同架构上判断是否执行,跳过的原因标签为 “skipif_platform-” 加架构名,多个架构之间使用 “&” 拼接;
                • 以上例子为用例执行时,判断当前架构是否为 arrch64 或者 mips64,若是,则跳过用例不执行,若否则执行用例;

                在项目目录路径下存在文件 setting/skipif.py,所有条件判断跳过的函数写在此文件中。

                python
                #!/usr/bin/env python3
                +    
                Skip to content
                📔 阅读量:

                标签化管理

                标签说明

                根据现有业务需要,用例需要添加的标签有:

                • 脚本 ID :自动化用例脚本/函数 ID
                • *PMS用例ID :PMS 上对应的用例 ID(用例库 ID)
                • 用例级别 :对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示
                • 用例类型 :FUNC(功能)、PERF(性能)、STR(压力)、SEC(安全)、CTS(兼容性)、API(接口)、BASELINE(基线-预留)
                • *设备类型 :PPL(依赖外设的用例)、COL(依赖主控机的用例)
                • 一二级bug自动化 :BUG(由 Bug 转的用例)
                • *上线对象 :CICD,表示上线到 CICD 流水线的用例
                • 跳过原因 :skip-XXX,用于控制用例是否执行
                • 确认修复 :fixed-XXX,用于标记用例的修复状态
                • 废弃用例 :removed-已废弃,用于标记已经废弃的用例,此用例标签不会被添加,也不会被执行

                示例:

                脚本ID*PMS用例ID用例级别用例类型*设备类型一二级bug自动化*上线对象跳过原因确认修复废弃用例...
                679537679537L1FUNCPPLBUGCICDskip-XXXfixed-XXXremoved-已废弃...

                操作步骤

                1. 在子项目目录下新建 csv 文件,用于保存用例标签,以 用例脚本的 py 文件去掉首字符串 "test_" ,去掉用例序号后的字符串,取中间的名称作为 csv 文件的文件名 。

                  例如: 相册的用例文件为 test_album_xxx.py,xxx 表示用例的ID(也可以是自定义的数字代表用例序号),此时 csv 文件名就应为 album.csv

                  对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,所有 csv 文件建议放在一个 tags 目录下。

                  是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

                2. 第一列为脚本 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;用例标签可以无序。

                跳过用例

                传统跳过用例的方式是在用例脚本里面给用例添加装饰器(@pytest.mark.skip),解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多;

                将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;

                1. 固定跳过

                示例:

                脚本ID...(各种用例标签)跳过原因
                679537...skip-受到某新需求影响
                • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标签开头为 “skip-XXX”;
                • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标签,存在跳过标签则用例也不会被执行,最终的用例状态会被标签为 SKIPED

                2. 条件判断跳过

                示例:

                脚本ID...(各种用例标签)跳过原因
                001...skipif_platform-aarch64&mips64
                • 某些用例会因为不同的环境判断用例是否执行,常见的场景为在不同架构上判断是否执行,跳过的原因标签为 “skipif_platform-” 加架构名,多个架构之间使用 “&” 拼接;
                • 以上例子为用例执行时,判断当前架构是否为 arrch64 或者 mips64,若是,则跳过用例不执行,若否则执行用例;

                在项目目录路径下存在文件 setting/skipif.py,所有条件判断跳过的函数写在此文件中。

                python
                #!/usr/bin/env python3
                 # _*_ coding:utf-8 _*_
                 # SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
                 # SPDX-License-Identifier: GPL-2.0-only
                @@ -126,8 +126,8 @@
                         f"echo '{GlobalConfig.PASSWORD}'| "
                         "sudo -S dmidecode -s system-product-name | awk '{print $NF}'"
                     ).read().split("\n")[0]
                -    print(a)

                方法编写规范:

                • 方法名必须以 skipif 开头;
                • 方法必须有返回结果并且为布尔值(True 代表跳过,False 代表不跳过);
                • 方法只能有一个入参;

                csv 文件跳过原因一栏中填写为 “{函数名}-{参数}”,例如:skipif_platform-aarch64;在用例收集阶段会以第一个 “-” 进行分割,截取的左侧字符串作为函数名,在 skipif.py 文件中查找是否有同名函数,并将截取的右侧作为参数传递给该函数,通过获取该函数返回的布尔值,返回 True,则用例不执行,返回 False,则执行该用例。

                重要

                • 若函数需要多个参数,可自定义多个参数之间的连接符,连接符号不可使用下划线和逗号,推荐统一使用 & 符号;

                • 若需要多个 skipif 条件判断组合,使用 && 符号将两个方法分开,比如:skipif_platform-aarch64&&skipif_xdg_type-wayland

                确认修复

                针对于某些用例修复后,但不能立即删除跳过原因(skip-XXX)的用例,新增一列标签名为 “确认修复”,作为标记该用例是否已经修复,固定填入字段为 “fixed-已修复”。这样这条用例即使同时标记了 skip-XXX 也会正常执行。

                示例:

                用例ID...(各种用例标签)跳过原因确认修复
                679537...skip-受到某新需求影响fixed-已修复

                【同时标记了skipfixed,但仍然想要跳过用例】

                当 “跳过原因” 和 “确认修复” 中同时填入后,命令行传递参数 --ifixed yes,则代码不会执行该条用例。

                shell
                python3 manage.py run --ifixed yes

                看到这里有些同学可能要问了,我想恢复跳过执行,直接把 skip-XXX 这一列标签删掉不就好了,还搞什么确认修复干啥?

                这里给各位看官稍微解释一下:

                (以下流水线指的是每日构建的流水线,跑 AT 的全量用例)

                首先,流水线上跑的是 AT 历史 Tag,跳过用例的标签(skip-XXX) 是在最新的代码上提交的,我们采用最新的 csv 文件覆盖历史 csv 文件的设计来实现了对历史 Tag 上用例的跳过;

                然后,在日常跳过用例的过程中,同时也在修复一些用例,修复后的这些用例在本地调试的时候我们不希望继续跳过,但是此时,修复的这些用例可能还不稳定,不适合马上放到流水线去跑,也就是说流水线上我们是希望他继续跳过的,因此,咱不能直接把 skip-XXX 干掉;

                这里就矛盾了,一个需求是想修复了立马解除跳过,另一个需求又不想修复了立马解除跳过,怎么办呢?

                我们使用“确认修复”来标记这条用例已经修复了,这样你本地调试用例的时候这条已修复的用例是会执行的,同时在流水线上将 --ifixed yes 参数加上,那么流水线上执行时这条用例仍然是跳过的状态,后续你打 Tag 的时候,把 “跳过原因” 和 “确认修复” 中的标签全部删掉就可以了。

                这就是“确认修复”这个标签的背景,需要各位看官稍微品一品。

                废弃用例

                针对某些用例,由于需求变更,环境影响或评估不再适用于自动化测试时,用例需要废弃,则新增一列标签名为 “废弃用例”,该列存在 “removed-{废弃原因}”,则用例不会执行。

                用例ID...(各种用例标签)跳过原因确认修复废弃用例
                679537...skip-受到某新需求影响fixed-已修复removed-已废弃

                设计思路

                上面介绍 Pytest 框架提供的标签功能 mark,使用时需要为每一个用例添加标签装饰器,则操作复杂,可维护性差,其根本问题就是标签分散在每一条用例的装饰器上,难以集中维护;于是乎将所有标签使用 csv 文件进行集中管理,并通过 Pytest 的钩子函数,读取 csv 文件,动态添加标签到用例中。

                CSV文件格式

                此配置文件需要维护大量的标签数据,且要方便能使用 Excel 打开进行编辑查看,更重要的是我们不想引入三方依赖,CSV 文件几乎是唯一能满足所有的要求的文件格式。

                - + print(a)

                方法编写规范:

                • 方法名必须以 skipif 开头;
                • 方法必须有返回结果并且为布尔值(True 代表跳过,False 代表不跳过);
                • 方法只能有一个入参;

                csv 文件跳过原因一栏中填写为 “{函数名}-{参数}”,例如:skipif_platform-aarch64;在用例收集阶段会以第一个 “-” 进行分割,截取的左侧字符串作为函数名,在 skipif.py 文件中查找是否有同名函数,并将截取的右侧作为参数传递给该函数,通过获取该函数返回的布尔值,返回 True,则用例不执行,返回 False,则执行该用例。

                重要

                • 若函数需要多个参数,可自定义多个参数之间的连接符,连接符号不可使用下划线和逗号,推荐统一使用 & 符号;

                • 若需要多个 skipif 条件判断组合,使用 && 符号将两个方法分开,比如:skipif_platform-aarch64&&skipif_xdg_type-wayland

                确认修复

                针对于某些用例修复后,但不能立即删除跳过原因(skip-XXX)的用例,新增一列标签名为 “确认修复”,作为标记该用例是否已经修复,固定填入字段为 “fixed-已修复”。这样这条用例即使同时标记了 skip-XXX 也会正常执行。

                示例:

                用例ID...(各种用例标签)跳过原因确认修复
                679537...skip-受到某新需求影响fixed-已修复

                【同时标记了skipfixed,但仍然想要跳过用例】

                当 “跳过原因” 和 “确认修复” 中同时填入后,命令行传递参数 --ifixed yes,则代码不会执行该条用例。

                shell
                python3 manage.py run --ifixed yes

                看到这里有些同学可能要问了,我想恢复跳过执行,直接把 skip-XXX 这一列标签删掉不就好了,还搞什么确认修复干啥?

                这里给各位看官稍微解释一下:

                (以下流水线指的是每日构建的流水线,跑 AT 的全量用例)

                首先,流水线上跑的是 AT 历史 Tag,跳过用例的标签(skip-XXX) 是在最新的代码上提交的,我们采用最新的 csv 文件覆盖历史 csv 文件的设计来实现了对历史 Tag 上用例的跳过;

                然后,在日常跳过用例的过程中,同时也在修复一些用例,修复后的这些用例在本地调试的时候我们不希望继续跳过,但是此时,修复的这些用例可能还不稳定,不适合马上放到流水线去跑,也就是说流水线上我们是希望他继续跳过的,因此,咱不能直接把 skip-XXX 干掉;

                这里就矛盾了,一个需求是想修复了立马解除跳过,另一个需求又不想修复了立马解除跳过,怎么办呢?

                我们使用“确认修复”来标记这条用例已经修复了,这样你本地调试用例的时候这条已修复的用例是会执行的,同时在流水线上将 --ifixed yes 参数加上,那么流水线上执行时这条用例仍然是跳过的状态,后续你打 Tag 的时候,把 “跳过原因” 和 “确认修复” 中的标签全部删掉就可以了。

                这就是“确认修复”这个标签的背景,需要各位看官稍微品一品。

                废弃用例

                针对某些用例,由于需求变更,环境影响或评估不再适用于自动化测试时,用例需要废弃,则新增一列标签名为 “废弃用例”,该列存在 “removed-{废弃原因}”,则用例不会执行。

                用例ID...(各种用例标签)跳过原因确认修复废弃用例
                679537...skip-受到某新需求影响fixed-已修复removed-已废弃

                设计思路

                上面介绍 Pytest 框架提供的标签功能 mark,使用时需要为每一个用例添加标签装饰器,则操作复杂,可维护性差,其根本问题就是标签分散在每一条用例的装饰器上,难以集中维护;于是乎将所有标签使用 csv 文件进行集中管理,并通过 Pytest 的钩子函数,读取 csv 文件,动态添加标签到用例中。

                CSV文件格式

                此配置文件需要维护大量的标签数据,且要方便能使用 Excel 打开进行编辑查看,更重要的是我们不想引入三方依赖,CSV 文件几乎是唯一能满足所有的要求的文件格式。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\257\274\345\207\272.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\257\274\345\207\272.html" index f80f87df..a043b2c0 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\257\274\345\207\272.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\345\257\274\345\207\272.html" @@ -8,23 +8,23 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                导出CSV文件

                【使用方法一】

                框架提供导出指定标签用例的功能:

                shell
                youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD -ec case_list.csv

                表示导出 deepin-album 的用例中标记了 CICD 标签的用例,导出 CSV 文件的字段格式已经适配了 CICD 的要求。

                【使用方法二】

                也可以使用配置文件选项:

                ini
                ;导出的csv文件名称,比如:case_list.csv
                +    
                Skip to content
                📔 阅读量:

                导出CSV文件

                【使用方法一】

                框架提供导出指定标签用例的功能:

                shell
                youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD -ec case_list.csv

                表示导出 deepin-album 的用例中标记了 CICD 标签的用例,导出 CSV 文件的字段格式已经适配了 CICD 的要求。

                【使用方法二】

                也可以使用配置文件选项:

                ini
                ;导出的csv文件名称,比如:case_list.csv
                 EXPORT_CSV_FILE =

                命令行执行:

                shell
                youqu manage.py csvctl -a apps/autotest_deepin_album -t CICD

                参数说明:

                ini
                -a 如果不给就是apps目录下所有的;
                 -t 要导出用例的标签;
                -case_list.csv 文件名称可以自定义,在report目录下会自动生成;
                - +case_list.csv 文件名称可以自定义,在report目录下会自动生成;
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.html" index e622349f..c8314ecb 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\346\240\207\347\255\276\350\207\252\345\212\250\345\220\214\346\255\245.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                标签自动同步

                自动同步脚本 ID 到 CSV 文件

                支持自动同步脚本 ID(用例 py 文件的 ID)到 CSV 文件;

                【使用方法一】

                配置文件方式,通过一下几个配置来控制:

                ini
                [csvctl]
                +    
                Skip to content
                📔 阅读量:

                标签自动同步

                自动同步脚本 ID 到 CSV 文件

                支持自动同步脚本 ID(用例 py 文件的 ID)到 CSV 文件;

                【使用方法一】

                配置文件方式,通过一下几个配置来控制:

                ini
                [csvctl]
                 ;将py文件的case id同步到csv文件
                 ;yes, 开启同步
                 ;no, 关闭同步
                @@ -35,8 +35,8 @@
                 ;因此应该配置为: music = 81
                 ;这样才能将PMS与本地CSV文件建立联系。
                 ;如果你的应用分了很多模块,只需要将对应的信息依次配置好就行了。
                -music = 53

                将以上信息配置好之后,在命令行执行:

                shell
                youqu manage.py pmsctl -p2c

                每次执行时原 CSV 文件会自动备份在 report 目录下,因此你不用担心脚本执行导致你的数据丢失。

                【使用方法二】

                按照我们一贯的风格,你也可以不去管配置文件,完全通过命令行参数传入:

                youqu manage.py pmsctl -p2c -u ut00xxxx -p you_password -plc music:81

                每次操作会将 CSV 文件先备份到 report/pms2csv_back 目录下;

                - +music = 53

                将以上信息配置好之后,在命令行执行:

                shell
                youqu manage.py pmsctl -p2c

                每次执行时原 CSV 文件会自动备份在 report 目录下,因此你不用担心脚本执行导致你的数据丢失。

                【使用方法二】

                按照我们一贯的风格,你也可以不去管配置文件,完全通过命令行参数传入:

                youqu manage.py pmsctl -p2c -u ut00xxxx -p you_password -plc music:81

                每次操作会将 CSV 文件先备份到 report/pms2csv_back 目录下;

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" index 3a67cf63..39e0d531 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\350\277\234\347\250\213\344\272\244\344\272\222\345\274\217\346\216\247\345\210\266.html" @@ -8,20 +8,20 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                远程交互式控制

                在用例执行过程中控制远程机器执行复杂的 UI 操作或命令行操作。

                在远程测试机上部署一个完整的 YouQu 环境以提供 UI 交互的基础能力,然后将这些基础能力通过 RPC 服务的方式提供出来,在服务端通过调用 RPC 接口从而控制远程机器执行用例步骤。

                slaves对象提供远程机器信息

                slaves 是 YouQu 提供的一个全局对象,它保存了远程测试机的信息列表;

                机器信息有 2 种方式传入:

                • 命令行

                  shell
                  youqu manage.py run --slaves root@192.168.1.1:password1

                  多个机器信息用 / 分割:root@192.168.1.1:password1/root@192.168.1.2:password2

                • 配置文件

                  setting/globalconfig.ini 里面:

                  ini
                  ;=============================== SLAVE CONFIG ===================================
                  +    
                  Skip to content
                  📔 阅读量:

                  远程交互式控制

                  在用例执行过程中控制远程机器执行复杂的 UI 操作或命令行操作。

                  在远程测试机上部署一个完整的 YouQu 环境以提供 UI 交互的基础能力,然后将这些基础能力通过 RPC 服务的方式提供出来,在服务端通过调用 RPC 接口从而控制远程机器执行用例步骤。

                  slaves对象提供远程机器信息

                  slaves 是 YouQu 提供的一个全局对象,它保存了远程测试机的信息列表;

                  机器信息有 2 种方式传入:

                  • 命令行

                    shell
                    youqu manage.py run --slaves root@192.168.1.1:password1

                    多个机器信息用 / 分割:root@192.168.1.1:password1/root@192.168.1.2:password2

                  • 配置文件

                    setting/globalconfig.ini 里面:

                    ini
                    ;=============================== SLAVE CONFIG ===================================
                     ;附属的测试机,用例步骤中与其他机器进行交互
                     ;        ┌─ slave ${user}@${ip}:${password}
                     ; master ┼─ slave mikigo@192.168.8.11:admin123
                    @@ -86,8 +86,8 @@
                             password="xxx", 
                             transfer_appname="autotest_my_app"  # APP工程的名称
                         )
                    -    r.start_terminal()

                    代码补全

                    所有的远程调用方法,都是通过 RPC 客户端对象提供的,本身无法提供代码补全,但我们仍然实现了,让你能像调用本地方法一样调用远程方法。

                  - + r.start_terminal()

                  代码补全

                  所有的远程调用方法,都是通过 RPC 客户端对象提供的,本身无法提供代码补全,但我们仍然实现了,让你能像调用本地方法一样调用远程方法。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.html" "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.html" index 9d67deb4..ee6ab639 100644 --- "a/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.html" +++ "b/\346\214\207\345\215\227/\347\211\271\350\211\262\345\212\237\350\203\275/\351\207\215\345\220\257\347\261\273\345\234\272\346\231\257.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                重启类场景

                对于重启类场景的用例需要解决的核心问题是,重启之后如何让用例能继续重启前的步骤继续执行,YouQu 集成了自研的 letmego 技术方案;

                详细技术方案、实现细节、Demo可以看 letmego 官方在线文档;

                使用方法

                使用方法很简单,只需要给应用方法层的唯一出口类加一个装饰器(@letmego.mark)即可:

                python
                import letmego
                +    
                Skip to content
                📔 阅读量:

                重启类场景

                对于重启类场景的用例需要解决的核心问题是,重启之后如何让用例能继续重启前的步骤继续执行,YouQu 集成了自研的 letmego 技术方案;

                详细技术方案、实现细节、Demo可以看 letmego 官方在线文档;

                使用方法

                使用方法很简单,只需要给应用方法层的唯一出口类加一个装饰器(@letmego.mark)即可:

                python
                import letmego
                 
                 @letmego.mark
                 class DeepinMusicWidget(WindowWidget, TitleWidget, PopWidget):
                @@ -51,8 +51,8 @@
                     @staticmethod
                     def reboot():
                         """letmego reboot"""
                -        os.system("echo '1' | sudo -S reboot")

                驱动执行

                因为重启类场景需要注册自启服务以及对用例执行过程的处理,驱动执行的时候加 --autostart yes :

                shell
                youqu manage.py run --autostart yes

                执行环境

                默认使用虚拟环境执行,也就是说如果您是部署自动化环境是用的 env_dev.sh 是无法使用此技术方案的,解决方法也很简单,执行一下:bash env.sh,以此激活虚拟环境即可。

                - + os.system("echo '1' | sudo -S reboot")

                驱动执行

                因为重启类场景需要注册自启服务以及对用例执行过程的处理,驱动执行的时候加 --autostart yes :

                shell
                youqu manage.py run --autostart yes

                执行环境

                默认使用虚拟环境执行,也就是说如果您是部署自动化环境是用的 env_dev.sh 是无法使用此技术方案的,解决方法也很简单,执行一下:bash env.sh,以此激活虚拟环境即可。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\216\257\345\242\203/\345\205\250\345\261\200\351\205\215\347\275\256.html" "b/\346\214\207\345\215\227/\347\216\257\345\242\203/\345\205\250\345\261\200\351\205\215\347\275\256.html" index 2090943f..474d4128 100644 --- "a/\346\214\207\345\215\227/\347\216\257\345\242\203/\345\205\250\345\261\200\351\205\215\347\275\256.html" +++ "b/\346\214\207\345\215\227/\347\216\257\345\242\203/\345\205\250\345\261\200\351\205\215\347\275\256.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                全局配置 - setting.conf

                配置文件

                全局配置模块 setting 包含了以下配置文件:

                (1)ini 配置文件

                主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

                (2)py 配置文件

                主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

                一些支持人工修改或自定义的配置项都在 ini 配置文件里面,py 文件是不需要人工去修改的;

                配置对象获取

                导入全局配置对象

                py
                from setting import conf

                通过 conf 对象能获取到所有可获取的配置项的值,比如:

                py
                conf.PASSWORD

                这样可以获取到 globalconfig.ini 配置文件中 PASSWORD 配置的值。

                除了上面这种导入方式,还可以这样导入:

                py
                from setting.globalconfig import GlobalConfig

                GlobalConfig 也是全局配置对象,实际上 confGlobalConfig 的别名,你可以根据自己喜欢选择用哪个;

                APP工程配置对象

                所有应用库配置对象都是继承框架的全局配置类的:

                python
                from setting.globalconfig import _GlobalConfig
                +    
                Skip to content
                📔 阅读量:

                全局配置 - setting.conf

                配置文件

                全局配置模块 setting 包含了以下配置文件:

                (1)ini 配置文件

                主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

                (2)py 配置文件

                主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

                一些支持人工修改或自定义的配置项都在 ini 配置文件里面,py 文件是不需要人工去修改的;

                配置对象获取

                导入全局配置对象

                py
                from setting import conf

                通过 conf 对象能获取到所有可获取的配置项的值,比如:

                py
                conf.PASSWORD

                这样可以获取到 globalconfig.ini 配置文件中 PASSWORD 配置的值。

                除了上面这种导入方式,还可以这样导入:

                py
                from setting.globalconfig import GlobalConfig

                GlobalConfig 也是全局配置对象,实际上 confGlobalConfig 的别名,你可以根据自己喜欢选择用哪个;

                APP工程配置对象

                所有应用库配置对象都是继承框架的全局配置类的:

                python
                from setting.globalconfig import _GlobalConfig
                 
                 class _Config(_GlobalConfig):
                     pass
                @@ -363,8 +363,8 @@
                 START_DATE =
                 
                 ;结束日期
                -END_DATE =
                - +END_DATE =
                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\216\257\345\242\203/\347\216\257\345\242\203\351\203\250\347\275\262.html" "b/\346\214\207\345\215\227/\347\216\257\345\242\203/\347\216\257\345\242\203\351\203\250\347\275\262.html" index 151982fb..e184cac2 100644 --- "a/\346\214\207\345\215\227/\347\216\257\345\242\203/\347\216\257\345\242\203\351\203\250\347\275\262.html" +++ "b/\346\214\207\345\215\227/\347\216\257\345\242\203/\347\216\257\345\242\203\351\203\250\347\275\262.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                环境部署 - env.sh

                安装

                项目根目录下运行 env.sh 即可。

                shell
                $ bash env.sh

                密码问题

                使用的默认密码是 1

                您可以使用 -p 选项传入密码:bash env.sh -p ${my_password}

                也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                定制依赖

                1. 新增依赖

                如果应用库还需要其他 Python 依赖库,只需要在应用库根目录下保存一个 requirement.txt 文件;

                shell
                autotest_xxx
                +    
                Skip to content
                📔 阅读量:

                环境部署 - env.sh

                安装

                项目根目录下运行 env.sh 即可。

                shell
                $ bash env.sh

                密码问题

                使用的默认密码是 1

                您可以使用 -p 选项传入密码:bash env.sh -p ${my_password}

                也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                定制依赖

                1. 新增依赖

                如果应用库还需要其他 Python 依赖库,只需要在应用库根目录下保存一个 requirement.txt 文件;

                shell
                autotest_xxx
                 ├── requirement.txt
                 ├── case	
                 ...

                里面写入需要安装的三方依赖,比如像这样:

                shell
                PyYAML==6.0  # 指定安装某个版本
                @@ -30,8 +30,8 @@
                 ...

                里面写入需要安装的三方依赖,比如像这样:

                python3-pyaudio

                2. 裁剪依赖

                在某些情况下,可能你只需要安装一些最最基础的依赖,其他的都不需要,比如纯接口自动化的项目,它不需要 UI 自动化相关的依赖。

                你只需要在应用库根目录下,存放一个 BASICENV 的普通文件,里面不需要写任何内容,这样执行 env.sh 时,只会安装最基础的依赖。

                shell
                autotest_xxx
                 ├── BASICENV  # 可以使用:touch BASICENV 创建文件
                 ├── case	
                -...

                基础依赖仅安装最基础的几个包;

                裁剪依赖新增依赖 是不冲突的,可以同时使用。

                开发环境部署

                在开发过程中,如果你想直接部署在本机上:

                shell
                $ bash env.sh -D

                这种方式安装的环境不会有 youqu 这个命令,用例执行都使用 python3 驱动:

                shell
                $ python3 manage.py run

                虚拟环境解释器

                YouQu 默认采用虚拟化部署,虚拟环境实际安装的位置是在 $HOME/.local/share/virtualenvs/youqu-oHTM7l7G 目录下;其中,

                youqu-oHTM7l7G 此目录名称前面部分是你的代码根目录的名称,后面部分是生成的随机字符串。

                激活虚拟环境

                在开发过程中有可能需要在终端激活虚拟环境,以便进行一些开发调试;

                在框架根目录下命令行输入:

                shell
                $ youqu-shell

                即可在终端激活当前虚拟环境。

                删除虚拟环境

                在项目根目录下输入:

                shell
                $ youqu-rm

                依赖治理

                依赖治理原则

                依赖最少化——始终保持最少的依赖项。

                依赖治理思路

                • 使用标准库

                  尽量使用标准库或系统预装库来实现功能。

                  如果确实需要引入三方库,应该尽量将三方库里面使用到的部分剥离出来使用,从而避免全量引入三方库。

                • 面向服务的架构设计

                  将功能进行服务化封装部署,通过服务接口、远程过程调用等方式提供功能。

                依赖治理的意义

                大多数情况下,在写一些功能时,首先想到的就是去搜索看有没有现成的工具直接能用,行话叫不要重复造轮子。

                但这样做有一个很严重的问题,就是当你写一个大型项目时,会引入非常非常多的依赖。

                依赖项越多,依赖关系就越复杂,后期越容易出问题,如依赖关系错乱冲突导致安装失败、依赖安装下载过程网络波动导致安装失败、安装过程耗时等等问题。

                - +...

                基础依赖仅安装最基础的几个包;

                裁剪依赖新增依赖 是不冲突的,可以同时使用。

                开发环境部署

                在开发过程中,如果你想直接部署在本机上:

                shell
                $ bash env.sh -D

                这种方式安装的环境不会有 youqu 这个命令,用例执行都使用 python3 驱动:

                shell
                $ python3 manage.py run

                虚拟环境解释器

                YouQu 默认采用虚拟化部署,虚拟环境实际安装的位置是在 $HOME/.local/share/virtualenvs/youqu-oHTM7l7G 目录下;其中,

                youqu-oHTM7l7G 此目录名称前面部分是你的代码根目录的名称,后面部分是生成的随机字符串。

                激活虚拟环境

                在开发过程中有可能需要在终端激活虚拟环境,以便进行一些开发调试;

                在框架根目录下命令行输入:

                shell
                $ youqu-shell

                即可在终端激活当前虚拟环境。

                删除虚拟环境

                在项目根目录下输入:

                shell
                $ youqu-rm

                依赖治理

                依赖治理原则

                依赖最少化——始终保持最少的依赖项。

                依赖治理思路

                • 使用标准库

                  尽量使用标准库或系统预装库来实现功能。

                  如果确实需要引入三方库,应该尽量将三方库里面使用到的部分剥离出来使用,从而避免全量引入三方库。

                • 面向服务的架构设计

                  将功能进行服务化封装部署,通过服务接口、远程过程调用等方式提供功能。

                依赖治理的意义

                大多数情况下,在写一些功能时,首先想到的就是去搜索看有没有现成的工具直接能用,行话叫不要重复造轮子。

                但这样做有一个很严重的问题,就是当你写一个大型项目时,会引入非常非常多的依赖。

                依赖项越多,依赖关系就越复杂,后期越容易出问题,如依赖关系错乱冲突导致安装失败、依赖安装下载过程网络波动导致安装失败、安装过程耗时等等问题。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\256\200\344\273\213/YouQu\346\230\257\344\273\200\344\271\210.html" "b/\346\214\207\345\215\227/\347\256\200\344\273\213/YouQu\346\230\257\344\273\200\344\271\210.html" index fc93fb3e..c1d9b2c5 100644 --- "a/\346\214\207\345\215\227/\347\256\200\344\273\213/YouQu\346\230\257\344\273\200\344\271\210.html" +++ "b/\346\214\207\345\215\227/\347\256\200\344\273\213/YouQu\346\230\257\344\273\200\344\271\210.html" @@ -8,20 +8,20 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:
                Flag

                众所周知,操作系统领域长期被国外占领,恰逢国产操作系统百年一遇之大变局,我辈正站在一个新的历史起点上,不再只是跟随者,而要成为引领者。

                自动化测试框架,是提升国产操作系统质量的关键一环,这不仅是一项技术的革新,更是一次精神的磨砺。我们要以坚定的决心,攻克一个又一个难题,让我们的操作系统在稳定性和易用性上,达到世界顶尖水平。

                YouQu 是什么?

                YouQu(有趣)是统信公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。🔥

                YouQu 能做什么?

                ☑ 💻 Linux 桌面应用 UI 自动化测试

                ☑ 🌏 Web UI 自动化测试

                ☑ 🚌 Linux DBus 接口自动化测试

                ☑ 🚀 命令行自动化测试

                ☑ 🕷️ HTTP 接口自动化测试

                爱上 YouQu 的 N 个理由

                • 无处不在的代码补全

                  让编写自动化测试用例成为一种享受。

                • 提供统一的接口

                  编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;

                • 多种元素定位方案

                  除了常用的属性定位、图像识别、OCR识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你。

                • 用例标签化管理

                  提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情。

                • 功能强大的执行管理器

                  让你可以方便的在本地执行、远程执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想。

                • 远程交互式控制

                  用例步骤过程中控制远程机器。

                • 自动输出日志

                  你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》。

                • 一键部署环境

                  让你再也不用为环境部署而烦恼。

                • 自动生成多种报告

                  你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能。

                • 自定义断言

                  对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效。

                • 用例超时控制

                  不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行。

                • 软硬件兼容

                  完美兼容 WaylandX11 显示协议,硬件兼容 x86_64aarch64loongarch64sw64,真正做到一套代码,随处执行。

                开源许可证

                YouQu 在 GPL-2.0 下发布。

                - +
                Skip to content
                📔 阅读量:
                Flag

                众所周知,操作系统领域长期被国外占领,恰逢国产操作系统百年一遇之大变局,我辈正站在一个新的历史起点上,不再只是跟随者,而要成为引领者。

                自动化测试框架,是提升国产操作系统质量的关键一环,这不仅是一项技术的革新,更是一次精神的磨砺。我们要以坚定的决心,攻克一个又一个难题,让我们的操作系统在稳定性和易用性上,达到世界顶尖水平。

                YouQu 是什么?

                YouQu(有趣)是统信公司开源的一个用于 Linux 操作系统的自动化测试框架,支持多元化元素定位和断言、用例标签化管理和执行、强大的日志和报告输出等特色功能,同时完美兼容 X11、Wayland 显示协议,环境部署简单,操作易上手。🔥

                YouQu 能做什么?

                ☑ 💻 Linux 桌面应用 UI 自动化测试

                ☑ 🌏 Web UI 自动化测试

                ☑ 🚌 Linux DBus 接口自动化测试

                ☑ 🚀 命令行自动化测试

                ☑ 🕷️ HTTP 接口自动化测试

                爱上 YouQu 的 N 个理由

                • 无处不在的代码补全

                  让编写自动化测试用例成为一种享受。

                • 提供统一的接口

                  编写方法时只需要导入一个包就可以使用到核心库提供的所有功能;

                • 多种元素定位方案

                  除了常用的属性定位、图像识别、OCR识别以外,我们还提供基于 UI 的元素定位方案,其使用简单且高效,效果一定能惊讶到你。

                • 用例标签化管理

                  提供用例标签化管理、批量跳过和批量条件跳过的功能,你想不到一个 csv 文件原来能干这么多事情。

                • 功能强大的执行管理器

                  让你可以方便的在本地执行、远程执行任何用例集的用例,其丰富的自定义配置项,满足你对执行器所有的幻想。

                • 远程交互式控制

                  用例步骤过程中控制远程机器。

                • 自动输出日志

                  你再也不用为每个方法单独写输出日志的代码,一切我们给你搞定了,日志输出不仅内容丰富,颜值也绝对在线,我们还自己设计了一款终端输出主题叫《五彩斑斓的黑》。

                • 一键部署环境

                  让你再也不用为环境部署而烦恼。

                • 自动生成多种报告

                  你想输出什么报告形式都行,而且我们在报告中还加入了失败录屏和失败截图的功能。

                • 自定义断言

                  对断言进行了二次封装,提供更友好化的错误提示,让定位问题精准高效。

                • 用例超时控制

                  不仅支持单条用例超时控制,而且还支持动态控制用例批量执行的总时间,确保 CI 环境下能顺畅运行。

                • 软硬件兼容

                  完美兼容 WaylandX11 显示协议,硬件兼容 x86_64aarch64loongarch64sw64,真正做到一套代码,随处执行。

                开源许可证

                YouQu 在 GPL-2.0 下发布。

                + \ No newline at end of file diff --git "a/\346\214\207\345\215\227/\347\256\200\344\273\213/\345\277\253\351\200\237\345\274\200\345\247\213.html" "b/\346\214\207\345\215\227/\347\256\200\344\273\213/\345\277\253\351\200\237\345\274\200\345\247\213.html" index e09a2b63..898393eb 100644 --- "a/\346\214\207\345\215\227/\347\256\200\344\273\213/\345\277\253\351\200\237\345\274\200\345\247\213.html" +++ "b/\346\214\207\345\215\227/\347\256\200\344\273\213/\345\277\253\351\200\237\345\274\200\345\247\213.html" @@ -8,20 +8,20 @@ - + - - + + - + -
                Skip to content
                📔 阅读量:

                快速开始

                安装

                从 PyPI 安装:

                shell
                $ sudo pip3 install youqu
                不加 sudo ?

                不加 sudo 也可以:

                shell
                pip3 install youqu

                但可能出现 youqu-startproject 命令无法使用;

                这是因为不加 sudo 时,youqu-startproject 命令会生成在 $HOME/.local/bin 下,

                而此路径可能不在环境变量(PATH)中,因此您需要添加环境变量:

                shell
                export PATH=$PATH:$HOME/.local/bin

                创建项目

                您可以在任意目录下,使用 youqu-startproject 命令创建一个项目:

                shell
                $ youqu-startproject my_project

                注意

                不要以 root 用户执行命令!

                如果 youqu-startproject 后面不加参数,默认的项目名称为:youqu

                安装依赖

                进入项目根目录:

                shell
                $ cd my_project

                安装部署 YouQu 执行所需环境:

                shell
                $ bash env.sh
                shell
                $ bash env.sh -D
                密码问题

                使用的默认密码是 1

                您可以使用 -p 选项传入密码:bash env.sh -p ${my_password}

                也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                创建 APP 工程

                使用 startapp 命令自动创建 APP 工程:

                shell
                $ youqu manage.py startapp autotest_deepin_some

                APP 工程名称命名规范

                APP 工程名称需要符合 Python 文件命名规范(字母、数字、下划线)。

                自动创建的 APP 工程遵循完整的 PO 设计模式,让你可以专注于用例和方法的编写维护。

                这样在 apps 目录下会创建一个子项目工程: autotest_deepin_some,同时新建好工程模板目录和模板文件:

                shell
                my_project
                +    
                Skip to content
                📔 阅读量:

                快速开始

                安装

                从 PyPI 安装:

                shell
                $ sudo pip3 install youqu
                不加 sudo ?

                不加 sudo 也可以:

                shell
                pip3 install youqu

                但可能出现 youqu-startproject 命令无法使用;

                这是因为不加 sudo 时,youqu-startproject 命令会生成在 $HOME/.local/bin 下,

                而此路径可能不在环境变量(PATH)中,因此您需要添加环境变量:

                shell
                export PATH=$PATH:$HOME/.local/bin

                创建项目

                您可以在任意目录下,使用 youqu-startproject 命令创建一个项目:

                shell
                $ youqu-startproject my_project

                注意

                不要以 root 用户执行命令!

                如果 youqu-startproject 后面不加参数,默认的项目名称为:youqu

                安装依赖

                进入项目根目录:

                shell
                $ cd my_project

                安装部署 YouQu 执行所需环境:

                shell
                $ bash env.sh
                shell
                $ bash env.sh -D
                密码问题

                使用的默认密码是 1

                您可以使用 -p 选项传入密码:bash env.sh -p ${my_password}

                也可以修改配置文件 setting/globalconfig.ini 里面的 PASSWORD 配置项;

                创建 APP 工程

                使用 startapp 命令自动创建 APP 工程:

                shell
                $ youqu manage.py startapp autotest_deepin_some

                APP 工程名称命名规范

                APP 工程名称需要符合 Python 文件命名规范(字母、数字、下划线)。

                自动创建的 APP 工程遵循完整的 PO 设计模式,让你可以专注于用例和方法的编写维护。

                这样在 apps 目录下会创建一个子项目工程: autotest_deepin_some,同时新建好工程模板目录和模板文件:

                shell
                my_project
                 ├── apps
                    ├── autotest_deepin_some  # <----- APP工程
                 .   .   ├── case  # 用例目录
                @@ -108,8 +108,8 @@
                   -y PARALLEL, --parallel PARALLEL
                                         yes:表示所有测试机并行跑,执行相同的测试用例;no:表示测试机分布式执行,服务端会根据收集到的测试用例自
                                         动分配给各个测试机执行。

                除了这些特有参数以外,它同样支持本地执行的所有参数;

                在命令行这样运行:

                shell
                $ youqu manage.py remote -a apps/autotest_deepin_music -c uos@10.8.13.x3/uos@10.8.13.x4 -k "xxx" -t "xxx"

                所有用例执行完之后会在 report 目录下回收各个测试机执行的测试报告。

                注意:如果远程机器没有搭建自动化测试环境,记得加上参数 -e

                shell
                $ youqu manage.py remote -a ... -e

                执行前确保远程机器已经开启了 ssh 服务,否则会提示无法连接,如果没有开启,请手动开启:

                shell
                $ sudo systemctl restart ssh
                -$ sudo systemctl enable ssh

                配置文件其他相关配置项详细说明,请查看配置文件中的注释内容。

                3.2. 远程多机器分布式异步负载均衡执行

                多机器分布式异步负载均衡执行也是用本地作为服务端控制远程机器执行,但远程机器执行的用例不同,而是所有远程机器执行的用例之和,为你想要执行的用例集;

                似乎有点难以理解,我用大白话举例描述下:

                服务端想要执行 10 条用例,现在远程机器有 5 台,然后服务端就先拿着第 1 条用例给远程 1 号机执行,拿第 2 条用例给远程 2 号机执行...,如此循环直到所有用例执行完,这就是负载均衡执行。

                使用方法和前面一样,只是需要增加一个参数 --parallel

                shell
                $ youqu manage.py remote -a ... --parallel no
                - +$ sudo systemctl enable ssh

                配置文件其他相关配置项详细说明,请查看配置文件中的注释内容。

                3.2. 远程多机器分布式异步负载均衡执行

                多机器分布式异步负载均衡执行也是用本地作为服务端控制远程机器执行,但远程机器执行的用例不同,而是所有远程机器执行的用例之和,为你想要执行的用例集;

                似乎有点难以理解,我用大白话举例描述下:

                服务端想要执行 10 条用例,现在远程机器有 5 台,然后服务端就先拿着第 1 条用例给远程 1 号机执行,拿第 2 条用例给远程 2 号机执行...,如此循环直到所有用例执行完,这就是负载均衡执行。

                使用方法和前面一样,只是需要增加一个参数 --parallel

                shell
                $ youqu manage.py remote -a ... --parallel no
                + \ No newline at end of file diff --git "a/\350\247\204\345\210\222/\346\234\252\346\235\245\350\247\204\345\210\222.html" "b/\350\247\204\345\210\222/\346\234\252\346\235\245\350\247\204\345\210\222.html" index 7a7ca9e2..efe4fffa 100644 --- "a/\350\247\204\345\210\222/\346\234\252\346\235\245\350\247\204\345\210\222.html" +++ "b/\350\247\204\345\210\222/\346\234\252\346\235\245\350\247\204\345\210\222.html" @@ -8,20 +8,20 @@ - + - - - + + + -
                Skip to content
                📔 阅读量:

                未来规划

                💡 桌面应用性能自动化测试

                需优化解决的性能自动化问题

                1、环境问题,测试人员在本地编写代码,环境不好搭建,框架只提供 Docker 环境部署,适合在生产环境运行,但是对测试人员本地编写代码安装环境很不友好,因为代码编辑器调试代码只能通过入口文件执行,不能在编辑器中直接执行单个用例脚本;

                2、在 Docker 里面执行,代码报错看不到报错信息,不好定位问题;

                3、强制依赖串口线,不插串口线,环境也无法部署,给想要尝试或者愿意尝试的人员造成了一些困扰,还依赖较多设备(服务端-测试机),一些团队并不能找到那么多机器;

                4、那些好不容易尝试用起来的人员,使用一段时间后会痛恨 1 和 2 的问题,让他们觉得难度有点大,团队中普遍人员代码能力不强,尝试人员都觉得难搞,其他人员也就可想而知;

                方案

                性能自动化支持以下功能

                1、因地制宜(手上有什么设备就用什么方案)

                【低配版】只有一台机器

                • 本机执行方案;

                • 本机执行,本机同步解析;

                • 本机执行,外部机器异步解析;

                【中配版】有两台机器,有网络,但是没有串口线

                • 服务端-客户端,通过远程网络连接控制。

                【高配版】有两台机器,并且有串口线,有没有网络无所谓

                • 服务端-客户端,通过串口线连接控制。

                【顶配版】高配 + 继电器

                • 最完美的方案。

                2、环境安装、代码调试环境、执行环境要对编码人员更加友好;

                - +
                Skip to content
                📔 阅读量:

                未来规划

                💡 桌面应用性能自动化测试

                需优化解决的性能自动化问题

                1、环境问题,测试人员在本地编写代码,环境不好搭建,框架只提供 Docker 环境部署,适合在生产环境运行,但是对测试人员本地编写代码安装环境很不友好,因为代码编辑器调试代码只能通过入口文件执行,不能在编辑器中直接执行单个用例脚本;

                2、在 Docker 里面执行,代码报错看不到报错信息,不好定位问题;

                3、强制依赖串口线,不插串口线,环境也无法部署,给想要尝试或者愿意尝试的人员造成了一些困扰,还依赖较多设备(服务端-测试机),一些团队并不能找到那么多机器;

                4、那些好不容易尝试用起来的人员,使用一段时间后会痛恨 1 和 2 的问题,让他们觉得难度有点大,团队中普遍人员代码能力不强,尝试人员都觉得难搞,其他人员也就可想而知;

                方案

                性能自动化支持以下功能

                1、因地制宜(手上有什么设备就用什么方案)

                【低配版】只有一台机器

                • 本机执行方案;

                • 本机执行,本机同步解析;

                • 本机执行,外部机器异步解析;

                【中配版】有两台机器,有网络,但是没有串口线

                • 服务端-客户端,通过远程网络连接控制。

                【高配版】有两台机器,并且有串口线,有没有网络无所谓

                • 服务端-客户端,通过串口线连接控制。

                【顶配版】高配 + 继电器

                • 最完美的方案。

                2、环境安装、代码调试环境、执行环境要对编码人员更加友好;

                + \ No newline at end of file diff --git "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.html" "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.html" index 7586e130..a3b02c97 100644 --- "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.html" +++ "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\237\272\347\241\200\346\241\206\346\236\266\350\256\276\350\256\241\346\226\271\346\241\210.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                🎨 作者:mikigo 📔 阅读量:

                AT 基础框架设计方案

                一、目标

                做一个简单、好用、功能强大的自动化测试框架。

                • 作为自动化测试的一个基础框架,任何应用都能很方便的接入进来;
                • 提供所有自动化测试所需要的底层功能,并对外提供唯一的接口,方便应用库使用;
                • 整合公共库,减少应用库代码量和方法维护。

                二、设计方案

                1、统一概念

                • 基础框架

                  本项目是一个自动化测试的基础框架(AutoTest Basic Frame),全称为“自动化测试基础框架(AT 基础框架)”。

                  AT 基础框架是做为一个自动化测试的基础框架来设计的,它提供了自动化测试所要用的基础功能,任何应用接入进来都能快速方便的进行方法和用例编写,同时在用例标签化管理、批量跳过、标签化执行、分布式执行、多种报告输出、优美的执行日志、失败自动录屏和截图、自动环境清理等等,它都提供了完善的解决方案,更重要的是这一切使用起来都非常简单。

                  基础框架中包含应用库(apps)、核心库(src)、公共方法库(public)。

                • 应用库(apps

                  各个应用自己的仓库,里面主要包含的是用例、方法及一些测试资源,比如文件管理器叫 autotest_dde_file_manager

                • 核心库(src

                  核心库自动化测试所要用的到所有底层核心功能,这是最重要的一个部分,灵魂。具体功能模块及说明会在下面第四个章节详细描述。

                • 公共方法库(public

                  多个应用都要用到的一些操作方法,按照应用划分存放,主要是为了减少代码量,消除应用间的耦合关系。

                2、架构图

                整体的框架设计在《自动化测试架构设计》文档里面已经有详细描述了,这里贴一下整体的架构图:

                架构图

                为了突显本文的重点,抽取其中重要功能模块,如下图:

                核心模块

                3、目录结构

                shell
                youqu  # 自动化测试基础框架
                +    
                Skip to content
                🎨 作者:mikigo 📔 阅读量:

                AT 基础框架设计方案

                一、目标

                做一个简单、好用、功能强大的自动化测试框架。

                • 作为自动化测试的一个基础框架,任何应用都能很方便的接入进来;
                • 提供所有自动化测试所需要的底层功能,并对外提供唯一的接口,方便应用库使用;
                • 整合公共库,减少应用库代码量和方法维护。

                二、设计方案

                1、统一概念

                • 基础框架

                  本项目是一个自动化测试的基础框架(AutoTest Basic Frame),全称为“自动化测试基础框架(AT 基础框架)”。

                  AT 基础框架是做为一个自动化测试的基础框架来设计的,它提供了自动化测试所要用的基础功能,任何应用接入进来都能快速方便的进行方法和用例编写,同时在用例标签化管理、批量跳过、标签化执行、分布式执行、多种报告输出、优美的执行日志、失败自动录屏和截图、自动环境清理等等,它都提供了完善的解决方案,更重要的是这一切使用起来都非常简单。

                  基础框架中包含应用库(apps)、核心库(src)、公共方法库(public)。

                • 应用库(apps

                  各个应用自己的仓库,里面主要包含的是用例、方法及一些测试资源,比如文件管理器叫 autotest_dde_file_manager

                • 核心库(src

                  核心库自动化测试所要用的到所有底层核心功能,这是最重要的一个部分,灵魂。具体功能模块及说明会在下面第四个章节详细描述。

                • 公共方法库(public

                  多个应用都要用到的一些操作方法,按照应用划分存放,主要是为了减少代码量,消除应用间的耦合关系。

                2、架构图

                整体的框架设计在《自动化测试架构设计》文档里面已经有详细描述了,这里贴一下整体的架构图:

                架构图

                为了突显本文的重点,抽取其中重要功能模块,如下图:

                核心模块

                3、目录结构

                shell
                youqu  # 自动化测试基础框架
                 ├── apps  # 应用库
                 │   ├── autotest_dde_file_manager  # 单独的应用仓库(应用库详细目录结构请看应用库设计方案)
                 │   │   ├── case  # 用例
                @@ -122,8 +122,8 @@
                         self.click(*self.ui.btn_center("侧边栏-音乐"))   
                     
                     def click_xxx_by_attr(self):
                -        pass

                公共方法库意义:

                • 公共方法库里面所封装的一些操作方法都是至少被 2 个应用都用到的,这样做可以减少整体代码量,从而减轻应用库代码的维护工作。

                • 公共方法库里面的编写形式(命名规则、定位的方案写法、注释的写法等等)具有一定的模板作用,这样即使是各个应用库都独立维护,所有的编码风格都是趋于相同的,因为大家都应该参照公共库里面的一些写法来写自己应用库里面的一些方法类,这样使得从公司的角度去看所有应用的自动化测试项目都是统一的。

                • 可以通过公共方法库里面的一些方法,了解到其他应用的功能,对于我们需求理解,了解系统的方方面面也有好处。

                当然,如果你的应用本身是属于根本就不需要和其他应用交互的,那么你可能不会用到这里面的功能,没关系,你所有的方法都可以直接写在应用库的业务层。

                4、conftest.py

                conftest.py 从功能上将是属于核心库(src)的内容,但是由于它的特殊性,即它是对应用库中的用例生效的,而且它的作用域是当前目录及以下,因此我们将它放到项目根目录。我们框架中有不少核心功能都是在这里面进行开发的,后面第四章会讲到细节。

                pytest.ini 作用和 conftest.py 类似,是 Pytest 框架的固定配置文件,目前配置了一些通用的命令行执行参数,也放在项目根目录。

                根目录下的 conftest.py 文件只会用来写 Hook 函数,apps 目录下的 的 conftest.py 文件只会用来写 fixture

                5、setting

                全局配置模块,包含了以下配置文件:

                (1)ini 配置文件

                主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

                (2)config.py 配置文件

                主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

                - + pass

                公共方法库意义:

                • 公共方法库里面所封装的一些操作方法都是至少被 2 个应用都用到的,这样做可以减少整体代码量,从而减轻应用库代码的维护工作。

                • 公共方法库里面的编写形式(命名规则、定位的方案写法、注释的写法等等)具有一定的模板作用,这样即使是各个应用库都独立维护,所有的编码风格都是趋于相同的,因为大家都应该参照公共库里面的一些写法来写自己应用库里面的一些方法类,这样使得从公司的角度去看所有应用的自动化测试项目都是统一的。

                • 可以通过公共方法库里面的一些方法,了解到其他应用的功能,对于我们需求理解,了解系统的方方面面也有好处。

                当然,如果你的应用本身是属于根本就不需要和其他应用交互的,那么你可能不会用到这里面的功能,没关系,你所有的方法都可以直接写在应用库的业务层。

                4、conftest.py

                conftest.py 从功能上将是属于核心库(src)的内容,但是由于它的特殊性,即它是对应用库中的用例生效的,而且它的作用域是当前目录及以下,因此我们将它放到项目根目录。我们框架中有不少核心功能都是在这里面进行开发的,后面第四章会讲到细节。

                pytest.ini 作用和 conftest.py 类似,是 Pytest 框架的固定配置文件,目前配置了一些通用的命令行执行参数,也放在项目根目录。

                根目录下的 conftest.py 文件只会用来写 Hook 函数,apps 目录下的 的 conftest.py 文件只会用来写 fixture

                5、setting

                全局配置模块,包含了以下配置文件:

                (1)ini 配置文件

                主要配置一些全局的配置项,譬如:失败重跑次数、是否失败录屏、单条用例超时时间、会话超时时间、执行时日志级别、生成的报告类型、以及分布式执行的一些策略配置项等等。

                (2)config.py 配置文件

                主要提供配置文件读取、动态获取一些常量(如项目根目录绝对路径 (BASE_DIR)、系统架构(SYS_FRAME)、时间字符串(strftime)、本机 USERNAME IP 等等)、公共 URL 等。

                + \ No newline at end of file diff --git "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.html" "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.html" index cd022624..941501ad 100644 --- "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.html" +++ "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/AT\345\272\224\347\224\250\345\272\223\350\256\276\350\256\241\346\226\271\346\241\210.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                🎨 作者:mikigo 📔 阅读量:

                AT 应用库设计方案

                一、目标

                AT 应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计,以实现应用库高效的编写、维护用例及其方法。

                二、方案设计

                文件管理器从业务复杂度和用例量来讲,在系统所有应用中,是很有代表性的,难度也是最大的,因此我们选取文件管理器作为应用库改造的实验应用,给后续其他应用改造提供切实可行的思路和方案。

                1、分层设计图

                整体仍然遵循 PO 设计理念,根据业务需要,将文管业务层进行 3 层划分:

                应用库架构图(文件管理器)

                2、目录结构

                shell
                autotest_dde_file_manager  # 应用仓库
                +    
                Skip to content
                🎨 作者:mikigo 📔 阅读量:

                AT 应用库设计方案

                一、目标

                AT 应用库改造是基于自动化测试基础框架进行用例方法和业务逻辑的重新设计,以实现应用库高效的编写、维护用例及其方法。

                二、方案设计

                文件管理器从业务复杂度和用例量来讲,在系统所有应用中,是很有代表性的,难度也是最大的,因此我们选取文件管理器作为应用库改造的实验应用,给后续其他应用改造提供切实可行的思路和方案。

                1、分层设计图

                整体仍然遵循 PO 设计理念,根据业务需要,将文管业务层进行 3 层划分:

                应用库架构图(文件管理器)

                2、目录结构

                shell
                autotest_dde_file_manager  # 应用仓库
                 ├── case  # 用例
                 │   ├── assert_res  # 断言的图片资源目录
                 │   ├── test_xxx_001.py
                @@ -120,8 +120,8 @@
                         dfm.click_xxx_title_by_ui()
                         dfm.click_xxx_right_by_ui()
                         dfm.dog.print_desc()
                -        dfm.ui.print_number()

                四、工程改造实施步骤

                1、基础框架代码拉取

                1.1. 将自动化基础框架的功能拉到本地(参考《快速开始》章节)

                1.2. 将应用库代码拉到基础框架下 apps 目录下,应用库的仓库命名应该是长这样的 autotest_deepin_xxx

                2、调整工程目录

                按照 方案设计-目录结构 进行目录调整,尽量使用编辑器进行相应的调整,编辑器推荐使用 Pycharm ,以下操作均在 Pycharm 里面可实现。

                2.1. 需要移动 py 文件或目录,直接在编辑器里面,使用鼠标选中并按住,之后拖动到目标位置即可,Pycharm 会尽可能的自动解决移动导致的路径问题。注意,我说的是“尽可能”,有些骚操作编辑器是无法自动处理的。如果没有被编辑器自动处理的路径问题,后续只能手动解决。

                2.2. 需要重命名文件或目录,在编辑器里面选中文件,然后使用快捷键 Shift + F6 (如果快捷键没反应,文件右键菜单 Refactor —— Rename),然后在输入框中输入要重命名的名称,同时,确认勾选 Search for referencesSearch in comments and strings 这两个选项,最后按回车或者鼠标点 Refactor

                注意,此时编辑器可能会提示你,你这个重命名的操作关联了多个模块,它被多个地方都使用到了,相关的模块是否也一起改名了,这不废话吗,用这个功能就是想把关联到的都修改,不然我为什么不用文管的重命名功能呢,别想了,直接点左下角的 Refactor 按钮,就是干。

                类名、函数名的重命名都尽量采用这种方案,因为编辑器会自动给我们找到关联的地方,然后同步修改掉。你可千万别直接删了修改名称,不然你可能会花上一天的时间来解决重命名的问题。

                3、实现核心库接口

                3.1. BaseWidget

                BaseWidget 里面把该写的都写好,你可以参考上面的设计理念来写。

                如果你嫌麻烦,你可以参考文件管理器的实际工程代码 autotest_dde_file_manager

                3.2. 操作层

                如果你是新写项目,你会发现一切都是那么的简单、直接,按照我们提供给你的接口写用例的操作方法就好了。

                如果你是想对原来的工程进行改造,你需要按照核心库方法的调用,将你之前写的每个方案进行对应的修改,包括类和方法的命名、方法内所要用到不同定位方法的写法修改。

                这时候你可能你的代码中可能会有一些报错,不用担心,你可以从业务逻辑出发,想清楚这个方法是干什么的、操作的对象是什么、参数是什么,注意这些修改是会影响到用例代码里面的,没关系,用例里面本来也应该被关联修改。

                3.3. 把配置模块写好,这部分基本可以复制文管的代码。

                4、路径处理

                4.1. 导入路径

                方法和用例中都会涉及到导入路径的修改,在修改路径时,建议你使用 Ctrl + Shift + R 全局替换,会将整个项目下的相同地方都修改到,当然,你也可以在小弹窗中修改全局替换为局部目录下替换。处理那种没有关联关系,但是又是相同名称的重命名,我也推荐使用这种方式进行重命名。

                注意,全局替换的方式任然无法保证真的全局被替换了(可能是编辑器的 Bug 吧),所以你仍然需要手动看下各处是否修改到位。

                4.2. 资源路径

                一些用例资源需要根据 config.py 里面的路径配置进行资源路径的拼接,如果你原来本来就有一个函数专门用于组装路径的,那你只需要修改这一个地方就好了,如果你之前并没有这样的设计,那可能需要修改大量涉及到资源路径的地方。

                5、调试和编写用例

                以上几个步骤做完,基本就可以进行用例代码的调试了,这部分工作主要解决你之前几个步骤遗漏的问题,如果所有用例都调试通过了,那么工程改造就全部完成了。

                - + dfm.ui.print_number()

                四、工程改造实施步骤

                1、基础框架代码拉取

                1.1. 将自动化基础框架的功能拉到本地(参考《快速开始》章节)

                1.2. 将应用库代码拉到基础框架下 apps 目录下,应用库的仓库命名应该是长这样的 autotest_deepin_xxx

                2、调整工程目录

                按照 方案设计-目录结构 进行目录调整,尽量使用编辑器进行相应的调整,编辑器推荐使用 Pycharm ,以下操作均在 Pycharm 里面可实现。

                2.1. 需要移动 py 文件或目录,直接在编辑器里面,使用鼠标选中并按住,之后拖动到目标位置即可,Pycharm 会尽可能的自动解决移动导致的路径问题。注意,我说的是“尽可能”,有些骚操作编辑器是无法自动处理的。如果没有被编辑器自动处理的路径问题,后续只能手动解决。

                2.2. 需要重命名文件或目录,在编辑器里面选中文件,然后使用快捷键 Shift + F6 (如果快捷键没反应,文件右键菜单 Refactor —— Rename),然后在输入框中输入要重命名的名称,同时,确认勾选 Search for referencesSearch in comments and strings 这两个选项,最后按回车或者鼠标点 Refactor

                注意,此时编辑器可能会提示你,你这个重命名的操作关联了多个模块,它被多个地方都使用到了,相关的模块是否也一起改名了,这不废话吗,用这个功能就是想把关联到的都修改,不然我为什么不用文管的重命名功能呢,别想了,直接点左下角的 Refactor 按钮,就是干。

                类名、函数名的重命名都尽量采用这种方案,因为编辑器会自动给我们找到关联的地方,然后同步修改掉。你可千万别直接删了修改名称,不然你可能会花上一天的时间来解决重命名的问题。

                3、实现核心库接口

                3.1. BaseWidget

                BaseWidget 里面把该写的都写好,你可以参考上面的设计理念来写。

                如果你嫌麻烦,你可以参考文件管理器的实际工程代码 autotest_dde_file_manager

                3.2. 操作层

                如果你是新写项目,你会发现一切都是那么的简单、直接,按照我们提供给你的接口写用例的操作方法就好了。

                如果你是想对原来的工程进行改造,你需要按照核心库方法的调用,将你之前写的每个方案进行对应的修改,包括类和方法的命名、方法内所要用到不同定位方法的写法修改。

                这时候你可能你的代码中可能会有一些报错,不用担心,你可以从业务逻辑出发,想清楚这个方法是干什么的、操作的对象是什么、参数是什么,注意这些修改是会影响到用例代码里面的,没关系,用例里面本来也应该被关联修改。

                3.3. 把配置模块写好,这部分基本可以复制文管的代码。

                4、路径处理

                4.1. 导入路径

                方法和用例中都会涉及到导入路径的修改,在修改路径时,建议你使用 Ctrl + Shift + R 全局替换,会将整个项目下的相同地方都修改到,当然,你也可以在小弹窗中修改全局替换为局部目录下替换。处理那种没有关联关系,但是又是相同名称的重命名,我也推荐使用这种方式进行重命名。

                注意,全局替换的方式任然无法保证真的全局被替换了(可能是编辑器的 Bug 吧),所以你仍然需要手动看下各处是否修改到位。

                4.2. 资源路径

                一些用例资源需要根据 config.py 里面的路径配置进行资源路径的拼接,如果你原来本来就有一个函数专门用于组装路径的,那你只需要修改这一个地方就好了,如果你之前并没有这样的设计,那可能需要修改大量涉及到资源路径的地方。

                5、调试和编写用例

                以上几个步骤做完,基本就可以进行用例代码的调试了,这部分工作主要解决你之前几个步骤遗漏的问题,如果所有用例都调试通过了,那么工程改造就全部完成了。

                + \ No newline at end of file diff --git "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.html" "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.html" index 054fc2d2..4faf322d 100644 --- "a/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.html" +++ "b/\350\247\204\345\210\222/\346\241\206\346\236\266\350\256\276\350\256\241/\350\207\252\345\212\250\345\214\226\346\265\213\350\257\225\346\236\266\346\236\204\350\256\276\350\256\241v1.0.html" @@ -8,19 +8,19 @@ - + - - - + + + -
                Skip to content
                🎨 作者:mikigo 📔 阅读量:

                自动化测试架构设计规划

                • 目标:
                  • 应用 AT 架构工程化,参考性能自动化工程完成工程化改造。
                  • 应用间用例解耦,解除所有交叉调用的方法,各应用能跟随自身迭代周期独立维护 AT 用例。
                  • 完成公共方法的抽取整合,形成一套独立于应用间的公共方法库,各应用方法里面不存在被多个应用调用的情况。
                  • 用例实现标签化管理,为将来适配更多的 AT 运用场景提供支撑,原则上可实现无限扩展,在每日构建和持续集成流程落地使用。
                  • 代码规范问题清零,符合 Shell CheckPylint、系统部相关编码规范要求。
                • 意义:
                  • 统一成研 AT 架构设计思路,消除 AT 代码实现和维护上可能出现的分歧,改善历史 AT 无工程化设计的缺陷,提高架构专业性。
                  • 各应用 AT 代码相互独立,契合应用独立发布特性,可支持迭代期间独立新增、维护和执行。
                  • 方法调用逻辑得到简化,编写和维护更高效;公共库抽取,减少方法重复编写,提高代码利用率;平均编写一条用例从 40 分钟降低至 30 分钟,日产出用例从 12 条/天提升至 16 条/天。
                  • 可灵活支撑不同的自动化运用场景,如 CI、冒烟测试、集成测试、回归测试、专项测试等。

                一、背景介绍

                提示

                这里介绍以前的AT框架情况以及存在的一些问题;

                1、原有架构介绍

                原AT框架架构图

                原有自动化测试架构整体分为三层:用例层(业务逻辑层)、中间层(元素定位和操作方法层)、核心层(底层功能库层)。

                • 用例层:即应用的用例,专注于业务功能逻辑,不关心元素的定位和操作;
                • 中间层:元素的定位和操作方法层,每个方法均对应一个元素的一个具体操作,也可以是多个操作的组合操作,中间层主要服务于用例层,具有可扩展性和复用性;
                • 核心层:主要封装的底层功能实现,此层在框架中提供一些通用的接口能力,功能模块相对独立,核心层主要服务于操作层,比如:通过图像识别的元素定位模块、通过 UI 坐标的元素定位模块、通过属性定位的元素定位模块、键鼠操作的基础方操作模块、Dbus 接口操作模块、文件的增删改查操作模块等。

                2、自动化的应用

                • CI 流程

                  • 每日构建流水线:是对研发每日提交的代码进行测试,AT 的大致流程:每日下班之后会将各应用进行打包,然后在测试机上安装更新 deb 包,最后进行自动化测试。

                  • 持续集成流水线:是对应用提交集成的版本进行测试,AT 的大致流程:每日下载最新的 ISO 进行 PXE 部署,然后测试机安装最新的镜像,最后进行自动化测试。

                • 验收测试

                  • 在各验收节点进行自动化验收,目前的策略是全用例覆盖全架构。
                • 回归测试

                  • 回归测试今年规划建设中,旨在回归测试时执行自动化测试用例,减少功能测试的重复劳动力。

                3、存在的问题

                • 各应用之间存在耦合

                  在自动化测试项目初期,所有应用是整体发布,我们是将所有应用看成是一个整体,各应用作为其中的一个模块,所以存在应用间方法交叉调用的问题,这样从最初的设计来讲确实能够减少重复代码的编写。

                  但是,现在应用走独立发布,各应用都有自己的迭代节奏,在新需求快速变化的过程中,自动化维护变得异常困难,原因就是自动化项目里面各个应用的有比较多的耦合关系,因此我们需要进行解耦,以适应应用不同的迭代周期。

                • 无法精准的划分用例范围

                  用例执行的范围不够精准,目前自动化用例执行时,主要通过用例的关键词 core(核心)来区分用例是否为核心用例,但是这样的区分太宽泛了,不能适应自动化测试在多场景下的应用。很多场景下我们还需要根据用例的等级、用例的类型、用例来源等等,不同的维度来挑选要执行的用例。在用例脚本中添加关键字需要人工一条条的改,费时费力,而且不好维护。

                • 受新需求影响跳过的用例不好维护

                  目前需要跳过的用例都需要在对应的用例脚本里面,添加跳过用例的代码,后续解除跳过的时候又需要找到这条脚本,删掉跳过用例的代码。在跳过用例较多的情况下,维护起来有难度。

                • 编写用例时逻辑比较复杂,需要调用多个应用的方法模块。

                • 框架扩展性不足,无法整合性能自动化、压测自动化、安全自动化等专项测试。

                二、方案设计

                为解决以上问题,适应不断丰富的测试场景,更好的发挥自动化测试的作用,需要对自动化架构及各功能模块进行重新设计规划。

                1、架构设计

                现AT框架架构图

                2、设计思路

                框架的运行逻辑:

                通过核心层提供一个基础能力,业务层根据实际业务需求(测试用例)动态加载核心层,执行入口加载相应的用例集并控制执行,应用层根据实际测试需求,通过相应的配置项进行配置,从而触发自动化测试任务。

                • 核心层:

                  基本保持不变,部分模块会涉及到新功能开发,核心层各功能模块保持独立性,提供通用的接口能力,供上层调用;底层核心模块包括:

                  • 图像识别模块
                  • UI 定位模块
                  • Dbus 接口操作模块
                  • 属性定位模块
                  • 日志模块
                  • 键鼠操作模块
                  • 文件操作模块
                  • 录屏模块
                  • 自定义断言模块
                  • 用例执行模块
                  • PXE 装机模块
                  • 键鼠信号模拟模块
                  • OCR 模块
                • 业务层:

                  以应用为维度划分,应用内包含多个测试类型,如功能测试、性能测试、漏洞扫描等,后续可以根据需要嫁接进来。其中功能测试设计思路:

                  • 以应用为维度划分,并将测试数据和测试资源整合进来,增加用例标签 csv 文件,用于给每条用例打标签。

                    各标签所使用对应的字段名称,使用 csv 文件维护用例与标签的对应关系,对用例实现标签化管理,可以组合其中的标签而从驱动对应的自动化用例执行,兼容现有用例标签,且支持用例标签可扩展;

                    为什么使用csv格式

                    使用 csv 格式文件可以方便的使用 Excel 表格打开进行编辑,同时由于 csv 文件实际是以都好分隔的文本文件,代码中可以在不依赖三方库的情况下方便快速的解析它,可操作性和可维护性较高。

                  • 各个应用之间,用例、方法、标签和资源都是相互独立的,编写和维护用例时只需要自己应用下的方法和公共库即可。

                  • 结构举例:

                    shell
                    .
                    +    
                    Skip to content
                    🎨 作者:mikigo 📔 阅读量:

                    自动化测试架构设计规划

                    • 目标:
                      • 应用 AT 架构工程化,参考性能自动化工程完成工程化改造。
                      • 应用间用例解耦,解除所有交叉调用的方法,各应用能跟随自身迭代周期独立维护 AT 用例。
                      • 完成公共方法的抽取整合,形成一套独立于应用间的公共方法库,各应用方法里面不存在被多个应用调用的情况。
                      • 用例实现标签化管理,为将来适配更多的 AT 运用场景提供支撑,原则上可实现无限扩展,在每日构建和持续集成流程落地使用。
                      • 代码规范问题清零,符合 Shell CheckPylint、系统部相关编码规范要求。
                    • 意义:
                      • 统一成研 AT 架构设计思路,消除 AT 代码实现和维护上可能出现的分歧,改善历史 AT 无工程化设计的缺陷,提高架构专业性。
                      • 各应用 AT 代码相互独立,契合应用独立发布特性,可支持迭代期间独立新增、维护和执行。
                      • 方法调用逻辑得到简化,编写和维护更高效;公共库抽取,减少方法重复编写,提高代码利用率;平均编写一条用例从 40 分钟降低至 30 分钟,日产出用例从 12 条/天提升至 16 条/天。
                      • 可灵活支撑不同的自动化运用场景,如 CI、冒烟测试、集成测试、回归测试、专项测试等。

                    一、背景介绍

                    提示

                    这里介绍以前的AT框架情况以及存在的一些问题;

                    1、原有架构介绍

                    原AT框架架构图

                    原有自动化测试架构整体分为三层:用例层(业务逻辑层)、中间层(元素定位和操作方法层)、核心层(底层功能库层)。

                    • 用例层:即应用的用例,专注于业务功能逻辑,不关心元素的定位和操作;
                    • 中间层:元素的定位和操作方法层,每个方法均对应一个元素的一个具体操作,也可以是多个操作的组合操作,中间层主要服务于用例层,具有可扩展性和复用性;
                    • 核心层:主要封装的底层功能实现,此层在框架中提供一些通用的接口能力,功能模块相对独立,核心层主要服务于操作层,比如:通过图像识别的元素定位模块、通过 UI 坐标的元素定位模块、通过属性定位的元素定位模块、键鼠操作的基础方操作模块、Dbus 接口操作模块、文件的增删改查操作模块等。

                    2、自动化的应用

                    • CI 流程

                      • 每日构建流水线:是对研发每日提交的代码进行测试,AT 的大致流程:每日下班之后会将各应用进行打包,然后在测试机上安装更新 deb 包,最后进行自动化测试。

                      • 持续集成流水线:是对应用提交集成的版本进行测试,AT 的大致流程:每日下载最新的 ISO 进行 PXE 部署,然后测试机安装最新的镜像,最后进行自动化测试。

                    • 验收测试

                      • 在各验收节点进行自动化验收,目前的策略是全用例覆盖全架构。
                    • 回归测试

                      • 回归测试今年规划建设中,旨在回归测试时执行自动化测试用例,减少功能测试的重复劳动力。

                    3、存在的问题

                    • 各应用之间存在耦合

                      在自动化测试项目初期,所有应用是整体发布,我们是将所有应用看成是一个整体,各应用作为其中的一个模块,所以存在应用间方法交叉调用的问题,这样从最初的设计来讲确实能够减少重复代码的编写。

                      但是,现在应用走独立发布,各应用都有自己的迭代节奏,在新需求快速变化的过程中,自动化维护变得异常困难,原因就是自动化项目里面各个应用的有比较多的耦合关系,因此我们需要进行解耦,以适应应用不同的迭代周期。

                    • 无法精准的划分用例范围

                      用例执行的范围不够精准,目前自动化用例执行时,主要通过用例的关键词 core(核心)来区分用例是否为核心用例,但是这样的区分太宽泛了,不能适应自动化测试在多场景下的应用。很多场景下我们还需要根据用例的等级、用例的类型、用例来源等等,不同的维度来挑选要执行的用例。在用例脚本中添加关键字需要人工一条条的改,费时费力,而且不好维护。

                    • 受新需求影响跳过的用例不好维护

                      目前需要跳过的用例都需要在对应的用例脚本里面,添加跳过用例的代码,后续解除跳过的时候又需要找到这条脚本,删掉跳过用例的代码。在跳过用例较多的情况下,维护起来有难度。

                    • 编写用例时逻辑比较复杂,需要调用多个应用的方法模块。

                    • 框架扩展性不足,无法整合性能自动化、压测自动化、安全自动化等专项测试。

                    二、方案设计

                    为解决以上问题,适应不断丰富的测试场景,更好的发挥自动化测试的作用,需要对自动化架构及各功能模块进行重新设计规划。

                    1、架构设计

                    现AT框架架构图

                    2、设计思路

                    框架的运行逻辑:

                    通过核心层提供一个基础能力,业务层根据实际业务需求(测试用例)动态加载核心层,执行入口加载相应的用例集并控制执行,应用层根据实际测试需求,通过相应的配置项进行配置,从而触发自动化测试任务。

                    • 核心层:

                      基本保持不变,部分模块会涉及到新功能开发,核心层各功能模块保持独立性,提供通用的接口能力,供上层调用;底层核心模块包括:

                      • 图像识别模块
                      • UI 定位模块
                      • Dbus 接口操作模块
                      • 属性定位模块
                      • 日志模块
                      • 键鼠操作模块
                      • 文件操作模块
                      • 录屏模块
                      • 自定义断言模块
                      • 用例执行模块
                      • PXE 装机模块
                      • 键鼠信号模拟模块
                      • OCR 模块
                    • 业务层:

                      以应用为维度划分,应用内包含多个测试类型,如功能测试、性能测试、漏洞扫描等,后续可以根据需要嫁接进来。其中功能测试设计思路:

                      • 以应用为维度划分,并将测试数据和测试资源整合进来,增加用例标签 csv 文件,用于给每条用例打标签。

                        各标签所使用对应的字段名称,使用 csv 文件维护用例与标签的对应关系,对用例实现标签化管理,可以组合其中的标签而从驱动对应的自动化用例执行,兼容现有用例标签,且支持用例标签可扩展;

                        为什么使用csv格式

                        使用 csv 格式文件可以方便的使用 Excel 表格打开进行编辑,同时由于 csv 文件实际是以都好分隔的文本文件,代码中可以在不依赖三方库的情况下方便快速的解析它,可操作性和可维护性较高。

                      • 各个应用之间,用例、方法、标签和资源都是相互独立的,编写和维护用例时只需要自己应用下的方法和公共库即可。

                      • 结构举例:

                        shell
                        .
                         ├── apps
                            ├── deepin_album  # 应用名 (用下划线连接是 Python 编码规范)
                            ├── album_assert  # 断言库
                        @@ -50,8 +50,8 @@
                             def click_xxx_by_attr(self):
                                 """通过属性定位的方式,点击某个元素"""
                                 ...
                        -    def ...

                        3、用例标签化管理

                        3.1、根据业务需要,用例可以添加对应的标签,比如:

                        • 用例级别:对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示;

                        • 用例类型:对应 coresmoke,或为空;

                        • 用例来源:对应 PMS 用例来源;

                          举例:

                          用例ID用例级别用例类型用例来源
                          001L1corexxx

                          标签支持扩展;

                        3.2、在每个应用目录下新建 csv 文件,用于保存用例标签,第一列为用例的 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;

                        对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,用于管理模块内的用例标签。是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

                        3.3、对照 PMS 上用例等级、用例类型和用例来源,标记所有已实现的用例标签,后续编写新增自动化用例时,每写一条都需要在对应的 csv 文件里面标记此条用例的标签。

                        3.4、跳过用例标签化

                        现有跳过用例的方式是在用例脚本里面给用例添加装饰器,解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多:

                        举例:

                        用例ID...(各种用例标签)跳过原因
                        001...skip-受到某新需求影响
                        • 将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;
                        • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标记为 “skip-跳过原因”;
                        • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标记,如果已经标记了跳过原因,最终的用例状态会被标记为 SKIPED,用例也不会被执行。

                        4、用例执行

                        4.1、标签化管理的驱动执行逻辑功能实现

                        • 开发根据用例标签文件里面的用例标签执行对应用例的功能,能支持多个标签的逻辑组合,执行入口能随意通过用例标签指定要执行的用例。
                        • 用例标签的驱动方式必须能支持标签的扩展,未来随着业务的变化可能需要增加各种各样的标签。

                        4.2、不同测试类型的用例执行

                        功能测试、漏洞扫描、性能测试等不同测试类型的用例是分开执行的,也就是在一次执行中,只能执行其中一种测试类型,具体要执行哪一种同样通过参数来控制。

                        4.3、分布式轮换执行

                        由于测试机资源有限,随着自动化用例数量的增加,CI 执行时间会越来越长。

                        分布式轮换执行的功能:

                        • 同一个应用的用例分散到不同架构的测试机上执行,缩短执行总时间;
                        • 第二天跑的时候同一个机器上会执行昨天没有执行到的用例,后续执行同理;
                        • 可以实现在全架构测试机上轮流执行用例,既能保证执行了所有的用例,又能在资源有限的情况下覆盖了所有的架构。

                        5、自动化测试平台

                        5.1、自动化测试平台作为前端界面系统,通过页面上的一些功能选项进行对应测试任务的管理或触发,业内比较流行的实现方案是使用 Vue + DRF 实现一个前后端分离的系统。

                        测试平台可能会涉及到的模块有:测试机资源管理模块、用例执行控制模块、结果展示模块、PXE 镜像安装模块等。

                        TIP

                        用户(测试、研发同学等)可以配置自己的测试计划,如执行哪个应用、执行用例的范围、在哪台机器上执行、镜像版本及下载地址、应用版本及下载地址、执行时间。

                        5.2、执行入口提供给测试平台的接口包括:用例执行接口、结果返回接口、镜像下载接口、测试机镜像安装接口、应用下载接口、测试机应用安装更新接口等。

                        前端平台目前还没有太多详细的方案,本次设计主要集中在后端这部分架构的设计上。

                        四、实施计划

                        近期任务计划

                        阶段目标计划开始时间计划结束时间
                        应用解耦、公共方法库抽离和方法文档整理:文管代码解耦2022/3/282022/4/8
                        应用解耦、公共方法库抽离和方法文档整理:图形图像应用代码解耦2022/4/112022/4/22
                        应用解耦、公共方法库抽离和方法文档整理:音视频应用代码解耦2022/4/112022/4/22
                        应用解耦、公共方法库抽离和方法文档整理:全局搜索代码解耦2022/4/252022/4/26
                        应用解耦、公共方法库抽离和方法文档整理:公共库建设2022/4/272022/5/5
                        应用解耦、公共方法库抽离和方法文档整理:封装的方法整理成一个表2022/5/62022/5/10
                        完成标签化管理和执行:用例标签分类评估2022/5/112022/5/11
                        完成标签化管理和执行:标签化执行驱动程序编写2022/5/122022/5/23
                        完成标签化管理和执行:需实现自动解析 csv 表格中的用例编号2022/5/122022/5/23
                        完成标签化管理和执行:编写爬虫脚本,爬取 pms 上用例的标签2022/5/112022/5/13
                        完成标签化管理和执行:编写定时自动维护本地 csv 文件脚本2022/5/112022/5/20

                        中期任务计划

                        阶段目标计划开始时间计划结束时间
                        目录结构调整2022/5/202022/6/2
                        完成全局和局部配置的具体方案和逻辑实现2022/6/62022/6/17
                        静态扫描问题清零2022/6/202022/7/1
                        完成新框架使用培训2022/7/42022/7/11
                        落地运行2022/7/122022/7/20
                        底层库用途说明文档编写2022/7/212022/7/28
                    - + def ...

                    3、用例标签化管理

                    3.1、根据业务需要,用例可以添加对应的标签,比如:

                    • 用例级别:对应 PMS 上用例级别,分别用 L1、L2、L3、L4 表示;

                    • 用例类型:对应 coresmoke,或为空;

                    • 用例来源:对应 PMS 用例来源;

                      举例:

                      用例ID用例级别用例类型用例来源
                      001L1corexxx

                      标签支持扩展;

                    3.2、在每个应用目录下新建 csv 文件,用于保存用例标签,第一列为用例的 ID,从第二列开始及之后的列,每一列都是一个用例标签;后续需要新增用例标签,可以直接在 csv 文件里面添加对应的列即可;

                    对于用例规模比较大的应用,比如文件管理器,建议分模块,每个模块建立一个 csv 文件,用于管理模块内的用例标签。是否分模块维护 csv 取决于应用的用例复杂度,同时我们应该充分考虑后期的可维护性,csv 文件太多了也是一个很糟糕的事情。

                    3.3、对照 PMS 上用例等级、用例类型和用例来源,标记所有已实现的用例标签,后续编写新增自动化用例时,每写一条都需要在对应的 csv 文件里面标记此条用例的标签。

                    3.4、跳过用例标签化

                    现有跳过用例的方式是在用例脚本里面给用例添加装饰器,解除跳过时将装饰器代码删掉,这种方式需要修改用例代码,而通过 csv 文件来管理跳过用例则会方便很多:

                    举例:

                    用例ID...(各种用例标签)跳过原因
                    001...skip-受到某新需求影响
                    • 将跳过用例操作也整合进入用例标签,在 csv 文件中新增一列为“跳过原因”;
                    • 如果应用受到新需求影响需要跳过,则在此列备注具体的跳过原因。跳过的原因统一标记为 “skip-跳过原因”;
                    • 用例执行时判断 csv 文件里面跳过原因列是否存在跳过标记,如果已经标记了跳过原因,最终的用例状态会被标记为 SKIPED,用例也不会被执行。

                    4、用例执行

                    4.1、标签化管理的驱动执行逻辑功能实现

                    • 开发根据用例标签文件里面的用例标签执行对应用例的功能,能支持多个标签的逻辑组合,执行入口能随意通过用例标签指定要执行的用例。
                    • 用例标签的驱动方式必须能支持标签的扩展,未来随着业务的变化可能需要增加各种各样的标签。

                    4.2、不同测试类型的用例执行

                    功能测试、漏洞扫描、性能测试等不同测试类型的用例是分开执行的,也就是在一次执行中,只能执行其中一种测试类型,具体要执行哪一种同样通过参数来控制。

                    4.3、分布式轮换执行

                    由于测试机资源有限,随着自动化用例数量的增加,CI 执行时间会越来越长。

                    分布式轮换执行的功能:

                    • 同一个应用的用例分散到不同架构的测试机上执行,缩短执行总时间;
                    • 第二天跑的时候同一个机器上会执行昨天没有执行到的用例,后续执行同理;
                    • 可以实现在全架构测试机上轮流执行用例,既能保证执行了所有的用例,又能在资源有限的情况下覆盖了所有的架构。

                    5、自动化测试平台

                    5.1、自动化测试平台作为前端界面系统,通过页面上的一些功能选项进行对应测试任务的管理或触发,业内比较流行的实现方案是使用 Vue + DRF 实现一个前后端分离的系统。

                    测试平台可能会涉及到的模块有:测试机资源管理模块、用例执行控制模块、结果展示模块、PXE 镜像安装模块等。

                    TIP

                    用户(测试、研发同学等)可以配置自己的测试计划,如执行哪个应用、执行用例的范围、在哪台机器上执行、镜像版本及下载地址、应用版本及下载地址、执行时间。

                    5.2、执行入口提供给测试平台的接口包括:用例执行接口、结果返回接口、镜像下载接口、测试机镜像安装接口、应用下载接口、测试机应用安装更新接口等。

                    前端平台目前还没有太多详细的方案,本次设计主要集中在后端这部分架构的设计上。

                    四、实施计划

                    近期任务计划

                    阶段目标计划开始时间计划结束时间
                    应用解耦、公共方法库抽离和方法文档整理:文管代码解耦2022/3/282022/4/8
                    应用解耦、公共方法库抽离和方法文档整理:图形图像应用代码解耦2022/4/112022/4/22
                    应用解耦、公共方法库抽离和方法文档整理:音视频应用代码解耦2022/4/112022/4/22
                    应用解耦、公共方法库抽离和方法文档整理:全局搜索代码解耦2022/4/252022/4/26
                    应用解耦、公共方法库抽离和方法文档整理:公共库建设2022/4/272022/5/5
                    应用解耦、公共方法库抽离和方法文档整理:封装的方法整理成一个表2022/5/62022/5/10
                    完成标签化管理和执行:用例标签分类评估2022/5/112022/5/11
                    完成标签化管理和执行:标签化执行驱动程序编写2022/5/122022/5/23
                    完成标签化管理和执行:需实现自动解析 csv 表格中的用例编号2022/5/122022/5/23
                    完成标签化管理和执行:编写爬虫脚本,爬取 pms 上用例的标签2022/5/112022/5/13
                    完成标签化管理和执行:编写定时自动维护本地 csv 文件脚本2022/5/112022/5/20

                    中期任务计划

                    阶段目标计划开始时间计划结束时间
                    目录结构调整2022/5/202022/6/2
                    完成全局和局部配置的具体方案和逻辑实现2022/6/62022/6/17
                    静态扫描问题清零2022/6/202022/7/1
                    完成新框架使用培训2022/7/42022/7/11
                    落地运行2022/7/122022/7/20
                    底层库用途说明文档编写2022/7/212022/7/28
                + \ No newline at end of file