Deep Dive: Testing

Strategies for testing Copilot-powered applications.

Status: Placeholder - to be expanded with detailed content.

Topics to Cover

  • Unit testing tool handlers
  • Integration testing with real API
  • Mocking the Copilot client
  • Testing streaming behavior
  • Snapshot testing for responses
  • E2E test patterns

Quick Reference

Testing tool handlers (unit tests)

import { describe, it, expect } from "vitest";

// Tool handler is a pure function - easy to test
function weatherHandler({ city }: { city: string }) {
  return { temp: 20, condition: "sunny", city };
}

describe("weatherHandler", () => {
  it("returns weather for valid city", () => {
    const result = weatherHandler({ city: "London" });
    expect(result).toHaveProperty("temp");
    expect(result.city).toBe("London");
  });
});

Mocking the client

// Create a mock that mimics SDK behavior
const mockSession = {
  send: vi.fn().mockImplementation(async function* () {
    yield { type: "turnStart" };
    yield { type: "textDelta", delta: "Hello" };
    yield { type: "turnEnd", text: "Hello" };
  }),
  submitToolResult: vi.fn()
};

const mockClient = {
  createSession: vi.fn().mockResolvedValue(mockSession),
  close: vi.fn()
};

Testing with real API (integration)

import { CopilotClient } from "@github/copilot-sdk";

describe("integration", () => {
  let client: CopilotClient;

  beforeAll(async () => {
    client = await CopilotClient.create({
      agent: { name: "test", version: "1.0.0" }
    });
  });

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

  it("responds to basic prompt", async () => {
    const session = await client.createSession();
    const response = await session.send("Say hello");
    expect(response.text).toBeTruthy();
  });
});

Challenges

  • Non-determinism: LLM responses vary between runs
  • Cost: Real API calls cost money
  • Latency: Integration tests are slow
  • Rate limits: Can’t run thousands of tests quickly

Strategies

  1. Test tool handlers separately - They’re deterministic
  2. Use mocks for unit tests - Fast and reliable
  3. Reserve integration tests for critical paths - Fewer but meaningful
  4. Snapshot test with fuzzy matching - Allow for variation

See Also

  • SDK test files in copilot-sdk/nodejs/test/
  • Vitest documentation for async generator testing