一碱呼,簡(jiǎn)介
Playwright 官方介紹https://playwright.dev/python/
跨瀏覽器和平臺(tái)
- 跨瀏覽器。Playwright 支持所有現(xiàn)代渲染引擎宏悦,包括 Chromium天揖、WebKit 和 Firefox柬泽。
- 跨平臺(tái)。在 Windows、Linux 和 macOS 上進(jìn)行本地測(cè)試或在 CI 上進(jìn)行無頭或有頭測(cè)試佣渴。
- 跨語言。在TypeScript初斑、JavaScript辛润、Python、.NET越平、Java中使用 Playwright API 频蛔。
- 測(cè)試移動(dòng)網(wǎng)絡(luò)。適用于 Android 和 Mobile Safari 的 Google Chrome 瀏覽器的本機(jī)移動(dòng)仿真秦叛。相同的渲染引擎適用于您的桌面和云端晦溪。
穩(wěn)定性
- 自動(dòng)等待。Playwright 在執(zhí)行動(dòng)作之前等待元素可操作挣跋。它還具有一組豐富的內(nèi)省事件三圆。兩者的結(jié)合消除了人為超時(shí)的需要——這是不穩(wěn)定測(cè)試的主要原因。
- Web優(yōu)先斷言避咆。Playwright 斷言是專門為動(dòng)態(tài)網(wǎng)絡(luò)創(chuàng)建的舟肉。檢查會(huì)自動(dòng)重試,直到滿足必要的條件查库。
- 追蹤路媚。配置測(cè)試重試策略,捕獲執(zhí)行跟蹤樊销、視頻整慎、屏幕截圖以消除薄片脏款。
運(yùn)行機(jī)制
瀏覽器在不同進(jìn)程中運(yùn)行屬于不同來源的 Web 內(nèi)容。Playwright 與現(xiàn)代瀏覽器架構(gòu)保持一致撤师,并在進(jìn)程外運(yùn)行測(cè)試。這使得 Playwright 擺脫了典型的進(jìn)程內(nèi)測(cè)試運(yùn)行器的限制拧揽。
- 多重一切。測(cè)試跨越多個(gè)選項(xiàng)卡淤袜、多個(gè)來源和多個(gè)用戶的場(chǎng)景。為不同的用戶創(chuàng)建具有不同上下文的場(chǎng)景饮怯,并在您的服務(wù)器上運(yùn)行它們,所有這些都在一次測(cè)試中完成蓖墅。
- 可信事件。懸停元素论矾,與動(dòng)態(tài)控件交互,產(chǎn)生可信事件贪壳。Playwright 使用與真實(shí)用戶無法區(qū)分的真實(shí)瀏覽器輸入管道。
- 測(cè)試框架闰靴,穿透 Shadow DOM彪笼。Playwright 選擇器穿透影子 DOM 并允許無縫地輸入幀配猫。
完全隔離-快速執(zhí)行
- 瀏覽器上下文。Playwright 為每個(gè)測(cè)試創(chuàng)建一個(gè)瀏覽器上下文杏死。瀏覽器上下文相當(dāng)于一個(gè)全新的瀏覽器配置文件。這提供了零開銷的完全測(cè)試隔離淑翼。創(chuàng)建一個(gè)新的瀏覽器上下文只需要幾毫秒。
- 登錄一次玄括。保存上下文的身份驗(yàn)證狀態(tài)并在所有測(cè)試中重用它。這繞過了每個(gè)測(cè)試中的重復(fù)登錄操作遭京,但提供了獨(dú)立測(cè)試的完全隔離银还。
強(qiáng)大的工具
- 代碼生成器风宁。通過記錄您的操作來生成測(cè)試。將它們保存為任何語言蛹疯。
- 調(diào)試。檢查頁面热监、生成選擇器捺弦、逐步執(zhí)行測(cè)試、查看點(diǎn)擊點(diǎn)孝扛、探索執(zhí)行日志列吼。
- 跟蹤查看器。捕獲所有信息以調(diào)查測(cè)試失敗苦始。Playwright 跟蹤包含測(cè)試執(zhí)行截屏寞钥、實(shí)時(shí) DOM 快照、動(dòng)作資源管理器陌选、測(cè)試源等等理郑。
二,下載和安裝
python 版本要求 python3.7+ 版本咨油。
安裝 playwright:
pip install playwright
安裝所需的瀏覽器 chromium,firefox 和 webkit:
playwright install
僅需這一步即可安裝所需的瀏覽器您炉,并且不需要安裝驅(qū)動(dòng)包了(解決了selenium啟動(dòng)瀏覽器,總是要找對(duì)應(yīng)驅(qū)動(dòng)包的痛點(diǎn))
ps:如果安裝報(bào)錯(cuò)役电,提示缺少Visual C++赚爵, 解決辦法: 安裝Microsoft Visual C++ Redistributable 2019
https://aka.ms/vs/16/release/VC_redist.x64.exe
直接點(diǎn)擊就可以下載了,下載后直接安裝即可法瑟。
三冀膝,簡(jiǎn)單使用
Playwright 支持2種運(yùn)行方式:同步和異步。以下為同步:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # 啟動(dòng) chromium 瀏覽器
page = browser.new_page() # 打開一個(gè)標(biāo)簽頁
page.goto("https://www.baidu.com") # 打開百度地址
print(page.title()) # 打印當(dāng)前頁面title
browser.close() # 關(guān)閉瀏覽器對(duì)象
如果不習(xí)慣with語句霎挟,也可以用start() 和stop() 的方式:
from playwright.sync_api import sync_playwright
playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False)
page = browser.new_page()
page.goto("https://www.baidu.com/")
browser.close()
playwright.stop()
四:定位元素
playwright 可以通過 CSS selector, XPath selector, HTML 屬性(比如 id, data-test-id)或者是 text 文本內(nèi)容定位元素窝剖。
- Selector 選擇器
操作元素,可以先定位再操作
# 先定位再操作
page.locator('#kw').fill("playwright")
page.locator('#su').click()
也可以直接調(diào)用fill 和 click 方法氓扛,傳Selector選擇器
page.fill('#kw', "playwright")
page.click('#su')
- CSS 或 XPath 選擇器
可以使用xpath 和 css 元素
# CSS and XPath
page.fill('css=#kw', "playwright")
page.click('xpath=//*[@id="su"]')
當(dāng) DOM 結(jié)構(gòu)發(fā)生變化時(shí)枯芬,這些選擇器可能會(huì)中斷。長(zhǎng) CSS 或 XPath 鏈?zhǔn)菍?dǎo)致測(cè)試不穩(wěn)定采郎。
- text 文本選擇器
文本選擇器是一個(gè)非常實(shí)用的定位方式千所,根據(jù)頁面上看到的text文本就可以定位了,比如我們經(jīng)常在selenium中使用xpath 的文本選擇器定位
完全匹配文本 //*[text()="百度一下"]
包含某個(gè)文本 //*[contains(text(),"百度一下")]
playwright 封裝了text文本定位的方式蒜埋,也可以支持2種文本定位方式
page.click("text=百度一下") # 模糊匹配
page.click("text='百度一下 '") # 完全匹配
ps:text=百度一下和 text='百度一下' 的區(qū)別:
text=百度一下 沒有加引號(hào)(單引號(hào)或者雙引號(hào))淫痰,模糊匹配,對(duì)大小寫不敏感
text='百度一下' 有引號(hào)整份,精確匹配籽孙,對(duì)大小寫敏感
-
Selector 選擇器組合定位
不同的selector可組合使用犯建,用>>連接
form >> [name="wd"] 定位方式等價(jià)于
page.locator("form").locator('[name="wd"]')
- 內(nèi)置定位器
這些是 playwright 推薦的內(nèi)置定位器瓜客。
page.get_by_role()通過顯式和隱式可訪問性屬性進(jìn)行定位。
page.get_by_text()通過文本內(nèi)容定位玻熙。
page.get_by_label()通過關(guān)聯(lián)標(biāo)簽的文本定位表單控件疯攒。
page.get_by_placeholder()按占位符定位輸入。
page.get_by_alt_text()通過替代文本定位元素枚尼,通常是圖像筷转。
page.get_by_title()通過標(biāo)題屬性定位元素呜舒。
page.get_by_test_id()根據(jù)data-testid屬性定位元素(可以配置其他屬性)
五,操作
fill() 輸入文字
Type 輸入
一個(gè)字符一個(gè)字符地輸入字段唤殴,就好像它是一個(gè)使用locator.type()的真實(shí)鍵盤的用戶到腥。
page.locator('#kw').type('playwright')
- 鼠標(biāo)點(diǎn)擊 click()
執(zhí)行簡(jiǎn)單的人工點(diǎn)擊乡范。
# Generic click
page.get_by_role("button").click()
# Double click
page.get_by_text("Item").dblclick()
# Right click
page.get_by_text("Item").click(button="right")
# Shift + click
page.get_by_text("Item").click(modifiers=["Shift"])
# Hover over element
page.get_by_text("Item").hover()
# Click the top left corner
page.get_by_text("Item").click(position={ "x": 0, "y": 0})
在幕后,這個(gè)和其他與指針相關(guān)的方法:
1,等待具有給定選擇器的元素出現(xiàn)在 DOM 中 (不用自己去寫輪詢等待了)
2,等待它顯示出來渠脉,即不為空芋膘,不display:none,不visibility:hidden (這個(gè)太人性化了臂拓,不用去判斷元素是否隱藏)
3,等待它停止移動(dòng)习寸,例如,直到 css 轉(zhuǎn)換完成
4,將元素滾動(dòng)到視圖中 (這個(gè)太人性化了童番,不用自己去滾動(dòng)了)
5,等待它在動(dòng)作點(diǎn)接收指針事件,例如轨香,等待直到元素變得不被其他元素遮擋
6,如果元素在上述任何檢查期間分離,則重試
由此可見科雳,click() 方法優(yōu)化了selenium 點(diǎn)擊元素的遇到的一些痛點(diǎn)問題脓杉,比如元素遮擋,不在當(dāng)前屏幕尿赚,元素未出現(xiàn)在DOM中或隱藏不可見等不可點(diǎn)擊的狀態(tài)凌净。
- 文件上傳
(1)您可以使用locator.set_input_files()方法選擇要上傳的輸入文件屋讶。
它期望第一個(gè)參數(shù)指向類型為 的輸入元素"file"。數(shù)組中可以傳遞多個(gè)文件斩芭。
如果某些文件路徑是相對(duì)的乐疆,則它們將相對(duì)于當(dāng)前工作目錄進(jìn)行解析诀拭。空數(shù)組清除所選文件细卧。
# Select one file
page.get_by_label("Upload file").set_input_files('myfile.pdf')
# Select multiple files
page.get_by_label("Upload files").set_input_files(['file1.txt', 'file2.txt'])
# Remove all the selected files
page.get_by_label("Upload file").set_input_files([])
# Upload buffer from memory
page.get_by_label("Upload file").set_input_files(
files=[
{"name": "test.txt", "mimeType": "text/plain", "buffer": b"this is a test"}
],
)
(2)如果不是input輸入框贪庙,必須點(diǎn)開文件框的情況
可以使用page.expect_file_chooser() 監(jiān)聽到彈出框这橙,在彈出框上輸入文件路徑
with self.page.expect_file_chooser() as fc_info:
self.page.get_by_placeholder("請(qǐng)選擇文件").click()
file_chooser = fc_info.value
file_chooser.set_files("Upload file")
幾個(gè)操作方法
file_chooser.element 返回與此文件選擇器關(guān)聯(lián)的輸入元素导披。
file_chooser.is_multiple() 返回此文件選擇器是否接受多個(gè)文件。
file_chooser.page 返回此文件選擇器所屬的頁面鹰晨。
設(shè)置與此選擇器關(guān)聯(lián)的文件輸入的值止毕。如果其中一些filePaths是相對(duì)路徑,那么它們將相對(duì)于當(dāng)前工作目錄進(jìn)行解析忍疾。對(duì)于空數(shù)組谨朝,清除所選文件。
file_chooser.set_files(files)
file_chooser.set_files(files, **kwargs)
幾個(gè)參數(shù)
files pathlib.Path
no_wait_after 啟動(dòng)導(dǎo)航的操作正在等待這些導(dǎo)航發(fā)生并等待頁面開始加載荚孵。您可以通過設(shè)置此標(biāo)志來選擇退出等待收叶。您僅在特殊情況下才需要此選項(xiàng)共苛,例如導(dǎo)航到無法訪問的頁面。默認(rèn)為false.
timeout 以毫秒為單位的最長(zhǎng)時(shí)間澄峰,默認(rèn)為 30 秒辟犀,傳遞0以禁用超時(shí)〔E澹可以使用browser_context.set_default_timeout()或page.set_default_timeout()方法更改默認(rèn)值席楚。
(3)高級(jí)操作-事件監(jiān)聽filechooser
page.on("filechooser", lambda file_chooser: file_chooser.set_files(r"D:\tou.png"))
# 點(diǎn)擊選擇文件按鈕,會(huì)觸發(fā) filechooser 事件
page.get_by_label("選擇文件").click()
page.on("filechooser", ) 會(huì)自動(dòng)監(jiān)聽filechooser 事件垮斯,只要有點(diǎn)擊了選擇文件按鈕只祠,就會(huì)自動(dòng)觸發(fā)。
- focus()聚焦給定元素
對(duì)于處理焦點(diǎn)事件的動(dòng)態(tài)頁面牺氨,您可以使用locator.focus()聚焦給定元素墩剖。
page.get_by_label('password').focus()
- drag_to 拖動(dòng)
您可以使用locator.drag_to()執(zhí)行拖放操作岭皂。此方法將:
將鼠標(biāo)懸停在要拖動(dòng)的元素上爷绘。
按鼠標(biāo)左鍵进倍。
將鼠標(biāo)移動(dòng)到將接收放置的元素。
松開鼠標(biāo)左鍵陶因。
page.locator("#item-to-be-dragged").drag_to(page.locator("#item-to-drop-at"))
如果您想精確控制拖動(dòng)操作垂蜗,請(qǐng)使用較低級(jí)別的方法贴见,如locator.hover()、mouse.down()镣衡、mouse.move()和mouse.up()。
page.locator("#item-to-be-dragged").hover()
page.mouse.down()
page.locator("#item-to-drop-at").hover()
page.mouse.up()
如果您的頁面依賴于dragover正在調(diào)度的事件望浩,則您至少需要移動(dòng)兩次鼠標(biāo)才能在所有瀏覽器中觸發(fā)它黍图。要可靠地發(fā)出第二次鼠標(biāo)移動(dòng)助被,請(qǐng)重復(fù)mouse.move()或locator.hover()兩次。操作順序是:懸停拖動(dòng)元素搔弄,鼠標(biāo)向下丰滑,懸停放置元素,第二次懸停放置元素炫刷,鼠標(biāo)向上郁妈。
六,等待
- 強(qiáng)制等待
time.sleep() 不再使用
Playwright 在查找元素的時(shí)候具有自動(dòng)等待功能顾彰,如果你在調(diào)試的時(shí)候需要使用等待涨享,你應(yīng)該使用page.wait_for_timeout(5000) 代替 time.sleep(5)并且最好不要等待超時(shí)仆百。
page.wait_for_timeout(5000)
- 顯示等待
在延遲加載的頁面中,使用locator.wait_for()等待元素可見是很有用的栏账≌辉矗或者,像locator.click()這樣的頁面交互會(huì)自動(dòng)等待元素茶鹃。
# Click triggers navigation
page.get_by_text("Login").click()
# Click will auto-wait for the element
page.get_by_label("User Name").wait_for()
# Click triggers navigation
page.get_by_text("Login").click()
# Fill will auto-wait for element
page.get_by_label("User Name").fill("John Doe")