0
# Unit Testing
1
2
Lightweight test classes for basic functionality verification, focusing on object creation, parameter validation, and method availability without requiring external API calls or network dependencies. Unit tests provide fast feedback during development and ensure proper integration configuration.
3
4
## Capabilities
5
6
### Chat Model Unit Tests
7
8
Unit testing for chat model implementations with initialization, environment variable configuration, and basic functionality verification.
9
10
```python { .api }
11
from langchain_tests.unit_tests import ChatModelUnitTests
12
13
class ChatModelUnitTests(ChatModelTests):
14
"""Unit tests for chat models."""
15
16
# Required abstract properties
17
@property
18
def chat_model_class(self):
19
"""Chat model class to test."""
20
21
@property
22
def chat_model_params(self) -> dict:
23
"""Model initialization parameters."""
24
25
# Optional configuration
26
@property
27
def init_from_env_params(self) -> dict:
28
"""Parameters for environment variable initialization test."""
29
30
def test_init(self) -> None:
31
"""Test model initialization with provided parameters."""
32
33
def test_init_from_env(self) -> None:
34
"""Test initialization from environment variables."""
35
36
def test_init_streaming(self) -> None:
37
"""Test streaming initialization."""
38
39
def test_bind_tool_pydantic(self) -> None:
40
"""Test Pydantic tool binding."""
41
42
def test_with_structured_output(self) -> None:
43
"""Test structured output configuration."""
44
45
def test_standard_params(self) -> None:
46
"""Test standard parameter handling."""
47
48
def test_serdes(self) -> None:
49
"""Test serialization and deserialization."""
50
51
def test_init_time(self) -> None:
52
"""Benchmark initialization performance."""
53
```
54
55
#### Usage Example
56
57
```python
58
from langchain_tests.unit_tests import ChatModelUnitTests
59
from my_integration import MyChatModel
60
61
class TestMyChatModelUnit(ChatModelUnitTests):
62
@property
63
def chat_model_class(self):
64
return MyChatModel
65
66
@property
67
def chat_model_params(self):
68
return {
69
"api_key": "test-api-key",
70
"model": "test-model-name",
71
"temperature": 0.7
72
}
73
74
@property
75
def init_from_env_params(self):
76
return {
77
"model": "test-model-from-env"
78
}
79
```
80
81
### Embeddings Unit Tests
82
83
Unit testing for embeddings model implementations with initialization and configuration verification.
84
85
```python { .api }
86
from langchain_tests.unit_tests import EmbeddingsUnitTests
87
88
class EmbeddingsUnitTests(EmbeddingsTests):
89
"""Unit tests for embeddings models."""
90
91
# Required abstract properties
92
@property
93
def embeddings_class(self):
94
"""Embeddings class to test."""
95
96
@property
97
def embedding_model_params(self) -> dict:
98
"""Model parameters for initialization."""
99
100
# Optional configuration
101
@property
102
def init_from_env_params(self) -> dict:
103
"""Parameters for environment variable initialization test."""
104
105
def test_init(self) -> None:
106
"""Test model initialization with provided parameters."""
107
108
def test_init_from_env(self) -> None:
109
"""Test initialization from environment variables."""
110
```
111
112
#### Usage Example
113
114
```python
115
from langchain_tests.unit_tests import EmbeddingsUnitTests
116
from my_integration import MyEmbeddings
117
118
class TestMyEmbeddingsUnit(EmbeddingsUnitTests):
119
@property
120
def embeddings_class(self):
121
return MyEmbeddings
122
123
@property
124
def embedding_model_params(self):
125
return {
126
"api_key": "test-api-key",
127
"model": "text-embedding-3-small"
128
}
129
```
130
131
### Tools Unit Tests
132
133
Unit testing for tool implementations with schema validation and parameter verification.
134
135
```python { .api }
136
from langchain_tests.unit_tests import ToolsUnitTests
137
138
class ToolsUnitTests(ToolsTests):
139
"""Unit tests for tools."""
140
141
# Required abstract properties
142
@property
143
def tool_constructor(self):
144
"""Tool class or instance to test."""
145
146
@property
147
def tool_constructor_params(self) -> dict:
148
"""Constructor parameters for tool initialization."""
149
150
@property
151
def tool_invoke_params_example(self) -> dict:
152
"""Example parameters for tool invocation."""
153
154
# Optional configuration
155
@property
156
def init_from_env_params(self) -> dict:
157
"""Parameters for environment variable initialization test."""
158
159
def test_init(self) -> None:
160
"""Test tool initialization."""
161
162
def test_init_from_env(self) -> None:
163
"""Test initialization from environment variables."""
164
165
def test_has_name(self) -> None:
166
"""Test that tool has a name."""
167
168
def test_has_input_schema(self) -> None:
169
"""Test that tool has an input schema."""
170
171
def test_input_schema_matches_invoke_params(self) -> None:
172
"""Test that input schema matches example invoke parameters."""
173
```
174
175
#### Usage Example
176
177
```python
178
from langchain_tests.unit_tests import ToolsUnitTests
179
from my_integration import MyTool
180
181
class TestMyToolUnit(ToolsUnitTests):
182
@property
183
def tool_constructor(self):
184
return MyTool
185
186
@property
187
def tool_constructor_params(self):
188
return {
189
"api_key": "test-api-key",
190
"base_url": "https://api.example.com"
191
}
192
193
@property
194
def tool_invoke_params_example(self):
195
return {
196
"query": "test query",
197
"limit": 10
198
}
199
```
200
201
## Base Classes
202
203
### ChatModelTests
204
205
Base abstract class for chat model testing with extensive configuration options.
206
207
```python { .api }
208
from langchain_tests.unit_tests.chat_models import ChatModelTests
209
210
class ChatModelTests(BaseStandardTests):
211
"""Base class for chat model testing."""
212
213
# Required abstract properties
214
@property
215
def chat_model_class(self):
216
"""Chat model class to test."""
217
218
@property
219
def chat_model_params(self) -> dict:
220
"""Model initialization parameters."""
221
222
# Feature support configuration
223
@property
224
def has_tool_calling(self) -> bool:
225
"""Whether the model supports tool calling. Default: False."""
226
227
@property
228
def tool_choice_value(self):
229
"""Tool choice parameter value. Default: None."""
230
231
@property
232
def has_tool_choice(self) -> bool:
233
"""Whether the model supports tool choice. Default: False."""
234
235
@property
236
def has_structured_output(self) -> bool:
237
"""Whether the model supports structured output. Default: False."""
238
239
@property
240
def structured_output_kwargs(self) -> dict:
241
"""Additional structured output parameters. Default: {}."""
242
243
@property
244
def supports_json_mode(self) -> bool:
245
"""Whether the model supports JSON mode. Default: False."""
246
247
# Multimodal input support
248
@property
249
def supports_image_inputs(self) -> bool:
250
"""Whether the model supports image inputs. Default: False."""
251
252
@property
253
def supports_image_urls(self) -> bool:
254
"""Whether the model supports image URLs. Default: False."""
255
256
@property
257
def supports_pdf_inputs(self) -> bool:
258
"""Whether the model supports PDF inputs. Default: False."""
259
260
@property
261
def supports_audio_inputs(self) -> bool:
262
"""Whether the model supports audio inputs. Default: False."""
263
264
@property
265
def supports_video_inputs(self) -> bool:
266
"""Whether the model supports video inputs. Default: False."""
267
268
# Performance and metadata
269
@property
270
def returns_usage_metadata(self) -> bool:
271
"""Whether the model returns usage metadata. Default: False."""
272
273
@property
274
def supported_usage_metadata_details(self) -> dict:
275
"""Usage metadata details configuration. Default: {}."""
276
277
# Input format support
278
@property
279
def supports_anthropic_inputs(self) -> bool:
280
"""Whether the model supports Anthropic-style inputs. Default: False."""
281
282
@property
283
def supports_image_tool_message(self) -> bool:
284
"""Whether the model supports image tool messages. Default: False."""
285
286
# Testing configuration
287
@property
288
def enable_vcr_tests(self) -> bool:
289
"""Whether to enable VCR (HTTP recording) tests. Default: True."""
290
291
# Fixtures
292
@pytest.fixture
293
def model(self):
294
"""Chat model fixture for testing."""
295
296
@pytest.fixture
297
def my_adder_tool(self):
298
"""Tool fixture for testing tool calling functionality."""
299
```
300
301
### EmbeddingsTests
302
303
Base abstract class for embeddings model testing.
304
305
```python { .api }
306
from langchain_tests.unit_tests.embeddings import EmbeddingsTests
307
308
class EmbeddingsTests(BaseStandardTests):
309
"""Base class for embeddings testing."""
310
311
# Required abstract properties
312
@property
313
def embeddings_class(self):
314
"""Embeddings class to test."""
315
316
@property
317
def embedding_model_params(self) -> dict:
318
"""Model parameters for initialization."""
319
320
# Fixtures
321
@pytest.fixture
322
def model(self):
323
"""Embeddings model fixture for testing."""
324
```
325
326
### ToolsTests
327
328
Base abstract class for tool testing.
329
330
```python { .api }
331
from langchain_tests.unit_tests.tools import ToolsTests
332
333
class ToolsTests(BaseStandardTests):
334
"""Base class for tool testing."""
335
336
# Required abstract properties
337
@property
338
def tool_constructor(self):
339
"""Tool class or instance to test."""
340
341
@property
342
def tool_constructor_params(self) -> dict:
343
"""Constructor parameters for tool initialization."""
344
345
@property
346
def tool_invoke_params_example(self) -> dict:
347
"""Example parameters for tool invocation."""
348
349
# Fixtures
350
@pytest.fixture
351
def tool(self):
352
"""Tool fixture for testing."""
353
```
354
355
## Test Utilities
356
357
### Schema Generation Functions
358
359
Utility functions for generating test schemas and models.
360
361
```python { .api }
362
from langchain_tests.unit_tests.chat_models import (
363
generate_schema_pydantic,
364
generate_schema_pydantic_v1_from_2
365
)
366
367
def generate_schema_pydantic():
368
"""Generate a Pydantic model for testing structured output."""
369
370
def generate_schema_pydantic_v1_from_2():
371
"""Generate a Pydantic V1 model from V2 for compatibility testing."""
372
```
373
374
### Base Standard Tests
375
376
Foundation class providing override protection for all test classes.
377
378
```python { .api }
379
from langchain_tests.base import BaseStandardTests
380
381
class BaseStandardTests:
382
"""Base class for all standard tests with override protection."""
383
384
def test_no_overrides_DO_NOT_OVERRIDE(self) -> None:
385
"""Ensures standard tests aren't overridden by implementation classes."""
386
```
387
388
## Environment Variable Testing
389
390
Unit tests include support for testing initialization from environment variables, which is crucial for production deployments where API keys and configuration are provided via environment variables rather than hardcoded parameters.
391
392
### Configuration Pattern
393
394
```python
395
class TestMyModelUnit(ChatModelUnitTests):
396
@property
397
def init_from_env_params(self):
398
# Parameters to use when testing environment variable initialization
399
# These should NOT include sensitive data like API keys
400
return {
401
"model": "gpt-3.5-turbo",
402
"temperature": 0.5,
403
"max_tokens": 1000
404
}
405
```
406
407
The `test_init_from_env()` method will attempt to initialize your model class with the specified parameters, expecting that sensitive configuration like API keys will be read from environment variables rather than passed as parameters.
408
409
## Performance Testing
410
411
Unit tests include basic performance benchmarking through the `test_init_time()` method, which measures model initialization time. This helps identify performance regressions and ensures initialization stays within acceptable bounds.
412
413
The benchmark uses pytest-benchmark integration and can be configured through pytest command line options for detailed performance analysis.