@agentforge/testing 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +366 -0
- package/dist/index.cjs +19162 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +708 -0
- package/dist/index.d.ts +708 -0
- package/dist/index.js +19105 -0
- package/dist/index.js.map +1 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# @agentforge/testing
|
|
2
|
+
|
|
3
|
+
Testing utilities and helpers for the AgentForge framework.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @agentforge/testing
|
|
9
|
+
# or
|
|
10
|
+
pnpm add -D @agentforge/testing
|
|
11
|
+
# or
|
|
12
|
+
yarn add -D @agentforge/testing
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🎭 **Mock Factories** - Create mock LLMs, tools, and states for testing
|
|
18
|
+
- 🔧 **Test Helpers** - Assertion helpers and state builders
|
|
19
|
+
- 📦 **Fixtures** - Pre-built sample agents, tools, and conversations
|
|
20
|
+
- 🏃 **Test Runners** - Agent test runner and conversation simulator
|
|
21
|
+
- 📸 **Snapshot Testing** - State and message snapshot utilities
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { describe, it, expect } from 'vitest';
|
|
27
|
+
import {
|
|
28
|
+
createMockLLM,
|
|
29
|
+
createMockTool,
|
|
30
|
+
createStateBuilder,
|
|
31
|
+
createAgentTestRunner,
|
|
32
|
+
assertMessageContains,
|
|
33
|
+
} from '@agentforge/testing';
|
|
34
|
+
|
|
35
|
+
describe('My Agent', () => {
|
|
36
|
+
it('should respond to greetings', async () => {
|
|
37
|
+
// Create mock LLM
|
|
38
|
+
const llm = createMockLLM({
|
|
39
|
+
responses: ['Hello! How can I help you?']
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Create test state
|
|
43
|
+
const state = createStateBuilder()
|
|
44
|
+
.addHumanMessage('Hi')
|
|
45
|
+
.build();
|
|
46
|
+
|
|
47
|
+
// Run agent
|
|
48
|
+
const runner = createAgentTestRunner(agent);
|
|
49
|
+
const result = await runner.run(state);
|
|
50
|
+
|
|
51
|
+
// Assert
|
|
52
|
+
expect(result.passed).toBe(true);
|
|
53
|
+
assertMessageContains(result.messages, 'Hello');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Mock Factories
|
|
59
|
+
|
|
60
|
+
### Mock LLM
|
|
61
|
+
|
|
62
|
+
Create mock language models for testing:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { createMockLLM, createEchoLLM, createErrorLLM } from '@agentforge/testing';
|
|
66
|
+
|
|
67
|
+
// Basic mock with predefined responses
|
|
68
|
+
const llm = createMockLLM({
|
|
69
|
+
responses: ['Response 1', 'Response 2']
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Echo LLM (echoes input)
|
|
73
|
+
const echoLLM = createEchoLLM();
|
|
74
|
+
|
|
75
|
+
// Error LLM (always throws)
|
|
76
|
+
const errorLLM = createErrorLLM('Custom error message');
|
|
77
|
+
|
|
78
|
+
// Custom response generator
|
|
79
|
+
const customLLM = createMockLLM({
|
|
80
|
+
responseGenerator: (messages) => {
|
|
81
|
+
const lastMsg = messages[messages.length - 1];
|
|
82
|
+
return `You said: ${lastMsg.content}`;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Mock Tools
|
|
88
|
+
|
|
89
|
+
Create mock tools for testing:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { createMockTool, createEchoTool, createCalculatorTool } from '@agentforge/testing';
|
|
93
|
+
import { z } from 'zod';
|
|
94
|
+
|
|
95
|
+
// Basic mock tool
|
|
96
|
+
const tool = createMockTool({
|
|
97
|
+
name: 'my_tool',
|
|
98
|
+
schema: z.object({ input: z.string() }),
|
|
99
|
+
implementation: async ({ input }) => `Processed: ${input}`
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Echo tool
|
|
103
|
+
const echoTool = createEchoTool();
|
|
104
|
+
|
|
105
|
+
// Calculator tool
|
|
106
|
+
const calcTool = createCalculatorTool();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Test Helpers
|
|
110
|
+
|
|
111
|
+
### State Builder
|
|
112
|
+
|
|
113
|
+
Build test states easily:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { createStateBuilder } from '@agentforge/testing';
|
|
117
|
+
|
|
118
|
+
const state = createStateBuilder()
|
|
119
|
+
.addHumanMessage('Hello')
|
|
120
|
+
.addAIMessage('Hi there!')
|
|
121
|
+
.set('customField', 'value')
|
|
122
|
+
.build();
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Assertions
|
|
126
|
+
|
|
127
|
+
Helpful assertion functions:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import {
|
|
131
|
+
assertMessageContains,
|
|
132
|
+
assertLastMessageContains,
|
|
133
|
+
assertToolCalled,
|
|
134
|
+
assertCompletesWithin,
|
|
135
|
+
} from '@agentforge/testing';
|
|
136
|
+
|
|
137
|
+
// Assert message contains text
|
|
138
|
+
assertMessageContains(messages, 'hello');
|
|
139
|
+
|
|
140
|
+
// Assert last message contains text
|
|
141
|
+
assertLastMessageContains(messages, 'goodbye');
|
|
142
|
+
|
|
143
|
+
// Assert tool was called
|
|
144
|
+
assertToolCalled(toolCalls, 'calculator', { operation: 'add' });
|
|
145
|
+
|
|
146
|
+
// Assert completes within time
|
|
147
|
+
await assertCompletesWithin(async () => {
|
|
148
|
+
await agent.invoke(input);
|
|
149
|
+
}, 1000);
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Fixtures
|
|
153
|
+
|
|
154
|
+
Pre-built test data:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import {
|
|
158
|
+
simpleGreeting,
|
|
159
|
+
multiTurnConversation,
|
|
160
|
+
sampleTools,
|
|
161
|
+
calculatorTool,
|
|
162
|
+
} from '@agentforge/testing';
|
|
163
|
+
|
|
164
|
+
// Use sample conversations
|
|
165
|
+
const messages = simpleGreeting;
|
|
166
|
+
|
|
167
|
+
// Use sample tools
|
|
168
|
+
const tools = sampleTools;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Test Runners
|
|
172
|
+
|
|
173
|
+
### Agent Test Runner
|
|
174
|
+
|
|
175
|
+
Run integration tests on agents:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import { createAgentTestRunner } from '@agentforge/testing';
|
|
179
|
+
|
|
180
|
+
const runner = createAgentTestRunner(agent, {
|
|
181
|
+
timeout: 5000,
|
|
182
|
+
captureSteps: true,
|
|
183
|
+
validateState: true,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const result = await runner.run({ messages: [new HumanMessage('Test')] });
|
|
187
|
+
|
|
188
|
+
expect(result.passed).toBe(true);
|
|
189
|
+
expect(result.executionTime).toBeLessThan(5000);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Conversation Simulator
|
|
193
|
+
|
|
194
|
+
Simulate multi-turn conversations:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { createConversationSimulator } from '@agentforge/testing';
|
|
198
|
+
|
|
199
|
+
const simulator = createConversationSimulator(agent, {
|
|
200
|
+
maxTurns: 5,
|
|
201
|
+
verbose: true,
|
|
202
|
+
stopCondition: (messages) => {
|
|
203
|
+
const lastMsg = messages[messages.length - 1];
|
|
204
|
+
return lastMsg.content.includes('goodbye');
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const result = await simulator.simulate([
|
|
209
|
+
'Hello',
|
|
210
|
+
'What can you do?',
|
|
211
|
+
'Help me with a task'
|
|
212
|
+
]);
|
|
213
|
+
|
|
214
|
+
expect(result.completed).toBe(true);
|
|
215
|
+
expect(result.turns).toBe(3);
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Snapshot Testing
|
|
219
|
+
|
|
220
|
+
Create and compare state snapshots:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
import {
|
|
224
|
+
createSnapshot,
|
|
225
|
+
assertMatchesSnapshot,
|
|
226
|
+
compareStates,
|
|
227
|
+
createStateDiff,
|
|
228
|
+
} from '@agentforge/testing';
|
|
229
|
+
|
|
230
|
+
// Create snapshot
|
|
231
|
+
const snapshot = createSnapshot(state, {
|
|
232
|
+
normalizeTimestamps: true,
|
|
233
|
+
normalizeIds: true,
|
|
234
|
+
excludeFields: ['_internal']
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Assert matches snapshot
|
|
238
|
+
assertMatchesSnapshot(state);
|
|
239
|
+
|
|
240
|
+
// Compare states
|
|
241
|
+
const isEqual = compareStates(state1, state2);
|
|
242
|
+
|
|
243
|
+
// Create diff
|
|
244
|
+
const diff = createStateDiff(stateBefore, stateAfter);
|
|
245
|
+
console.log(diff.changed); // { field: { from: 'old', to: 'new' } }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Complete Example
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { describe, it, expect } from 'vitest';
|
|
252
|
+
import {
|
|
253
|
+
createMockLLM,
|
|
254
|
+
createMockTool,
|
|
255
|
+
createStateBuilder,
|
|
256
|
+
createAgentTestRunner,
|
|
257
|
+
createConversationSimulator,
|
|
258
|
+
assertMessageContains,
|
|
259
|
+
assertToolCalled,
|
|
260
|
+
assertMatchesSnapshot,
|
|
261
|
+
} from '@agentforge/testing';
|
|
262
|
+
import { createReActAgent } from '@agentforge/patterns';
|
|
263
|
+
|
|
264
|
+
describe('ReAct Agent Integration Tests', () => {
|
|
265
|
+
const llm = createMockLLM({
|
|
266
|
+
responses: [
|
|
267
|
+
'I need to use the calculator tool.',
|
|
268
|
+
'The result is 4.'
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
const calculatorTool = createMockTool({
|
|
273
|
+
name: 'calculator',
|
|
274
|
+
implementation: async ({ operation, a, b }) => {
|
|
275
|
+
if (operation === 'add') return `${a + b}`;
|
|
276
|
+
return '0';
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const agent = createReActAgent({
|
|
281
|
+
llm,
|
|
282
|
+
tools: [calculatorTool],
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('should use tools to solve problems', async () => {
|
|
286
|
+
const runner = createAgentTestRunner(agent, {
|
|
287
|
+
timeout: 5000,
|
|
288
|
+
captureSteps: true
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const state = createStateBuilder()
|
|
292
|
+
.addHumanMessage('What is 2 + 2?')
|
|
293
|
+
.build();
|
|
294
|
+
|
|
295
|
+
const result = await runner.run(state);
|
|
296
|
+
|
|
297
|
+
expect(result.passed).toBe(true);
|
|
298
|
+
assertMessageContains(result.messages, 'calculator');
|
|
299
|
+
assertToolCalled(result.finalState.toolCalls, 'calculator');
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('should handle multi-turn conversations', async () => {
|
|
303
|
+
const simulator = createConversationSimulator(agent, {
|
|
304
|
+
maxTurns: 3,
|
|
305
|
+
verbose: false
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const result = await simulator.simulate([
|
|
309
|
+
'Hello',
|
|
310
|
+
'Calculate 5 + 3',
|
|
311
|
+
'Thank you'
|
|
312
|
+
]);
|
|
313
|
+
|
|
314
|
+
expect(result.completed).toBe(true);
|
|
315
|
+
expect(result.turns).toBe(3);
|
|
316
|
+
assertMatchesSnapshot(result.messages);
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## API Reference
|
|
322
|
+
|
|
323
|
+
### Mocks
|
|
324
|
+
|
|
325
|
+
- `createMockLLM(config?)` - Create a mock LLM
|
|
326
|
+
- `createEchoLLM()` - Create an echo LLM
|
|
327
|
+
- `createErrorLLM(message?)` - Create an error LLM
|
|
328
|
+
- `createMockTool(config?)` - Create a mock tool
|
|
329
|
+
- `createEchoTool(name?)` - Create an echo tool
|
|
330
|
+
- `createCalculatorTool()` - Create a calculator tool
|
|
331
|
+
|
|
332
|
+
### Helpers
|
|
333
|
+
|
|
334
|
+
- `createStateBuilder()` - Create a state builder
|
|
335
|
+
- `createConversationState(messages)` - Create conversation state
|
|
336
|
+
- `createReActState(config?)` - Create ReAct agent state
|
|
337
|
+
- `createPlanningState(config?)` - Create planning agent state
|
|
338
|
+
|
|
339
|
+
### Assertions
|
|
340
|
+
|
|
341
|
+
- `assertMessageContains(messages, content)` - Assert message contains text
|
|
342
|
+
- `assertLastMessageContains(messages, content)` - Assert last message contains text
|
|
343
|
+
- `assertToolCalled(toolCalls, name, args?)` - Assert tool was called
|
|
344
|
+
- `assertCompletesWithin(fn, maxMs)` - Assert completes within time
|
|
345
|
+
- `assertStateHasFields(state, fields)` - Assert state has fields
|
|
346
|
+
- `assertMatchesSnapshot(state, config?)` - Assert matches snapshot
|
|
347
|
+
|
|
348
|
+
### Runners
|
|
349
|
+
|
|
350
|
+
- `createAgentTestRunner(agent, config?)` - Create agent test runner
|
|
351
|
+
- `createConversationSimulator(agent, config?)` - Create conversation simulator
|
|
352
|
+
|
|
353
|
+
### Fixtures
|
|
354
|
+
|
|
355
|
+
- `simpleGreeting` - Simple greeting conversation
|
|
356
|
+
- `multiTurnConversation` - Multi-turn conversation
|
|
357
|
+
- `sampleTools` - Array of sample tools
|
|
358
|
+
- `calculatorTool` - Calculator tool
|
|
359
|
+
- `searchTool` - Search tool
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
MIT
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
|