《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现、移除、显示和隐藏)

news/2024/11/19 4:18:19/文章来源:https://www.cnblogs.com/du-hong/p/18303190

1.简介

在我们日常工作中进行UI自动化测试时,保证测试的稳定性至关重要。其中一个关键方面是正确地定位和操作网页中的元素。在网页中,元素可能处于不同的状态,有些可能在页面加载完成之前不在DOM中,需要某些操作后才会出现,而其他元素可能一直存在于DOM中,但最初处于隐藏状态,需要通过操作才能使其出现进而处于可见状态。 因此如果在执行脚本时没有考虑到元素的状态,很可能导致脚本执行失败。为了保证自动化测试的稳定性,我们需要确保在执行操作之前,所需的元素已经达到了指定状态。

下面宏哥将介绍和分析讲解三种常用的元素等待方式:wait_for_timeout(),wait_for(),wait_for_selector() 和 wait_for_element_state()以及四者之间的优劣势。

2.强制等待

2.1wait_for_timeout()

wait_for_timeout() 方法会等待调用方法时指定的时间。‌

这个方法用于设置一个等待的超时时间,‌它允许程序在执行某些操作前等待指定的时间。‌如果在设定的时间内操作未完成,‌则可能会抛出超时错误。‌这种机制在编程中非常有用,‌尤其是在需要等待某个条件满足或资源可用时。‌例如,‌在使用playwright进行网页自动化测试时,‌wait_for_timeout()方法可以用来确保在继续执行操作之前,‌网页元素已经加载完成或处于可操作状态。‌如果元素未在给定的时间内加载完成,‌则可以通过捕获超时错误来处理这种情况,‌从而避免操作失败。官方定义的函数如下:

    def wait_for_timeout(self, timeout: float) -> None:"""Page.wait_for_timeoutWaits for the given `timeout` in milliseconds.Note that `page.waitForTimeout()` should only be used for debugging. Tests using the timer in production are goingto be flaky. Use signals such as network events, selectors becoming visible and others instead.**Usage**```py# wait for 1 secondawait page.wait_for_timeout(1000)``````py# wait for 1 secondpage.wait_for_timeout(1000)```Parameters----------timeout : floatA timeout to wait for"""return mapping.from_maybe_impl(self._sync(self._impl_obj.wait_for_timeout(timeout=timeout)))

3.自动等待

3.1.wait_for()

wait_for() 是先定位元素,再等待元素满足指定状态。先定位元素,再使用wait_for() 方法也可以等待元素到达指定的状态。

如果元素已满足条件,则立即返回。否则,它会等待直到超时时间到达为止。

该方法接受两个关键字参数:
timeout:指定最大等待时间(以毫秒为单位)。默认为 30000(30秒),但可以更改。
state:指定要等待的状态。默认为 ‘visible’。可以是 ‘attached’、‘detached’、‘hidden’ 或 ‘visible’ 中的一个。

官方定义的函数如下:

    def wait_for(self,*,timeout: typing.Optional[float] = None,state: typing.Optional[Literal["attached", "detached", "hidden", "visible"]] = None) -> None:"""Locator.wait_forReturns when element specified by locator satisfies the `state` option.If target element already satisfies the condition, the method returns immediately. Otherwise, waits for up to`timeout` milliseconds until the condition is met.**Usage**```pyorder_sent = page.locator(\"#order-sent\")await order_sent.wait_for()``````pyorder_sent = page.locator(\"#order-sent\")order_sent.wait_for()```Parameters----------timeout : Union[float, None]Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value canbe changed by using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods.state : Union["attached", "detached", "hidden", "visible", None]Defaults to `'visible'`. Can be either:- `'attached'` - wait for element to be present in DOM.- `'detached'` - wait for element to not be present in DOM.- `'visible'` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that elementwithout any content or with `display:none` has an empty bounding box and is not considered visible.- `'hidden'` - wait for element to be either detached from DOM, or have an empty bounding box or`visibility:hidden`. This is opposite to the `'visible'` option."""return mapping.from_maybe_impl(self._sync(self._impl_obj.wait_for(timeout=timeout, state=state)))

宏哥还是按之前toast的消息那个demo来演示,这里就不写demo的HTML代码,不知道的可以看宏哥之前的文章:传送门

3.1.1代码设计

3.1.2参考代码
# coding=utf-8🔥# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2024-07-16
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态
'''# 3.导入模块
from playwright.sync_api import Playwright, sync_playwright, expectdef run(playwright: Playwright) -> None:browser = playwright.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("E:/Desktop/test/toast.html")# 点击 点击关注 按钮page.locator("#hongge").click()# 等待元素出现在dompage.locator('//html/body/div').wait_for(state="attached")# 获取元素文本print(page.locator('//html/body/div').inner_text())page.locator('//html/body/div').wait_for(state="detached")print("元素已经从DOM移除")page.wait_for_timeout(1000)context.close()browser.close()with sync_playwright() as playwright:run(playwright)
3.1.3运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.运行代码后电脑端的浏览器的动作。如下图所示:

3.2wait_for_selector()

page.wait_for_selector() 是 Playwright 中的一个方法,‌用于等待与指定 CSS 选择器匹配的元素出现在页面中。‌

这个方法接受一个选择器参数和一个可选的选项参数。‌常用的选项参数包括:‌

  • visible:‌指定元素必须可见,‌默认为 False。‌
  • hidden:‌指定元素必须隐藏,‌默认为 False。‌
  • state:‌可以设置为 visible、‌hidden、‌attached 或 detached,‌用于等待元素达到特定的状态。‌
  • timeout:‌设置等待的超时时间,‌以毫秒为单位。‌如果在指定的时间内元素未达到等待的状态,‌则会抛出超时异常。‌

官方定义的函数如下:

    def wait_for_selector(self,selector: str,*,state: typing.Optional[Literal["attached", "detached", "hidden", "visible"]] = None,timeout: typing.Optional[float] = None,strict: typing.Optional[bool] = None) -> typing.Optional["ElementHandle"]:"""ElementHandle.wait_for_selectorReturns element specified by selector when it satisfies `state` option. Returns `null` if waiting for `hidden` or`detached`.Wait for the `selector` relative to the element handle to satisfy `state` option (either appear/disappear from dom,or become visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, themethod will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, thefunction will throw.**Usage**```pyawait page.set_content(\"<div><span></span></div>\")div = await page.query_selector(\"div\")# waiting for the \"span\" selector relative to the div.span = await div.wait_for_selector(\"span\", state=\"attached\")``````pypage.set_content(\"<div><span></span></div>\")div = page.query_selector(\"div\")# waiting for the \"span\" selector relative to the div.span = div.wait_for_selector(\"span\", state=\"attached\")```**NOTE** This method does not work across navigations, use `page.wait_for_selector()` instead.Parameters----------selector : strA selector to query for.state : Union["attached", "detached", "hidden", "visible", None]Defaults to `'visible'`. Can be either:- `'attached'` - wait for element to be present in DOM.- `'detached'` - wait for element to not be present in DOM.- `'visible'` - wait for element to have non-empty bounding box and no `visibility:hidden`. Note that elementwithout any content or with `display:none` has an empty bounding box and is not considered visible.- `'hidden'` - wait for element to be either detached from DOM, or have an empty bounding box or`visibility:hidden`. This is opposite to the `'visible'` option.timeout : Union[float, None]Maximum time in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to disable timeout. The default value canbe changed by using the `browser_context.set_default_timeout()` or `page.set_default_timeout()` methods.strict : Union[bool, None]When true, the call requires selector to resolve to a single element. If given selector resolves to more than oneelement, the call throws an exception.Returns-------Union[ElementHandle, None]"""return mapping.from_impl_nullable(self._sync(self._impl_obj.wait_for_selector(selector=selector, state=state, timeout=timeout, strict=strict)))

1.等待元素出现在DOM中

page.wait_for_selector("定位方法", state='attached')

2.等待从DOM中移除

page.wait_for_selector("定位方法", state='detached')

3.等待元素可见

page.wait_for_selector("定位方法", state="visible")

4.等待元素不可见(隐藏)

page.wait_for_selector("定位方法", state='hidden')

如果没有传 state 参数,默认情况下是等待元素可见 visible

page.wait_for_selector("定位方法")
3.2.1等待元素出现和移除

默认情况下,在HTML页面的DOM节点里面是没有这个元素的,通过某些操作(点击【点击关注】按钮),这个元素才出现,如下图所示:

宏哥还是按之前toast的消息那个demo来演示,这里就不写demo的HTML代码,不知道的可以看宏哥之前的文章:传送门

3.2.1.1代码设计

3.2.1.2参考代码
# coding=utf-8🔥# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2024-07-16
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态
'''# 3.导入模块
from playwright.sync_api import Playwright, sync_playwright, expectdef run(playwright: Playwright) -> None:browser = playwright.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("E:/Desktop/test/toast.html")# 点击 点击关注 按钮page.locator("#hongge").click()# 等待元素出现在domloc_msg = page.wait_for_selector('//html/body/div', state="attached")# 获取元素文本print(loc_msg.inner_text())page.wait_for_selector('//html/body/div', state="detached")print("元素已经从DOM移除")page.wait_for_timeout(1000)context.close()browser.close()with sync_playwright() as playwright:run(playwright)
3.2.1.3运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.运行代码后电脑端的浏览器的动作。如下图所示:

3.2.2等待元素显示和隐藏

默认情况下,在HTML页面的元素本身就在DOM里,只是通过某些操作,状态发生改变:隐藏和显示。如下提示语本来就在DOM里,只是默认是隐藏状态。宏哥还在之前的演示demo找到了一个这样的场景,刚好用来演示。

3.2.2.1代码设计

3.2.2.2参考代码
# coding=utf-8🔥# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2024-07-16
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态
'''# 3.导入模块
from playwright.sync_api import Playwright, sync_playwright, expectdef run(playwright: Playwright) -> None:browser = playwright.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("https://sahitest.com/demo/visible.htm")#点击隐藏按钮page.locator("//html/body/form/input[4]").click()page.wait_for_selector("#uv", state="hidden")print("元素已经隐藏")page.wait_for_timeout(1000)# 点击显示按钮page.locator("//html/body/form/input[5]").click()loc_msg = page.wait_for_selector("#uv", state="visible")print("元素已经显示")# 获取元素文本print(loc_msg.inner_text())page.wait_for_timeout(1000)context.close()browser.close()with sync_playwright() as playwright:run(playwright)
3.2.2.3运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.运行代码后电脑端的浏览器的动作(注意:using visibility显示和隐藏,可以加长等待时间,看的更清楚)。如下图所示:

3.3 wait_for_element_state()

wait_for_load_state(),等待事件被触发。等待前面按钮触发的事件加载完成,才进行下面的操作。

在Python的Playwright库中,‌wait_for_load_state()方法用于等待页面达到特定的加载状态。‌该方法接受三个参数:‌

  • state:‌页面应该达到的加载状态,‌可以是load、‌domcontentloadednetworkidle。‌这些状态分别代表页面的不同加载程度,‌其中load表示页面完全加载,‌domcontentloaded表示文档内容已经加载,‌而networkidle则表示网络几乎无连接,‌即页面加载已完成。‌

  • timeout:‌等待的最长时间,‌单位为毫秒。‌默认值为30 * 1000,‌即30秒。‌这个参数用于设置等待操作的最大超时时间,‌以避免程序长时间等待而无法继续执行。‌

  • wait_until:‌等待的事件类型,‌可以是load、‌domcontentloaded、‌networkidle0networkidle2中的一个。‌这个参数用于指定等待的具体事件类型,‌以便更精确地控制等待的条件。‌

通过使用wait_for_load_state()方法,‌可以确保在继续执行后续操作之前,‌页面已经完全加载完成,‌从而避免因页面元素未完全加载而导致的操作失败或错误。

官方定义的函数如下:

    def wait_for_load_state(self,state: typing.Optional[Literal["domcontentloaded", "load", "networkidle"]] = None,*,timeout: typing.Optional[float] = None) -> None:"""Page.wait_for_load_stateReturns when the required load state has been reached.This resolves when the page reaches a required load state, `load` by default. The navigation must have beencommitted when this method is called. If current document has already reached the required state, resolvesimmediately.**Usage**```pyawait page.get_by_role(\"button\").click() # click triggers navigation.await page.wait_for_load_state() # the promise resolves after \"load\" event.``````pypage.get_by_role(\"button\").click() # click triggers navigation.page.wait_for_load_state() # the promise resolves after \"load\" event.``````pyasync with page.expect_popup() as page_info:await page.get_by_role(\"button\").click() # click triggers a popup.popup = await page_info.value# Wait for the \"DOMContentLoaded\" event.await popup.wait_for_load_state(\"domcontentloaded\")print(await popup.title()) # popup is ready to use.``````pywith page.expect_popup() as page_info:page.get_by_role(\"button\").click() # click triggers a popup.popup = page_info.value# Wait for the \"DOMContentLoaded\" event.popup.wait_for_load_state(\"domcontentloaded\")print(popup.title()) # popup is ready to use.```Parameters----------state : Union["domcontentloaded", "load", "networkidle", None]Optional load state to wait for, defaults to `load`. If the state has been already reached while loading currentdocument, the method resolves immediately. Can be one of:- `'load'` - wait for the `load` event to be fired.- `'domcontentloaded'` - wait for the `DOMContentLoaded` event to be fired.- `'networkidle'` - **DISCOURAGED** wait until there are no network connections for at least `500` ms. Don't usethis method for testing, rely on web assertions to assess readiness instead.timeout : Union[float, None]Maximum operation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. The default value canbe changed by using the `browser_context.set_default_navigation_timeout()`,`browser_context.set_default_timeout()`, `page.set_default_navigation_timeout()` or`page.set_default_timeout()` methods."""return mapping.from_maybe_impl(self._sync(self._impl_obj.wait_for_load_state(state=state, timeout=timeout)))

宏哥在这个网站:https://www.jq22.com/ 找了一个demo,只有加载完成才会出现文字,然后对其进行定位打印文本。

3.3.1代码设计

3.3.2参考代码
# coding=utf-8🔥# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2024-07-16
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态
'''# 3.导入模块
from playwright.sync_api import Playwright, sync_playwright, expectdef run(playwright: Playwright) -> None:browser = playwright.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("https://www.jq22.com/demo/jquery-jdt20160820/")page.wait_for_load_state()print(page.locator('//*[@id="progress_content"]/i[4]/span').inner_text())context.close()browser.close()with sync_playwright() as playwright:run(playwright)
3.3.3运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出,如下图所示:

2.运行代码后电脑端的浏览器的动作。如下图所示:

敲黑板!!!1.注意自动化测试的加载的时间不要超过此方法的默认时间,超时就会报错了哈!!!这个网站需要加载40S才会出现文字,如下图所示:

3.3.4代码设计

3.3.5参考代码
# coding=utf-8🔥# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2024-07-16
@author: 北京-宏哥
北京宏哥(微信搜索:北京宏哥,关注宏哥,提前解锁更多测试干货!)
Project: 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态
'''# 3.导入模块
from playwright.sync_api import Playwright, sync_playwright, expectdef run(playwright: Playwright) -> None:browser = playwright.chromium.launch(headless=False)context = browser.new_context()page = context.new_page()page.goto("https://sahitest.com/demo/php/delayedLoadInner.php")page.wait_for_load_state()print(page.locator("//html/body/div").inner_text())print(page.locator("//html/body/span").inner_text())context.close()browser.close()with sync_playwright() as playwright:run(playwright)
3.3.6运行代码

1.运行代码,右键Run'Test',就可以看到控制台输出(.运行代码控制台报错,因为加载这个页面需要40s,而此方法默认30000ms=30s,超时报错),如下图所示:

2.运行代码后电脑端的浏览器的动作。如下图所示:

4.小结

4.1wait_for() 和 wait_for_selector()使用区别

wait_for() 方法 和 wait_for_selector()使用区别:

page.locator('定位元素').wait_for() 返回的是None,后面不能继续操作元素

page.wait_for_selector("定位方法") 返回的是locator 对象,后面可以继续操作元素

好了,今天时间也不早了,宏哥就讲解和分享到这里,感谢您耐心的阅读,希望对您有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/779556.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BACnet初学者教程,第三章:什么是 BACnet/IP 网络

第三章:什么是 BACnet/IP 网络平时调试BACnet协议,一个好用的 BACnet 调试工具和模拟器必不可少,推荐一款: 官网地址:https://www.redisant.cn/bacnetexplorerBACnet/IP 网络是一个或多个 IP 子网(IP 域)的集合,这些子网分配有单个 BACnet 网络号。BACnet 互联网络由两…

BACnet初学者教程,第四章:介绍 BACnet 虚拟链路层

第四章:介绍 BACnet 虚拟链路层平时调试BACnet协议,一个好用的 BACnet 调试工具和模拟器必不可少,推荐一款: 官网地址:https://www.redisant.cn/bacnetexplorer虚拟链路层 (VLL) 背后的基本概念是向现有的 BACnet 网络层呈现某些网络拓扑和功能的视图,利用新协议中内置的…

读零信任网络:在不可信网络中构建安全系统12源代码和构建系统

读零信任网络:在不可信网络中构建安全系统12源代码和构建系统1. 建立应用信任 1.1. 软件正在吞噬整个世界 1.2. 零信任网络需要关注应用程序的安全性,这似乎违反直觉,毕竟网络是不可信的,因此可以预见网络上存在不可信的应用 1.3. 运行在数据中心的软件堪称一切魔法之源,因…

雷达气象相关词汇(二 偏振参量)

参考自https://www.radartutorial.eu/15.weather/wr20.en.html 双偏振雷达 使用双偏振是区分冰雹和雨滴的一种方法。雷达发射和接收线性极化电磁波信号,并在水平和垂直偏振之间快速切换,在单个发射脉冲之间或在脉冲组之间交替。现代双偏振雷达通常同时传输两个偏振方向。示意…

第十章 自定义模块

10.1 导入模块 1.什么是python模块? ​ Python模块(Module),是一个Python文件,以.py结尾 模块可以定义函数,类和变量,模块里也能包含可执行的代码 2.模块的作用: ​ python中有很多各种不同的模块,每一个模块都可以帮助我们快速的实现一些功能 3.模块的导入方式: # 模块在使用…

雷达气象相关词汇(一 扫描模式)

参考自https://www.radartutorial.eu/15.weather/wr20.en.html https://en.wikipedia.org/wiki/Plan_position_indicator PPI(平面位置显示) A plan position indicator (PPI) is a type of radar display that represents the radar antenna in the center of the display, wi…

searchLights 动画

LOGO扫光效果.logo { width: 200px; height: 70px; display: flex; line-height: 70px; position: relative; overflow: hidden } .logo img { width: 100%; height: 70px } \3c p>.logo:before { } \3c br> @-webkit-keyframes searchLights { } \3c br> @-o-keyfram…

JavaWeb后端开发2024-08-08

Maven Apache Maven 是一个项目管理和构建工具,它基于项目对象模型(POM)的概念,通过一小段描述信息来管理项目的构建。Maven作用 依赖管理统一的项目结构项目构建仓库安装Maven<mirror> <id>alimaven</id> <name>aliyun maven</name> <u…

Golang语言之gRPC程序设计示例

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.RPC协议介绍1.什么是RPC2.什么是GRPC3.安装gRPC环境3.1 使用gRPC的前提3.2 安装protoc3.3 安装go plugin二.Protocol Buffer的使用指南1.使用Protocol Buffer的基本流程概述2.编写产品服务等proto文件…

迅雷赚钱宝1代刷OpenWRT单网口接在主路由下,内网访问正常,外网无法访问的解决办法。

1. 问题缘由OpenWRT单网口NAS(迅雷赚钱宝1代),接在主路由下面提供NAS服务,配置有基于eth0的DHCPv6Client来获取IPv6公网IP,以实现通过IPv6公网,提供对外的NAS服务。发现在局域网访问DDNS-go的管理界面9876端口正常访问,DDNS-go已允许外网访问,但通过手机数据流量模拟外…

c#农历开源库

https://6tail.cn/calendar/api.html非常牛逼 Unity将当前时间转为天干地支using System; using Lunar; using UnityEngine;public class GanZhiTimeConverter : MonoBehaviour {private void Start(){var solar = Solar.FromDate(DateTime.Now);Debug.Log(solar.Lunar.YearInG…

关于算法竞赛,青岛农业大学ACM实验室简介

大家好,我是青岛农业大学ACM实验室的杨兴睿,一名帅气的acmer~( ̄▽ ̄~)(~ ̄▽ ̄)~,尽管你在官网或者其他地方看过各种各样天花乱坠的宣传,我可以很明确的告诉你那是不真实的,今天用这篇博客给大家介绍一下最真实的ACM实验室。 我们先从算法竞赛开始讲起吧,算法竞赛也是…