Skip to main content

Overview

aixyz provides a loadEnv utility from aixyz/test for loading environment variables during tests. Combined with Bun’s built-in test runner, you can write both deterministic and non-deterministic agent tests.

Test File Convention

Place your test file alongside your agent:
app/
  agent.ts
  agent.test.ts    # Tests for the agent
  tools/
    weather.ts

Writing Tests

import { describe, expect, test } from "bun:test";
import { ToolLoopAgent } from "ai";
import { loadEnv } from "aixyz/test";
import agent, { accepts } from "./agent";

// Deterministic tests — no API calls, always run
test("default export is a ToolLoopAgent", () => {
  expect(agent).toBeInstanceOf(ToolLoopAgent);
});

test("has convertTemperature tool registered", () => {
  expect(agent.tools).toHaveProperty("convertTemperature");
});

test("accepts config uses exact scheme", () => {
  expect(accepts.scheme).toBe("exact");
});

// Non-deterministic tests — require API key, skip gracefully in CI
describe("non deterministic agent test", () => {
  loadEnv();

  test.skipIf(!process.env.OPENAI_API_KEY)("agent can convert temperature", async () => {
    const result = await agent.generate({
      prompt: "convert 100 degrees celsius to fahrenheit",
    });
    expect(result.text).toContain("212");
  });
});

loadEnv()

The loadEnv function from aixyz/test loads environment variables for test runs. It loads .env.test.local (where your OPENAI_API_KEY lives for tests) while .env.local is ignored during testing.
import { loadEnv } from "aixyz/test";

describe("tests needing env vars", () => {
  loadEnv();

  // process.env is now populated
});

Deterministic vs Non-Deterministic

TypeDescriptionCI-Safe
DeterministicValidate agent type, tools, configYes
Non-deterministicCall LLM and validate response contentNo*
* Use test.skipIf(!process.env.OPENAI_API_KEY) to skip gracefully when no API key is available.

Running Tests

# Run all tests
bun test

# Run a specific test file
bun test app/agent.test.ts
See the Agent with Tests template for a complete working example.