1. 程式人生 > 其它 >python中elements遍歷_pytestpyppeteer:在pytest中執行pyppeteer

python中elements遍歷_pytestpyppeteer:在pytest中執行pyppeteer

技術標籤:python中elements遍歷在每個執行中執行多個查詢

pytest-pyppeteer

pytest-pyppeteer[1]是我寫的一個 pytest 外掛,支援在 pytest 中執行pyppeteer[2],起因是為了解決工作中的一個測試需求,現在將其開源並做簡單介紹。

背景

為什麼不用 selenium?

主要的原因是 selenium 的配置比較繁瑣,最常見的問題是需要保持 webdriver 和瀏覽器版本的一致性。

pyppeteer 的簡單介紹

pyppeteer 是 puppeteer[3]的非官方 python 版本,幾乎實現了和其相同的 API,可以非常方便的去操作 Chrome 瀏覽器。

pyppeteer 的侷限性

目前最明顯的問題是沒有提供跨瀏覽器的解決方案,最新的 puppeteer 已經提供對 Firefox 的支援,但是 pyppeteer 可能還需要一些時間。

安裝

推薦使用pipenv[4]管理虛擬環境,並替換為國內 pip 源。

$pipenvinstallpytest-pyppeteer

僅支援 python >= 3.7

快速開始

用下面這個測試用例來說明:斷言電影《活著》的豆瓣評分大於 9.0。

fromdataclassesimportdataclass

frompytest_pyppeteer.modelsimportBrowser


@dataclass(init=False)
classElements:
"""收集所有使用到的頁面元素,可以為 XPath 或者 CSS Selector。"""

#查詢輸入框
query="#inp-query"

#點選搜尋
apply=".inp-btn>input:nth-child(1)"

#第一條結果
first_result=(
"#root>div>div>div>div>div:nth-child(1)>div.item-roota.cover-link"
)

#評分
rating=(
"#interest_sectl>div.rating_wrap.clearbox>div.rating_self.clearfix>strong"
)


asyncdeftest_lifetimes(pyppeteer:Browser):
page=awaitpyppeteer.new_page()
awaitpage.goto('https://movie.douban.com/')

awaitpage.type(Elements.query,"活著")
awaitpage.click(Elements.apply)

awaitpage.waitfor(Elements.first_result)
awaitpage.click(Elements.first_result)

awaitpage.waitfor(Elements.rating)
rating=awaitpage.get_value(Elements.rating)

assertfloat(rating)>=9.0

執行測試用例,看一下效果:

640?wx_fmt=gif

這裡我們無需指定瀏覽器的路徑,pytest-pyppeteer 會在對應平臺預設的安裝路徑下搜尋 Chrome 的可執行檔案。

也可以通過 --executable-path命令列選項顯示的指定 Chrome 的路徑。

或者,在你的conftest.py檔案中指定:

@pytest.fixture(scope="session")
defexecutable_path(executable_path):
ifexecutable_pathisNone:
return"path/to/Chrome/or/Chromium"
returnexecutable_path

其它支援的命令列選項,包括:

  • --headless:使用瀏覽器的無頭模式;

  • --args:為瀏覽器指定其它引數。例如:指定代理伺服器:

    $pytest--argsproxy-server"localhost:5555,direct://"--argsproxy-bypass-list"192.0.0.1/8;10.0.0.1/8"
  • --window-size:指定瀏覽器的大小,預設是 800*600;--window-size 0 0表示最大化瀏覽器;

同時操作多個瀏覽器

用下面這個測試用例來說明:斷言書籍《活著》的豆瓣評分高於其電影的評分。

importasyncio
fromdataclassesimportdataclass

frompytest_pyppeteer.modelsimportBrowser,Page


@dataclass(init=False)
classElements:
"""公共物件庫"""

query="#inp-query"
apply=".inp-btn>input:nth-child(1)"


@dataclass(init=False)
classBookElements(Elements):
url="https://book.douban.com/"

first_result='(//*[@]/a)[1]'
rating="#interest_sectl>div>div.rating_self.clearfix>strong"


@dataclass(init=False)
classMovieElements(Elements):
url="https://movie.douban.com/"

first_result=(
"#root>div>div>div>div>div:nth-child(1)>div.item-roota.cover-link"
)
rating=(
"#interest_sectl>div.rating_wrap.clearbox>div.rating_self.clearfix>strong"
)


asyncdefquery_rating(pyppeteer:Browser,name:str,elements:Elements):
"""獲取電影或者書籍的評分。"""

page:Page=awaitpyppeteer.new_page()

awaitpage.goto(elements.url)

awaitpage.type(elements.query,name)
awaitpage.click(elements.apply)

awaitpage.waitfor(elements.first_result)
awaitpage.click(elements.first_result)

awaitpage.waitfor(elements.rating)
rating=awaitpage.get_value(elements.rating)

returnrating


asyncdeftest_multiple_pyppeteer(pyppeteer_factory):
pyppeteer1=awaitpyppeteer_factory()
pyppeteer2=awaitpyppeteer_factory()

movie_rating,book_rating=awaitasyncio.gather(
query_rating(pyppeteer1,"活著",MovieElements),
query_rating(pyppeteer2,"活著",BookElements)
)

assertbook_rating>=movie_rating

通過pyppeteer_factory 可以獲取多個瀏覽器例項,分別執行不同的操作,再利用 python 標準庫asyncio可以很方便的進行非同步呼叫,節省時間。

執行測試用例,看一下效果:

640?wx_fmt=gif

Github 倉庫

更多功能可以訪問:https://github.com/luizyao/pytest-pyppeteer,如果能幫助到你的話,可以給個 star,也歡迎提 issue 和 pr。

pytest 中文文件(v6.1.1)

之前翻譯過 pytest v5.1.3 的官方文件並開源,目前計劃更新到 v6.1.1 版本。

專案更多進度可以訪問:https://github.com/luizyao/pytest-chinese-doc/tree/6.1.1

參考資料

[1]

pytest-pyppeteer: https://github.com/luizyao/pytest-pyppeteer

[2]

pyppeteer: https://github.com/pyppeteer/pyppeteer

[3]

puppeteer: https://github.com/puppeteer/puppeteer/

[4]

pipenv: https://github.com/pypa/pipenv