@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 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
+