playwright結合Pytest為您的 Web 應用程序編寫端到端的測試。
安裝pytest插件
C:\Users\lifeng01>pip install pytest-playwright
Collecting pytest-playwright
Using cached pytest_playwright-0.2.2-py3-none-any.whl (9.8 kB)
Requirement already satisfied: pytest in d:\python\python37\lib\site-packages (from pytest-playwright) (6.2.5)
Requirement already satisfied: playwright>=1.13 in d:\python\python37\lib\site-packages (from pytest-playwright) (1.17.0)
Requirement already satisfied: python-slugify in d:\python\python37\lib\site-packages (from pytest-playwright) (5.0.2)
Requirement already satisfied: pytest-base-url in d:\python\python37\lib\site-packages (from pytest-playwright) (1.4.2)
Requirement already satisfied: typing-extensions in d:\python\python37\lib\site-packages (from playwright>=1.13->pytest-playwright) (3.7.4.3)
Requirement already satisfied: pyee>=8.0.1 in d:\python\python37\lib\site-packages (from playwright>=1.13->pytest-playwright) (8.2.2)
Requirement already satisfied: websockets>=8.1 in d:\python\python37\lib\site-packages (from playwright>=1.13->pytest-playwright) (9.1)
Requirement already satisfied: greenlet>=1.0.0 in d:\python\python37\lib\site-packages (from playwright>=1.13->pytest-playwright) (1.0.0)
Requirement already satisfied: atomicwrites>=1.0 in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (1.3.0)
Requirement already satisfied: attrs>=19.2.0 in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (19.3.0)
Requirement already satisfied: py>=1.8.2 in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (1.9.0)
Requirement already satisfied: toml in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (0.10.0)
Requirement already satisfied: colorama in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (0.4.3)
Requirement already satisfied: pluggy<2.0,>=0.12 in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (0.13.1)
Requirement already satisfied: packaging in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (20.9)
Requirement already satisfied: importlib-metadata>=0.12 in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (1.7.0)
Requirement already satisfied: iniconfig in d:\python\python37\lib\site-packages (from pytest->pytest-playwright) (1.0.1)
Requirement already satisfied: requests>=2.9 in d:\python\python37\lib\site-packages (from pytest-base-url->pytest-playwright) (2.25.0)
Requirement already satisfied: text-unidecode>=1.3 in d:\python\python37\lib\site-packages (from python-slugify->pytest-playwright) (1.3)
Requirement already satisfied: zipp>=0.5 in d:\python\python37\lib\site-packages (from importlib-metadata>=0.12->pytest->pytest-playwright) (3.1.0)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in d:\python\python37\lib\site-packages (from requests>=2.9->pytest-base-url->pytest-playwright) (1.26.2)
Requirement already satisfied: certifi>=2017.4.17 in d:\python\python37\lib\site-packages (from requests>=2.9->pytest-base-url->pytest-playwright) (2020.4.5.1)
Requirement already satisfied: idna<3,>=2.5 in d:\python\python37\lib\site-packages (from requests>=2.9->pytest-base-url->pytest-playwright) (2.9)
Requirement already satisfied: chardet<4,>=3.0.2 in d:\python\python37\lib\site-packages (from requests>=2.9->pytest-base-url->pytest-playwright) (3.0.4)
Requirement already satisfied: pyparsing>=2.0.2 in d:\python\python37\lib\site-packages (from packaging->pytest->pytest-playwright) (2.4.7)
Installing collected packages: pytest-playwright
Successfully installed pytest-playwright-0.2.2
編寫測試用例
import pytest
from playwright.sync_api import Page
def test_baidu_com(page: Page):
page.goto("https://www.baidu.com")
# xpath定位輸入框,輸入文本內容
page.fill('//*[@id="kw"]', "秦時明月")
# css點位點擊“百度一下”按鈕
page.click('#su')
# 打印title名稱
print(page.title)
if __name__ == '__main__':
pytest.main(["-v", "test_baidu_example.py"])
名詞解釋:
test_baidu_com(page: Page):自動完成配置類型 (page是pytest_playwright插件提供的一個夾函數,page指定到類型為Page,Page是playwright庫提供的一個類,page指定類型為Page就可以調用Page類中的一些列方法 )
命令行輸入命令執行:
PS F:\project_gitee\Test\playwrightProject\cases> pytest --browser chromium --video on
================================================================================== test session starts ==================================================================================
platform win32 -- Python 3.7.7, pytest-6.2.5, py-1.9.0, pluggy-0.13.1
rootdir: F:\project_gitee\Test\playwrightProject\cases
plugins: allure-pytest-2.9.43, anyio-3.3.4, base-url-1.4.2, clarity-1.0.1, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-3.1.1, lazy-fixture-0.6.3, metadata-1.11.0, pikachu-0.1.0, playwrigh
t-0.2.2, rerunfailures-9.1.1, xdist-2.2.1
collected 1 item
test_baidu_example.py . [100%]
=================================================================================== 1 passed in 1.97s ===================================================================================
命令行常用基礎命令:
# 運行測試
pytest
# 開啟頁面運行
pytest --headed
# 指定瀏覽器運行
pytest --browser firefox
# 開啟頁面運行並指定瀏覽器運行
pytest --headed --browser firefox
# 指定兩個瀏覽器運行,優先運行火狐再運行谷歌
pytest --browser firefox --browser chromium
# 使用瀏覽器頻道,支持谷歌瀏覽器(我的電腦其他瀏覽器是報錯的)
pytest --browser-channel chromium
# 用慢動作運行測試
pytest --slowmo 100
# 指定谷歌瀏覽器,開啟記錄每次測試的軌跡(生成一個.zip包,存放在test-results文件夾中)
pytest --browser chromium --tracing on(on:開;off:關)
# 指定谷歌瀏覽器,開啟每次測試錄制視頻(生成一個.webm包,存放在test-results文件夾中)
pytest --browser chromium --video on(on:開;off:關)
# 指定谷歌瀏覽器,開啟每次測試后是否自動截屏(生成一個.png圖片,存放在test-results文件夾中)
pytest --browser chromium --screenshot on
- 通過瀏覽器跳過測試:
import pytest
from playwright.sync_api import Page
@pytest.mark.skip_browser("firefox")
def test_baidu_com(page: Page):
page.goto("https://www.baidu.com")
# xpath定位輸入框,輸入文本內容
page.fill('//*[@id="kw"]', "秦時明月")
# css點位點擊“百度一下”按鈕
page.click('#su')
# 打印title名稱
print(page.title)
if __name__ == '__main__':
pytest.main(["-v", "test_baidu_example.py"])
- 在特定瀏覽器上運行:
import pytest
from playwright.sync_api import Page
@pytest.mark.only_browser("chromium")
def test_baidu_com(page: Page):
page.goto("https://www.baidu.com")
# xpath定位輸入框,輸入文本內容
page.fill('//*[@id="kw"]', "秦時明月")
# css點位點擊“百度一下”按鈕
page.click('#su')
# 打印title名稱
print(page.title)
if __name__ == '__main__':
pytest.main(["-v", "test_baidu_example.py"])
忽略 HTTPS 錯誤和設置自定義視口大小
- 第一種是寫在conftest.py中,然后直接運行測試用例:
# conftest.py
import pytest
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
return {
**browser_context_args,
"ignore_https_errors": True,
}
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
return {
**browser_context_args,
"viewport": {
"width": 1920,
"height": 1080,
}
}
- 測試用例寫法如下(最好這樣寫,不然運行就報錯,作者已采坑):
import pytest
from playwright.sync_api import Page
def test_example(page: Page):
page.goto("http://www.baidu.com")
assert page.title() == "百度一下,你就知道"
page.close()
if __name__ == '__main__':
pytest.main(["-v", "test_example.py"])
- 命令行運行測試用例:
PS F:\project_gitee\Test\playwrightProject\cases> pytest --headed --browser chromium
================================================================================== test session starts ==================================================================================
platform win32 -- Python 3.7.7, pytest-6.2.5, py-1.9.0, pluggy-0.13.1
rootdir: F:\project_gitee\Test\playwrightProject\cases
plugins: allure-pytest-2.9.43, anyio-3.3.4, asyncio-0.16.0, base-url-1.4.2, clarity-1.0.1, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-3.1.1, lazy-fixture-0.6.3, metadata-1.11.0, pikachu-
0.1.0, playwright-0.2.2, rerunfailures-9.1.1, xdist-2.2.1
collected 1 item
test_example.py . [100%]
=================================================================================== 1 passed in 2.39s ===================================================================================
- 第二種是直接在用例中增加指定參數即可:
import pytest
from playwright.sync_api import sync_playwright
def test_example():
with sync_playwright() as p:
browser = p.chromium.launch(headless=False)
page = browser.new_context(
ignore_https_errors=True,
viewport={
"width": 1920,
"height": 1040,
}
)
page = page.new_page()
page.goto("http://www.baidu.com")
assert page.title() == "百度一下,你就知道"
browser.close()
if __name__ == '__main__':
pytest.main(["-v", "test_example.py"])
名詞解釋:p.chromium.launch(headless=False):headless=False是開啟有頁面運行(默認是True,也就是無頭瀏覽器)
- 第三種是模擬手機瀏覽器
# conftest.py
import pytest
@pytest.fixture(scope="session")
def browser_context_args(browser_context_args, playwright):
iphone_11 = playwright.devices['iPhone 11 Pro']
return {
**browser_context_args,
**iphone_11,
}
- 測試用例寫法如下(最好這樣寫,不然運行就報錯,作者已采坑):
import pytest
from playwright.sync_api import Page
def test_example(page: Page):
page.goto("http://www.baidu.com")
assert page.title() == "百度一下,你就知道"
page.close()
if __name__ == '__main__':
pytest.main(["-v", "test_example.py"])
- 命令行運行測試用例:
PS F:\project_gitee\Test\playwrightProject\cases> pytest --headed --browser chromium
================================================================================== test session starts ==================================================================================
platform win32 -- Python 3.7.7, pytest-6.2.5, py-1.9.0, pluggy-0.13.1
rootdir: F:\project_gitee\Test\playwrightProject\cases
plugins: allure-pytest-2.9.43, anyio-3.3.4, asyncio-0.16.0, base-url-1.4.2, clarity-1.0.1, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-3.1.1, lazy-fixture-0.6.3, metadata-1.11.0, pikachu-
0.1.0, playwright-0.2.2, rerunfailures-9.1.1, xdist-2.2.1
collected 1 item
test_example.py F [100%]
======================================================================================= FAILURES ========================================================================================
________________________________________________________________________________ test_example[chromium] _________________________________________________________________________________
page = <Page url='https://m.baidu.com/?from=844b&vit=fps'>
def test_example(page: Page):
page.goto("http://www.baidu.com")
> assert page.title() == "百度一下,你就知道"
E AssertionError: assert '百度一下' == '百度一下,你就知道'
E - 百度一下,你就知道
E + 百度一下
test_example.py:15: AssertionError
================================================================================ short test summary info ================================================================================
FAILED test_example.py::test_example[chromium] - AssertionError: assert '百度一下' == '百度一下,你就知道'
=================================================================================== 1 failed in 3.14s ===================================================================================
這里運行后,打開的web頁面,是一個手機形狀的頁面,仿的是手機瀏覽器(代碼中指定的是iPhone 11 Pro)
持久上下文
它的意思就是打開一個web頁面,會在這個web頁面開多個新標簽頁面去執行測試用例。
例如:我有兩個測試用例需要執行,如果使用持久上下文,就會打開一個web頁面,然后web頁面的第一個標簽頁運行第一個測試用例,第二個標簽頁運行第二個測試用例,直到把所有測試用例運行完了,關閉整個web頁面,結束。
當然,如果你沒有使用持久上下文,那就是打開web頁面執行第一個測試用例,執行完第一個測試用例關閉web頁面,然后再打開web頁面執行第二個測試用例,執行完第二個測試用例關閉web頁面,結束。
import pytest
from playwright.sync_api import BrowserType
from typing import Dict
@pytest.fixture(scope="session")
def context(
browser_type: BrowserType,
browser_type_launch_args: Dict,
browser_context_args: Dict
):
context = browser_type.launch_persistent_context("./data", **{
**browser_type_launch_args,
**browser_context_args,
"locale": "de-DE",
})
yield context
context.close()
名詞解釋:
./data用戶數據目錄的路徑,它存儲瀏覽器會話數據,如cookie和本地存儲。browser_type_launch_args如果沒有設置值,返回的就是一個空字典;它里面的參數就是和p.chromium.launch()中的傳參一致的,此處了解下,后面具體介紹。browser_context_args如果沒有設置值,返回的就是一個空字典;它里面的參數就和context = browser.new_context()中的傳參一致的,此處了解下,后面具體介紹。locale指定用戶區域設置,例如' en-GB '、' de-DE '等。
命令行運行測試用例:
PS F:\project_gitee\Test\playwrightProject\cases> pytest --headed --browser chromium
================================================================================== test session starts ==================================================================================
platform win32 -- Python 3.7.7, pytest-6.2.5, py-1.9.0, pluggy-0.13.1
rootdir: F:\project_gitee\Test\playwrightProject\cases
plugins: allure-pytest-2.9.43, anyio-3.3.4, asyncio-0.16.0, base-url-1.4.2, clarity-1.0.1, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-3.1.1, lazy-fixture-0.6.3, metadata-1.11.0, pikachu-
0.1.0, playwright-0.2.2, rerunfailures-9.1.1, xdist-2.2.1
collected 2 items
test_baidu_example.py . [ 50%]
test_example.py . [100%]
=================================================================================== 2 passed in 3.12s ===================================================================================
必須知曉問題:
- 上述文章中的
browser_type_launch_args和browser_context_args都是pytest_playwright插件提供的測試夾會話: - 展示
pytest_playwright插件部分源碼:
@pytest.fixture(scope="session")
def browser_type_launch_args(pytestconfig: Any) -> Dict:
launch_options = {}
headed_option = pytestconfig.getoption("--headed")
if headed_option:
launch_options["headless"] = False
browser_channel_option = pytestconfig.getoption("--browser-channel")
if browser_channel_option:
launch_options["channel"] = browser_channel_option
slowmo_option = pytestconfig.getoption("--slowmo")
if slowmo_option:
launch_options["slow_mo"] = slowmo_option
return launch_options
@pytest.fixture(scope="session")
def browser_context_args(
pytestconfig: Any,
playwright: Playwright,
device: Optional[str],
) -> Dict:
context_args = {}
if device:
context_args.update(playwright.devices[device])
base_url = pytestconfig.getoption("--base-url")
if base_url:
context_args["base_url"] = base_url
video_option = pytestconfig.getoption("--video")
capture_video = video_option in ["on", "retain-on-failure"]
if capture_video:
context_args["record_video_dir"] = artifacts_folder.name
return context_args
以上總結或許能幫助到你,或許幫助不到你,但還是希望能幫助到你,如有疑問、歧義,直接私信留言會及時修正發布;非常期待你的點贊和分享喲,謝謝!
未完,待續…
一直都在努力,希望您也是!
微信搜索公眾號:就用python
文章作者:李 鋒|編輯排版:梁莉莉

