前言
上一篇文章地址:
pywinauto:Windows桌面应用自动化测试(五)-CSDN博客
下一篇文章地址:
暂无
一、实战常用方法
1、应用窗口可能是动态的
自动化测试过程中可能会遇到应用连不上的情况,使用inspect定位了一下窗口,可能是应用窗口名称变化导致的,那么这种情况怎么处理呢?这里给出一种处理方式:
print("开始连接应用...", datetime.now())
title_list = ['Form0', 'Form1']
for i in range(2):
try:
# 连接应用
self.app = Application(backend='uia').connect(title=title_list[i]) # Form
print("开始连接窗口...", datetime.now())
# 获取窗口
self.dialog = self.app.window(title=title_list[i]) # Form
break
except:
print(f"连接应用,第{i+1}次失败!")
print("连接应用成功!", datetime.now())
该代码的主要功能是尝试连接并获取一个 Windows 应用程序窗口。它使用两个可能的窗口标题进行尝试,并在成功连接后打印成功消息。如果第一次尝试失败,则会尝试第二个窗口标题。在两次尝试都失败的情况下,它会打印每次失败的消息。
2、使用pywinauto自动化很慢
遇到过很多次,每次的原因不一样,小结如下:
(1)win系统高负载
这种情况需要尽可能保持运行环境低负载。
(2)一些应用导致自动化很慢
这种情况尽可能保证只有被测对象打开。
(3)被测对象应用很大
使用加速:
from pywinauto.timings import Timings
Timings.fast()
from pywinauto.timings import Timings
这一行代码从 pywinauto.timings
模块中导入了 Timings
类。Timings
类提供了一些与时间相关的全局设置,用于控制 pywinauto 在自动化测试过程中等待窗口或控件出现、消失、响应等的时间间隔。
Timings.fast()
这一行代码调用了 Timings
类的 fast
方法。这个方法将 pywinauto 的各种时间设置调到较短的时间间隔,以加快自动化测试的执行速度。具体来说,fast
方法通常会将以下几个参数的默认值调低:
Timings.window_find_timeout
: 查找窗口的超时时间Timings.window_find_retry
: 查找窗口的重试时间间隔Timings.exists_timeout
: 检查控件存在性的超时时间Timings.exists_retry
: 检查控件存在性的重试时间间隔Timings.wait_until_ready_timeout
: 等待控件准备就绪的超时时间Timings.wait_until_ready_retry
: 等待控件准备就绪的重试时间间隔
通过调用 Timings.fast()
,你可以使得 pywinauto 在自动化测试过程中使用较短的等待时间,从而加快测试的速度。这在需要快速进行测试的场景下非常有用。
3、最小化应用会影响元素操作么
会影响元素继续操作,因为UI自动化是基于桌面显示的,最小化应用后不能操作已经加载的元素。
但是,不会影响到加载过的元素,此时放大,依旧能操作界面元素。
4、元素是按照什么顺序展示的
这一点很重要,因为当获取到多个元素时,得知道目标元素的下标,这种通常是从上层到下层、从上到下、从左到右的顺序,但这并不严谨。
在 pywinauto
中,多个同类型元素的顺序是基于它们在 UI 树中的顺序。这个顺序通常与元素在窗口中出现的顺序一致。pywinauto
使用的底层技术(如 UI Automation 或 MSAA)提供了一种按顺序遍历 UI 元素树的方法。
以下是几个关键点,说明 pywinauto
如何显示和处理多个同类型元素的顺序:
UI 树遍历 : pywinauto
通过遍历 UI 树来找到匹配的元素。UI 树是按照元素在窗口中出现的顺序进行组织的。
Find Elements : 当你使用 find_elements
方法时,pywinauto
会返回一个列表,列表中的元素顺序与它们在 UI 树中的顺序一致。
窗口标题和控件类型 : 你可以通过指定窗口标题和控件类型来获取匹配的元素。pywinauto
会按照它们在 UI 树中的顺序返回这些元素。
简而言之,UI 树遍历的顺序通常是按照**深度优先搜索(DFS)**进行的,这意味着 pywinauto
会先遍历一个控件的所有子控件,然后再移动到下一个兄弟控件。这种遍历顺序与控件在 UI 树中的结构有关,而不是它们在屏幕上视觉显示的顺序。
5、应用程序最小化到任务栏的断言方式
可以通过2个条件来判断,一是桌面上不显示应用界面(此时通过title连不上应用),二是任务栏有该应用在运行,因此可以这样设计:
def is_mini(self):
# 确认在任务栏有该程序
taskbar_app = Application("uia").connect(title="任务栏")
taskbar_win = taskbar_app.window(title="任务栏")
taskbar_win_status = taskbar_win.child_window(title_re=".*666.exe.*").exists()
# 确认窗口不显示在桌面
app_status = None
title_list = ['Form0', 'Form1']
for i in range(2):
try:
# 连接应用
Application(backend='uia').connect(title=title_list[i]) # Form
app_status = True
break
except:
app_status = None
if not app_status and taskbar_win_status:
print("已缩放到最小")
else:
raise AssertionError("没有缩放到最小!")
6、窗口对象是实时的
假设有这么一个场景,我连接了应用也连接了窗口dialog ,此时,我手动去打开一些窗口,这些窗口也是基于dialog的子窗口,如果知道这个窗口的元素定位方式,我还能对这个新窗口进行操作么?
答案是肯定的,pywinauto可以并自动通过重新遍历 dialog
窗口的子窗口来找到并操作新打开的窗口。
app = Application(backend='uia').connect(title="Form") # Form
dialog = self.app.window(title="Form") # Form