Playwright自动化测试
1.概述:
Playwright 是一个开源工具,用于自动化浏览器测试。它主要用于测试网站在不同浏览器和平台之间的功能兼容性。
Playwright 可以很好地模拟用户的操作,如点击按钮,输入文本等。它还可以模拟输入事件,如键盘和鼠标事件,以及浏览器的特定事件,如浏览器窗口的大小改变等。
2.优点:
playwright支持Chrome、Firefox、Safari、Microsoft Edge 等主流浏览器,支持以有头模式、无头模式运行浏览器。
playwright提供了同步和异步API,可以结合Pytest测试框架使用,并且支持自动录制浏览器端的操作脚本。
playwright环境搭建比selenium简单,还有他们两区别:传送门 ,传送门2
3.常用的元素定位(传送门):
##########################################基础元素定位############################################## # 定位文字信息(返回元素,exact表示是否精确匹配),并点击 page.get_by_text('账密登录', exact=True).click() # 通过id定位并输入内容 page.locator('#form_item_phone').fill("test123") # 根据元素角色进行定位,并点击 page.get_by_role("button", name="登 录").click() # 定位提示信息为 请输入名称 的输入框 page.get_by_placeholder('请输入名称', exact=True).click # 通过标题文本进行定位元素 page.get_by_title("Issues count") ###################################css定位######################################################### # 定位id=user的元素 page.locator('#user') # id定位并获取text menu = page.locator('#app > section > section > aside > div > ul > li:nth-child(1)') print("元素的text:", menu.text_content()) # 定位css为 homepage的元素 page.locator('.homepage') # xpath定位相对位置为/html/body/div[1]/div[3] 的元素 page.locator('/html/body/div[1]/div[3]') ########################################高级css定位################################################### # 获取元素的text列表(可以通过浏览器复制selector) test = page.locator( '#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator( "._title_1ec6m_20").all_inner_texts() print(test) # 遍历元素的text列表 menu = page.locator( '#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator( "._title_1ec6m_20").all() for div in menu: print("333333", div.inner_text()) # 多级css定位并点击(nth指定子级下标) page.locator('#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator( "._title_1ec6m_20").nth(1).click() ########################################locator定位器################################################# ##https://blog.csdn.net/karl41/article/details/119334673 page.locator('#username') # d选择器: #username 【# 表示ID】 page.locator('.btn-primary') # class选择器:.btn-primary 【. 号表示class】 page.locator('p') # 标签选择器:p 【选择所有 p 元素】 # 子元素及分组相关 page.locator('div, p') # 分组选择器:div,p 【同时选择所有 div 元素和所有 p 元素】 page.locator('div p') # 后端选择器:div p 【选择 div 元素内部的所有 p 元素(包括子元素、孙子元素】 page.locator('div > p') # 子元素选择器:div>p 【选择 div 元素下的 p 子元素】 page.locator('div + p') # 相邻选择器:div+p 【选择 div 元素之后的所有兄弟 p 元素 # 子元素和后代元素 page.locator('.Username > button') # 子元素 >,定位和父级元素相邻的元素,只能定位“亲儿子”; page.locator('.Username >> button') # 定位后代元素 >>,定位父级元素下的所有元素,只要位于父元素下,都可以定位 ; # nth的用法 page.locator("button").nth(0) # 选择第一个匹配的button,数字0表示元素在其父元素的子元素中的位置索引 page.locator("button >> nth=1") # 选择第二个匹配的button page.locator("button >> nth=-1") # 选择最后一个匹配的button ## locator定位器(这三个效果是一样的) cell_locator = page.locator('.ant-table-tbody').locator("tr").nth(1).locator("td").all_text_contents() cell_locator = page.locator('.ant-table-tbody>tr').nth(1).locator("td").all_text_contents() cell_locator =.page.locator('.ant-table-tbody>tr>>nth=1').locator("td").all_text_contents() ##多层级定位 page.locator('.parent-class').locator('.child-class') page.locator('.parent-class').locator('.child-class').nth(2) ## first和last page.locator("button").first # 选择第一个button元素 page.locator("button").last # 选择最后一个匹配的button ## 属性选择器 page.locator('input[id="username"]') # input[id=“username”] 选择 id 属性等于 “username” 的所有元素,[ ] 表示属性】 page.locator('input[id*="erna"]') # input[id*=“erna”] 【选择 id 属性包含单词 “erna” 的所有元素】 page.locator('input[id^="use"]') # input[id^=“use”] 【选择 id 属性以 “use” 开头的所有元素】 page.locator('input[id$="me"]') # input[id$=“me”] 【选择 id 属性以 “me” 结尾的所有元素】 page.locator('[title~=flower]') # [title~=flower] 【选择 title 属性包含单词 “flower” 的所有元素】 page.locator('[lang|=en]') # [lang|=en] 【选择 lang 属性值以 “en” 开头的所有元素】 page.locator('input[name="username"][id="username"]') # input[name=“username”][id=“username”] 【选择同时满足多个属性的元素】 ###解释nth()、nth-child()区别(nth:是Playwright库自带的函数, nth-child是css选择器里的方法) #这两个代码效果一样 cell_locator = self.page.locator('.ant-table-tbody').locator("tr").nth(1).locator("td").nth(1) cell_locator1 = self.page.locator(".ant-table-body > tr:nth-child(1) > td:nth-child(1)")
4.简单的方法
######################################等待元素############################################# #在8秒内等待text为”知识中心“出现,并点击(超时会报错 ) page.wait_for_selector("text=知识中心", timeout=8000).click() #在3秒内等待id为form_item出现 page.wait_for_selector("#form_item", timeout=3000) # 设置最大等待超时时间(超过该时间则会报错 ) page.wait_for_timeout(3000) #等待id为my-id元素,从DOM中完全移除 page.wait_for_selector("#my-id", state="detached") ###################################元素统计################################################# ##获取当前页面包含”知识中心“的个数 locator = page.locator("text=知识中心").count() print("找到知识中心有:{}条".format(locator)) ########################################判断################################################ ##判断元素text为知识中心 if page.locator("text=知识中心").count(): print("找到元素了") ######################################等待元素############################################# #在8秒内等待text为”知识中心“出现,并点击(超时会报错 ) page.wait_for_selector("text=知识中心", timeout=8000).click() #在3秒内等待id为form_item出现 page.wait_for_selector("#form_item", timeout=3000) # 设置最大等待超时时间(超过该时间则会报错 ) page.wait_for_timeout(3000) #等待id为my-id元素,从DOM中完全移除 page.wait_for_selector("#my-id", state="detached") ###################################元素统计################################################# ##获取当前页面包含”知识中心“的个数 locator = page.locator("text=知识中心").count() print("找到知识中心有:{}条".format(locator)) #####################################键盘操作############################################# page.get_by_placeholder("密码").press("Enter") page.keyboard.insert_text("嗨") page.keyboard.press("Shift+A") page.keyboard.press("Backspace") page.keyboard.press(" ") # 使用空格字符
5.常用方法:
#!/usr/bin/env python # -*- coding: utf-8 -*- ###____________________________________登录操作________________________________________________ import time from playwright.sync_api import sync_playwright from datetime import datetime def ai_01_login(url, username, password): """登录操作""" # ##使用同步的方式启动playwright playwright = sync_playwright().start() ##指定为有头模式,Ture为无头模式 browser = playwright.chromium.launch(headless=False) ##新建一个浏览器上下文(相当于浏览器窗口,用于隔离各个页面之间的环境。) # context = browser.new_context() ##创建一个新的页面(_blank) page = browser.new_page() try: ##打开url page.goto(url) ## 暂停代码的执行,显示Playwright窗口,以便进行相关操作,如元素定位或录制操作。 # page.pause() ## 设置最大等待超时时间(超过该时间则会报错 ) # page.wait_for_timeout(3000) # 定位文字信息,返回元素 page.get_by_text('账密登录', exact=True).click() # 通过id定位并输入内容 page.locator('#form_item_phone').fill(username) page.locator('#form_item_password').fill(password) # 根据元素角色进行定位 page.get_by_role("button", name="登 录").click() # 在8秒内等待元素出现,并点击 page.wait_for_selector("text={}".format(username), timeout=8000).click() page.locator("text=知识中心").wait_for(timeout=8000) page.locator("text=知识中心").click() time.sleep(3) print("登录成功") # 多级css定位并点击(1表示文档) page.locator('#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator( "._title_1ec6m_20").nth(1).click() time.sleep(3) timedata = page.locator( '#app > section > section > main > div > div._table_ywkou_56 > div > div > div > div > div > div > div > div > div > table > tbody > tr:nth-child(1) > td:nth-child(5)').text_content() timestamp = int(time.mktime(time.strptime(timedata, "%Y-%m-%d %H:%M:%S"))) if int(time.time()) - timestamp < 30: print("上传成功,最新文件创建时间:{}".format(timedata)) except Exception as e: print(f"发生错误:{e}") finally: # 确保即使发生异常,也不会关闭 playwright 实例 pass ai_01_login("https://home.qa.lightai.cn/#/login", "17388963381", "xiawei1314") ###____________________________________获取每一行每一列____________________________________ from playwright.sync_api import sync_playwright # 启动 Playwright 的同步 API with sync_playwright() as p: # 创建浏览器并打开新页面 browser = p.chromium.launch() page = browser.new_page() # 假设我们导航到了一个包含表格的页面 page.goto('http://example.com/some-page-with-table') # 定位到表格中的所有行 <tr> rows = page.locator('table tr') # 异步获取所有行元素 row_elements = rows.all() # 遍历每一行 for row in row_elements: # 定位到当前行的所有单元格 <td> 或 <th> cells = row.locator('td') # 异步获取当前行的所有单元格元素 cell_elements = cells.all() # 遍历当前行的每个单元格,并打印文本内容 for cell in cell_elements: cell_text = cell.text_content() print(cell_text) # 打印行分隔符 print('-----') # 关闭浏览器 browser.close() ###__________________________________获取每一行的指定列__________________________________________ from playwright.sync_api import sync_playwright # 启动 Playwright 的同步 API with sync_playwright() as p: # 创建浏览器并打开新页面 browser = p.chromium.launch() page = browser.new_page() # 导航到包含表格的页面 page.goto('http://example.com/some-page-with-table') # 定位到每一行的第2列单元格 # 注意:索引从0开始,所以第2列的索引是1 cells = page.locator('table tr td:nth-child(2)') # 异步获取所有匹配的单元格元素 cell_elements = cells.all() # 遍历每个单元格,并打印其文本内容 for cell in cell_elements: cell_text = cell.text_content() print(cell_text) # 关闭浏览器 browser.close() #___________________________________________执行后不要关闭浏览器(链接传送门,传送门2)___________________________________________________ import time,os from playwright.sync_api import Playwright, sync_playwright def initialize_browser22(): """打开浏览器,指定调试端口""" import subprocess # 定义要执行的命令 command = ( 'cd C:\\Program Files\\Google\\Chrome\\Application && ' 'start chrome.exe --remote-debugging-port=9222 --user-data-dir=d:\\playwright\\user_data' ) try: # 使用subprocess.run来执行命令 result = subprocess.run(command, shell=True, text=True, capture_output=True) # 检查命令的返回码 if result.returncode == 0: print("命令执行成功") else: print("命令执行失败,返回码:", result.returncode) except: print("执行出现异常") def ai_01_login22(url,username,password): """登录操作""" with sync_playwright() as playwright: browser = playwright.chromium.connect_over_cdp("http://localhost:9222") default_context = browser.contexts[0] page = default_context.pages[0] print(page) ##直接打开网址 page.goto(url) ##新建上下文后打开网址(相当于新标签窗口) # page = default_context.new_page() # page.goto(url) # 定位文字信息,返回元素 page.get_by_text('账密登录', exact=True).click() # 通过id定位并输入内容 page.locator('#form_item_phone').fill(username) page.locator('#form_item_password').fill(password) # 根据元素角色进行定位 page.get_by_role("button", name="登 录").click() # 在8秒内等待元素出现,并点击 page.wait_for_selector("text={}".format(username), timeout=8000).click() page.locator("text=知识中心").wait_for(timeout=8000) page.locator("text=知识中心").click() time.sleep(10) print("登录成功") #---------------- # #关闭上下文 # page.close() # #关闭浏览器 # browser.close() # if __name__ == '__main__': #初始化浏览器(打开浏览器) initialize_browser22() ai_01_login22("https://home.qa.lightai.cn/#/login","17388963381","xiawei1314")
#!/usr/bin/env python3 # coding: utf-8 ######################################元素高亮、指定调试(调试用的)############################################################ """为了避免重复操作等麻烦步骤,这里我使用playwright连接指定浏览器,手动进入相关网址,页面直接进行相关事件操作""" __author__ = "梦无矶小仔" import subprocess from playwright.sync_api import sync_playwright, Page, BrowserContext def initialize_browser22(): """打开浏览器,指定调试端口""" # 定义要执行的命令(--remote-debugging-port 指定浏览器调试端口号,,--user-data-dir 用户配置文件目录) command = ( 'cd C:\\Program Files\\Google\\Chrome\\Application && ' 'start chrome.exe --remote-debugging-port=9222 --user-data-dir=d:\\playwright\\user_data' ) try: # 使用subprocess.run来执行命令 result = subprocess.run(command, shell=True, text=True, capture_output=True) # 检查命令的返回码 if result.returncode == 0: print("命令执行成功") else: print("命令执行失败,返回码:", result.returncode) except: print("执行出现异常") class Demo05: def __init__(self): """ 使用playwright连接谷歌浏览器(主要创建浏览器相关方法给后面使用) """ self.playwright = sync_playwright().start() # 连接已经打开的浏览器,找好端口 browser = self.playwright.chromium.connect_over_cdp("http://127.0.0.1:9222") self.default_context = browser.contexts[0] self.page = self.default_context.pages[0] def highlight(self): """打开网址,基础操作语法""" self.page.goto("https://www.baidu.com") ##高亮id=kw self.page.locator("#kw").highlight() ##执行并按回车 self.page.locator("#kw").fill("testhome") self.page.locator("#kw").press("Enter") ##高亮多个元素,文本testhome # self.page.get_by_text("testhome").highlight() ##将定位器返回到第n个元素。下标是从0开始的。nth(0)表示选择第一个元素。 #banana = self.page.get_by_role("listitem").nth(2) ##指定xx个高亮 # self.page.get_by_text("testhome").nth(8).highlight() ##使用first定位第一个 self.page.get_by_text("梦无矶").first.highlight() ##使用last定位最后一个 self.page.get_by_text("梦无矶").last.highlight() def locator_position(self): """locator定位操作""" #这这里可以直接操作不用重新创建page,也不用打开url(比较适合调试) self.page.locator("#kw").fill("testhome") self.page.locator("#kw").press("Enter") if __name__ == '__main__': ###启动浏览器(启动一次后面可以不用启动,常用于调试) #initialize_browser22() ##实例化用于连接浏览器 mwj = Demo05() #调用相关方法 #mwj.highlight() mwj.locator_position()
相关链接:
https://blog.csdn.net/liwenxiang629/article/details/129118199.........................................................运行环境问题:ImportError: DLL load failed,,汇总教程
https://cloud.tencent.com/developer/article/2326430........................................................................基础讲解 ,pytest的使用,,pytest执行后不显示日志
https://blog.csdn.net/lzf9651/article/details/134962943 ..................................................................元素定位基础,,元素定位和CSS技巧,定位进阶,,分类元素定位,,元素定位,,locator定位
https://blog.csdn.net/LIFENG0402/article/details/121550064..........................................................汇总用法 ,断言相关,,汇总教程,入门教程
https://blog.csdn.net/seanyang_/article/details/132252268.............................................................Playwright- 模拟接口,,api测试,,api测试2 ,,函数
https://cloud.tencent.com/developer/article/1890385 .....................................................................录制生成代码,生成代码
浙公网安备 33010602011771号