Vitrine de testes

Explore estratégias de teste do mundo real, exemplos de código e demos interativas. Cada seção cobre uma camada da pirâmide de testes com padrões de nível de produção que você pode aplicar nos seus projetos.

Testes de unidade

Cobertura: 92%

Testes rápidos e isolados com Vitest e React Testing Library

Os testes de unidade são a base da nossa pirâmide de testes. Com o Vitest para uma execução muito rápida e a React Testing Library para testes de componente, verificamos funções, hooks e componentes isolados. Todo componente deste projeto é coberto por testes de unidade focados, que validam comportamento e não detalhes de implementação.

🔒

Isolamento de testes

Cada teste roda de forma independente, com dependências simuladas, para resultados rápidos e determinísticos.

👤

Guiado por comportamento

Os testes verificam o que quem usa vê e faz, não detalhes internos de implementação.

🔄

Fluxo de TDD

O ciclo Vermelho → Verde → Refatorar conduz um desenvolvimento seguro e incremental.

Testes de exemplo

Teste de componente com React Testing Librarytypescript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect } from 'vitest';
import TDDPlayground from './TDDPlayground';

describe('TDDPlayground', () => {
  it('renders the exercise selector', () => {
    render(<TDDPlayground />);
    expect(
      screen.getByText(/select an exercise/i)
    ).toBeInTheDocument();
  });

  it('transitions through TDD phases', async () => {
    const user = userEvent.setup();
    render(<TDDPlayground />);

    // Start in RED phase
    expect(screen.getByText(/red/i)).toBeInTheDocument();

    // Run failing test → GREEN phase
    await user.click(screen.getByText(/run tests/i));
    expect(screen.getByText(/green/i)).toBeInTheDocument();
  });
});
Teste de hook customizadotypescript
import { renderHook, act } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { useTestRunner } from '@/hooks/useTestRunner';

describe('useTestRunner', () => {
  it('initializes with idle status', () => {
    const { result } = renderHook(() => useTestRunner());
    expect(result.current.status).toBe('idle');
    expect(result.current.results).toEqual([]);
  });

  it('runs tests and updates results', async () => {
    const { result } = renderHook(() => useTestRunner());

    await act(async () => {
      await result.current.runTests('return 2 + 2;');
    });

    expect(result.current.status).toBe('complete');
    expect(result.current.results.length).toBeGreaterThan(0);
  });
});
Testes do motor de asserçõestypescript
import { describe, it, expect } from 'vitest';
import { createExpect } from '@/lib/test-runner/assertions';

describe('Assertion Engine', () => {
  it('validates equality assertions', () => {
    const assertion = createExpect(42);
    expect(() => assertion.toBe(42)).not.toThrow();
    expect(() => assertion.toBe(99)).toThrow();
  });

  it('validates deep equality', () => {
    const obj = { name: 'test', items: [1, 2, 3] };
    const assertion = createExpect(obj);
    expect(() => assertion.toEqual({ name: 'test', items: [1, 2, 3] }))
      .not.toThrow();
  });
});

🎮 Experimente: playground de TDD

Viva o ciclo Vermelho-Verde-Refatorar de forma interativa. Escreva um teste que falha, faça-o passar e depois refatore.

Testes ponta a ponta

Taxa de aprovação: 100%

Validação de fluxos completos com Playwright

Os testes ponta a ponta validam fluxos completos de uso em toda a pilha da aplicação. Com o Playwright, automatizamos interações reais no navegador (navegar, clicar, preencher formulários e verificar o que aparece) para pegar problemas de integração que só os testes de unidade não enxergam.

🌍

Testes em vários navegadores

Rode os testes no Chromium, no Firefox e no WebKit para garantir um comportamento consistente entre navegadores.

⏳

Espera automática

O Playwright espera sozinho os elementos ficarem acionáveis, eliminando esperas fixas instáveis.

🔌

Interceptação de rede

Simule respostas de API e condições de rede para resultados determinísticos.

🔍

Trace Viewer

Depure testes que falharam com capturas de tela passo a passo, instantâneos do DOM e logs de rede.

Specs de exemplo

Navegação e teste de fumaçatypescript
import { test, expect } from '@playwright/test';

test.describe('Site Navigation', () => {
  test('navigates to all main pages', async ({ page }) => {
    await page.goto('/');

    // Verify homepage loads
    await expect(
      page.getByText('Test Automation Lab')
    ).toBeVisible();

    // Navigate to playgrounds
    await page.getByRole('link', { name: /playgrounds/i }).click();
    await expect(page).toHaveURL('/praticar');
    await expect(
      page.getByText('Interactive Test Playgrounds')
    ).toBeVisible();

    // Navigate to testing showcase
    await page.getByRole('link', { name: /testing/i }).click();
    await expect(page).toHaveURL('/qualidade');
  });
});
E2E de playground interativotypescript
import { test, expect } from '@playwright/test';

test.describe('TDD Playground', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/praticar/playgrounds/tdd');
  });

  test('completes a full TDD cycle', async ({ page }) => {
    // Select an exercise
    await page.getByTestId('exercise-selector').click();
    await page.getByText(/string calculator/i).click();

    // Write test code in the editor
    const editor = page.getByTestId('test-editor');
    await expect(editor).toBeVisible();

    // Run tests — expect RED phase
    await page.getByTestId('run-tests-btn').click();
    await expect(page.getByTestId('phase-indicator'))
      .toContainText('RED');

    // Write implementation → GREEN phase
    await page.getByTestId('run-tests-btn').click();
    await expect(page.getByTestId('phase-indicator'))
      .toContainText('GREEN');
  });
});

🚀 Integração com o CI

Os testes E2E rodam automaticamente em todo pull request pelo GitHub Actions. O pipeline usa o sharding nativo do Playwright para rodar os testes em paralelo em vários workers, mantendo o retorno rápido mesmo com a suíte crescendo.

Testes de API

Endpoints: 12

Validação de requisição/resposta e testes de contrato

Os testes de API validam o contrato entre o frontend e os serviços de backend. Usamos o MSW (Mock Service Worker) para interceptar requisições no nível do service worker, o que permite testes de integração realistas sem um servidor rodando. Essa abordagem testa o ciclo completo da requisição: cabeçalhos, payloads, códigos de status e tratamento de erros.

📋

Testes de contrato

Verifique se o formato de requisição e resposta bate com o contrato esperado da API.

⚠️

Cenários de erro

Teste respostas 4xx/5xx, timeouts e falhas de rede com elegância.

🔧

Mock Service Worker

Intercepte requisições na camada de rede para testes de integração realistas.

Testes de exemplo

Handler de requisição do MSWtypescript
import { http, HttpResponse } from 'msw';

export const handlers = [
  // Mock GET /api/users
  http.get('/api/users', () => {
    return HttpResponse.json([
      { id: 1, name: 'Alice', role: 'admin' },
      { id: 2, name: 'Bob', role: 'user' },
    ]);
  }),

  // Mock POST /api/users
  http.post('/api/users', async ({ request }) => {
    const body = await request.json();
    return HttpResponse.json(
      { id: 3, ...body },
      { status: 201 }
    );
  }),

  // Mock error scenarios
  http.get('/api/users/:id', ({ params }) => {
    if (params.id === '999') {
      return HttpResponse.json(
        { error: 'User not found' },
        { status: 404 }
      );
    }
    return HttpResponse.json({
      id: params.id, name: 'Test User'
    });
  }),
];
Teste de integração de APItypescript
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { setupServer } from 'msw/node';
import { handlers } from './msw/handlers';

const server = setupServer(...handlers);

beforeAll(() => server.listen());
afterAll(() => server.close());

describe('API Testing Sandbox Integration', () => {
  it('fetches and displays user list', async () => {
    const response = await fetch('/api/users');
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data).toHaveLength(2);
    expect(data[0]).toHaveProperty('name', 'Alice');
  });

  it('handles 404 errors gracefully', async () => {
    const response = await fetch('/api/users/999');
    expect(response.status).toBe(404);

    const data = await response.json();
    expect(data.error).toBe('User not found');
  });
});

🎮 Experimente: sandbox de testes de API

Envie requisições a endpoints de API simulados e inspecione as respostas em tempo real. Experimente métodos HTTP, cabeçalhos e payloads diferentes.

Testes de regressão visual

Capturas: 48

Verificação de interface pixel a pixel entre navegadores

Os testes de regressão visual pegam mudanças de interface não intencionais comparando capturas de tela com referências aprovadas. Com a comparação de capturas nativa do Playwright, verificamos que os componentes são renderizados de forma idêntica entre navegadores e tamanhos de tela. Isso pega regressões de CSS, deslocamentos de layout e bugs de estilo que os testes funcionais deixam passar.

📸

Capturas de referência

Capture referências aprovadas para toda página e componente crítico.

🔬

Comparação de pixels

Detecte diferenças de subpixel com limites configuráveis para controlar a sensibilidade.

📱

Verificações responsivas

Teste em celular, tablet e desktop para pegar regressões de layout.

🌙

Validação do modo escuro

Garanta que os temas sejam renderizados corretamente com a emulação de color-scheme.

Specs de exemplo

Teste de captura visualtypescript
import { test, expect } from '@playwright/test';

test.describe('Visual Regression', () => {
  test('homepage matches baseline', async ({ page }) => {
    await page.goto('/');
    await page.waitForLoadState('networkidle');

    await expect(page).toHaveScreenshot('homepage.png', {
      maxDiffPixelRatio: 0.01,
      animations: 'disabled',
    });
  });

  test('playgrounds page matches baseline', async ({ page }) => {
    await page.goto('/praticar');
    await page.waitForLoadState('networkidle');

    await expect(page).toHaveScreenshot('playgrounds.png', {
      maxDiffPixelRatio: 0.01,
    });
  });

  test('dark mode renders correctly', async ({ page }) => {
    await page.emulateMedia({ colorScheme: 'dark' });
    await page.goto('/');
    await page.waitForLoadState('networkidle');

    await expect(page).toHaveScreenshot('homepage-dark.png', {
      maxDiffPixelRatio: 0.01,
    });
  });
});
Comparação visual de componentetypescript
import { test, expect } from '@playwright/test';

test.describe('Component Visual Tests', () => {
  const viewports = [
    { width: 375, height: 812, name: 'mobile' },
    { width: 768, height: 1024, name: 'tablet' },
    { width: 1440, height: 900, name: 'desktop' },
  ];

  for (const viewport of viewports) {
    test(`framework comparison at ${viewport.name}`,
      async ({ page }) => {
        await page.setViewportSize({
          width: viewport.width,
          height: viewport.height,
        });
        await page.goto('/praticar/playgrounds/frameworks');
        await page.waitForLoadState('networkidle');

        await expect(page).toHaveScreenshot(
          `frameworks-${viewport.name}.png`
        );
      }
    );
  }
});

🎮 Experimente: comparação de frameworks

Compare frameworks de teste lado a lado. Veja como Playwright, Cypress e outras ferramentas enfrentam os mesmos desafios de teste.