JavaScript

Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress

7 min de leitura

Guia Completo de Testes End-to-End em JavaScript com Playwright e Cypress

Introdução aos Testes End-to-End 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. 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. Primeiros Passos: Instalação e Configuração Setup Playwright Comece instalando Playwright e sua CLI: Crie seu primeiro teste em : Execute com . Setup Cypress Para Cypress, o processo é semelhante: Crie seu teste em : Estratégias de Escrita e Boas Práticas Seletores Robustos Use ao invés de classes CSS que podem mudar: Atualize seu HTML: Page Object

<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 &#039;@playwright/test&#039;;

test(&#039;deve fazer login com sucesso&#039;, async ({ page }) =&gt; {

await page.goto(&#039;https://exemplo.com/login&#039;);

await page.fill(&#039;input[name=&quot;email&quot;]&#039;, &#039;usuario@teste.com&#039;);

await page.fill(&#039;input[name=&quot;senha&quot;]&#039;, &#039;123456&#039;);

await page.click(&#039;button:has-text(&quot;Entrar&quot;)&#039;);

await expect(page).toHaveURL(&#039;https://exemplo.com/dashboard&#039;);

await expect(page.locator(&#039;h1&#039;)).toContainText(&#039;Bem-vindo&#039;);

});</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(&#039;Login&#039;, () =&gt; {

beforeEach(() =&gt; {

cy.visit(&#039;https://exemplo.com/login&#039;);

});

it(&#039;deve fazer login com sucesso&#039;, () =&gt; {

cy.get(&#039;input[name=&quot;email&quot;]&#039;).type(&#039;usuario@teste.com&#039;);

cy.get(&#039;input[name=&quot;senha&quot;]&#039;).type(&#039;123456&#039;);

cy.get(&#039;button&#039;).contains(&#039;Entrar&#039;).click();

cy.url().should(&#039;include&#039;, &#039;/dashboard&#039;);

cy.get(&#039;h1&#039;).should(&#039;contain&#039;, &#039;Bem-vindo&#039;);

});

});</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>&lt;button data-testid=&quot;login-button&quot;&gt;Entrar&lt;/button&gt;</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(&#039;[data-testid=&quot;email&quot;]&#039;);

this.senhaInput = page.locator(&#039;[data-testid=&quot;senha&quot;]&#039;);

this.loginButton = page.locator(&#039;[data-testid=&quot;login-btn&quot;]&#039;);

}

async login(email, senha) {

await this.emailInput.fill(email);

await this.senhaInput.fill(senha);

await this.loginButton.click();

}

}

// test.spec.js

import { LoginPage } from &#039;./pages/LoginPage&#039;;

test(&#039;login flow&#039;, async ({ page }) =&gt; {

const loginPage = new LoginPage(page);

await page.goto(&#039;https://exemplo.com/login&#039;);

await loginPage.login(&#039;user@teste.com&#039;, &#039;123456&#039;);

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(&#039;[data-testid=&quot;success-message&quot;]&#039;, { timeout: 5000 });

await expect(page.locator(&#039;[data-testid=&quot;success-message&quot;]&#039;)).toBeVisible();

// Cypress - espera automática por padrão

cy.get(&#039;[data-testid=&quot;success-message&quot;]&#039;).should(&#039;be.visible&#039;);</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(&#039;lista produtos sem chamar API real&#039;, async ({ page }) =&gt; {

await page.route(&#039;**/api/produtos&#039;, route =&gt; {

route.abort(&#039;blockedbyclient&#039;);

});

await page.goto(&#039;https://exemplo.com/produtos&#039;);

await expect(page.locator(&#039;p&#039;)).toContainText(&#039;Erro ao carregar produtos&#039;);

});

// Cypress

it(&#039;usa dados mockados&#039;, () =&gt; {

cy.intercept(&#039;GET&#039;, &#039;/api/usuarios&#039;, {

statusCode: 200,

body: [{ id: 1, nome: &#039;João&#039; }]

}).as(&#039;getUsers&#039;);

cy.visit(&#039;/usuarios&#039;);

cy.wait(&#039;@getUsers&#039;);

cy.contains(&#039;João&#039;).should(&#039;be.visible&#039;);

});</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: &#039;./tests&#039;,

webServer: {

command: &#039;npm run dev&#039;,

url: &#039;http://localhost:3000&#039;,

reuseExistingServer: !process.env.CI,

},

use: {

baseURL: &#039;http://localhost:3000&#039;,

screenshot: &#039;only-on-failure&#039;,

video: &#039;retain-on-failure&#039;,

},

});</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: &#039;18&#039;

  • run: npm ci &amp;&amp; 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>

Comentários

Mais em JavaScript

O que Todo Dev Deve Saber sobre DOM em JavaScript: Seleção, Manipulação e Traversal de Elementos
O que Todo Dev Deve Saber sobre DOM em JavaScript: Seleção, Manipulação e Traversal de Elementos

Seleção de Elementos no DOM A base de qualquer manipulação do DOM é saber loc...

Estruturas de Controle em JavaScript: if, switch e Tratamento de Fluxo: Do Básico ao Avançado
Estruturas de Controle em JavaScript: if, switch e Tratamento de Fluxo: Do Básico ao Avançado

Estruturas Condicionais: A Base da Lógica em JavaScript As estruturas de cont...

Como Usar Novidades do ECMAScript: ES2022, ES2023 e ES2024 na Prática em Produção
Como Usar Novidades do ECMAScript: ES2022, ES2023 e ES2024 na Prática em Produção

ES2022: Top-Level Await e Class Fields O ES2022 trouxe melhorias significativ...