Skip to content

Commit f245afb

Browse files
janneronkkomrbean-bremen
authored andcommitted
Split TestCase into mixin class and TestCase class
Having TestCaseMixin allows you to use PyFakeFs with, for example, asynctest.TestCase or django.test.TestCase.
1 parent 89b091e commit f245afb

File tree

2 files changed

+105
-67
lines changed

2 files changed

+105
-67
lines changed

Diff for: pyfakefs/fake_filesystem_unittest.py

+91-67
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,92 @@ def load_doctests(loader, tests, ignore, module,
103103
return tests
104104

105105

106-
class TestCase(unittest.TestCase):
106+
class TestCaseMixin(object):
107+
"""Test case mixin that automatically replaces file-system related
108+
modules by fake implementations.
109+
110+
Attributes:
111+
additional_skip_names: names of modules inside of which no module
112+
replacement shall be performed, in addition to the names in
113+
:py:attr:`fake_filesystem_unittest.Patcher.SKIPNAMES`.
114+
patch_path: if False, modules named *path* will not be patched with
115+
the fake ``os.path`` module. Set this to False when you need
116+
to import some other module named ``path``, for example::
117+
118+
from my_module import path
119+
120+
Irrespective of patch_path, module ``os.path`` is still
121+
correctly faked if imported the usual way using ``import
122+
os`` or ``import os.path``.
123+
modules_to_reload: A list of modules that need to be reloaded
124+
to be patched dynamically; may be needed if the module
125+
imports file system modules under an alias
126+
127+
.. note:: This is done independently of `use_dynamic_patch`
128+
129+
.. caution:: Reloading modules may have unwanted side effects.
130+
use_dynamic_patch: If `True`, dynamic patching after setup is used
131+
(for example for modules loaded locally inside of functions).
132+
Can be switched off if it causes unwanted side effects.
133+
modules_to_patch: A dictionary of fake modules mapped to the
134+
patched module names. Can be used to add patching of modules
135+
not provided by `pyfakefs`.
136+
If you want to patch a class in a module imported using
137+
`from some_module import SomeClass`, you have to specify
138+
`some_module.Class` as the key for the fake class.
139+
140+
If you specify attributes `additional_skip_names` or `patch_path` here
141+
and you have DocTests, consider also specifying the same arguments to
142+
:py:func:`load_doctests`.
143+
144+
Example usage in derived test classes::
145+
146+
from unittest import TestCase
147+
from fake_filesystem_unittest import TestCaseMixin
148+
149+
class MyTestCase(TestCase, TestCaseMixin):
150+
def __init__(self, methodName='runTest'):
151+
super(MyTestCase, self).__init__(
152+
methodName=methodName,
153+
additional_skip_names=['posixpath'])
154+
155+
import sut
156+
157+
class AnotherTestCase(TestCase, TestCaseMixin):
158+
def __init__(self, methodName='runTest'):
159+
super(MyTestCase, self).__init__(
160+
methodName=methodName, modules_to_reload=[sut])
161+
"""
162+
163+
additional_skip_names = None
164+
patch_patch = True
165+
modules_to_reload = None
166+
use_dynamic_patch = True
167+
modules_to_patch = None
168+
169+
@property
170+
def fs(self):
171+
return self._stubber.fs
172+
173+
def setUpPyfakefs(self):
174+
"""Bind the file-related modules to the :py:class:`pyfakefs` fake file
175+
system instead of the real file system. Also bind the fake `open()`
176+
function, and on Python 2, the `file()` function.
177+
178+
Invoke this at the beginning of the `setUp()` method in your unit test
179+
class.
180+
"""
181+
self._stubber = Patcher(additional_skip_names=self.additional_skip_names,
182+
patch_path=self.patch_path,
183+
use_dynamic_patch=self.use_dynamic_patch,
184+
modules_to_reload=self.modules_to_reload,
185+
modules_to_patch=self.modules_to_patch)
186+
187+
self._stubber.setUp()
188+
self.addCleanup(self._stubber.tearDown)
189+
190+
191+
class TestCase(unittest.TestCase, TestCaseMixin):
107192
"""Test case class that automatically replaces file-system related
108193
modules by fake implementations.
109194
"""
@@ -120,64 +205,14 @@ def __init__(self, methodName='runTest',
120205
Args:
121206
methodName: The name of the test method (same as in
122207
unittest.TestCase)
123-
additional_skip_names: names of modules inside of which no module
124-
replacement shall be performed, in addition to the names in
125-
:py:attr:`fake_filesystem_unittest.Patcher.SKIPNAMES`.
126-
patch_path: if False, modules named *path* will not be patched with
127-
the fake ``os.path`` module. Set this to False when you need
128-
to import some other module named ``path``, for example::
129-
130-
from my_module import path
131-
132-
Irrespective of patch_path, module ``os.path`` is still
133-
correctly faked if imported the usual way using ``import
134-
os`` or ``import os.path``.
135-
modules_to_reload: A list of modules that need to be reloaded
136-
to be patched dynamically; may be needed if the module
137-
imports file system modules under an alias
138-
139-
.. note:: This is done independently of `use_dynamic_patch`
140-
141-
.. caution:: Reloading modules may have unwanted side effects.
142-
use_dynamic_patch: If `True`, dynamic patching after setup is used
143-
(for example for modules loaded locally inside of functions).
144-
Can be switched off if it causes unwanted side effects.
145-
modules_to_patch: A dictionary of fake modules mapped to the
146-
patched module names. Can be used to add patching of modules
147-
not provided by `pyfakefs`.
148-
If you want to patch a class in a module imported using
149-
`from some_module import SomeClass`, you have to specify
150-
`some_module.Class` as the key for the fake class.
151-
152-
If you specify arguments `additional_skip_names` or `patch_path` here
153-
and you have DocTests, consider also specifying the same arguments to
154-
:py:func:`load_doctests`.
155-
156-
Example usage in derived test classes::
157-
158-
class MyTestCase(fake_filesystem_unittest.TestCase):
159-
def __init__(self, methodName='runTest'):
160-
super(MyTestCase, self).__init__(
161-
methodName=methodName,
162-
additional_skip_names=['posixpath'])
163-
164-
import sut
165-
166-
class AnotherTestCase(fake_filesystem_unittest.TestCase):
167-
def __init__(self, methodName='runTest'):
168-
super(MyTestCase, self).__init__(
169-
methodName=methodName, modules_to_reload=[sut])
170208
"""
171209
super(TestCase, self).__init__(methodName)
172-
self._stubber = Patcher(additional_skip_names=additional_skip_names,
173-
patch_path=patch_path,
174-
use_dynamic_patch=use_dynamic_patch,
175-
modules_to_reload=modules_to_reload,
176-
modules_to_patch=modules_to_patch)
177210

178-
@property
179-
def fs(self):
180-
return self._stubber.fs
211+
self.additional_skip_names = additional_skip_names
212+
self.patch_path = patch_path
213+
self.modules_to_reload = modules_to_reload
214+
self.use_dynamic_patch = use_dynamic_patch
215+
self.modules_to_patch = modules_to_patch
181216

182217
@Deprecator('add_real_file')
183218
def copyRealFile(self, real_file_path, fake_file_path=None,
@@ -219,17 +254,6 @@ def copyRealFile(self, real_file_path, fake_file_path=None,
219254
"supports NOT creating missing directories")
220255
return self._stubber.fs.add_real_file(real_file_path, read_only=False)
221256

222-
def setUpPyfakefs(self):
223-
"""Bind the file-related modules to the :py:class:`pyfakefs` fake file
224-
system instead of the real file system. Also bind the fake `open()`
225-
function, and on Python 2, the `file()` function.
226-
227-
Invoke this at the beginning of the `setUp()` method in your unit test
228-
class.
229-
"""
230-
self._stubber.setUp()
231-
self.addCleanup(self._stubber.tearDown)
232-
233257
@DeprecationWarning
234258
def tearDownPyfakefs(self):
235259
"""This method is deprecated and exists only for backward

Diff for: tests/fake_filesystem_unittest_test.py

+14
Original file line numberDiff line numberDiff line change
@@ -324,5 +324,19 @@ def test_add_real_directory(self):
324324
self.assertTrue(self.fs.exists(os.path.join(real_dir_path, 'fake_filesystem.py')))
325325

326326

327+
class TestPyfakefsTestCase(unittest.TestCase):
328+
def setUp(self):
329+
class TestTestCase(fake_filesystem_unittest.TestCase):
330+
def runTest(self):
331+
pass
332+
333+
self.test_case = TestTestCase('runTest')
334+
335+
def test_test_case_type(self):
336+
self.assertIsInstance(self.test_case, unittest.TestCase)
337+
338+
self.assertIsInstance(self.test_case, fake_filesystem_unittest.TestCaseMixin)
339+
340+
327341
if __name__ == "__main__":
328342
unittest.main()

0 commit comments

Comments
 (0)