Cookie Consent by Free Privacy Policy Generator 📌 Playwright with Python - A Quick Guide


✅ Playwright with Python - A Quick Guide


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

In this guide, we'll see how to set up a basic Playwright project using Python and Pytest. Then, how to implement the Page Object Pattern and a few other things.

This guide requires a basic knowledge of Python.

Preconditions

The packages required are:

  • playwright

  • pytest-playwright

  • pytest-xdist

The folder structure

The base folder structure for our project:

/pages
/tests
conftest.py
requirements.txt

Installation

We add the required packages to the requirements.txt file:

requirements.txt

playwright>=1.44.0
pytest-playwright>=0.5.0
pytest-xdist>=3.6.1

Then we run the following command:

pip install -r requirements.txt

Note: instead of pip, pip3 might be required depending on the OS.

Then:

playwright install

This command will install the required browsers.

Adding a Basic Test

A basic login test using Playwright:

/tests/test_login.py

from playwright.sync_api import Page, expect


def test_login_success(page: Page):
    page.goto('https://react-redux.realworld.io/#/login')
    page.get_by_placeholder('Email').type('[email protected]')
    page.get_by_placeholder('Password').type('Test123456')
    page.get_by_role('button', name='Sign in').click()
    expect(page.get_by_role('link', name='test_playwright_login')).to_be_visible()

Running this test

This runs a single test in headed mode. Playwright runs in headless mode by default.

pytest -k test_login_success --headed

Running all the tests

pytest

Selecting the browsers

pytest --browser webkit --browser firefox

Implementing the Page Object Pattern

To start using the POM we add:

pages/login_page.py

from playwright.sync_api import Page


class Login:

    def __init__(self, page: Page):
        self.page = page
        self.email_input = page.get_by_placeholder('Email')
        self.password_input = page.get_by_placeholder('Password')
        self.signin_button = page.get_by_role('button', name='Sign in')

    def goto(self):
        self.page.goto('/#/login')

pages/navbar_page.py

from playwright.sync_api import Page


class Navbar:

    def __init__(self, page: Page):
        self.page = page

    def user_link(self, username: str):
        return self.page.get_by_role('link', name=username)

We add the base URL of our app to the conftest.py as a fixture like this:

conftest.py

import pytest


@pytest.fixture(scope='session')
def base_url():
    return 'https://react-redux.realworld.io/'

And now the test looks like this:

tests/test_login.py

from playwright.sync_api import Page, expect

from pages.login_page import Login
from pages.navbar_page import Navbar


def test_login_success(page: Page):
    login = Login(page)
    navbar = Navbar(page)
    login.goto()
    login.email_input.type('[email protected]')
    login.password_input.type('Test123456')
    login.signin_button.click()
    expect(navbar.user_link('test_playwright_login')).to_be_visible()

Using Pytest fixtures to Instantiate the Page Objects

Instead of instantiating the page objects in each test, we use Pytest fixtures.

We add the following to conftest.py

conftest.py

import pytest
from playwright.sync_api import Page
from pages.login_page import Login
from pages.navbar_page import Navbar


@pytest.fixture(scope='session')
def base_url():
    return 'https://react-redux.realworld.io/'


@pytest.fixture
def page(page: Page) -> Page:
    timeout = 10000
    page.set_default_navigation_timeout(timeout)
    page.set_default_timeout(timeout)
    return page


@pytest.fixture
def login(page) -> Login:
    return Login(page)

@pytest.fixture
def navbar(page) -> Navbar:
    return Navbar(page)

Note: we use the "page" fixture to define timeouts.

Now the test looks like this:

tests/test_login.py

from playwright.sync_api import expect


def test_login_success(login, navbar):
    login.goto()
    login.email_input.type('[email protected]')
    login.password_input.type('Test123456')
    login.signin_button.click()
    expect(navbar.user_link('test_playwright_login')).to_be_visible()

Removing User Data Values from the Test

We create a users.py file to store user's data, just one user for now. The DictObject is a utility class to access dictionary values using object notation. It could be moved elsewhere, but for now, we keep it here.

users.py

import json


class DictObject(object):
    def __init__(self, dict_):
        self.__dict__.update(dict_)

    @classmethod
    def from_dict(cls, d):
        return json.loads(json.dumps(d), object_hook=DictObject)


USERS = DictObject.from_dict({
    'user_01': {
        'username': 'test_playwright_login',
        'email': '[email protected]',
        'password': 'Test123456'
    }
})

And we update the test:

tests/test_login.py

from playwright.sync_api import expect

from users import USERS

def test_login_success(login, navbar):
    login.goto()
    login.email_input.type(USERS.user_01.email)
    login.password_input.type(USERS.user_01.password)
    login.signin_button.click()
    expect(navbar.user_link(USERS.user_01.username)).to_be_visible()

Running tests in parallel

To run the tests in parallel we use pytest-xdist. We should already have it installed by this point.

pytest -n 5

Where -n is the number of workers.

Managing Environment Data

Usually, we want the tests to run in different environments. So we want to set the base URL based on the selected env.

We add these changes to the conftest.py file:

conftest.py

def pytest_addoption(parser):
    parser.addoption("--env", action="store", default="staging")


@pytest.fixture(scope='session', autouse=True)
def env_name(request):
    return request.config.getoption("--env")


@pytest.fixture(scope='session')
def base_url(env_name):
    if env_name == 'staging':
        return 'https://react-redux.realworld.io/'
    elif env_name == 'production':
        return 'https://react-redux.production.realworld.io/'
    else:
        exit('Please provide a valid environment')

After this, we can pass as an argument the environment name like this:

pytest --env staging

Defining Global Before and After Test

@pytest.fixture(scope="function", autouse=True)
def before_each_after_each(page: Page, base_url):
    # The code here runs before each test
    print(before the test runs)

    # Go to the starting url before each test.
    page.goto(base_url)
    yield

    # This code runs after each test
    print(after the test runs)

This fixture can be added to the conftest.py and apply it to every test. Or it can be defined inside a single test module and be applied only to the tests inside that module.

Tagging the Tests

To tag the tests we can use Pytest marker feature.

import pytest

@pytest.mark.login
def test_login_success():
    # ...

We must register our custom markers in the pytest.ini file (a new file added in the root folder).

pytest.ini

[pytest]
markers =
    login: mark test as a login test.
    slow: mark test as slow.

And to run a custom marker/tag we use:

pytest -m login

Tooling

Codegen

This generates a test capturing actions in real time. It's useful for generating locators and assertions. But if we are using POM, then the generated code needs to be refactored into it.

Playwright Inspector

This is a debugger util that enables running a test step by step, among other things.

Trace Viewer

The trace viewer records the result of a test so it can be reviewed later with a live preview of each action performed. This is super useful specially when running tests from CI.

...

✅ Playwright with Python - A Quick Guide


📈 38.72 Punkte

✅ Playwright Testing and GitHub Actions Tutorial: Run Your Playwright Tests on Every Code Commit


📈 36.65 Punkte

✅ Introducing Auto Playwright: Transforming Playwright Tests with AI


📈 36.65 Punkte

✅ Python Pulse - 🔴 Testing your Flask app with Playwright


📈 24.17 Punkte

✅ End-to-End-Tests: Microsoft veröffentlicht Testingtool Playwright für Python


📈 24.17 Punkte

✅ Effective End-to-End Testing: A Beginner's Guide to Playwright


📈 23.94 Punkte

✅ Basic Step-by-Step Guide to Setting Up a Project Using Playwright


📈 23.94 Punkte

✅ A Guide To Visual Regression Testing With PlayWright and How to Get Started


📈 23.94 Punkte

✅ 🚀 Mastering Website Previews: A Step by Step Guide to Playwright and Chromium! ✨


📈 23.94 Punkte

✅ The Python FAQ: Quick answers to common Python questions


📈 20.63 Punkte

✅ SQL to Python Pandas: A SQL User's Quick Guide


📈 20.4 Punkte

✅ A Quick Guide to Beautiful Scatter Plots in Python


📈 20.4 Punkte

✅ Playwright Web Scraping 2024 - Tutorial


📈 18.32 Punkte

✅ Box Test Steps in Playwright


📈 18.32 Punkte

✅ Web Scraping Dynamic Websites With Scrapy Playwright


📈 18.32 Punkte

✅ Cypress vs. Playwright: Which Is the Best Testing Tool?


📈 18.32 Punkte

✅ How to track anything on the internet or use Playwright for fun and profit


📈 18.32 Punkte

✅ Web Application Testing with Microsoft’s Playwright (12 of 12) | Automated Software Testing


📈 18.32 Punkte

✅ Mock The API Data (Request and Responses) With Playwright


📈 18.32 Punkte

✅ The best testing setup for frontends, with Playwright and NextJS


📈 18.32 Punkte

✅ e2e testing with Playwright | OD111


📈 18.32 Punkte

✅ Test automation for AutoCAD Web using Playwright and visual comparison


📈 18.32 Punkte

✅ Automated Testing with Playwright


📈 18.32 Punkte

✅ Cypress vs Playwright: A Comparative Analysis


📈 18.32 Punkte

✅ Implementing Page Object Model for Playwright Tests


📈 18.32 Punkte

✅ Live demo of automated cloud application testing using Azure and Playwright


📈 18.32 Punkte

✅ Cypress vs. Playwright for Node: A Head-to-Head Comparison


📈 18.32 Punkte

✅ WebAuthn E2E Testing: Playwright, Selenium, Puppeteer


📈 18.32 Punkte

✅ Playwright Q&A | DIS251H


📈 18.32 Punkte

✅ Configuring Snapshot Tests in Playwright


📈 18.32 Punkte

✅ How to Run Playwright Test Cases in CI/CD Pipeline Bitbucket


📈 18.32 Punkte

✅ Puppeteer Vs Playwright: Scrape a Strapi-Powered Website


📈 18.32 Punkte











matomo

Datei nicht gefunden!