Playwright之初体验
參考文件
官方文檔:https://playwright.dev/docs/intro
GitHub鏈接:https://github.com/microsoft/playwright-python
Playwright簡介
Playwright Test是專門為滿足端到端測試的需求而創(chuàng)建的。Playwright支持所有現(xiàn)代搜索引擎,包括Chrome、WebKit和Firefox。在Windows、Linux和macOS上測試,使用Android和mobile Safari的Google Chrome原生移動模擬進行測試。
環(huán)境安裝
安裝python環(huán)境
Playwright安裝
使用pip install playwright命令進行安裝
使用playwright install命令進行各種工具包和依賴,有報錯,我們先不管,繼續(xù)往下走
安裝pytest插件:pip install pytest-playwright
簡單跑一個demo,發(fā)現(xiàn)報錯了,我們換一種執(zhí)行方式
我們使用pytest命令執(zhí)行發(fā)現(xiàn)沒有報錯
Playwright的自帶工具
Playwright codegen
我們在pycharm中使用終端,輸入該命令,之后,就會啟用被測瀏覽器,并且啟用inspector記錄操作的腳本
Playwright inspector
之后我們可以將inspector里面的代碼復(fù)制到pycharm里面自己編輯了
當然,我們也可以針對某個瀏覽器的網(wǎng)址,比如說https://www.baidu.com/
回車之后,瀏覽器自動啟動一個標簽,以及一個inspector來記錄操作代碼
也可以固定瀏覽器某個窗口的大小進行操作
Playwright codegen --viewport-size=800,600 www.baidu.com
訪問移動端手機瀏覽器,比如說蘋果13
Playwright codegen --device=“iPhone 13” www.baidu.com
幫助我們自動記錄和管理cookie信息
首先我們使用如下命令Playwright codegen --save-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
然后瀏覽器啟動一個窗口
接下來我們自動輸入密碼,如下:
之后,我們把啟動的瀏覽器關(guān)掉
接下來,我們再次使用如下命令再次回車
Playwright codegen --load-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
瀏覽器會再次啟動一個新窗口,但是此窗口瀏覽器的地址我們可以看到是登錄狀態(tài)的
Trace Viewer是Playwright的另一個神器,顧名思義就是痕跡查看,也就是我們后期可以查看我們之前都操作了哪些地方
Playwright架構(gòu)技術(shù)介紹
Playwright是由Puppeteer-https://puppeteer.bootcss.com/改造過來的,Puppeteer 是一個 Node 庫,它提供了一個高級 API 來通過 DevTools 協(xié)議控制 Chromium 或 Chrome。Puppeteer 默認以 headless 模式運行,但是可以通過修改配置文件運行“有頭”模式。再加上,Playwright官方?jīng)]有給出架構(gòu)圖,所以我們可以參考Puppeteer的架構(gòu)圖來學(xué)習Playwright
首先我們可以通過Puppeteer來控制瀏覽器的,他是通過谷歌開發(fā)者協(xié)議,簡稱CDP,該協(xié)議是建立在WebSocket協(xié)議之上
這里的Brower其實是一個瀏覽器實例,一個瀏覽器可以包含很多個上下文,也就是包含很多Context,通俗來講,就跟我們打開了一個谷歌瀏覽器,又開啟了一個無痕模式瀏覽器一樣,Brower的Context具有獨立的Session,cookie&cache
一個Context可以包含很多個Page頁面,一個Page是一個獨立頁面
一個Page可以包含很多個Frame,一個Frame可以理解為是一個框架,可以包含多個子框架
再往下就是ExecutionContext,它是javascript的執(zhí)行環(huán)境,每一個Frame都有一個默認的javascript的執(zhí)行環(huán)境
在Playwright中,這些概念也是一樣的
第一個Playwright腳本
from playwright.sync_api import sync_playwrightdef test_pla():with sync_playwright() as p:#實例化一個瀏覽器,使用谷歌為例#代碼運行默認是無頭模式運行,如果要看運行效果,可以加入?yún)?shù)headlessbrowser = p.chromium.launch(headless=False)#實例化一個頁面page = browser.new_page()#打開一個網(wǎng)站page.goto("https://www.bilibili.com")#打印網(wǎng)頁標題print(page.title())#關(guān)閉瀏覽器browser.close()運行之后:
Playwright瀏覽器控制
谷歌官方相關(guān)命令地址:https://peter.sh/experiments/chromium-command-line-switches/
from playwright.sync_api import sync_playwrightdef test_pla():with sync_playwright() as p:#實例化一個瀏覽器,使用谷歌為例#代碼運行默認是無頭模式運行,如果要看運行效果,可以加入?yún)?shù)headless#--start-maximized表示窗口最大化,no_viewport表示的是默認窗口大小失效#slow_mo表示的是每一步操作,默認等待3sbrowser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)#實例化一個頁面page = browser.new_page(no_viewport=True)#打開一個網(wǎng)站page.goto("https://www.zhihu.com")#打印網(wǎng)頁標題print(page.title())#點擊開通機構(gòu)號page.get_by_text("開通機構(gòu)號").click()#后退page.go_back()#前進page.go_forward()#刷新page.reload()#關(guān)閉瀏覽器browser.close()Playwright瀏覽器啟動參數(shù)詳解
executable_path——數(shù)據(jù)路徑
channel——指定使用哪種瀏覽器
args——參數(shù)數(shù)組
ignore_default_args——忽略默認參數(shù),慎用,使用不當,腳本無法執(zhí)行
timeout——等待瀏覽器實例啟動的最長時間,單位毫秒,一般是30s,設(shè)置為0,功能失效
headless——有頭和無頭模式運行的設(shè)置
traces_dir——數(shù)據(jù)報錯路徑
chromium_sandbox——是否啟動谷歌沙盒瀏覽器
等等,基本所有參數(shù)都是launch()函數(shù)里面的,可以自行查看
Playwright xpath元素定位
XML Path Language
from playwright.sync_api import sync_playwrightdef test_pla():with sync_playwright() as p:#實例化一個瀏覽器,使用谷歌為例#代碼運行默認是無頭模式運行,如果要看運行效果,可以加入?yún)?shù)headless#--start-maximized表示窗口最大化,no_viewport表示的是默認窗口大小失效#slow_mo表示的是每一步操作,默認等待3sbrowser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)#實例化一個頁面page = browser.new_page(no_viewport=True)#打開一個網(wǎng)站page.goto("https://www.baidu.com")"""/:從根節(jié)點選取//:從非根節(jié)點選取*:任意節(jié)點選取@:根據(jù)屬性篩選text():根據(jù)文本篩選and:關(guān)聯(lián)屬性或者鏈接文本[]:可以防止下標/屬性/鏈接文本.:選取當前節(jié)點..:選取當前節(jié)點的父節(jié)點contains:包含"""#使用單一屬性定位, 點擊百度首頁設(shè)置按鈕,使用text_content獲取內(nèi)容t_1 = page.locator("//span[@name='tj_settingicon']").text_content()print(t_1)#多屬性定位t_2 = page.locator("//span[@id='s-usersetting-top' and @name='tj_settingicon']").text_content()print(t_2)#父節(jié)點定位t_3 = page.locator('//div[@id="u1"]/span').text_content()print(t_3)#通過下標進行定位,新聞這個按鈕t_4 = page.locator('//div[@id="s-top-left"]/a[1]').text_content()print(t_4)#通過.和..來定位t_5= page.locator('//a[@name="tj_fanyi"]/div/../../../../../a[1]').text_content()print(t_5)#通過文本定位t_6 = page.locator('//a[text()="新聞"]').text_content()print(t_6)#通過模糊匹配定位t_7 = page.locator('//a[contains(text(),"hao")]').text_content()print(t_7)#關(guān)閉瀏覽器browser.close()運行之后:
Playwright css定位
css定位方式有五種,分別是:
id選擇器
class選擇器
元素選擇器
屬性選擇器
層級選擇器
Playwright特有定位方式
""" 特有元素定位方法 locator.get_by_alt_text(text,**kwargs), alt屬性 locator.get_by_label(text,**kwargs),label屬性 locator.get_by_placeholder(text,**kwargs),placeholder屬性 locator.get_by_role(role,**kwargs),role屬性 locator.get_by_text(text,**kwargs) locator.get_by_title(text,**kwargs) """Playwright元素常用操作
我們以該網(wǎng)頁為例子進行測試
登陸頁面,我們輸入用戶名、密碼、驗證碼,點擊登錄
同時,我們介紹怎么處理iframe進行上傳文件以及自動化,在上傳文件中,我們要注意,每一個圖片都有一個隨機的字符串
所以我們可以使用父節(jié)點定位方式進行定位處理
“//*[@id=‘filePicker’]/div[2]/input”
接下來是圖片的上傳,圖片我們先使用set_input_files函數(shù),絕對路徑處理,前面添加r
r"C:\Users\jinlai\111.jpg"
具體代碼如下:
接下來我們看下拉框怎么處理
#下拉框收貨地址處理,我們需要定位到要操作的輸入框,然后根據(jù)內(nèi)容屬性處理即可
page.select_option('//*[@id="province"]',value='19280') page.select_option('//*[@id="city"]',value='19281') page.select_option('//*[@id="district"]',value='19283') page.select_option('//*[@id="twon"]',value='19285') from playwright.sync_api import Playwright, sync_playwright, expectplaywright = sync_playwright().start() browser = playwright.chromium.launch(headless=False,slow_mo=2000) context = browser.new_context() page = browser.new_page() page.goto("http://testingedu.com.cn:8000/Home/user/login.html") #輸入用戶名 page.fill('//*[@id="username"]','13800138006') #輸入密碼 page.fill('//*[@id="password"]','123456') #輸入驗證碼,這里做了處理 page.fill('//*[@id="verify_code"]','1111') #點擊登錄 page.click('//*[@id="loginform"]/div/div[6]/a')#打開地址管理頁面 page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html") #點擊增加新地址 page.click("//*[@class='co_blue']") #點擊并輸入收貨人 page.fill("//*[@name='consignee']","ceshi") #點擊并輸入手機或者電話 page.fill("//*[@name='mobile']","13176358824")#下拉框收貨地址處理 page.select_option('//*[@id="province"]',value='19280') page.select_option('//*[@id="city"]',value='19281') page.select_option('//*[@id="district"]',value='19283') page.select_option('//*[@id="twon"]',value='19285')#點擊并輸入詳細地址 page.fill("//*[@name='address']","凱勝家園小區(qū)2號樓2單元802") #點擊報錯按鈕 page.click("//*[@id='address_submit']")#刷新頁面 page.reload() #刪除新增的地址 page.click('//span[text()="ceshi"]/../..//a[text()="刪除"]') #關(guān)閉瀏覽器 browser.close()如何獲取多個元素
比如說獲取所有搜索商品的名字
我們可以使用query_selector_all方法
具體代碼如下:
from playwright.sync_api import Playwright, sync_playwright, expectplaywright = sync_playwright().start() browser = playwright.chromium.launch(headless=False,slow_mo=2000) context = browser.new_context() page = browser.new_page() page.goto("http://testingedu.com.cn:8000/Home/user/login.html") #輸入用戶名 page.fill('//*[@id="username"]','13800138006') #輸入密碼 page.fill('//*[@id="password"]','123456') #輸入驗證碼,這里做了處理 page.fill('//*[@id="verify_code"]','1111') #點擊登錄 page.click('//*[@id="loginform"]/div/div[6]/a')#進入地址管理頁面 page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html")#點擊搜索框輸入內(nèi)容 page.fill('//input[@class="search_usercenter_text"]','手機') #點擊搜索 page.click('//a[text()="搜索"]') #query_selector_all方法獲取所有元素 goods = page.query_selector_all('//div[@class="shop-list-splb p"]//div[@class="shop_name2"]') for good in goods:print(good.text_content().strip()) #strip去除空格#關(guān)閉瀏覽器 browser.close()運行結(jié)果之后:
頁面上顯示:
兩者相對應(yīng)。
Playwright元素常用操作
import refrom playwright.sync_api import Playwright, sync_playwright, expectplaywright = sync_playwright().start() browser = playwright.chromium.launch(headless=False,slow_mo=5000) context = browser.new_context() page = browser.new_page() page.goto("http://testingedu.com.cn:8000/Home/user/login.html") #輸入用戶名 page.fill('//*[@id="username"]','13800138006') #輸入密碼 page.fill('//*[@id="password"]','123456') #輸入驗證碼,這里做了處理 page.fill('//*[@id="verify_code"]','1111') #點擊登錄 page.click('//*[@id="loginform"]/div/div[6]/a')#進入產(chǎn)品站 page.goto("http://testingedu.com.cn:8000/Home/Goods/goodsInfo/id/55.html")#點擊加入購物車 page.click('//*[@id="join_cart"]') #點擊彈層叉號 page.click('//*[@class="layui-layer-ico layui-layer-close layui-layer-close1"]')#鼠標懸停,我的購物車按鈕,以及點擊去購物車結(jié)算 page.hover('//span[text()="我的購物車"]') page.click('//a[@class="c-btn"]')#點擊去結(jié)算 page.click('//a[text()="去結(jié)算"]')#點擊提交訂單 page.click('//button[@class="checkout-submit"]')#獲取訂單號,我們可以使用正則表達式獲取 t = page.locator('//p[@class="succ-p"]').text_content() print(t) text = re.findall(r'\d{18}',t)[0] print(text)""" 接下來,我們進入到我的訂單頁面,點擊我的訂單的時候,我們發(fā)現(xiàn)打開了一個新的網(wǎng)頁,在selenium中,是通過切換句柄實現(xiàn)的,而在playwright中,我們可以使用新的寫法 """ print("444") with context.expect_page() as new_page_info:page.click('a[target="_blank"]') #點擊我的訂單 new_page = new_page_info.value new_page.wait_for_load_state() print(new_page.title())#點擊取消訂單,并格式化 new_page.click('//em[text()="{}"]/../..//a[text()="取消訂單"]'.format(text))#點擊彈層里面的確定按鈕 new_page.click('//*[@class="layui-layer-btn layui-layer-btn-"]/a[text()="確定"]') #刷新頁面 new_page.reload()#關(guān)閉瀏覽器 browser.close()Playwright自動化框架設(shè)計
Playwright作為一個新進的自動化特殊工具,在易用性方面做了很多工作。針對Playwright我們甚至可以不用做任何處理,把它當成一個封裝好的第三方庫去使用即可。
那么整體的框架又該怎么去設(shè)計呢?又該考慮哪些問題呢?
如果我們站在公司的角度上來說,公司層面需要打造一個通用性很強的自動化框架。也就是說a項目能用,b項目也能用。另外還需要將測試結(jié)果、測試過程等都完整的輸出出來,這是基本條件。不然我們花了很多時間寫代碼,換一個項目就不能用了,幾乎需要從頭到尾的再寫寫一遍,那就沒有任何意義。而測試人員都是拿結(jié)果的,畫的結(jié)果越詳細越好。除此之外,我們也應(yīng)該考慮到,在一個公司寫一個完整的框架和使用框架,不太可能是一個人去完成。我們需要考慮代碼托管和持續(xù)集成等等問題。所以大體的思路呢便有了。我們也可以根據(jù)剛剛的這個思路細化出一個架構(gòu)圖來
我們可以將整體的架構(gòu),從上到下可以分成五個層次。一是數(shù)據(jù)層、服務(wù)層、對象層,用例層和輸出層。
數(shù)據(jù)方面,為了擁有一定的適應(yīng)性,我們可以設(shè)計框架,讓它支持多種外部數(shù)據(jù)格式。如說新老版本的excel、yaml等等。
而服務(wù)層方面,因為需要針對excel文件的操作,所以需要自己去封裝excel讀寫庫等等。
對象層面,我們實際上是借助于PO思想進行設(shè)計就可以了。
用例方面主要是考慮用例該如何去組織,該如何去執(zhí)行。
當然我們選擇pytest,在用例執(zhí)行的過程中,我們是需要進行日志和報告的輸出的。所以我們需要封裝日志,并且加入allure測試報告。最后我們需要考慮的是,在整個框架的實現(xiàn)過程中,可能某些第三方庫有些人沒有安裝。為了讓框架的執(zhí)行更加簡單一點,我們可以直接將整個框架打包到docker里面,這樣去執(zhí)行。就不用擔心環(huán)境的問題了。框架設(shè)計好之后,我們可以打開pycharm,把目錄結(jié)構(gòu)呢大體的來設(shè)計一下。
我們新建一個工程。新建好之后呢,按照我們剛剛的設(shè)計思路,將整體的目錄結(jié)構(gòu)呢可以設(shè)置成下面這種樣子。
首先我們新建一個python package,比如叫做common,在common中,我們要做的事情呢,一般就是把一些公共用的庫在這兒。比如excel的讀寫啊、日志啊等等,
再新建一個package,比如叫做ddt。我們在利用外部文件來執(zhí)行測試用例的時候呢,實際上就是一個數(shù)據(jù)驅(qū)動。那我們可以把數(shù)據(jù)驅(qū)動的一些執(zhí)行的邏輯代碼放到此處。
再接著我們需要存放文件。比如說我們的測試用例、日志結(jié)果等等,我們可以新建一個文件夾,叫做lib。在lib文件下我們可以再新建一個cases,用來存放用例,再新建一個日志的文件夾,log用于存放日志。
最后我們還可以將結(jié)果和報告單獨的進行設(shè)計。result和report。為了運行方便,我們也可以在根目錄下創(chuàng)建一個runner。運行入口,我們可以新建一個runner的文件。那么整體的結(jié)構(gòu)呢我們就可以按照這種格式設(shè)計完成了
Playwright自動化框架之excel文件讀取
直接上代碼吧
好了,先介紹這里吧~后面再更新哈哈
總結(jié)
以上是生活随笔為你收集整理的Playwright之初体验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PS快捷入门
- 下一篇: android 跑马灯出现重复跳动、不滚