Каковы плюсы и минусы Playwright для автоматизации тестирования?

Ответ

Плюсы с точки зрения инженера по автоматизации:

  • Кроссплатформенность и поддержка браузеров: Единый API для Chromium, Firefox и WebKit. Это позволяет легко тестировать кросс-браузерную совместимость.
  • Автоматическое ожидание (Auto-waiting): Playwright автоматически ждет, пока элементы станут интерактивными (visible, enabled, stable). Это резко снижает количество sleep и явных ожиданий в коде, делая тесты стабильнее.
  • Высокая скорость и надежность: Прямое взаимодействие с браузером через DevTools Protocol (а не через медленный WebDriver) делает выполнение быстрым и менее подверженным флакy.
  • Мощные возможности для эмуляции: Встроенная поддержка мобильных viewport, геолокации, языков, разрешений (камера, микрофон).
  • Поддержка сетевых запросов: Можно перехватывать и мокать API-запросы, что полезно для изоляции тестов фронтенда.

Минусы и сложности:

  • Кривая обучения и документация: Сообщество и количество готовых решений пока меньше, чем у Selenium. Документация хороша, но иногда не хватает глубоких примеров для сложных кейсов.
  • Отсутствие поддержки legacy-браузеров: Не подходит для тестирования Internet Explorer или старых версий Safari.
  • Отладка: Отладка сложных сценариев может быть менее интуитивной, особенно при работе с несколькими контекстами или страницами.

Пример кода на Python, демонстрирующий auto-waiting и перехват запроса:

import re
from playwright.sync_api import sync_playwright, expect

def test_login_and_api_call():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()

        # Мокаем API-ответ перед навигацией
        page.route(
            re.compile(r".*/api/user/profile"),
            lambda route: route.fulfill(json={"name": "Test User"})
        )

        page.goto("https://example-app.com/login")
        # Auto-waiting: fill и click будут ждать готовности элементов
        page.fill("#username", "test_user")
        page.fill("#password", "password123")
        page.click("button[type='submit']")

        # Assertion с автоматическим ожиданием
        expect(page.locator(".user-profile")).to_have_text("Test User")

        browser.close()

Ответ 18+ 🔞

А, ну так это ж про Playwright! Давай разберем, что за зверь такой, с точки зрения человека, который эту автоматизацию каждый день пилит.

Что там хорошего, или почему инженер может обнять и плакать от счастья:

  • Один для всех, как швейцарский нож: Единый API под Chromium, Firefox и WebKit. Не надо плясать с бубном и переписывать половину кода, чтобы проверить, не разъехалось ли всё в другом браузере. Красота, ёпта.
  • Автоматическое ожидание — просто песня: Сам ждёт, пока кнопка не станет кликабельной, или поле не появится. Никаких этих вечных time.sleep(10) на всякий случай, после которых тест всё равно падает. Стабильность вырастает просто овердохуища.
  • Быстрый, как ужаленный: Работает напрямую с браузером через его же родной протокол, а не через медленного посредника. Тесты летают, и флаки (эти внезапные падения) случаются реже — волнение ебать снижается.
  • Эмулировать можно всё, что угодно: Хочешь — телефон какой-нибудь, хочешь — язык браузера поменяй или разрешение на камеру дай. Всё из коробки, без костылей.
  • Сеть под полным контролем: Можно ловить запросы к бэкенду и подсовывать им свои заглушки. Хочешь проверить, как фронт упадёт при ошибке 500? Легко. Это для изолированного тестирования просто бомба.

А теперь ложка дёгтя, или с чем можно обосраться:

  • Разобраться — та ещё задача: Сообщество поменьше, чем у того же Selenium. Документация вроде есть, но когда упираешься в сложную, нестандартную хрень, готовых решений можешь и не найти. Придётся самому ковыряться, блядь.
  • Со старьём не работает: Забудь про Internet Explorer или древние Safari. Если у вас на проекте такое наследство — тут только Selenium и молитва.
  • Отладка иногда — просто пиздец: Особенно когда у тебя несколько вкладок или контекстов крутятся. Бывает, сидишь и думаешь: "Ну в какой же момент оно всё пошло по пизде?" — и тратишь полдня на поиск одной строчки.

Вот, смотри, как это примерно выглядит в коде. Просто почувствуй разницу:

import re
from playwright.sync_api import sync_playwright, expect

def test_login_and_api_call():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()
        page = context.new_page()

        # Ловим апишку и подменяем ответ, пока пользователь даже не успел моргнуть
        page.route(
            re.compile(r".*/api/user/profile"),
            lambda route: route.fulfill(json={"name": "Test User"})
        )

        page.goto("https://example-app.com/login")
        # Магия auto-waiting: просто говорим "заполни" и "кликни", а он сам дождётся
        page.fill("#username", "test_user")
        page.fill("#password", "password123")
        page.click("button[type='submit']")

        # И проверяем результат — опять же, с умным ожиданием
        expect(page.locator(".user-profile")).to_have_text("Test User")

        browser.close()

Короче, инструмент — огонь. Но как и любой мощный инструмент, требует, чтобы руки росли из нужного места и голова думала. А то можно и так накрутить, что сам от себя охуеешь.