Playwright for Python: Installation and initial use

write in front

Automated communication

1. Introduction to Playwright

1.1 Brief introduction

Playwright is an automated testing tool launched by Microsoft that was created specifically to meet end-to-end testing needs. Playwright supports all modern rendering engines, including Chromium, WebKit and Firefox. You can perform local or continuous integration testing on Windows, Linux and macOS, headless or headed, and you can also use Google Chrome to perform local simulation testing on Android and Mobile Safari.

Three automated testing (or crawler) libraries commonly used today:

Library Selenium Puppeteer Playwright
JavaScript support Official support Official support Official support
Python asynchronous support none Third party, and has a lot of bugs Official support
Python synchronization support Official support none Official support
maintainer Community Google Microsoft
Operational browser Chrome/Firefox/Safari/Edge Chrome/Firefox Chrome/Firefox/Safari/Edge
Simulation operation richness generally Excellent very good
Cookie support generally generally API is very friendly
Agent switching support generally generally Excellent

1.2 Supported platforms

Linux macOS Windows
Chromium 89.0.4344.0 support support support
WebKit 14.1 support support support
Firefox 84.0b9 support support support

1.3 Supported languages

JavaScript and TypeScript: https://github.com/microsoft/playwright
Java: https://github.com/microsoft/playwright-java
Python: https://github.com/microsoft/playwright-python
C#: https://github.com/microsoft/playwright-sharp

1.4 Official documentation (python)

Documentation: https://playwright.dev/python/docs/intro
API: https://playwright.dev/python/docs/api/class-playwright

2. Start

2.1 Installation requirements

  • Python 3.8 or higher.
  • Windows 10+, Windows Server 2016+ or Windows Subsystem for Linux (WSL).
  • MacOS 12 Monterey or MacOS 13 Ventura.
  • Debian 11, Debian 12, Ubuntu 20.04 or Ubuntu 22.04.

2.2 Installation

Install playwright and browser binaries for Chromium, Firefox and WebKit

  • pip installation
pip install playwright  # 安装playwright
playwright install  # 安装浏览器驱动
  • conda installation
conda install playwright  # 安装playwright
playwright install   # 安装浏览器驱动

2.3 Code examples

Currently installed version:
python=3.9.5
playwright=1.37.0

# -*- coding: utf-8 -*-
# @Time    : 2023/9/1 10:52
# @Author  : chenyinhua
# @File    : test_demo.py
# @Software: PyCharm
# @Desc:

import re
from playwright.sync_api import sync_playwright, expect

# 同步API (初学者建议先使用同步API)
with sync_playwright() as playwright:
    """
    在使用 with sync_playwright() as playwright: 时,Playwright 会创建一个 Playwright 实例,并将其作为 playwright 变量绑定到 with 代码块中。
    在代码块结束时,会自动调用 playwright.close() 方法来关闭所有已创建的页面和浏览器实例。
    这样可以确保资源的正常释放和关闭,避免资源泄漏和浪费。因此,使用 with sync_playwright() as playwright: 是一个推荐的方式来管理 Playwright 的实例。
    """
    # 默认是无头模式
    # browser = playwright.chromium.launch()
    # 使用有头模式
    browser = playwright.chromium.launch(headless=False, channel="chrome")
    """
    通过调用 browser.new_context() 方法,我们可以在当前浏览器实例中创建一个新的上下文。
    这个新的上下文将与原始上下文相互隔离,它们不会共享 cookies、缓存等数据。
    您可以在同一个浏览器实例中创建多个上下文,每个上下文可以具有自己的页面和状态。
    可以理解为浏览器的无痕模式
    """
    context = browser.new_context()

    """
     一般来说,一个page对应一个浏览器选项卡。而Page对象的作用在于和页面的内容进行交互,以及导航和加载新的页面。
    在上下文中创建一个新的页面时,该页面会继承上下文的各种属性和设置,例如 cookies、请求拦截器、代理等。
    此外,在同一上下文中创建的页面之间共享网络连接,因此加载速度更快。
    """
    page = context.new_page()

    # 访问地址
    page.goto("https://www.gitlink.org.cn/")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("GitLink"))

    # 点击按钮,会新开窗口打开页面
    page.locator("//a[text()='开源项目']").click()
    # 此处需要更新页面的值
    page = page.wait_for_event("popup")
    # 断言网页标题=开源项目
    expect(page).to_have_title(re.compile("开源项目"))

2.4 Assertions

Playwright provides the expect function, which waits until an expected condition is met.

import re
from playwright.sync_api import expect

expect(page).to_have_title(re.compile("GitLink"))

官方详细说明:https://playwright.dev/python/docs/test-assertions

后续会详细说明断言的具体用法。

2.5 Locators

Locators are a core component of Playwright's automatic wait and retry capabilities. Locators are used to find elements on the page at any moment and are used to perform operations on the elements, such as .click, .fill, etc.

import re
from playwright.sync_api import expect

page.goto("https://www.gitlink.org.cn/")
expect(page).to_have_title(re.compile("GitLink"))
page.locator("//a[text()='开源项目']").click()

官方详细说明:https://playwright.dev/python/docs/locators

后续会详细说明定位的具体用法。

2.6 Test Isolation

The Playwright Pytest plugin is based on the concept of test fixtures, where built-in page fixtures are passed into your tests. Pages are isolated between tests due to the browser context. The browser context is equivalent to a brand new browser profile, in which each test gets a brand new environment, even if multiple tests are running in the same browser.

import re
from playwright.sync_api import Page, expect


def test_gitlink_demo(page: Page):
    # 访问地址
    page.goto("https://www.gitlink.org.cn/")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("GitLink"))

    # 点击按钮,会新开窗口打开页面
    page.locator("//a[text()='开源项目']").click()
    # 此处需要更新页面的值
    page = page.wait_for_event("popup")
    # 断言网页标题=开源项目
    expect(page).to_have_title(re.compile("开源项目"))

该部分与【pytest插件支持】一节相关。可以跳到该章节详细理解。

2.7 Using Test Hooks

We can use various fixtures to execute code before or after testing and share objects between them. For example, function-scoped firmware with autouse behaves like beforeEach/afterEach, while module-scoped firmware with autouse behaves like beforeAll/afterAll, running before and after all tests.

import pytest
from playwright.sync_api import Page


@pytest.fixture(scope="function", autouse=True)
def before_each_after_each(page: Page):
    print("beforeEach")
    # Go to the starting url before each test.
    page.goto("https://playwright.dev/")
    yield
    print("afterEach")

def test_main_navigation(page: Page):
    # Assertions use the expect API.
    expect(page).to_have_url("https://playwright.dev/")

3. Run the test

We can run a single test, a set of tests, or all tests. Tests can be run on one browser or multiple browsers. By default, tests run headless, which means no browser window will be opened while running the test, and the results will be displayed in the terminal. If you prefer, you can run your tests in headed mode using the --headed flag.

  • Run tests using Chromium
pytest

  • Run a single test file
pytest test_login.py

  • Run a set of tests
pytest tests/todo-page/ tests/landing-page/

  • Run the specified test method
pytest -k "test_add_a_todo_item"

  • Run tests using headless mode
pytest --headed test_login.py

  • Specify the browser to run the test
pytest test_login.py --browser webkit

  • Specify multiple browsers to run tests
pytest test_login.py --browser webkit --browser firefox

  • Parallel testing (usually browsers will test one by one)
    Note: installation requiredpytest-xdist

pytest --numprocesses auto

4. Debug debugging

Since Playwright runs in Python, we can debug it using the debugger of your choice, such as using the Python plug-in in Visual Studio Code. Playwright provides the Playwright Inspector tool, which allows you to step through Playwright API calls, view their debug logs and explore locators. Playwright Inspector makes debugging and troubleshooting easier.

  • Bash
# 开启调试
PWDEBUG=1 
# 关闭调试
PWDEBUG=0
# 运行测试
pytest -s
  • PowerShell
# Window可以使用这个
# 开启调试
$env:PWDEBUG=1
# 关闭调试
$env:PWDEBUG=0
# 运行测试
pytest -s
  • Batch
# Window可以使用这个
# 开启调试
set PWDEBUG=1
# 关闭调试
set PWDEBUG=0
# 运行测试
pytest -s

5. Script recording Test generator

Playwright comes with test generation out of the box and is a great way to start testing quickly. It opens two windows, a browser window where you can interact with the website you wish to test, and a Playwright Inspector window where you can record tests, copy tests, clear tests, and change the test language. Through Playwright Inspector, you can easily record tests and perform related operations, enabling you to quickly generate and manage test code.

We can first experience the script recording function.

python -m playwright codegen 录制脚本
 –help 帮助文档
 -o 生成自动化脚本的目录(文件默认生成的地址为你cmd运行命令的地址,也可以在命令中输入需要保存的地址)
 –target 脚本语言,包含 JS 和 Python,分别对应值为:python 和 javascript
 -b 指定浏览器驱动

Execute the command in cmd: python -m playwright codegen -o "./test_code.py" --target python-pytest

Refer to other commands:python -m playwright codegen --target python -o test.py -b chromium https://www.baidu.com

Note: If you need to stop script recording, just close the browser.

Insert image description here

6. Trace viewer Trace viewer

Playwright Trace Viewer is a GUI tool that can trace Playwright tests, which means we can go back and forward through each test operation and visually see what is happening during each operation.

6.1 Start tracking

Can be used browser_context.tracingfor tracking purposes. The code reference is as follows:

import re
from playwright.sync_api import sync_playwright, expect


with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    context = browser.new_context()
    # 在新开页面之前,开始跟踪记录
    context.tracing.start(screenshots=True, snapshots=True, sources=True)
    page = context.new_page()
    
    page.goto("https://www.gitlink.org.cn/")
    expect(page).to_have_title(re.compile("GitLink"))

    page.locator("//a[text()='开源项目']").click()
    page = page.wait_for_event("popup")
    expect(page).to_have_title(re.compile("开源项目"))

    # 停止跟踪记录,并将记录保存到trace.zip(zip文件名可自定义)
    context.tracing.stop(path="trace.zip")

6.1 View tracking records

Execute the command in cmd: playwright show-trace trace.zip.

After we execute the command, the page that opens to view is as follows:
Insert image description here

7. pytest plug-in support

Playwright provides a Pytest plugin pytest-playwrightto support end-to-end testing.

Install pytest plugin: pip install pytest-playwright.

Note: All content in this chapter must be installed pytest-playwrightto take effect.

7.1 Use

Run the test using pytest:pytest --browser webkit --headed

--headedIndicates running in headless mode.

pytest.ini We can also configure the running command line parameters in the pytest configuration file , as shown below:

# content of pytest.ini
[pytest]
# Run firefox with UI
addopts = --headed --browser firefox

7.2 CLI arguments

  • –headed: Whether to run the test in headless mode or headless mode, the default is headless mode;
  • –browser: Run tests in different browsers, you can specify multiple times; the default is chromium;
  • –browser-channel: The browser channel to use. Browser channels represent browsers for a specific version and release channel. For example, you can specify a specific Chrome browser version or release channel, such as beta or dev;
  • –slowmo: Slow down Playwright operations by the specified number of milliseconds. Can be used to view the progress of the operation (default is 0);
  • –device: the device to be simulated;
  • –output: directory used to store artifacts generated by tests (default is test-results);
  • –tracing: Whether to log tracing information for each test. Optional values: on, off or retain-on-failure (default is off);
  • –video: Whether to record a video for each test. Optional values: on, off or retain-on-failure (default is off);
  • --screenshot: Whether to automatically capture a screenshot after each test. Optional values: on, off or only-on-failure (default is off);
  • --full-page-screenshot: Whether to take a full page screenshot on failure. By default, only the viewport portion is captured. The --screenshot option needs to be enabled (default is off);

7.3 Fixture

pytest is configured with Playwright-specific fixtures. To use these fixtures, pass the fixture name as an argument to the test function.
In the following example, we will pagepass it as a parameter to the Fixture test function.

import re
from playwright.sync_api import Page, expect


def test_gitlink_demo(page: Page):
    # 访问地址
    page.goto("https://www.gitlink.org.cn/")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("GitLink"))

    # 点击按钮,会新开窗口打开页面
    page.locator("//a[text()='开源项目']").click()
    # 此处需要更新页面的值
    page = page.wait_for_event("popup")
    # 断言网页标题=开源项目
    expect(page).to_have_title(re.compile("开源项目"))

7.3.1 Function scope

These fixtures are created when requested within a test function and destroyed at the end of the test.

  • context: New browser context for testing.
  • page: A new browser page for testing.

7.3.2 Session scope

These fixtures are created when requested within a test function and destroyed at the end of all tests.

  • playwright: Playwright instance.
  • browser_type: BrowserType instance of the current browser.
  • browser: Browser instance launched by Playwright.
  • browser_name: browser name, string type.
  • browser_channel: browser channel, string type.
  • is_chromium, is_webkit, is_firefox: Boolean values ​​corresponding to browser types respectively.

7.3.3 Custom fixture options

For browser and context fixtures, use the following fixtures to define custom launch options.

  • browser_type_launch_args: Override the launch parameters of browser_type.launch(). It should return a dictionary.
  • browser_context_args: Override options of browser.new_context(). It should return a dictionary.

Context options (browser.new_context()) can also be overridden for individual tests by using the browser_context_args tag.

import pytest

@pytest.mark.browser_context_args(timezone_id="Europe/Berlin", locale="en-GB")
def test_browser_context_args(page):
    assert page.evaluate("window.navigator.userAgent") == "Europe/Berlin"
    assert page.evaluate("window.navigator.languages") == ["de-DE"]

7.4 Parallel testing

If the computer's CPU is high enough, we can use it to pytest-xdistrun multiple tests in parallel to speed up the execution time of the entire test suite.

# install dependency
pip install pytest-xdist
# use the --numprocesses flag
# 根据硬件和测试的性质,可以将 numprocesses 设置为从 2 到机器上的 CPU 数量的任意值。
# 如果设置得过高,可能会出现意外行为。
pytest --numprocesses auto

7.5 Example

7.5.1 Configuring slow mode

We can --slowmoconfigure slow mode using parameters.
for example:pytest --slowmo 100

Or you can implement the code as follows:

# run.py
import pytest

pytest.main( ['--headed', '--browser=chromium', "--browser-channel=chrome", "--slowmo=10"])

7.5.2 Skip X Browser Test

We can use a decorator @pytest.mark.skip_browserto skip this test case and skip executing the X browser.

# test_demo.py
import re
from playwright.sync_api import Page, expect
import pytest


@pytest.mark.skip_browser("webkit")
def test_gitlink_demo(page: Page):
    # 访问地址
    page.goto("https://www.gitlink.org.cn/")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("GitLink"))

7.5.3 Specify the browser where the test case runs

We can use decorators @pytest.mark.only_browserto specify the browser on which the test case will be executed.

# test_demo.py
import re
from playwright.sync_api import Page, expect
import pytest


@pytest.mark.only_browser("webkit")
def test_gitlink_demo(page: Page):
    # 访问地址
    page.goto("https://www.gitlink.org.cn/")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("GitLink"))

7.5.4 Specify the browser channel for test case execution

We can use command line parameters --browser-channelto specify running browser parameters.
for example:pytest --browser-channel chrome

Or you can implement the code as follows:

# run.py
import pytest

pytest.main( ['--headed', '--browser=chromium', "--browser-channel=chrome"])

7.5.5 Configure base-url/host

We can use the command function base-urlto configure the base-url/host of the run.
for example:pytest --base-url https://www.gitlink.org.cn/

# run.py
import pytest

pytest.main( ['--headed', '--browser=chromium', "--browser-channel=chrome", "--base-url=https://www.gitlink.org.cn"])

Then in our test function, we just need to write the relative path. Reference is as follows:

# test_demo.py
def test_gitlink_demo(page: Page):
    # 访问地址,这里写的相对地址
    page.goto("/expore")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("开源项目"))

7.5.6 Ignore HTTPS errors

# conftest.py
import pytest

@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
    return {
    
    
        **browser_context_args,
        "ignore_https_errors": True
    }

7.5.7 Custom window size

# conftest.py
import pytest

@pytest.fixture(scope="session")
def browser_context_args(browser_context_args):
    return {
    
    
        **browser_context_args,
        "viewport": {
    
    
            "width": 1920,
            "height": 1080,
        }
    }

7.5.8 Device Simulation

# 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,
    }

7.5.9 Persistent context

When using a persistent context, all pages in the test are created from the persistent context.

# conftest.py
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("./foobar", **{
    
    
        **browser_type_launch_args,
        **browser_context_args,
        "locale": "de-DE",
    })
    yield context
    context.close()

Then in the test method, we need to use the returned contextone to create a new one page. The reference is as follows:

# test_demo.py
import re
from playwright.sync_api import Page, expect
import pytest

def test_gitlink_demo2(context):
	# 新建一个页面
	page = context.new_page()
    # 访问地址
    page.goto("/explore")
    # 断言网页标题=GitLink
    expect(page).to_have_title(re.compile("开源项目"))

7.5.10 Compatible with unittest.TestCase

The following is an example compatible with unittest.TestCase. It should be noted that this method has a limitation: only one browser can be specified, and a browser matrix cannot be generated when multiple browsers are specified.

import pytest
import unittest

from playwright.sync_api import Page


class MyTest(unittest.TestCase):
    @pytest.fixture(autouse=True)
    def setup(self, page: Page):
        self.page = page

    def test_foobar(self):
        self.page.goto("https://microsoft.com")
        self.page.locator("#foobar").click()
        assert self.page.evaluate("1 + 1") == 2

7.5.11 Use with pdb

Use breakpoint() statements in test code to pause execution and get the pdb REPL (Python debugger) interactive interface.

def test_bing_is_working(page):
    page.goto("https://bing.com")
    breakpoint()
    # ...

Guess you like

Origin blog.csdn.net/FloraCHY/article/details/132620350