Skip to Content
DocumentaçãoGuiasTesting Guide

Guia de Testes do Synkra AIOS

EN | PT | ES


Guia completo sobre a estratégia de testes, ferramentas e melhores práticas do Synkra AIOS.

Versão: 2.1.0 Última Atualização: 2026-01-29


Índice

  1. Visão Geral
  2. Estratégia de Testes
  3. Testes Unitários
  4. Testes de Integração
  5. Testes End-to-End
  6. Testes de Agentes
  7. Testes Cross-Platform
  8. Cobertura e Métricas
  9. Integração CI/CD
  10. Escrevendo Bons Testes
  11. Mocking e Fixtures
  12. Referência de Comandos NPM
  13. Resolução de Problemas

Visão Geral

O AIOS segue uma estratégia abrangente de testes que garante qualidade de código em todas as camadas do framework. Nossa filosofia de testes é baseada em:

  • Test-Driven Development (TDD) para funcionalidades core
  • Testes em Camadas com testes unitários, de integração e E2E
  • Verificação Cross-Platform para Windows, macOS e Linux
  • Testes Específicos de Agentes para comportamentos de agentes de IA
  • Quality Gates Automatizados integrados com CI/CD

Pirâmide de Testes

┌─────────────┐ │ E2E │ ← Poucos, Lentos, Caros │ Tests │ ├─────────────┤ │ Integration │ ← Alguns, Velocidade Média │ Tests │ ├─────────────┤ │ Unit │ ← Muitos, Rápidos, Baratos │ Tests │ └─────────────┘
CamadaQuantidadeVelocidadeMeta de Cobertura
Unitários100+< 30s80%+ de linhas
Integração30-501-5mCaminhos críticos
E2E10-205-15mFluxos de usuário

Estratégia de Testes

Estrutura de Diretórios

tests/ ├── unit/ # Testes unitários │ ├── quality-gates/ # Componentes de quality gate │ ├── squad/ # Testes do sistema de squads │ ├── mcp/ # Testes de configuração MCP │ ├── manifest/ # Testes de manipulação de manifest │ └── documentation-integrity/ # Testes do gerador de docs ├── integration/ # Testes de integração │ ├── squad/ # Integração do squad designer │ ├── windows/ # Testes específicos do Windows │ └── *.test.js # Testes gerais de integração ├── e2e/ # Testes end-to-end │ └── story-creation-clickup.test.js ├── performance/ # Benchmarks de performance │ ├── decision-logging-benchmark.test.js │ └── tools-system-benchmark.test.js ├── security/ # Testes de segurança │ └── core-security.test.js ├── health-check/ # Testes do sistema de health check │ ├── engine.test.js │ └── healers.test.js ├── regression/ # Testes de regressão │ └── tools-migration.test.js ├── setup.js # Setup global de testes └── fixtures/ # Fixtures e mocks de teste

Convenção de Nomenclatura de Testes

TipoPadrãoExemplo
Unitário*.test.js ou *.spec.jsgreeting-builder.test.js
Integração*.test.js em integration/contextual-greeting.test.js
E2E*.test.js em e2e/story-creation-clickup.test.js
Benchmark*-benchmark.test.jsdecision-logging-benchmark.test.js

Testes Unitários

Testes unitários verificam funções e classes individuais de forma isolada.

Configuração (jest.config.js)

module.exports = { testEnvironment: 'node', coverageDirectory: 'coverage', testMatch: [ '**/tests/**/*.test.js', '**/tests/**/*.spec.js', '**/.aios-core/**/__tests__/**/*.test.js', ], testTimeout: 30000, verbose: true, setupFilesAfterEnv: ['<rootDir>/tests/setup.js'], coverageThreshold: { global: { branches: 25, functions: 30, lines: 30, statements: 30, }, '.aios-core/core/': { lines: 45, }, }, };

Escrevendo Testes Unitários

/** * Testes Unitários do Quality Gate Manager * * @story 2.10 - Quality Gate Manager */ const { QualityGateManager, } = require('../../../.aios-core/core/quality-gates/quality-gate-manager'); describe('QualityGateManager', () => { let manager; beforeEach(() => { manager = new QualityGateManager({ layer1: { enabled: true }, layer2: { enabled: true }, layer3: { enabled: true }, }); }); describe('constructor', () => { it('deve criar manager com config padrão', () => { const defaultManager = new QualityGateManager(); expect(defaultManager).toBeDefined(); expect(defaultManager.layers).toBeDefined(); }); it('deve criar manager com config personalizada', () => { const customManager = new QualityGateManager({ layer1: { enabled: false }, }); expect(customManager.layers.layer1.enabled).toBe(false); }); }); describe('runLayer', () => { it('deve lançar erro para número de camada inválido', async () => { await expect(manager.runLayer(4)).rejects.toThrow('Invalid layer number: 4'); }); }); describe('formatDuration', () => { it('deve formatar milissegundos', () => { expect(manager.formatDuration(500)).toBe('500ms'); }); it('deve formatar segundos', () => { expect(manager.formatDuration(5000)).toBe('5.0s'); }); it('deve formatar minutos', () => { expect(manager.formatDuration(120000)).toBe('2.0m'); }); }); });

Melhores Práticas de Organização de Testes

describe('ComponentName', () => { // Setup e teardown beforeAll(() => { /* Setup global */ }); afterAll(() => { /* Limpeza global */ }); beforeEach(() => { /* Setup por teste */ }); afterEach(() => { /* Limpeza por teste */ }); // Agrupar por método/funcionalidade describe('methodName', () => { it('deve tratar entrada válida', () => {}); it('deve lançar erro com entrada inválida', () => {}); it('deve tratar casos extremos', () => {}); }); describe('outro método', () => { // Mais testes... }); });

Testes de Integração

Testes de integração verificam se múltiplos componentes funcionam corretamente juntos.

Setup para Testes de Integração

// tests/setup.js process.env.NODE_ENV = 'test'; process.env.AIOS_DEBUG = 'false'; // Pular testes de integração por padrão if (process.env.SKIP_INTEGRATION_TESTS === undefined) { process.env.SKIP_INTEGRATION_TESTS = 'true'; } // Timeout global de teste (aumentado para CI) jest.setTimeout(process.env.CI ? 30000 : 10000); // Helper para pular testes de integração condicionalmente global.describeIntegration = process.env.SKIP_INTEGRATION_TESTS === 'true' ? describe.skip : describe; global.testIntegration = process.env.SKIP_INTEGRATION_TESTS === 'true' ? test.skip : test;

Escrevendo Testes de Integração

/** * Testes de Integração para Sistema de Saudação Contextual * * Testes end-to-end de: * - Todos os 3 tipos de sessão * - Git configurado vs não configurado * - Filtragem de visibilidade de comandos * - Cenários de fallback */ const GreetingBuilder = require('../../.aios-core/development/scripts/greeting-builder'); describe('Testes de Integração de Saudação Contextual', () => { let builder; beforeEach(() => { builder = new GreetingBuilder(); }); describeIntegration('Geração de Saudação End-to-End', () => { test('deve gerar saudação completa para nova sessão', async () => { const greeting = await builder.build({ sessionType: 'new', agent: 'dev', gitConfigured: true, }); expect(greeting).toContain('Welcome'); expect(greeting).toContain('Quick Commands'); }); test('deve tratar git não configurado graciosamente', async () => { const greeting = await builder.build({ sessionType: 'new', agent: 'dev', gitConfigured: false, }); expect(greeting).not.toContain('git commit'); }); }); });

Executando Testes de Integração

# Executar todos os testes incluindo integração SKIP_INTEGRATION_TESTS=false npm test # Executar apenas testes de integração npm test -- --testPathPattern=integration # Executar teste de integração específico npm test -- tests/integration/contextual-greeting.test.js

Testes End-to-End

Testes E2E verificam fluxos completos de usuário do início ao fim.

Estrutura de Teste E2E

/** * Teste E2E: Criação de Story com ClickUp * * Testa o fluxo completo: * 1. Usuário inicia criação de story * 2. Story é gerada a partir de template * 3. Story é sincronizada com ClickUp * 4. Arquivo local é atualizado com ID do ClickUp */ describe('Story Creation E2E', () => { const TEST_PROJECT = 'test-project'; beforeAll(async () => { // Configurar ambiente de teste await setupTestProject(TEST_PROJECT); }); afterAll(async () => { // Limpar artefatos de teste await cleanupTestProject(TEST_PROJECT); }); test('deve criar story e sincronizar com ClickUp', async () => { // Passo 1: Criar story const story = await createStory({ title: 'Test Story', type: 'feature', }); expect(story.id).toBeDefined(); expect(story.file).toMatch(/\.md$/); // Passo 2: Verificar sincronização com ClickUp const clickupTask = await getClickUpTask(story.clickupId); expect(clickupTask.name).toBe('Test Story'); // Passo 3: Verificar atualização do arquivo local const localContent = await readFile(story.file); expect(localContent).toContain(story.clickupId); }, 60000); // Timeout estendido para E2E });

Melhores Práticas de Testes E2E

PráticaDescrição
Ambiente IsoladoCada teste E2E deve ter seus próprios dados
Limpeza ExplícitaSempre limpar recursos criados
Timeouts EstendidosTestes E2E precisam de timeouts maiores (30-60s)
Serviços ReaisUsar serviços reais, não mocks
IdempotenteTestes devem ser repetíveis

Testes de Agentes

Testar agentes de IA requer considerações especiais para comportamento de persona e execução de comandos.

Categorias de Testes de Agentes

CategoriaTestaPropósito
PersonaEstilo de resposta, tomVerificar se agente mantém personagem
ComandosExecução de tarefasVerificar se comandos funcionam
FallbackTratamento de errosVerificar degradação graciosa
CompatibilidadeSuporte legadoVerificar se agentes antigos funcionam

Testes de Compatibilidade de Agentes

/** * Testes de Compatibilidade Retroativa de Agentes * * Garante que agentes de versões anteriores do AIOS continuem funcionando. */ const { loadAgent } = require('../../.aios-core/core/registry/agent-loader'); describe('Compatibilidade Retroativa de Agentes', () => { describe('Formato de Agente Legado (v1.x)', () => { test('deve carregar agente sem metadados de visibilidade', async () => { const agent = await loadAgent('legacy-agent-v1'); expect(agent).toBeDefined(); expect(agent.name).toBeDefined(); expect(agent.commands).toBeDefined(); }); test('deve aplicar visibilidade padrão quando ausente', async () => { const agent = await loadAgent('legacy-agent-v1'); // Visibilidade padrão deve ser aplicada agent.commands.forEach((cmd) => { expect(cmd.visibility).toBeDefined(); }); }); }); describe('Formato de Agente Atual (v2.x)', () => { test('deve carregar agente com metadados completos', async () => { const agent = await loadAgent('dev'); expect(agent.slashPrefix).toBeDefined(); expect(agent.icon).toBeDefined(); expect(agent.persona).toBeDefined(); }); }); });

Testando Comandos de Agentes

describe('Comandos de Agentes', () => { let agent; beforeAll(async () => { agent = await activateAgent('dev'); }); test('*help deve exibir comandos disponíveis', async () => { const result = await agent.executeCommand('*help'); expect(result.output).toContain('Available Commands'); expect(result.exitCode).toBe(0); }); test('*create-story deve validar campos obrigatórios', async () => { await expect(agent.executeCommand('*create-story')).rejects.toThrow( 'Missing required field: title' ); }); });

Testes Cross-Platform

O AIOS suporta Windows, macOS e Linux. Testes cross-platform garantem comportamento consistente.

Arquivos de Teste Específicos por Plataforma

tests/ ├── integration/ │ ├── windows/ │ │ └── shell-compat.test.js # Testes de shell Windows │ ├── macos/ │ │ └── permission.test.js # Testes de permissão macOS │ └── linux/ │ └── symlink.test.js # Testes de symlink Linux

Utilitários de Teste Cross-Platform

/** * Utilitários de teste cross-platform */ const os = require('os'); const path = require('path'); const isWindows = process.platform === 'win32'; const isMacOS = process.platform === 'darwin'; const isLinux = process.platform === 'linux'; // describe específico por plataforma const describeWindows = isWindows ? describe : describe.skip; const describeMacOS = isMacOS ? describe : describe.skip; const describeLinux = isLinux ? describe : describe.skip; // Normalizar separadores de path para asserções function normalizePath(p) { return p.replace(/\\/g, '/'); } // Obter diretório temporário apropriado para a plataforma function getTempDir() { return path.join(os.tmpdir(), 'aios-tests'); } module.exports = { isWindows, isMacOS, isLinux, describeWindows, describeMacOS, describeLinux, normalizePath, getTempDir, };

Testes Específicos do Windows

/** * Testes de Compatibilidade de Shell Windows */ const { describeWindows } = require('../utils/platform'); describeWindows('Compatibilidade de Shell Windows', () => { test('deve tratar separadores de path do Windows', () => { const path = 'C:\\Users\\test\\project'; const normalized = normalizePath(path); expect(normalized).toBe('C:/Users/test/project'); }); test('deve executar comandos PowerShell', async () => { const result = await executeShell('Get-Location', { shell: 'powershell' }); expect(result.exitCode).toBe(0); }); test('deve tratar fallback para cmd.exe', async () => { const result = await executeShell('dir', { shell: 'cmd' }); expect(result.exitCode).toBe(0); }); });

Configuração de Matrix CI

# .github/workflows/test.yml name: Testes Cross-Platform on: [push, pull_request] jobs: test: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node-version: [18, 20, 22] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm test - name: Executar Testes Específicos de Plataforma run: npm run test:platform

Cobertura e Métricas

Configuração de Cobertura

// jest.config.js - Seção de cobertura module.exports = { collectCoverageFrom: [ 'src/**/*.js', '.aios-core/**/*.js', 'bin/**/*.js', 'packages/**/*.js', 'scripts/**/*.js', '!**/node_modules/**', '!**/tests/**', '!**/coverage/**', '!**/__tests__/**', '!**/*.test.js', '!**/*.spec.js', // Excluir templates e arquivos gerados '!.aios-core/development/templates/**', '!.aios-core/product/templates/**', '!**/dist/**', // Excluir módulos com I/O pesado (melhor para testes de integração) '!.aios-core/core/health-check/checks/**', '!.aios-core/core/config/**', '!.aios-core/core/manifest/**', '!.aios-core/core/registry/**', '!.aios-core/core/utils/**', ], coverageThreshold: { global: { branches: 25, functions: 30, lines: 30, statements: 30, }, '.aios-core/core/': { lines: 45, }, }, coveragePathIgnorePatterns: ['/node_modules/', '/coverage/', '/.husky/', '/dist/'], };

Metas de Cobertura

MóduloMetaAtualNotas
Global30%~31%Baseline mínimo
Core45%~47%Lógica de negócios
Quality Gates80%TBDCaminho crítico
Squad System70%TBDVoltado ao usuário

Visualizando Relatórios de Cobertura

# Gerar relatório de cobertura npm run test:coverage # Abrir relatório HTML (macOS) open coverage/lcov-report/index.html # Abrir relatório HTML (Windows) start coverage/lcov-report/index.html # Abrir relatório HTML (Linux) xdg-open coverage/lcov-report/index.html

Estrutura do Relatório de Cobertura

coverage/ ├── lcov-report/ # Relatório HTML │ ├── index.html # Visão geral │ └── .aios-core/ # Cobertura por módulo ├── lcov.info # Formato LCOV (para CI) ├── coverage-summary.json # Resumo em JSON └── clover.xml # Formato Clover

Integração CI/CD

Workflow do GitHub Actions

# .github/workflows/test.yml name: Tests on: push: branches: [main, develop] pull_request: branches: [main, develop] jobs: unit-tests: name: Testes Unitários runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - name: Instalar dependências run: npm ci - name: Executar testes unitários run: npm test - name: Upload de cobertura uses: codecov/codecov-action@v4 with: files: ./coverage/lcov.info fail_ci_if_error: true integration-tests: name: Testes de Integração runs-on: ubuntu-latest needs: unit-tests steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - name: Instalar dependências run: npm ci - name: Executar testes de integração run: SKIP_INTEGRATION_TESTS=false npm test -- --testPathPattern=integration env: CLICKUP_API_KEY: ${{ secrets.CLICKUP_API_KEY }} quality-gate: name: Quality Gate runs-on: ubuntu-latest needs: [unit-tests, integration-tests] steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' - run: npm ci - name: Lint run: npm run lint - name: TypeCheck run: npm run typecheck - name: Threshold de cobertura run: npm run test:coverage -- --coverageReporters=text-summary

Hook Pre-commit

#!/bin/sh # .husky/pre-commit # Executar lint-staged npx lint-staged # Executar testes unitários rápidos npm test -- --passWithNoTests --testPathIgnorePatterns=integration,e2e

Integração com Quality Gate

O Sistema de Quality Gate do AIOS (veja Guia de Quality Gates) integra testes em múltiplas camadas:

CamadaTipo de TesteQuando
Layer 1Unitário + Lint + TypeCheckPre-commit
Layer 2Integração + Revisão de IACriação de PR
Layer 3E2E + Revisão HumanaAntes do merge

Escrevendo Bons Testes

Estrutura de Teste (Padrão AAA)

test('deve calcular preço total com desconto', () => { // Arrange - Configurar dados e condições de teste const cart = new ShoppingCart(); cart.addItem({ name: 'Widget', price: 100 }); cart.addItem({ name: 'Gadget', price: 50 }); const discount = 0.1; // 10% de desconto // Act - Executar o código em teste const total = cart.calculateTotal(discount); // Assert - Verificar os resultados expect(total).toBe(135); // (100 + 50) * 0.9 });

Diretrizes de Nomenclatura de Testes

RuimBom
test('test1')test('deve retornar null para entrada vazia')
test('works')test('deve calcular imposto corretamente')
test('error')test('deve lançar ValidationError para email inválido')

Casos Extremos a Testar

describe('validateEmail', () => { // Caminho feliz test('deve aceitar email válido', () => { expect(validateEmail('user@example.com')).toBe(true); }); // Casos extremos test('deve rejeitar string vazia', () => { expect(validateEmail('')).toBe(false); }); test('deve rejeitar null', () => { expect(validateEmail(null)).toBe(false); }); test('deve rejeitar undefined', () => { expect(validateEmail(undefined)).toBe(false); }); // Condições de fronteira test('deve aceitar email com parte local de um caractere', () => { expect(validateEmail('a@example.com')).toBe(true); }); test('deve rejeitar email sem símbolo @', () => { expect(validateEmail('userexample.com')).toBe(false); }); // Caracteres especiais test('deve aceitar email com sinal de mais', () => { expect(validateEmail('user+tag@example.com')).toBe(true); }); });

Padrões de Testes Assíncronos

// Usando async/await (recomendado) test('deve buscar dados do usuário', async () => { const user = await fetchUser(123); expect(user.name).toBe('John'); }); // Testando rejeição de promise test('deve rejeitar para usuário inexistente', async () => { await expect(fetchUser(999)).rejects.toThrow('User not found'); }); // Testando com callback done (legado) test('deve fazer callback com dados', (done) => { fetchUserCallback(123, (err, user) => { expect(err).toBeNull(); expect(user.name).toBe('John'); done(); }); });

Isolamento de Testes

describe('FileManager', () => { let tempDir; let fileManager; beforeEach(async () => { // Criar diretório temporário isolado para cada teste tempDir = await createTempDir(); fileManager = new FileManager(tempDir); }); afterEach(async () => { // Limpar após cada teste await removeTempDir(tempDir); }); test('deve criar arquivo', async () => { await fileManager.write('test.txt', 'content'); const exists = await fileManager.exists('test.txt'); expect(exists).toBe(true); }); test('não deve ver arquivos de outros testes', async () => { // Este teste inicia com um diretório limpo const files = await fileManager.list(); expect(files).toHaveLength(0); }); });

Mocking e Fixtures

Básico de Mocking com Jest

// Mock de um módulo jest.mock('fs-extra'); const fs = require('fs-extra'); // Implementação de mock fs.readFile.mockResolvedValue('file content'); fs.writeFile.mockResolvedValue(undefined); // Valor de retorno do mock fs.existsSync.mockReturnValue(true); // Implementação de mock para chamada específica fs.readFile.mockImplementation((path) => { if (path === 'config.json') { return Promise.resolve('{"key": "value"}'); } return Promise.reject(new Error('File not found')); });

Criando Test Fixtures

// tests/fixtures/agent-fixtures.js const MOCK_AGENT = { name: 'test-agent', slashPrefix: 'test', icon: '🧪', persona: { role: 'Test Agent', expertise: ['testing'], }, commands: [ { name: '*test', description: 'Run tests', visibility: 'all', }, ], }; const MOCK_SQUAD = { name: 'test-squad', version: '1.0.0', agents: [MOCK_AGENT], tasks: [], }; module.exports = { MOCK_AGENT, MOCK_SQUAD, };

Usando Fixtures em Testes

const { MOCK_AGENT, MOCK_SQUAD } = require('../fixtures/agent-fixtures'); describe('AgentLoader', () => { test('deve carregar agente da fixture', async () => { // Mock do sistema de arquivos para retornar dados da fixture jest.spyOn(fs, 'readFile').mockResolvedValue(JSON.stringify(MOCK_AGENT)); const agent = await loadAgent('test-agent'); expect(agent.name).toBe(MOCK_AGENT.name); expect(agent.commands).toHaveLength(1); }); });

Mocking de Serviços Externos

// Mock da API do ClickUp jest.mock('../../.aios-core/integrations/clickup-client'); const clickupClient = require('../../.aios-core/integrations/clickup-client'); describe('Story Sync', () => { beforeEach(() => { // Resetar mocks antes de cada teste jest.clearAllMocks(); // Configurar implementações de mock padrão clickupClient.createTask.mockResolvedValue({ id: 'task-123', name: 'Test Task', }); clickupClient.updateTask.mockResolvedValue({ id: 'task-123', status: 'in progress', }); }); test('deve criar task no ClickUp', async () => { const result = await syncStory({ title: 'New Feature' }); expect(clickupClient.createTask).toHaveBeenCalledWith({ name: 'New Feature', list_id: expect.any(String), }); expect(result.clickupId).toBe('task-123'); }); test('deve tratar erros da API do ClickUp', async () => { clickupClient.createTask.mockRejectedValue(new Error('API rate limited')); await expect(syncStory({ title: 'New Feature' })).rejects.toThrow( 'Failed to sync: API rate limited' ); }); });

Snapshot Testing

describe('GreetingBuilder', () => { test('deve gerar formato de saudação consistente', async () => { const builder = new GreetingBuilder(); const greeting = await builder.build({ agent: 'dev', sessionType: 'new', timestamp: new Date('2025-01-01T00:00:00Z'), // Timestamp fixo }); // Comparação de snapshot expect(greeting).toMatchSnapshot(); }); });

Referência de Comandos NPM

Comandos Básicos

ComandoDescrição
npm testExecutar todos os testes
npm run test:watchExecutar testes em modo watch
npm run test:coverageExecutar testes com relatório de cobertura

Comandos de Testes Filtrados

# Executar testes correspondendo ao padrão npm test -- --testPathPattern=unit # Executar arquivo de teste específico npm test -- tests/unit/greeting-builder.test.js # Executar testes correspondendo ao nome npm test -- --testNamePattern="should validate" # Executar testes em diretório específico npm test -- tests/integration/

Comandos de Cobertura

# Gerar relatório completo de cobertura npm run test:coverage # Cobertura com reporter específico npm test -- --coverage --coverageReporters=text # Cobertura para arquivos específicos npm test -- --coverage --collectCoverageFrom="src/**/*.js"

Opções do Modo Watch

# Watch em todos os testes npm run test:watch # Watch em arquivos específicos npm test -- --watch --testPathPattern=unit # Watch apenas em arquivos alterados npm test -- --watchAll=false --watch

Modo Debug

# Executar com saída verbose npm test -- --verbose # Executar teste único para debugging npm test -- --runInBand tests/unit/specific.test.js # Executar com debugger do Node node --inspect-brk node_modules/.bin/jest --runInBand

Comandos Específicos de CI

# Executar em modo CI (sem cores, cobertura, etc.) npm test -- --ci # Executar com máximo de workers npm test -- --maxWorkers=4 # Parar na primeira falha npm test -- --bail # Executar apenas arquivos alterados (Git) npm test -- --changedSince=main

Resolução de Problemas

Problemas Comuns

ProblemaSolução
Testes com timeoutAumentar testTimeout na config ou no teste específico
Testes async travandoGarantir que todas as promises são awaited ou retornadas
Mock não funcionandoVerificar se mock está antes do require()
Cobertura baixaAdicionar padrões --collectCoverageFrom
Testes flakyVerificar estado compartilhado, usar limpeza em beforeEach

Debugando Testes Travados

// Adicionar timeout a teste específico test('operação lenta', async () => { // ... }, 60000); // timeout de 60 segundos // Debug com saída no console test('debug test', async () => { console.log('Passo 1'); await step1(); console.log('Passo 2'); await step2(); console.log('Concluído'); });

Corrigindo Problemas de Mock

// Errado: Mock após require const myModule = require('./myModule'); jest.mock('./myModule'); // Correto: Mock antes do require jest.mock('./myModule'); const myModule = require('./myModule'); // Ou usar jest.doMock para mocking dinâmico beforeEach(() => { jest.resetModules(); jest.doMock('./myModule', () => ({ func: jest.fn().mockReturnValue('mocked'), })); });

Resolvendo Problemas de Cobertura

// Cobertura não coletando? Verificar caminhos module.exports = { collectCoverageFrom: [ // Usar caminhos relativos a partir da raiz do projeto 'src/**/*.js', // Padrões de exclusão '!**/node_modules/**', ], // Diretórios raiz para busca roots: ['<rootDir>'], };

Documentação Relacionada


Synkra AIOS v4 Guia de Testes