尝试使用Playwright自带的机制解决
以上三个问题都可以使用 page.wait_for_timeout(<timeout>) 加入固定的等待时间进行处理,但是需要在所有上述情景中加入等待,而且由于是固定等待时间,时间的长短也不好控制,过短的话没有效果,过长的话又会导致自动化测试执行时间的延长,而且页面加载时间可能是随机的、依赖环境的,无法准确预知。所以一般来说,不建议使用固定等待时间来处理。
创建浏览器对象时加入 slow_mo 参数,这样会使Playwright的每一步操作前都等待固定的时间,优点是不需要在每一步操作前进行添加,一次配置,全局可用,缺点和上面一样,本质同样是固定等待时间,而且涉及每一步操作,会更加拖慢执行速度
Playwright提供了 page.wait_for_load_state() 方法,支持3种参数 load domcontentloaded 和 networkidle ,可以等待页面加载至预期状态。但是经我测试发现这种方法并不是很好用,可以解决部分问题,但是还是有很大概率等待时间不足(即使我把三种参数都用上了)。

为了更优雅的解决这个问题,我就在Playwright的基础上进行了扩展

扩展Playwright
基本思路
必须抛弃掉固定等待时间的方法,即使用到固定等待时间,也需要在一个循环中判断达到某个条件(如元素出现)就退出循环。注意到Playwright提供了 page.on 注册回调函数的方法,那么就可以在回调函数中记录时间发生的时间,等待至一定时间内没有事件发生即为页面加载完毕(类似于networkidle )。

实现方法

# client.py
import time
from abc import ABC, abstractmethodfrom playwright.sync_api import sync_playwright, Frame, Pageclass Client(ABC):playwright = Nonebrowser = Nonedef __init__(self, url: str):self.url = urlself.context = Noneself.main_page = Noneself.last_busy_time = time.time()@abstractmethoddef register_page(self):passdef _update_busy_time(self, event=None) -> None:if isinstance(event, Page) or isinstance(event, Frame):self._register_busy_time(event)self.last_busy_time = time.time()def _register_busy_time(self, obj) -> None:obj.on('domcontentloaded', self._update_busy_time)obj.on('download', self._update_busy_time)obj.on('filechooser', self._update_busy_time)obj.on('frameattached', self._update_busy_time)obj.on('framedetached', self._update_busy_time)obj.on('framenavigated', self._update_busy_time)obj.on('load', self._update_busy_time)obj.on('pageerror', self._update_busy_time)obj.on('popup', self._update_busy_time)obj.on('request', self._update_busy_time)obj.on('requestfailed', self._update_busy_time)obj.on('requestfinished', self._update_busy_time)obj.on('response', self._update_busy_time)def start(self) -> None:Client.playwright = sync_playwright().start()Client.browser = Client.playwright.chromium.launch()self.context = Client.browser.new_context()self.main_page = self.context.new_page()self._register_busy_time(self.main_page)self.main_page.goto(self.url)self.register_page()
# page.py
import timeclass BasePage(object):def __init__(self, client, page=None):self.client = clientif not page:self.page = client.main_pageelse:self.page = pagedef wait_until_idle(self, timeout=1) -> None:while time.time() - self.client.last_busy_time < timeout:self.page.wait_for_timeout(100)

代码解析
在 Client 类中定义 last_busy_time 属性,用于记录最后一次页面事件发生的时间。
Client 类中的 _update_busy_time 方法,用于在 page.on 中注册回调方法,更新last_busy_time ,并当事件为打开新页面或frame时,在新页面或frame中对事件注册 page.on 回调(这里比较简单,只判断了事件类型,实际应用时可以根据需要定制)。
Client 类中的 _register_busy_time 方法,用于为页面事件注册回调函数(这里只是列举可能用到的事件类型,实际应根据项目特点进行定制)。
在 start 方法中创建第一个页面后,调用_register_busy_time 方法,即可将后续所有打开的页面和frame都对页面事件进行注册,只要发生对应的页面事件就会更新last_busy_time 属性为当前时间。
在 BasePage 类中定义了 wait_until_idle 方法,用于判断当页面空闲时间大于 timeout 时即停止等待,认为当前页面加载完毕,并且并且页面已经空闲的时候会即刻返回,不会增加测试执行时间。
总结
如上代码提供了一个自动等待页面空闲的方法,可以在任意需要等待的地方使用,使用效果优于等待固定时间。如果配合自己封装的 Element ,则可以在每一个操作前面加入此等待,这样就可以摆脱手动添加等待的烦恼;如果再配合重试机制,那么执行测试的稳定性将会更上一层楼。

扩展Playwright自动等待方法相关推荐

  1. mysql查询耗时_一种数据库高耗时查询的自动取消方法与流程

    本发明涉及数据库的查询方法,特别涉及一种数据库高耗时查询的自动取消方法. 背景技术: 有很多关系型数据库查询业务非常耗时,比如查询企业实时报表之类的,一次查询可能需要几分钟甚至更长.在很多时候,前端业 ...

  2. 软件测试自动生成测试数据,软件测试中测试数据的自动生成方法浅析

    一.引言 软件质量是制约计算机应用领域进一步发展的关键要素之一,保证软件质量.提高软件可靠性的重要手段是软件测试.软件测试中最关键的问题是测试数据的设计,它主要涉及两个方面,一是测试 数据生成,是测试 ...

  3. 35个Photoshop最强己付费扩展面板+自动修图PS插件

    安装方法:解压出(Extensions Plus For PS CC V5.1 photops 專版 Fix.exe)文件直接安装 建议安装时关闭数位等杀毒软体,因为有可能会误报,造成安装失败! 本软 ...

  4. 台式计算机屏幕扩展,电脑扩展显示器调整的方法

    随着电脑逐渐地走入了人们的生活,可有的小伙伴们连最基本的电脑显示屏安装都不会,哪里又会知道多屏的安装扩展呢?下面是学习啦小编为大家整理的关于电脑扩展显示器调整的方法,一起来看看吧! 电脑扩展显示器调整 ...

  5. 一种网络用户行为日志自动获取方法

    摘要 本发明公开了一种网络用户行为日志自动获取方法,其特征在于:在客户端与Web服务器之间加上一代理服务器,代理服务器第一次接受Web服务器返回的响应正文为HTML格式的用户响应即HTTP响应,在该H ...

  6. xml建模包括以下_一种基于xml建模的印刷出版中多元组合符号自动生成方法

    一种基于xml建模的印刷出版中多元组合符号自动生成方法 [技术领域] [0001] 本发明属于印刷出版技术领域,具体涉及一种基于XML建模的印刷出版中多元组 合符号自动生成方法. [背景技术] [00 ...

  7. 计算机的屏幕怎么扩展,电脑如何扩展屏幕_给电脑扩展屏幕的设置方法

    正常情况下,一台电脑就只有显示一个屏幕桌面,工作中经常要显示多个屏幕,这样可以一边工作,一边做其他事情.那么如何给电脑扩展屏幕?相信很多小伙伴还不懂怎么操作?别担心,下面给大家说一下给电脑扩展屏幕的具 ...

  8. php 自动注册变量,phpwind放自动注册方法

    phpwind放自动注册方法 更新时间:2006年12月02日 00:00:00   作者: 论坛老是有人暴力注册发广告  好烦 打开wind\register.htm 认证码*  请将图片中的数字或 ...

  9. 字符指针分拣C语言,一种货物自动分拣方法及系统与流程

    本发明属于自动分拣系统及方法领域,尤其是一种货物自动分拣方法及系统. 背景技术: 自动分拣系统包括控制装置.分类装置.输送装置和分拣道口,控制装置的作用是识别.接收和处理分拣信号,根据分拣信号的要求控 ...

  10. 关系型数据库横向扩展的三种方法

    本文是 Oracle Coherence 3.5一书,第一章: Achieving Performance, Scalability, and Availability Objectives,第二节: ...

最新文章

  1. 机器学习 对不平衡数据的四种处理方法
  2. Android开发--蓝牙操作
  3. 3YAdmin-专注通用权限控制与表单的后台管理系统模板
  4. 带缓冲的I/O操作和不带缓冲的I/O操作
  5. 使用docker 起容器配置负载均衡(加权)
  6. linux sort 排序 性能,Linux中sort 排序
  7. Window 的版本号管理策略
  8. android窗口泄漏
  9. 强连通分量(Tarjan)模板
  10. pdg文件格式 到 pdf文件格式 的转换
  11. Android 网页无法打开 net:ERR_UNKNOWN_URL_SCHEME
  12. python短信验证码登录_Python实现短信验证
  13. 算法创作|栈的应用——括号匹配问题解决方法
  14. 一个留学中介的CRM案例
  15. DRM系列(3)之DRM_IOCTL_MODE_MAP_DUMB
  16. 美的集团的命,智能家居来续?
  17. checkbox列表选择2
  18. 23 种设计模式的通俗解释,虽然有点污,但是秒懂
  19. 个人随笔-求学求职-工作经历-计划
  20. JAVA代码计算1900年到所求年份共多少天。

热门文章

  1. 传统超声图像处理方法总结
  2. 创建一个名为User的类
  3. 一篇教你学会Ansible
  4. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十五)地图编辑器的初步使用...
  5. 《跨界杂谈》华为印象之混搭(五)乞丐装
  6. 漫画算法-学习笔记(03)
  7. canvas制作加载动画并打包发布(原生js和react框架)
  8. 赛迪顾问:大数据助力农业现代化发展
  9. 认识C语言 Day_2 >生命周期、作用域
  10. [转载]打工辛酸路:我是一朵飘零的花之38