Upgrading from Selenium to Playwright

For a long time Selenium has been the default option for writing automated browser tests, but there are alternatives now available. One leading contender is Playwright, and while it does not have as much language support as Selenium, it does cover the main options (JavaScript, Python, Java and .Net) while providing full browser support.

With a large suite of automated Selenium tests, it might not make much sense to rewrite existing tests to use Playwright, but for new test suites it might make sense to switch over to Playwright. It has better affordances for testing, has easy control over the browser contexts without that getting in the way for normal usage and deals with single page applications and websockets. The python samples below are equivalent (other than playwright does not show browser by default).

Playwright

    import pytest
    from playwright.sync_api import sync_playwright

    @pytest.fixture
    def browser():
        playwright = sync_playwright().start()
        browser = playwright.chromium.launch()  # use params headless=False to see browser

        yield browser

        browser.close()
        playwright.stop()

    def test_blog_title(browser):
        page = browser.new_page()
        page.goto("https://www.selenium.dev/")
    
        # find the blog link in the header and then click on that link
        page.click("#main_navbar :text('blog')")
        title = page.title()
        assert title.startswith("Blog | Selenium"), title

        h1text = page.wait_for_selector('h1')
        assert h1text.inner_text() == "Selenium Blog"

Selenium

    import pytest
    from selenium import webdriver
    from selenium.webdriver.common.by import By

    @pytest.fixture
    def webbrowser():
        firefox = webdriver.Firefox() # default is to show the browser, use options to make headless
        yield firefox
        firefox.close()

    def test_blog_title(webbrowser):
        webbrowser.get("https://www.selenium.dev/")
        # want the blog link from header, so two stage process to get correct element

        header = webbrowser.find_element(By.ID,'main_navbar')
        blog = header.find_element(By.PARTIAL_LINK_TEXT , 'Blog')
        blog.click()

        title = webbrowser.title
        assert "Blog | Selenium" in title, title

        assert webbrowser.find_element(By.CSS_SELECTOR, 'h1').text == "Selenium Blog"