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
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();
});
});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);
});
});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
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');
});
});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: 12Validaçã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
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'
});
}),
];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: 48Verificaçã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
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,
});
});
});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.