<h2>Introdução aos Testes End-to-End</h2>
<p>Testes end-to-end (E2E) verificam sua aplicação como um usuário real faria: abrindo o navegador, clicando em botões, preenchendo formulários e validando resultados. Diferente de testes unitários que isolam funções, E2E testa fluxos completos da aplicação. Playwright e Cypress são as ferramentas mais populares para isso em JavaScript, cada uma com suas vantagens estratégicas.</p>
<p>Playwright é mantido pelo Google, suporta múltiplos navegadores (Chrome, Firefox, Safari) e é extremamente rápido. Cypress oferece uma experiência visual superior com debugging interativo e é mais intuitivo para iniciantes. Escolher entre elas depende do seu projeto, mas ambas resolvem o mesmo problema com abordagens diferentes.</p>
<h2>Primeiros Passos: Instalação e Configuração</h2>
<h3>Setup Playwright</h3>
<p>Comece instalando Playwright e sua CLI:</p>
<pre><code class="language-bash">npm install -D @playwright/test
npx playwright install</code></pre>
<p>Crie seu primeiro teste em <code>tests/exemplo.spec.ts</code>:</p>
<pre><code class="language-javascript">import { test, expect } from '@playwright/test';
test('deve fazer login com sucesso', async ({ page }) => {
await page.goto('https://exemplo.com/login');
await page.fill('input[name="email"]', 'usuario@teste.com');
await page.fill('input[name="senha"]', '123456');
await page.click('button:has-text("Entrar")');
await expect(page).toHaveURL('https://exemplo.com/dashboard');
await expect(page.locator('h1')).toContainText('Bem-vindo');
});</code></pre>
<p>Execute com <code>npx playwright test</code>.</p>
<h3>Setup Cypress</h3>
<p>Para Cypress, o processo é semelhante:</p>
<pre><code class="language-bash">npm install -D cypress
npx cypress open</code></pre>
<p>Crie seu teste em <code>cypress/e2e/login.cy.js</code>:</p>
<pre><code class="language-javascript">describe('Login', () => {
beforeEach(() => {
cy.visit('https://exemplo.com/login');
});
it('deve fazer login com sucesso', () => {
cy.get('input[name="email"]').type('usuario@teste.com');
cy.get('input[name="senha"]').type('123456');
cy.get('button').contains('Entrar').click();
cy.url().should('include', '/dashboard');
cy.get('h1').should('contain', 'Bem-vindo');
});
});</code></pre>
<h2>Estratégias de Escrita e Boas Práticas</h2>
<h3>Seletores Robustos</h3>
<p>Use <code>data-testid</code> ao invés de classes CSS que podem mudar:</p>
<pre><code class="language-javascript"></code></pre>
<p>Atualize seu HTML: <code><button data-testid="login-button">Entrar</button></code></p>
<h3>Page Object Model</h3>
<p>Organize testes complexos separando lógica de página em classes:</p>
<pre><code class="language-javascript">// pages/LoginPage.js
export class LoginPage {
constructor(page) {
this.page = page;
this.emailInput = page.locator('[data-testid="email"]');
this.senhaInput = page.locator('[data-testid="senha"]');
this.loginButton = page.locator('[data-testid="login-btn"]');
}
async login(email, senha) {
await this.emailInput.fill(email);
await this.senhaInput.fill(senha);
await this.loginButton.click();
}
}
// test.spec.js
import { LoginPage } from './pages/LoginPage';
test('login flow', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto('https://exemplo.com/login');
await loginPage.login('user@teste.com', '123456');
await expect(page).toHaveURL(/.*dashboard/);
});</code></pre>
<h3>Esperas Inteligentes</h3>
<p>Evite <code>sleep()</code>. Use esperas explícitas que observam elementos:</p>
<pre><code class="language-javascript">// Playwright - espera por elemento estar visível
await page.waitForSelector('[data-testid="success-message"]', { timeout: 5000 });
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
// Cypress - espera automática por padrão
cy.get('[data-testid="success-message"]').should('be.visible');</code></pre>
<h2>Testes Avançados e CI/CD</h2>
<h3>Testando APIs e Mocks</h3>
<p>Intercepte requisições para acelerar testes:</p>
<pre><code class="language-javascript">// Playwright
test('lista produtos sem chamar API real', async ({ page }) => {
await page.route('**/api/produtos', route => {
route.abort('blockedbyclient');
});
await page.goto('https://exemplo.com/produtos');
await expect(page.locator('p')).toContainText('Erro ao carregar produtos');
});
// Cypress
it('usa dados mockados', () => {
cy.intercept('GET', '/api/usuarios', {
statusCode: 200,
body: [{ id: 1, nome: 'João' }]
}).as('getUsers');
cy.visit('/usuarios');
cy.wait('@getUsers');
cy.contains('João').should('be.visible');
});</code></pre>
<h3>Integração com CI/CD</h3>
<p>Configure no seu <code>playwright.config.ts</code>:</p>
<pre><code class="language-javascript">export default defineConfig({
testDir: './tests',
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
use: {
baseURL: 'http://localhost:3000',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
});</code></pre>
<p>Configure no GitHub Actions (<code>.github/workflows/e2e.yml</code>):</p>
<pre><code class="language-yaml">name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci && npx playwright install
- run: npm run test:e2e
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/</code></pre>
<h2>Conclusão</h2>
<p><strong>Três pilares para dominar E2E:</strong> (1) Escolha a ferramenta conforme seu contexto — Playwright para velocidade e múltiplos navegadores, Cypress para experiência visual; (2) Use Page Object Model e <code>data-testid</code> para testes mantíveis que sobrevivem a mudanças CSS; (3) Integre ao seu pipeline CI/CD desde o início, capturando screenshots/vídeos de falhas.</p>
<p>A diferença entre um projeto robusto e frágil está na disciplina de escrita desde o primeiro teste. Comece simples, automatize fluxos críticos, e expanda gradualmente sua cobertura.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://playwright.dev" target="_blank" rel="noopener noreferrer">Documentação oficial Playwright</a></li>
<li><a href="https://docs.cypress.io" target="_blank" rel="noopener noreferrer">Documentação oficial Cypress</a></li>
<li><a href="https://frontendmasters.com" target="_blank" rel="noopener noreferrer">Best Practices for E2E Testing - Frontend Masters</a></li>
<li><a href="https://testing-library.com/docs/queries/about" target="_blank" rel="noopener noreferrer">Testing Library - Query Priority Guide</a></li>
<li><a href="https://kentcdodds.com/blog/the-testing-trophy-and-testing-javascript" target="_blank" rel="noopener noreferrer">Kent C. Dodds - The Testing Trophy</a></li>
</ul>