0
# Testing Framework Integration
1
2
Integration with popular Python testing frameworks including unittest and pytest. pyfakefs provides seamless integration through fixtures, base classes, decorators, and context managers to automatically patch filesystem modules during test execution.
3
4
## Capabilities
5
6
### pytest Integration
7
8
Automatic pytest integration through the `fs` fixture that provides a clean fake filesystem for each test.
9
10
```python { .api }
11
def fs() -> FakeFilesystem:
12
"""
13
pytest fixture that provides a FakeFilesystem instance.
14
15
Automatically patches all filesystem modules (os, os.path, pathlib, shutil, io, open)
16
and provides a clean fake filesystem for each test function.
17
18
Returns:
19
FakeFilesystem instance for creating files and directories
20
"""
21
22
def fs_class() -> FakeFilesystem:
23
"""
24
Class-scoped pytest fixture that provides a FakeFilesystem instance.
25
26
Same as fs fixture but shared across all test methods in a test class.
27
28
Returns:
29
FakeFilesystem instance for creating files and directories
30
"""
31
32
def fs_module() -> FakeFilesystem:
33
"""
34
Module-scoped pytest fixture that provides a FakeFilesystem instance.
35
36
Same as fs fixture but shared across all tests in a module.
37
38
Returns:
39
FakeFilesystem instance for creating files and directories
40
"""
41
42
def fs_session() -> FakeFilesystem:
43
"""
44
Session-scoped pytest fixture that provides a FakeFilesystem instance.
45
46
Same as fs fixture but shared across entire test session.
47
48
Returns:
49
FakeFilesystem instance for creating files and directories
50
"""
51
```
52
53
Usage example:
54
55
```python
56
import pytest
57
58
def test_file_operations(fs):
59
"""Test using the fs fixture."""
60
# Create test files
61
fs.create_file('/test/data.txt', contents='test data')
62
fs.create_dir('/test/subdir')
63
64
# Test file operations
65
import os
66
assert os.path.exists('/test/data.txt')
67
assert os.path.isfile('/test/data.txt')
68
assert os.path.isdir('/test/subdir')
69
70
with open('/test/data.txt', 'r') as f:
71
content = f.read()
72
assert content == 'test data'
73
74
def test_pathlib_operations(fs):
75
"""Test pathlib integration."""
76
from pathlib import Path
77
78
# Create test file
79
fs.create_file('/test/pathlib.txt', contents='pathlib test')
80
81
# Use pathlib
82
path = Path('/test/pathlib.txt')
83
assert path.exists()
84
assert path.is_file()
85
assert path.read_text() == 'pathlib test'
86
```
87
88
### unittest Integration
89
90
Base test class that automatically sets up pyfakefs for unittest-based tests.
91
92
```python { .api }
93
class TestCase(unittest.TestCase):
94
"""
95
Base test class that provides automatic pyfakefs setup.
96
97
Inherits from unittest.TestCase and automatically patches filesystem modules.
98
Provides access to the fake filesystem via the 'fs' attribute.
99
"""
100
fs: FakeFilesystem
101
102
def setUpPyfakefs(
103
self,
104
modules_to_reload: List[str] = None,
105
modules_to_patch: Dict[str, str] = None,
106
additional_skip_names: List[str] = None,
107
use_known_patches: bool = True,
108
use_cache: bool = True,
109
**kwargs
110
) -> None:
111
"""
112
Set up pyfakefs for this test case.
113
114
Args:
115
modules_to_reload: List of modules to reload after patching
116
modules_to_patch: Dict of module names to patch
117
additional_skip_names: Additional modules to skip patching
118
use_known_patches: Whether to use known patches for common modules
119
use_cache: Whether to use filesystem caching
120
"""
121
122
def tearDownPyfakefs(self) -> None:
123
"""Tear down pyfakefs and restore real filesystem modules."""
124
125
@classmethod
126
def setUpClassPyfakefs(
127
cls,
128
modules_to_reload: List[str] = None,
129
modules_to_patch: Dict[str, str] = None,
130
additional_skip_names: List[str] = None,
131
use_known_patches: bool = True,
132
use_cache: bool = True,
133
**kwargs
134
) -> None:
135
"""
136
Set up pyfakefs for the entire test class (Python 3.8+).
137
138
Args:
139
modules_to_reload: List of modules to reload after patching
140
modules_to_patch: Dict of module names to patch
141
additional_skip_names: Additional modules to skip patching
142
use_known_patches: Whether to use known patches for common modules
143
use_cache: Whether to use filesystem caching
144
"""
145
```
146
147
Usage example:
148
149
```python
150
import unittest
151
import os
152
from pyfakefs.fake_filesystem_unittest import TestCase
153
154
class MyTest(TestCase):
155
def setUp(self):
156
self.setUpPyfakefs()
157
158
def test_file_creation(self):
159
# Create a test file
160
self.fs.create_file('/test/example.txt', contents='Hello World')
161
162
# Test standard file operations
163
self.assertTrue(os.path.exists('/test/example.txt'))
164
165
with open('/test/example.txt', 'r') as f:
166
content = f.read()
167
self.assertEqual(content, 'Hello World')
168
169
def test_directory_operations(self):
170
# Create directory structure
171
self.fs.create_dir('/test/subdir')
172
self.fs.create_file('/test/subdir/file.txt', contents='test')
173
174
# Test directory operations
175
self.assertTrue(os.path.isdir('/test/subdir'))
176
files = os.listdir('/test/subdir')
177
self.assertEqual(files, ['file.txt'])
178
```
179
180
### Test Mixin
181
182
Mixin class for adding pyfakefs functionality to existing test classes.
183
184
```python { .api }
185
class TestCaseMixin:
186
"""
187
Mixin for adding pyfakefs to existing test classes.
188
189
Use this when you can't inherit from pyfakefs.TestCase but want
190
to add fake filesystem functionality to your tests.
191
"""
192
fs: FakeFilesystem
193
194
def setUpPyfakefs(self, **kwargs) -> None:
195
"""Set up pyfakefs for this test."""
196
197
def tearDownPyfakefs(self) -> None:
198
"""Tear down pyfakefs and restore real filesystem."""
199
```
200
201
Usage example:
202
203
```python
204
import unittest
205
from pyfakefs.fake_filesystem_unittest import TestCaseMixin
206
207
class MyExistingTest(unittest.TestCase, TestCaseMixin):
208
def setUp(self):
209
# Existing setup code
210
super().setUp()
211
self.setUpPyfakefs()
212
213
# Additional setup with fake filesystem
214
self.fs.create_file('/config.ini', contents='[section]\nkey=value')
215
216
def tearDown(self):
217
self.tearDownPyfakefs()
218
super().tearDown()
219
220
def test_config_reading(self):
221
# Test code that reads /config.ini
222
import configparser
223
config = configparser.ConfigParser()
224
config.read('/config.ini')
225
self.assertEqual(config['section']['key'], 'value')
226
```
227
228
### Decorator for Individual Tests
229
230
Decorator to patch filesystem modules for individual test methods.
231
232
```python { .api }
233
def patchfs(
234
additional_skip_names: List[str] = None,
235
modules_to_reload: List[str] = None,
236
modules_to_patch: Dict[str, str] = None,
237
use_known_patches: bool = True,
238
use_cache: bool = True
239
) -> Callable:
240
"""
241
Decorator to patch filesystem modules for a single test function.
242
243
The decorated function receives a 'fs' parameter with the FakeFilesystem instance.
244
245
Args:
246
additional_skip_names: Additional modules to skip patching
247
modules_to_reload: List of modules to reload after patching
248
modules_to_patch: Dict of module names to patch
249
use_known_patches: Whether to use known patches for common modules
250
use_cache: Whether to use filesystem caching
251
252
Returns:
253
Decorated function with filesystem patching
254
"""
255
```
256
257
Usage example:
258
259
```python
260
import unittest
261
import os
262
from pyfakefs.fake_filesystem_unittest import patchfs
263
264
class MyTest(unittest.TestCase):
265
@patchfs
266
def test_with_fake_fs(self, fs):
267
# Create test files
268
fs.create_file('/test.txt', contents='test content')
269
270
# Test file operations
271
self.assertTrue(os.path.exists('/test.txt'))
272
with open('/test.txt', 'r') as f:
273
content = f.read()
274
self.assertEqual(content, 'test content')
275
276
def test_without_fake_fs(self):
277
# This test uses the real filesystem
278
pass
279
```
280
281
### Context Manager
282
283
Context manager for temporary filesystem patching within test methods.
284
285
```python { .api }
286
class Patcher:
287
"""
288
Context manager for temporarily patching filesystem modules.
289
290
Provides manual control over when filesystem patching is active.
291
"""
292
fs: FakeFilesystem
293
294
def __init__(
295
self,
296
additional_skip_names: List[str] = None,
297
modules_to_reload: List[str] = None,
298
modules_to_patch: Dict[str, str] = None,
299
use_known_patches: bool = True,
300
use_cache: bool = True
301
) -> None:
302
"""
303
Initialize the patcher.
304
305
Args:
306
additional_skip_names: Additional modules to skip patching
307
modules_to_reload: List of modules to reload after patching
308
modules_to_patch: Dict of module names to patch
309
use_known_patches: Whether to use known patches for common modules
310
use_cache: Whether to use filesystem caching
311
"""
312
313
def __enter__(self) -> 'Patcher':
314
"""Enter the context and start filesystem patching."""
315
316
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
317
"""Exit the context and stop filesystem patching."""
318
319
class Pause:
320
"""
321
Context manager for temporarily pausing filesystem patching.
322
323
Allows temporary access to the real filesystem during test execution.
324
"""
325
326
def __init__(self, patcher: Union[Patcher, TestCase, FakeFilesystem]) -> None:
327
"""
328
Initialize the pause context manager.
329
330
Args:
331
patcher: Patcher instance, TestCase, or FakeFilesystem to pause
332
"""
333
334
def __enter__(self) -> 'Pause':
335
"""Enter the context and pause filesystem patching."""
336
337
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
338
"""Exit the context and resume filesystem patching."""
339
```
340
341
Usage example:
342
343
```python
344
import os
345
from pyfakefs.fake_filesystem_unittest import Patcher
346
347
def test_with_context_manager():
348
# Code here uses real filesystem
349
350
with Patcher() as patcher:
351
# Create fake files
352
patcher.fs.create_file('/fake.txt', contents='fake content')
353
354
# Test with fake filesystem
355
assert os.path.exists('/fake.txt')
356
with open('/fake.txt', 'r') as f:
357
content = f.read()
358
assert content == 'fake content'
359
360
# Code here uses real filesystem again
361
```
362
363
### pytest Configuration
364
365
Configure pyfakefs behavior for pytest runs.
366
367
```python { .api }
368
def pytest_addoption(parser) -> None:
369
"""Add pyfakefs-specific command line options to pytest."""
370
371
def pytest_configure(config) -> None:
372
"""Configure pyfakefs for the pytest session."""
373
```
374
375
Command line options:
376
377
```bash
378
# Skip patching specific modules
379
pytest --fs-skip-modules=module1,module2
380
381
# Use dynamic patching (slower but more compatible)
382
pytest --fs-no-cache
383
384
# Debug filesystem patching
385
pytest --fs-debug
386
```
387
388
## Integration Types
389
390
```python { .api }
391
from typing import List, Dict, Callable, Any, Optional, Union
392
393
# Configuration types
394
ModulesToPatch = Dict[str, str]
395
ModulesToReload = List[str]
396
SkipNames = List[str]
397
398
# Decorator type
399
PatchfsDecorator = Callable[[Callable], Callable]
400
```
401
402
## Helper Functions
403
404
Helper functions for managing user context and module reloading in tests.
405
406
```python { .api }
407
def set_uid(uid: int) -> None:
408
"""
409
Set the current user ID for filesystem operations.
410
411
Args:
412
uid: User ID to emulate
413
"""
414
415
def set_gid(gid: int) -> None:
416
"""
417
Set the current group ID for filesystem operations.
418
419
Args:
420
gid: Group ID to emulate
421
"""
422
423
def get_uid() -> int:
424
"""
425
Get the current user ID being emulated.
426
427
Returns:
428
Current user ID
429
"""
430
431
def get_gid() -> int:
432
"""
433
Get the current group ID being emulated.
434
435
Returns:
436
Current group ID
437
"""
438
439
def reset_ids() -> None:
440
"""Reset user and group IDs to defaults."""
441
442
def is_root() -> bool:
443
"""
444
Check if currently emulating root user.
445
446
Returns:
447
True if uid == 0, False otherwise
448
"""
449
450
def reload_cleanup_handler(name: str) -> None:
451
"""
452
Cleanup handler for module reloading.
453
454
Args:
455
name: Module name to clean up
456
"""
457
```
458
459
Usage example:
460
461
```python
462
from pyfakefs.helpers import set_uid, set_gid, reset_ids, is_root
463
464
def test_permission_checks(fs):
465
# Test as non-root user
466
set_uid(1000)
467
set_gid(1000)
468
469
# Create file with restricted permissions
470
fs.create_file('/secret.txt', contents='confidential', st_mode=0o600)
471
472
# Test access as different user
473
set_uid(1001)
474
try:
475
with open('/secret.txt', 'r') as f:
476
content = f.read() # Should raise PermissionError
477
except PermissionError:
478
print("Access denied as expected")
479
480
# Reset to defaults
481
reset_ids()
482
```
483
484
## Doctest Integration
485
486
Integration with Python's doctest module for testing documentation examples.
487
488
```python { .api }
489
def load_doctests(
490
loader: unittest.TestLoader,
491
tests: unittest.TestSuite,
492
ignore: Any,
493
module: Any,
494
additional_skip_names: List[str] = None,
495
**kwargs
496
) -> unittest.TestSuite:
497
"""
498
Load doctests with pyfakefs support.
499
500
Use this function in your test module's load_tests function to automatically
501
patch filesystem modules when running doctests.
502
503
Args:
504
loader: Test loader instance
505
tests: Existing test suite
506
ignore: Ignored parameter (for compatibility)
507
module: Module containing doctests
508
additional_skip_names: Additional modules to skip patching
509
**kwargs: Additional pyfakefs configuration options
510
511
Returns:
512
Updated test suite with doctests
513
"""
514
```
515
516
Usage example:
517
518
```python
519
import doctest
520
import unittest
521
from pyfakefs import fake_filesystem_unittest
522
523
def load_tests(loader, tests, ignore):
524
"""Load doctests with pyfakefs support."""
525
return fake_filesystem_unittest.load_doctests(
526
loader, tests, ignore, __name__
527
)
528
529
# Example doctest in your module:
530
def create_config_file():
531
"""
532
Create a configuration file.
533
534
>>> create_config_file()
535
>>> import os
536
>>> os.path.exists('/config/settings.ini')
537
True
538
>>> with open('/config/settings.ini', 'r') as f:
539
... content = f.read()
540
>>> 'debug=true' in content
541
True
542
"""
543
import os
544
os.makedirs('/config', exist_ok=True)
545
with open('/config/settings.ini', 'w') as f:
546
f.write('[DEFAULT]\ndebug=true\n')
547
```