Ответ
Плюсы с точки зрения инженера по автоматизации:
- Кроссплатформенность и поддержка браузеров: Единый 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()
Короче, инструмент — огонь. Но как и любой мощный инструмент, требует, чтобы руки росли из нужного места и голова думала. А то можно и так накрутить, что сам от себя охуеешь.