Testing Guide

Strategies for testing your AI voice agents

Testing AI agents is different from traditional software testing. This guide covers the testing pyramid for voice agents.

Testing Pyramid

Type Purpose
Unit Tests Test individual functions, utilities, and content parsing
Integration Tests Test bundle loading, handoffs, and API endpoints
Conversation Tests Test full conversation flows and personality consistency

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm test -- --watch

# Run specific test file
npm test -- agents.test.ts

# Run with coverage
npm test -- --coverage

Unit Testing

Testing Bundle Validation

// tests/bundle-validator.test.ts
import { describe, it, expect } from 'vitest';
import { validateBundle } from '../src/personas/bundle-validator';

describe('Bundle Validator', () => {
  it('validates a complete bundle', async () => {
    const result = await validateBundle('ferni');
    
    expect(result.valid).toBe(true);
    expect(result.errors).toHaveLength(0);
  });

  it('catches missing required fields', async () => {
    const result = await validateBundle('invalid-agent');
    
    expect(result.valid).toBe(false);
    expect(result.errors).toContain(
      'Missing required field: identity.id'
    );
  });
});

Testing Content Loaders

// tests/content-loader.test.ts
import { describe, it, expect } from 'vitest';
import { loadGreetings, loadStories } from '../src/personas/content-loader';

describe('Content Loader', () => {
  it('loads greetings for an agent', async () => {
    const greetings = await loadGreetings('ferni');
    
    expect(greetings).toBeInstanceOf(Array);
    expect(greetings.length).toBeGreaterThan(0);
    expect(greetings[0]).toHaveProperty('text');
  });
});

Integration Testing

Testing Handoff Logic

// tests/handoff.test.ts
import { describe, it, expect } from 'vitest';
import { findHandoffTarget } from '../src/team/handoff-router';

describe('Handoff Router', () => {
  it('routes investment questions to Jack', async () => {
    const target = await findHandoffTarget(
      'How should I invest my retirement savings?'
    );
    
    expect(target).toBe('jack');
  });

  it('routes habit questions to Maya', async () => {
    const target = await findHandoffTarget(
      'I want to build better morning habits'
    );
    
    expect(target).toBe('maya');
  });

  it('returns null for general conversation', async () => {
    const target = await findHandoffTarget(
      'How are you today?'
    );
    
    expect(target).toBeNull();
  });
});

Testing API Endpoints

// tests/api.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { createServer } from '../src/server';

describe('API Endpoints', () => {
  let server;
  let baseUrl;

  beforeAll(async () => {
    server = await createServer({ port: 0 });
    baseUrl = `http://localhost:${server.port}`;
  });

  afterAll(async () => {
    await server.close();
  });

  it('GET /api/agents returns agent list', async () => {
    const response = await fetch(`${baseUrl}/api/agents`);
    const data = await response.json();
    
    expect(response.status).toBe(200);
    expect(data.agents).toBeInstanceOf(Array);
  });
});

Dev Panel Testing

The Ferni dev panel provides interactive testing tools:

# Add ?dev to any URL
http://localhost:3000?dev

# Keyboard shortcuts
Cmd/Ctrl + Shift + D   Toggle dev panel
Cmd/Ctrl + Shift + U   Quick unlock all agents
Cmd/Ctrl + Shift + R   Reset to free tier

Dev Panel Features

Feature Description
Agent Switcher Instantly switch between agents to test handoffs
Expression Tester Trigger avatar expressions (happy, curious, thinking)
Tier Simulator Test free/premium tier behavior
Connection Status Monitor WebSocket connection state
Transcript Log View real-time conversation transcript

CI/CD Integration

# .github/workflows/test.yml
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Validate bundles
        run: npm run agents validate
      
      - name: Run unit tests
        run: npm test -- --coverage

Testing Checklist

Before deploying a new agent, verify:

  • Bundle validation passes (npm run agents validate)
  • Greetings and catchphrases are defined
  • Handoff triggers are tested
  • Personality is consistent across 10+ prompts
  • Dev panel features work
  • API endpoints return correct data