python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > python pywinauto

python pywinauto使用过程及问题小结

作者:大卫软件测试

在pywinauto库中,uia即UIAutomation,是微软提供的用于用户界面自动化测试和辅助功能访问的技术框架,UIAutomation支持自动化脚本与各种UI元素交互,本文给大家介绍python pywinauto使用过程及问题小结,感兴趣的朋友一起看看吧

1- pywinauto 中的uia是什么意思?

pywinauto库中,uia指的是UI Automation,这是Windows操作系统提供的一种技术框架,用于实现用户界面(UI)的自动化测试和辅助功能访问。UI Automation是微软从Windows Vista开始引入的核心技术,旨在为所有UI元素提供一致的编程接口,无论这些元素是由何种技术(如Win32、WPF、UWP等)实现的。

pywinauto中,通过指定backend="uia",用户可以选择使用UI Automation作为底层引擎来与应用程序的UI元素进行交互。这为自动化测试提供了更广泛的支持,尤其是在处理现代Windows应用(尤其是使用WPF和UWP技术构建的应用)时更为有效。UI Automation后端相比传统的win32后端,提供了更丰富和高级的元素属性、控制模式(Control Patterns)以及事件支持,使得自动化脚本可以更加灵活和强大。

使用UI Automation后端,开发者可以更容易地定位和操作UI元素,如获取元素的属性、模拟鼠标和键盘操作、监听UI事件等,这对于创建复杂的自动化测试场景尤其有用。

2-pywinauto 中main_window.child_window()方法及参数详细介绍

pywinauto中,child_window()方法是用于定位父窗口中的一个特定子窗口或控件。这对于自动化测试中准确地找到并操作特定的UI元素至关重要。下面是对child_window()方法及其参数的详细说明:

基本用法

child_window()方法属于窗口对象,用于在当前窗口的所有子窗口中搜索符合指定条件的第一个子窗口。基本语法如下:

Python

1parent_window.child_window(arguments)

其中,parent_window是你已经获取到的窗口对象,arguments是用于筛选子窗口的一系列关键字参数。

参数详解

child_window()方法接受多个关键字参数来精确地定位子窗口,常见的参数包括但不限于:

示例

假设你想在记事本应用的主窗口中找到名为“文件”(File)的菜单项,可以这样做:

Python

from pywinauto import Application
app = Application(backend="uia").start("notepad.exe")
main_window = app.window(title="无标题 - 记事本")
# 使用class_name和title定位子窗口
menu_item = main_window.child_window(class_name="MenuItem", title="文件")

注意事项

通过灵活运用child_window()方法及其参数,你可以高效地定位并操作UI自动化中的各种元素。

3-child_window() / children() / descendants()方法介绍

如果要获取父窗口下的所有直接子窗口(而不只是单个子窗口),可以使用children()方法,它会返回一个包含所有直接子元素的列表。此元素定位方式,需要window类型为: WindowSpecification

例如:

Python

all_direct_children = parent_window.children()

而如果你需要递归地获取所有子孙窗口(子窗口以及子窗口的子窗口等),可以使用descendants()方法, 此元素定位的方式,需要window类型为:UiaWrapper:

Python

all_descendants = parent_window.descendants()

总结来说,parent_window.child_window()是用于定位单个满足特定条件的子窗口,而不是获取所有子内容。 若要获取所有子内容,请根据需要使用children()descendants()

4-pywinauto打开程序时,程序启动的比较慢,或点击按钮弹窗比较慢,或者打开新窗口窗口渲染的比较慢,怎么添加合理的等待时间

在使用pywinauto进行自动化操作时,合理地添加等待时间是非常重要的,尤其是在程序启动慢、按钮点击后弹窗延迟或新窗口渲染速度较慢的情况下。这能确保脚本在继续执行下一步操作前,等待相关的UI元素准备就绪。以下是几种添加等待时间的方法:

1. 显式等待(推荐)

使用wait方法是最灵活且推荐的等待方式,它允许你指定等待的条件和超时时间。

等待窗口可见:

Python

app.Window(title="窗口标题").wait("visible", timeout=10)

等待控件可用:

Python

app.Dialog.child_window(title="按钮标题", control_type="Button").wait("enabled", timeout=20)

2. 静态等待(time.sleep)

虽然不如显式等待灵活,但在某些简单场景下可以使用time.sleep来简单地暂停脚本执行。

Python

import timetime.sleep(5)  # 等待5秒

3. 动态等待

对于某些不确定何时完成的操作,可以在循环中结合检查条件和短暂停顿来实现动态等待。

Python

import time
timeout = 30  # 总超时时间
interval = 1  # 检查间隔
start_time = time.time()
while time.time() - start_time < timeout:
    if app.Window(title="窗口标题").exists():
        break
    time.sleep(interval)
else:
    raise TimeoutError("窗口未在指定时间内出现")

4. 使用backend的特性

某些后端(如uia)提供了更高级的等待逻辑,例如在启动应用程序时可以利用Application().start(..., timeout=...)来指定启动超时时间。

5-pywinauto 打开的app有多个不同的窗口时,怎么定位具体的某个窗口

pywinauto中,如果一个应用程序打开了多个不同的窗口,要定位到具体的某个窗口,你可以根据窗口的特征来精确筛选。以下是一些常用的筛选方法:

1. 根据窗口标题(Title)

窗口标题通常是区分不同窗口最直观的属性。你可以使用窗口标题的精确文本或正则表达式来定位窗口。

Python

specific_window = app.window(title="窗口的精确标题")
# 或者使用正则表达式来模糊匹配
specific_window = app.window(title_re="窗口标题的一部分.*")

2. 结合类名(Class Name)

如果多个窗口的标题相似,但类名不同,你可以结合类名一起筛选。

Python

specific_window = app.window(title="窗口标题", class_name="窗口类名")

3. 控件类型(Control Type)和自动化ID(Automation ID)

在使用UIA后端时,如果窗口内有特定类型的控件或者控件具有唯一的Automation ID,也可以作为定位依据。

Python

# 假设窗口内有特定的控件类型或ID
specific_window = app.window(control_type="Window", automation_id="特定的自动化ID")

4. 使用子窗口或后代窗口

如果需要定位的窗口是另一个窗口的子窗口或后代,可以先定位到父窗口,再通过child_window()descendants()方法找到目标窗口。

Python

parent_window = app.window(title="父窗口标题")
specific_child_window = parent_window.child_window(title="子窗口标题")
# 或者遍历所有后代窗口找到匹配的
specific_descendant_window = parent_window.descendants(title="后代窗口标题")[0]  # 注意这会返回一个列表

5. 通过句柄(Handle)

如果你已经知道了窗口的句柄,可以直接通过句柄连接到窗口。

Python

from pywinauto.windows import win32functions
handle = win32functions.FindWindowEx(None, None, "窗口类名", "窗口标题")
specific_window = app.window(handle=handle)

注意事项

6-pywinauto 中element_info 和BaseWrapper的用法

pywinauto中,element_infoBaseWrapper是两个核心概念,它们在自动化测试和界面操作中扮演着重要角色。

element_info (pywinauto.element_info.ElementInfo)

element_info是一个底层的、面向元素信息的抽象类,它提供了对UI元素属性的访问和描述,但不直接支持操作。它是一个轻量级的包装,用于存储和传递关于UI元素的信息,如类名、标题、位置等,而不涉及实际的UI操作。element_info是所有控件信息的基础,无论控件是通过哪个后端(如win32, uia)来识别的。

当你使用pywinauto的方法(如child_window())来定位一个元素时,实际上就是在创建或查找一个element_info对象。element_info对象可以被用来创建更高级的包装对象,如BaseWrapper

BaseWrapper (pywinauto.base_wrapper.BaseWrapper)

BaseWrapper是基于element_info的更高层次的包装,它不仅包含了元素的信息,还提供了对元素进行操作的方法,如点击、发送文本、获取属性等。当你需要与UI元素进行交互时,比如点击一个按钮或填写一个文本框,你应该使用BaseWrapper对象。

BaseWrapperelement_info的直接扩展,它将底层的元素信息转换为可操作的对象。这意味着,你可以通过BaseWrapper直接执行如.click(), .set_text(), .texts(), .exists()等操作,使得自动化脚本编写更为直观和便利。

使用示例

假设你要操作一个按钮,可以按照以下步骤:

Python

from pywinauto import Application
app = Application().start("your_app.exe")
main_win = app.window(title="Main Window Title")
# 使用child_window()方法找到一个按钮,得到的是一个BaseWrapper实例
button = main_win.child_window(title="Click Me", control_type="Button")
# 然后,你可以直接调用BaseWrapper的方法来操作这个按钮
button.click()

在这个过程中,虽然没有直接使用element_info,但实际上child_window()内部处理了从element_infoBaseWrapper的转换,让你能够直接与UI元素进行交互。

7-pywinauto 的BaseWrapper类还有哪些方法,详细说明

根据搜索到的内容总结如下

pywinautoBaseWrapper类提供了许多方法来操作和查询UI元素。这些方法覆盖了从基本的属性访问到复杂的UI交互,下面是BaseWrapper类中一些常用方法的概览和简要说明:

常用属性和方法 .window_text(): 获取控件的文本内容。

控件定位和操作扩展

以上只列出了部分方法,实际上BaseWrapper类包含更多功能,涵盖了大多数自动化测试和UI操作的需求。具体的使用方法和参数细节,建议参考pywinauto的官方文档或直接查看源代码注释,以获取最全面和最新的信息。

Python

from pywinauto.controls.win32_controls import ButtonWrapper
button = ButtonWrapper(element)
button.click_input()

如果以上方法都不能解决问题,建议查阅 pywinauto 的官方文档或访问其GitHub页面查看是否有相关的问题报告或更新日志。同时,确保你的Python环境是最新的,并考虑升级 pywinauto 到最新稳定版。

8-pywinauto 都可以转换成什么控件类型Wrapper

pywinauto 提供了一系列针对不同控件类型的Wrapper类,这些类封装了对特定类型控件的操作方法,使得自动化操作更加直观和方便。以下是部分常用的控件类型及其对应的Wrapper类:

Button - ButtonWrapper

用于操作按钮,支持点击等操作。

Edit - EditWrapper

用于编辑框,支持文本的设置、获取等操作。

ComboBox - ComboBoxWrapper

用于组合框(下拉列表),支持选择项、获取选项列表等。

ListBox - ListBoxWrapper

用于列表框,支持选择项、获取项列表等。

CheckBox - CheckBoxWrapper

用于复选框,支持勾选、取消勾选及状态检查。

RadioButton - RadioButtonWrapper

用于单选按钮,支持选择及状态检查。

Menu - MenuWrapper

用于菜单项,支持展开菜单、选择菜单项等。

TreeView - TreeViewWrapper

用于树状视图控件,支持节点的展开、选择等。

TabItem - TabWrapper

用于选项卡控件中的单个选项卡。

Dialog - DialogWrapper

对话框窗口的特殊处理,虽然也是窗口,但可能包含特定于对话框的操作方法。

Window - WindowWrapper

通用窗口类,几乎所有窗口都可以用这个类来操作,但针对特定控件类型使用特定的Wrapper会更方便。

请注意,直接将element_info转换为特定的Wrapper类(如从element_infoButtonWrapper)并不总是直接支持,通常你不需要手动进行这样的转换。当你通过正确的筛选条件使用child_window()等方法时,pywinauto会自动为你提供最适合的Wrapper实例。如果需要更具体的控件操作,可以通过访问BaseWrapper实例的属性或方法来实现,因为大多数Wrapper类都是从BaseWrapper继承而来,已经包含了基础的交互方法。

在实际使用中,直接利用child_window()方法根据控件的属性(如标题、类名、控制类型等)来定位并操作控件即可,大多数情况下无需关心底层的Wrapper类转换。如果需要更高级或特定的功能,查阅pywinauto的文档或源码,了解特定Wrapper类的使用方法会更有帮助。

9-pywinauto打印获取的windows对象,一个是加了等待,一个是没加等待。

获取的window对象使用print(window),打印出来分别是uiawrapper.UIAWrapper - 'New mail', Dialog,另一个是<pywinauto.application.WindowSpecification object at 0x0000016B0DE556A0> 有什么区别

在使用pywinauto时,你观察到的区别反映了两种不同状态的窗口对象处理方式。

未使用等待(直接获取)

Python

window = app.window(title="New mail")
print(window)

输出类似于 <pywinauto.application.WindowSpecification object at 0x0000016B0DE556A0>,这表明你获得的是一个WindowSpecification对象。这个对象实际上是一个窗口的描述符或者说规范,它定义了你要找的窗口应该满足的条件(在这个例子中是标题为"New mail"的窗口)。但是,此时pywinauto尚未实际找到并实例化这个窗口,这意味着打印出来的信息是一个内存地址,代表了这个待查找窗口描述的实例。

使用等待后获取

Python

window = app.window(title="New mail").wait('visible')
print(window)

或者

Python

window = app.window(title="New mail").wait('exists', timeout=10)

输出为 uiawrapper.UIAWrapper - 'New mail', Dialog,这表示你成功获取到了一个实际的UI元素对象,它已经不是一个简单的查找规范,而是窗口实际存在的、可操作的对象。uiawrapper.UIAWrapperpywinauto内部用于包装UIA(UI Automation)元素的类,这意味着窗口不仅被找到了,而且已经准备好了进行进一步的交互操作,比如点击、输入文本等。

区别总结

在实际应用中,使用等待(如.wait('visible').wait('exists'))通常更为推荐,因为它确保了操作不会在窗口还没准备好时进行,提高了脚本的稳定性和可靠性。

10-我的pywinauto程序,Application.start()后,还需要执行application.connect() 后的app ,才能正常使用。否则此app获得的windows不可用,为什么?

pywinauto中,理论上,一旦你使用Application.start()方法启动了一个应用程序,它应该自动连接到这个新启动的应用实例,并且你能够直接通过返回的app实例进行窗口和控件的查找及操作,无需再次调用app.connect()

如果遇到必须先执行app.connect()后才能正常使用app获得的窗口或控件,这可能由几个原因引起:

解决方法建议:

如果问题持续,考虑查看pywinauto的官方文档或社区,可能有针对特定应

用或类似问题的解决方案。

我的问题其实应该是兼容问题,我增加start()后的等待时间,无效。

必须使用Application.connect()命令,重新获取app后,只有的操作才有效。

app = Application(backend="uia").start(outlook_path, timeout=30)
# 等待也是必须的
time.sleep(15)
# 必须使用connect()重新生成
app = Application(backend="uia").connect(class_name="Olk Host")
print("outlook第一次启动,打开outlook成功!, app=", app)

11-Application(backend="uia").start()参数中有timeout参数吗?

没有。

因为在标准的pywinauto文档和通常的使用中,直接的start()方法调用并不直接接受一个timeout参数用于等待应用程序启动完成。

通常,如果你想控制应用程序启动后的等待逻辑或处理超时,你需要采取一些额外的步骤,而不是直接通过start()方法的timeout参数(因为这个参数在标准用法中不存在)。以下是一些建议:

Python

app = Application(backend="uia").start("your_app_path")
main_window = app.window(title="Your Main Window Title").wait("visible", timeout=30)

这里,timeout=30就是等待窗口变为可见的最大时间,单位为秒。

异常处理:在尝试访问应用程序窗口或执行操作时,使用try-except结构来捕获可能的超时或失败异常,从而实现间接的超时控制。

自定义逻辑:根据应用程序的具体行为,你可能需要更定制化的逻辑来确定何时应用程序已成功启动并准备好进行自动化操作,这可能涉及检查特定进程的状态、窗口属性变化等。

综上所述,虽然直接在Application.start()方法中设置timeout参数不是标准用法,但通过上述方法你可以有效地控制和管理应用程序启动后的等待逻辑及超时处理。

12-Application(backend="uia").connect()参数中有timeout参数吗?

没有。

pywinauto提供了灵活的等待和超时控制机制来确保连接操作不会无限期地阻塞。

自动化等待与超时控制

虽然直接在connect()方法签名中没有公开timeout参数,但pywinautowait系列方法和自动化操作通常允许你指定一个超时限制,例如在尝试连接到一个窗口时:

Python

app = Application(backend="uia")
main_window = app.window(title="Your App Title").wait("exists", timeout=30)

在这个例子中,wait("exists", timeout=30)是尝试等待窗口存在最多30秒。如果窗口在指定时间内变得可访问,则继续执行;如果超时,则会抛出异常,允许你的脚本据此作出反应。

定制等待逻辑

对于更复杂的场景,你可能需要自定义等待逻辑,比如检查窗口是否不仅存在还满足其他条件(如“visible”、“enabled”等),并结合自定义的循环和超时处理。

总结

尽管Application(backend="uia").connect()直接调用时不带有一个明确的timeout参数,pywinauto提供的wait方法和自动化操作的灵活性让你能够有效控制连接和等待窗口出现的时间限制,实现类似超时处理的逻辑。通过这种方式,确保了自动化脚本既能够稳健地等待必要的窗口准备就绪,又能避免不必要的阻塞。

13-弹窗操作

pywinauto中,当需要连接并操作一个应用程序新弹出的窗口时,通常需要先确保新窗口已经出现,然后通过窗口的标题或其他属性来定位并操作它。以下是处理新弹窗的基本步骤:

1. 等待弹窗出现

使用pywinauto的等待功能确保弹窗已经打开。这可以通过循环检查窗口是否存在,或者使用更高级的等待方法来实现。

Python

from pywinauto import Application
from pywinauto.timings import wait_until_passes
app = Application().connect(title="主应用程序的标题")  # 首先连接到主应用程序
def is_popup_opened():
    try:
        app.window(title="弹窗的标题")
        return True
    except Exception:
        return False
# 等待弹窗出现,最多等待10秒
wait_until_passes(10, 1, is_popup_opened)

2. 定位并操作弹窗

一旦确认弹窗已经打开,就可以通过其标题或其它属性来定位并进行操作。

Python

popup_window = app.window(title="弹窗的标题")
# 例如,点击弹窗上的一个按钮
button_on_popup = popup_window.child_window(title="按钮的标题或自动化ID", control_type="Button")
button_on_popup.click()

3. 异常处理和重试机制

在实际操作中,可能需要添加适当的异常处理逻辑,以防窗口标题变化或打开速度过慢等情况。

4. 关闭弹窗

如果操作完成后需要关闭弹窗,可以调用窗口的关闭方法:

Python

popup_window.close()

注意事项:

14-AttributeError: 'UIAWrapper' object has no attribute 'print_control_identifiers'

pywinauto中,如果你遇到AttributeError: 'UIAWrapper' object has no attribute 'print_control_identifiers'错误,这意味着你尝试在一个基于UIA(UI Automation)的控件上使用了print_control_identifiers方法,但这个方法实际上并不直接存在于UIAWrapper对象中。

print_control_identifiers方法主要用于经典的Windows应用程序自动化(win32应用程序),它在Win32Window对象中可用。然而,对于基于UI Automation(UIA)的应用,如现代的UWP应用或使用了UIA框架构建的桌面应用,直接使用print_control_identifiers会报错。

对于UIAWrapper对象,你可以使用.legacy_properties()方法来获取控件的部分信息,但这通常不如print_control_identifiers那样详尽。

解决方案:

Python

1control = app.window(title="Your Window Title").child_window(auto_id="Your Control AutoId")
2print(control.properties)

这将打印出控件的属性字典,其中包含了控制类型、名称、位置等信息。

自定义打印函数:如果需要类似print_control_identifiers的详细输出,你可能需要自己编写一个函数来遍历.properties或使用UIA的其他方法来获取更详细的控件信息。

降级为win32:在某些情况下,如果应用同时支持UIA和win32,你可以尝试降级到win32模式来使用print_control_identifiers。但这取决于应用的具体实现和支持情况,且不是所有UIA应用都能这么做。

记住,UI Automation和经典Windows应用程序自动化在pywinauto中有一些差异,因此在处理不同类型的窗口和控件时,要相应地调整你的方法。

15-AttributeError: 'UIAWrapper' object has no attribute 'child_window'

UIAWrapper 窗口类型, 定位元素需要使用如下方法定位:ele = setWindow.descendants(title="Remove")[0]

当你在使用pywinauto遇到AttributeError: 'UIAWrapper' object has no attribute 'child_window'错误时,这意味着你尝试在一个基于UIA(UI Automation)的控件(UIAWrapper对象)上调用了child_window方法,但这个方法在UIAWrapper对象中并不可用。

UIAWrapper对象主要对应于使用UI Automation技术的应用程序,与传统的Win32应用程序使用的API有所不同。在UIAWrapper上,直接查找子窗口或控件的方法不是child_window,而是使用更符合UIA查询方式的属性和方法。

解决方案:

Python

controls = window.descendants(control_type="ControlType")  # 替换"ControlType"为实际控件类型,如"Button", "Edit",

直接属性访问:如果已知某些属性(如 namecontrol_type等),可以直接通过属性筛选。

Python

target_control = window.child_window(auto_id="目标控件的AutomationId")

注意:上述child_window方法是针对经典的win32应用程序,对于UIA,你应该使用更符合其查询机制的方法,如.descendants或直接属性筛选。

构造查询条件:使用更复杂的查询条件来精确定位控件,例如使用.filter()方法。

Python

1from pywinauto.controls.uia_controls import UIAWrapper
2control = UIAWrapper(handle=你的窗口句柄).filter(control_type="ControlType")[0]  # 替换"ControlType"和条件

确保理解你的应用是基于UI Automation还是传统的Win32,然后选择相应的API和方法来操作和查找控件。对于UIA应用,利用.descendants和属性筛选通常是最直接有效的方式。

16-pywinauto,已经找到窗口了,但使用window的方法print_control_identifiers()方法,会提示匹配到多个元素呢?There are 5 elements that match the criteria {'backend': 'uia', 'process': 22188}

当您已经成功定位到一个窗口,但在尝试使用 window.print_control_identifiers() 方法时遇到提示匹配到多个元素,这通常意味着您调用 print_control_identifiers() 的对象实际上是一个窗口集合或者是基于某些宽泛条件的窗口规范(WindowSpecification),而不是一个特定的窗口实例。

为了解决这个问题,确保您在调用 print_control_identifiers() 之前,已经准确地指定了一个唯一的窗口。这里有几个步骤可以帮助您:

Python

specific_window = windows[0]  # 假设'windows'是一个包含多个匹配窗口的列表
specific_window.print_control_identifiers()

确保每个步骤都尽可能具体和精确,以避免匹配到多个窗口的情况发生。

17-pywinauto, 使用Desktop(backend="uia")获取窗口

注意点1:
Desktop(backend="uia").windows()/window(),两个方法,只能查询所有的主窗口,不支持查询主窗口下都子窗口。
注意点2:
使用Desktop(backend="uia").windows()/window(),如果条件不能定位到窗口的情况下。
Desktop(backend="uia").windows()方法,结果返回空列表。
如下:
wins = Desktop(backend="uia").windows(title="Work or school account", class_name="Windows.UI.Core.CoreWindow")
print(wins)
结果:[]
Desktop(backend="uia").window()方法,结果返回WindowSpecification对象。
如下:
win = Desktop(backend="uia").window(title="Work or school account", class_name="Windows.UI.Core.CoreWindow")
print(win)
结果:<pywinauto.application.WindowSpecification object at 0x000001524BE87790>,不能使用返回的window()的返回值做判断。
注意点3:
如果窗口类型为:WindowSpecification,使用parent_window.child_window() 方式查询窗口元素。
如果窗口类型为:UIAWrapper,使用parent_window.parent_window.descendants() 方式查询窗口元素。

18-pywinauto ,通过元素的 element.rectangle() 方法,使用pyautogui,移动鼠标到元素位置,实现。

具体写法如下:

# 假设你想对窗口内的某个元素进行操作,首先找到该元素
element = main_window.child_window(title="Your Element Title", control_type="ControlTypeHere")  # 请替换为实际的标题和控件类型
# 获取元素的矩形信息
element_rectangle = element.rectangle()
# 使用 pyautogui 将鼠标移动到该位置
x, y = element_rectangle.left + (element_rectangle.width() // 2), element_rectangle.top + (element_rectangle.height() // 2)
pyautogui.moveTo(x, y)  # 移动到元素中心位置,也可以直接移到左上角,去掉加法部分即可

注意:element_rectangle.width 和element_rectangle.height返回的类型都是method;计算位置坐标是应使用element_rectangle.width() 和element_rectangle.height()形式。

否则报错:TypeError: unsupported operand type(s) for //: 'method' and 'int'(不支持这两两种类型使用//语法计算)

19-编码过程中,注意循环引用问题

E   ImportError: cannot import name 'assertTrue' from partially initialized module 'assertTool' (most likely due to a circular import)  --很可能是循环导入

问题:“文件a” 导入了 “文件b” 中的方法;“文件b” 也导入了“文件a”中的方法,导致循环导入问题。

20-pywinauot, 定位uiaWrapper 元素时,增加等待有时候不能解决问题。但是窗口最大化后,就能查找到元素了。

可能的原因:窗口布局变化

应用程序窗口在最大化之前和之后,其内部元素的布局可能会有细微的变化。这种布局变化可能会影响到元素的可访问性或者导致元素的属性(如坐标位置)发生变化。最大化窗口可能使得元素稳定地出现在预期的位置或状态,从而变得可被pywinauto识别。

21-pywinauto + pytest 执行的测试用例时,提示错误: Windows fatal exception: code 0x8001010d。 但是如果把此用例的内容,都放到一个文件中执行,不通过pytest,就没有这个错误提示。应该怎么解决

错误代码 0x8001010d 通常与COM(Component Object Model)错误相关,特别是“RPC服务器不可用”或“接口调用中出现错误”。在使用pywinauto进行GUI自动化测试时遇到这个问题,可能的原因有几个方面,尤其是在结合pytest使用时,可能与测试环境的初始化、资源释放、并发执行测试等方面有关。以下是一些可能的解决方案:

如果以上建议不能解决问题,可能需要更详细的日志来定位问题。考虑在pytest运行时增加日志级别(通过-vvv参数或配置logging模块),并查看是否有其他相关的警告或错误信息输出,这有助于更准确地定位问题所在。

您可能感兴趣的文章:
阅读全文