一、常见UI自动化框架分析
UI自动化的理解:定位元素--->操作元素---->断言
根据定位元素方法不同,衍生出来不同的UI自动化框架:
元素定位类型的:Selenium、Cypress、Appium、playwright
图像定位类型的:Airtest
与常用的selenium的对比
二、 playwright特性
1. 支持多平台
2. 支持多语言
官方文档有python、node、.net、java文档。
python:Installation | Playwright Python
node:Installation | Playwright
java:Installation | Playwright Java
.net:Installation | Playwright .NET
3.支持tab切换,不需要用句柄;更直观简单
4. 自带的playwright codegen可直接录制脚本
5.自动等待
Playwright在最目标元素操作之前会对其进行一系列可操作性检查,确保这些预期操作能正常运行。Playwright会自动等待所有相关检查通过,之后再执行请求操作。如果在规定的时间内没有通过所有检查,则会操作失败并显示TimeoutError。
比如,对于 page.click(selector, **kwargs),Playwright会在之前进行如下检查:
- 目标元素依附于DOM中
- 目标元素可见
- 目标元素是稳定的,如没有加载动画等
- 目标元素可以触发事件,没有被其它元素遮挡
- 目标元素已启用(Enabled)
Playwright提供自动等待API,自动等待元素出现(自动等待30s,等待时间可以自定义,单位毫秒),自动等待时间发送
自动识别浏览器超时。Playwright可以接收浏览器信号,如网络请求、页面导航和页面加载事件,以解决设置不稳定的睡眠时间的需要
快速隔离浏览器环境:Playwright支持上一个执行完成的浏览器实例作为下一个执行的开始
更加灵活的元素定位:Playwright支持面向用户的字符串定位,如通过文本内容和可访问标签来定位元素。
Playwright的自动等待机制解决了Selenium的痛点,无需二次开发,提高脚本稳定性
三、使用过程
3.1、安装
pip3 install pytest-playwright
pip3 install playwright
python3 -m playwright install # 或者直接playwright install
3.2、自动录制
--help查看对应的参数命令:python3 -m playwright codegen --help 会自动打开两个窗口,左侧浏览器区域,右侧代码生成区,左侧直接操作,右侧即可生成对应的操作。当然如果生成的代码元素定位想要更换,可点击Recode暂停后,点击下方的浏览器定位,点到左侧的元素区域,重新定位元素。
3.3、元素定位
官方文档:Locators | Playwright Python
playwright推荐使用定位器也就是locators,定位器是自动等待与重试的核心能力。更符合用户行为的定位器。
这些是推荐的内置定位器。
page.get_by_role()通过显式和隐式可访问性属性定位。
page.get_by_text()按文本内容定位。
page.get_by_label()通过关联标签的文本查找表单控件。
page.get_by_placeholder()按占位符查找输入。
page.get_by_alt_text()通过其文本替代品定位元素,通常是图像。
page.get_by_title()通过标题属性定位元素。
page.get_by_test_id()根据其data-testid属性定位元素(可以配置其他属性)。
当然除了这些,还有其他定位方法,selenium的8种by元素定位,id、xpath、css、等都可使用
还有W3C标准规定的webDriver协议为5种定位方式
CSS、Link text、Partial link text、Tag name、XPath
playwright把这些定位归类成3种,分别是:css、xpath、text
如:
page.locator("xpath=//h2")
page.locator("text=文本输入")
page.locator("#s-usersetting-top")
page.locator("input[name=\"wd\"]").click()
page.get_by_role("button", name="百度一下").click()
page2.get_by_placeholder("唱片名、表演者、条码、ISRC").click()
page2.get_by_text("或者,亲自来帮豆瓣添加:").click()
3.4、元素操作
官方文档:Locator | Playwright Python
下拉选择框:selectOpion、value、labei、index
文件上传:setInputFiles、单个文件、多个文件、拖放上传
鼠标点击:click、dbclick
鼠标拖动:down、up
鼠标移动:move
触摸屏幕:tag
键盘按键:press
截屏、录屏:screenshot、recordVideo
3.5、页面切换
expect_popup
from playwright.sync_api import Playwright, sync_playwright, expect
def run(playwright: Playwright) -> None:
browser = playwright.chromium.launch(headless=False)
context = browser.new_context()
page = context.new_page()
# 进入百度,搜索中国,搜索结果页面点击第一个后,打开新的tab,切换到新tab进行操作
page.goto("百度一下,你就知道")
page.locator("input[name=\"wd\"]").click()
page.locator("input[name=\"wd\"]").fill("中国")
page.get_by_role("button", name="百度一下").click()
# 点击结果页面,打开新的tab
with page.expect_popup() as popup_info:
page.get_by_role("link", name="中国,世界四大文明古国之一,百度百科").click()
# 切换到新页面,新页面上进行操作
page1 = popup_info.value
page1.get_by_role("link", name="首页").click()
page1.wait_for_url("百度百科_全球领先的中文百科全书")
# 回到第一个页面,重新操作
page.locator("input[name=\"wd\"]").click()
page.locator("input[name=\"wd\"]").fill("重新输入内容")
page.get_by_role("button", name="百度一下").click()
# ---------------------
context.close()
browser.close()
with sync_playwright() as playwright:
run(playwright)
3.6、断言
文字内容断言 # 获取文本内容,进行断言 content = page.text_content('[target="_blank"]:first-child') assert content == "新闻" 内部文字断言 # 获取内部文字,进行断言 text = page.inner_text('[target="_blank"]:first-child') assert text == "新闻" 属性断言 # 获取属性值,进行断言 attribute = page.get_attribute('#su', 'value') assert attribute == "百度一下" 复选框断言 page.hover('//*[@id="u1"]/*[text()="设置"]') page.click('//*[@id="s-user-setting-menu"]//*[text()="搜索设置"]') # 复选框状态,进行断言 checked = page.is_checked('//*[text()="全部语言"]') assert checked js表达式断言 # JS表达式,进行断言 js_content = page.locator('[data-index="4"]>a>[class="title-content-title"]').text_content() assert js_content == "长津湖超战狼2成中国影史票房冠军" 内部HTML断言 # 内部 HTML ,进行断言 html = page.inner_html('[class="hot-title"]') assert "百度热搜" in html 元素可见断言 # 元素可见性 ,进行断言 visible = page.is_visible('#su') assert visible 启动状态断言 # 启用状态(元素存在可点击) ,进行断言 enabled = page.is_enabled('#su') assert enabled 直接对比断言 assert page.title() == "百度一下,你就知道"
定位器断言官方文档:LocatorAssertions | Playwright Python
页面page断言官方文档:PageAssertions | Playwright Python
tips:
使用time.sleep()会导致超时问题:
建议使用page.wait_for_timeout(毫秒)替换time module的time.sleep(秒),会很好改善超时问题。因为Playwright内部是依赖于异步操作,而当使用time.sleep(秒)时,无法正确处理这种情况。