Para automatizar ou testar um navegador com Python, instale o Playwright, baixe os binários, abra uma página e interaja por meio de locators. A biblioteca cuida de grande parte das esperas antes de clicar ou preencher, enquanto expect valida estados visíveis para o usuário. Downloads e screenshots têm APIs próprias, e a integração com pytest permite isolar cada teste. O resultado é mais confiável do que scripts baseados em coordenadas, seletores frágeis e pausas fixas.
Playwright controla Chromium, Firefox e WebKit com uma API consistente. Ele é útil em testes de ponta a ponta, verificações de regressão e automações internas autorizadas. Para fundamentos de testes, consulte o guia de pytest em Python; para automação fora do navegador, veja automação de tarefas com Python.
Instalação e primeiro script
Crie um ambiente virtual Python e instale o pacote e um navegador:
python -m pip install playwright pytest pytest-playwright
python -m playwright install chromium
O segundo comando instala o navegador compatível com a versão da biblioteca. Em CI Linux, python -m playwright install --with-deps chromium também instala dependências do sistema. A documentação oficial do Playwright para Python mantém instruções por plataforma.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com", wait_until="domcontentloaded")
print(page.title())
page.screenshot(path="evidencia.png", full_page=True)
browser.close()
O modo síncrono é direto para scripts e pytest. A API assíncrona é apropriada quando a aplicação já usa asyncio; nesse caso, use async_playwright e await, seguindo os conceitos de async e await em Python. Não misture as duas APIs no mesmo fluxo.
Locators resistentes a mudanças
Um locator representa uma forma de encontrar elementos e é resolvido novamente a cada ação. Prefira atributos percebidos pelo usuário ou contratos explícitos de teste:
page.get_by_role("textbox", name="E-mail").fill("[email protected]")
page.get_by_label("Senha").fill("segredo-de-teste")
page.get_by_role("button", name="Entrar").click()
page.get_by_test_id("menu-perfil").click()
get_by_role aproxima o teste da acessibilidade e evita acoplamento à estrutura do HTML. get_by_label, get_by_placeholder e get_by_text expressam a interface. data-testid é uma boa saída quando o texto varia ou não existe papel acessível. CSS ainda é válido para casos específicos, mas seletores como div:nth-child(4) > span quebram quando o layout muda.
Locators são estritos: uma ação que encontra dois elementos falha em vez de escolher silenciosamente. Restrinja o escopo com filter, get_by_role encadeado ou um contêiner significativo. Evite .first apenas para esconder ambiguidade; torne a intenção do teste inequívoca.
Esperas sem pausas arbitrárias
Antes de agir, Playwright verifica se o elemento está visível, estável, habilitado e apto a receber eventos. Esse auto-waiting elimina muitos time.sleep. Para validar o resultado, use as asserções que tentam novamente até o prazo:
from playwright.sync_api import expect
page.get_by_role("button", name="Salvar").click()
expect(page.get_by_role("status")).to_have_text("Dados salvos")
expect(page).to_have_url("**/conta")
Espere o efeito relevante, não um intervalo escolhido por tentativa. Para uma resposta específica, envolva a ação com page.expect_response; para uma nova aba, use page.expect_popup. wait_for_load_state("networkidle") não deve ser uma regra geral, pois páginas com telemetria ou conexões persistentes podem nunca ficar ociosas. A asserção sobre o estado final comunica melhor o requisito.
Timeouts globais muito altos tornam falhas lentas. Mantenha um limite razoável e ajuste somente operações realmente demoradas. Se o sistema é instável, investigue a causa em vez de acumular esperas.
Downloads e screenshots
Capture o evento de download antes do clique para não perder uma conclusão rápida:
from pathlib import Path
with page.expect_download() as info:
page.get_by_role("link", name="Baixar relatório").click()
download = info.value
destino = Path("artifacts") / download.suggested_filename
destino.parent.mkdir(exist_ok=True)
download.save_as(destino)
assert destino.stat().st_size > 0
Em testes, prefira o diretório temporário do pytest e valide conteúdo, extensão ou cabeçalhos, não somente a existência. Nunca confie cegamente no nome sugerido para gravar arquivos em locais sensíveis.
Screenshots ajudam a diagnosticar, mas não substituem asserções. É possível capturar a página inteira, um locator ou uma imagem com animações desativadas:
page.screenshot(path="falha.png", full_page=True)
page.get_by_test_id("resumo").screenshot(path="resumo.png")
Não publique capturas com senhas, tokens, dados pessoais ou informações de clientes. Defina retenção curta para artifacts de CI e use contas com dados fictícios.
Testes com pytest
O plugin pytest-playwright fornece a fixture page e encerra os recursos. Um teste pequeno fica assim:
from playwright.sync_api import Page, expect
def test_pagina_exibe_titulo(page: Page) -> None:
page.goto("https://example.com")
expect(page.get_by_role("heading", name="Example Domain")).to_be_visible()
Execute com pytest --browser chromium. Configure a URL base e tracing no projeto quando houver vários testes. Cada caso deve criar seu próprio estado; autenticação reutilizável pode ser salva em storage_state, mas o arquivo contém credenciais e deve ficar fora do Git. Para organizar fixtures e parametrização, o artigo de testes automatizados com pytest aprofunda essas práticas.
Teste comportamento observável. Uma sequência enorme que cadastra, edita, exporta e exclui dados é difícil de diagnosticar. Divida cenários, prepare dados por APIs autorizadas quando possível e reserve a interface para aquilo que precisa ser comprovado pela interface.
Ética, segurança e limites
Capacidade técnica não equivale a permissão. Automatize sistemas próprios ou para os quais exista autorização clara. Leia termos de uso, respeite limites de requisição e não use Playwright para contornar CAPTCHA, bloqueios, autenticação, paywalls ou controles de acesso. Minimize dados coletados e cumpra regras de privacidade.
Use contas de teste com privilégio mínimo, segredos no gerenciador da CI e ambientes separados de produção. Se uma automação repetitiva pode sobrecarregar um serviço, aplique concorrência limitada e interrupção diante de erros. Para extração legítima de conteúdo público, avalie primeiro uma API; o guia de web scraping com Python discute escolhas e cuidados adicionais.
Controle o estado e reproduza falhas
Cada contexto do navegador é uma sessão isolada, com cookies, armazenamento local, permissões, idioma e viewport próprios. Crie um contexto novo para cenários independentes em vez de limpar estado manualmente. Quando o fluxo exigir autenticação prévia, gere o storage_state em uma preparação autorizada, proteja o arquivo resultante como credencial e limite sua validade. Não compartilhe um contexto mutável entre testes paralelos, pois navegação, diálogos e alterações de sessão podem interferir entre si.
Registre no projeto as premissas do ambiente. Fixe idioma e fuso horário quando a formatação afetar as verificações, escolha um viewport representativo e conceda somente as permissões necessárias. Simular todas as respostas pode deixar a suíte rápida, mas incapaz de detectar defeitos de integração. Reserve a interceptação de rotas para dependências controladas e cenários de erro explícitos, mantendo um conjunto menor de testes contra um ambiente realista.
O tracing do Playwright registra ações, snapshots, rede e locais no código. Ative traces em novas tentativas ou falhas, evitando guardar indefinidamente todas as execuções bem-sucedidas. A documentação oficial do Trace Viewer mostra como inspecioná-los. Trate os arquivos como sensíveis, pois podem conter texto da página, URLs, cabeçalhos e dados de sessão.
Erros comuns e checklist
- Não use
time.sleeppara sincronização normal; espere um estado ou evento. - Não baseie seletores em classes geradas ou posição no DOM.
- Não compartilhe página e dados mutáveis entre testes paralelos.
- Não trate screenshot como prova funcional sem asserções.
- Não registre credenciais, cookies ou dados pessoais em traces.
- Instale no CI a mesma família de navegador definida no projeto.
- Use locators por papel, rótulo ou contrato de teste.
- Valide o conteúdo dos downloads em diretório temporário.
- Guarde traces e imagens apenas quando necessários.
- Confirme autorização e impacto antes de automatizar.
Uma suíte confiável combina locators semânticos, esperas orientadas a estado, testes independentes e evidências protegidas. Comece por um fluxo crítico curto, rode-o localmente e na CI, examine qualquer intermitência e só então amplie a cobertura.