Skip to content

Commit

Permalink
Patch only modules with fake_filesystem_unittest.Patcher
Browse files Browse the repository at this point in the history
  • Loading branch information
john McGehee authored and mrbean-bremen committed Apr 14, 2017
1 parent 8548384 commit f6fc906
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 25 deletions.
28 changes: 25 additions & 3 deletions fake_filesystem_unittest_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,38 @@ def test_fakepathlib(self):
else:
self.assertTrue(self.fs.Exists('/fake_file.txt'))

import math as path

sys.path.append(os.path.join(os.path.dirname(__file__), 'fixtures'))
import module_with_attributes


class TestAttributesWithFakeModuleNames(TestPyfakefsUnittestBase):
"""Test that module attributes with names like `path` or `io` are not
stubbed out.
"""

def testAttributes(self):
"""Attributes of module under test are not patched"""
global path

self.assertEqual(module_with_attributes.os, 'os attribute value')
self.assertEqual(module_with_attributes.path, 'path attribute value')
self.assertEqual(module_with_attributes.pathlib, 'pathlib attribute value')
self.assertEqual(module_with_attributes.shutil, 'shutil attribute value')
self.assertEqual(module_with_attributes.tempfile, 'tempfile attribute value')
self.assertEqual(module_with_attributes.io, 'io attribute value')


import math as path
class TestPatchPathUnittestFailing(TestPyfakefsUnittestBase):
"""Tests the default behavior regarding the argument patch_path:
An own path module (in this case an alias to math) cannot be imported,
because it is faked by FakePathModule
"""

def __init__(self, methodName='runTest'):
super(TestPatchPathUnittestFailing, self).__init__(methodName, patch_path=True)
super(TestPatchPathUnittestFailing, self).__init__(methodName,
patch_path=True)

@unittest.expectedFailure
def test_own_path_module(self):
Expand All @@ -161,7 +182,8 @@ class TestPatchPathUnittestPassing(TestPyfakefsUnittestBase):
"""

def __init__(self, methodName='runTest'):
super(TestPatchPathUnittestPassing, self).__init__(methodName, patch_path=False)
super(TestPatchPathUnittestPassing, self).__init__(methodName,
patch_path=False)

def test_own_path_module(self):
self.assertEqual(2, path.floor(2.5))
Expand Down
Empty file added fixtures/__init__.py
Empty file.
31 changes: 31 additions & 0 deletions fixtures/module_with_attributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2017 John McGehee
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module is for testing pyfakefs
:py:class:`fake_filesystem_unittest.Patcher`. It defines attributes that have
the same names as file modules, sudh as 'io` and `path`. Since these are not
modules, :py:class:`fake_filesystem_unittest.Patcher` should not patch them.
Whenever a new module is added to
:py:meth:`fake_filesystem_unittest.Patcher._findModules`, the corresponding
attribute should be added here and in the test
:py:class:`fake_filesystem_unittest_test.TestAttributesWithFakeModuleNames`.
"""

os = 'os attribute value'
path = 'path attribute value'
pathlib = 'pathlib attribute value'
shutil = 'shutil attribute value'
tempfile = 'tempfile attribute value'
io = 'io attribute value'
68 changes: 46 additions & 22 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
for unit tests using the :py:class:`pyfakefs` module.
`fake_filesystem_unittest.TestCase` searches `sys.modules` for modules
that import the `os`, `io`, `path`, and `tempfile` modules.
that import the `os`, `io`, `path` `shutil`, `pathlib`, and `tempfile`
modules.
The `setUpPyfakefs()` method binds these modules to the corresponding fake
modules from `pyfakefs`. Further, the `open()` built-in is bound to a fake
Expand Down Expand Up @@ -67,9 +68,19 @@
"""The real (not faked) `os` module."""


def load_doctests(loader, tests, ignore, module): # pylint: disable=unused-argument
"""Load the doctest tests for the specified module into unittest."""
_patcher = Patcher()
def load_doctests(loader, tests, ignore, module,
additional_skip_names=None, patch_path=True): # pylint: disable=unused-argument
"""Load the doctest tests for the specified module into unittest.
Args:
loader, tests, ignore : arguments passed in from `load_tests()`
module: module under test
additional_skip_names: see :py:class:`TestCase` for an explanation
patch_path: see :py:class:`TestCase` for an explanation
File `example_test.py` in the pyfakefs release provides a usage example.
"""
_patcher = Patcher(additional_skip_names=additional_skip_names,
patch_path=patch_path)
globs = _patcher.replaceGlobs(vars(module))
tests.addTests(doctest.DocTestSuite(module,
globs=globs,
Expand All @@ -88,18 +99,22 @@ def __init__(self, methodName='runTest', additional_skip_names=None, patch_path=
file system related modules.
Args:
methodName: the name of the test method (as in unittest.TestCase)
additional_skip_names: names of modules inside of which no module replacement
shall be done
(additionally to the hard-coded list: 'os', 'glob', 'path', 'tempfile', 'io')
methodName: the name of the test method (same as unittest.TestCase)
additional_skip_names: names of modules inside of which no module
replacement shall be performed, in addition to the names in
attribute :py:attr:`fake_filesystem_unittest.Patcher.SKIPNAMES`.
patch_path: if False, modules named 'path' will not be patched with the
fake 'os.path' module. Set this to False when you need to import
some other module named 'path', for example,
`from my_module import path`
Irrespective of patch_path, module 'os.path' is still correctly faked
if imported the usual way using `import os` or `import os.path`.
some other module named 'path', for example::
from my_module import path
Irrespective of patch_path, module 'os.path' is still correctly faked
if imported the usual way using `import os` or `import os.path`.
Example usage in a derived test class:
If you specify arguments `additional_skip_names` or `patch_path` here
and you have DocTests, consider also specifying the same arguments to
:py:func:`load_doctests`.
Example usage in a derived test class::
class MyTestCase(fake_filesystem_unittest.TestCase):
def __init__(self, methodName='runTest'):
Expand Down Expand Up @@ -190,9 +205,14 @@ class Patcher(object):
"""
Instantiate a stub creator to bind and un-bind the file-related modules to
the :py:mod:`pyfakefs` fake modules.
For usage outside of TestCase (for example with pytest) use:
>>> with Patcher():
>>> doStuff()
The arguments are explained in :py:class:`TestCase`.
:py:class:`Patcher` is used in :py:class:`TestCase`. :py:class:`Patcher`
also works as a context manager for PyTest::
with Patcher():
doStuff()
"""
SKIPMODULES = set([None, fake_filesystem, fake_filesystem_shutil,
fake_tempfile, sys])
Expand Down Expand Up @@ -276,17 +296,21 @@ def _findModules(self):
(not inspect.ismodule(module)) or
name.split('.')[0] in self._skipNames):
continue
if 'os' in module.__dict__:
# IMPORTANT TESTING NOTE: Whenever you add a new module below, test
# it by adding an attribute in fixtures/module_with_attributes.py
# and a test in fake_filesystem_unittest_test.py, class
# TestAttributesWithFakeModuleNames.
if inspect.ismodule(module.__dict__.get('os')):
self._os_modules.add(module)
if self._patchPath and 'path' in module.__dict__:
if self._patchPath and inspect.ismodule(module.__dict__.get('path')):
self._path_modules.add(module)
if self.HAS_PATHLIB and 'pathlib' in module.__dict__:
if self.HAS_PATHLIB and inspect.ismodule(module.__dict__.get('pathlib')):
self._pathlib_modules.add(module)
if 'shutil' in module.__dict__:
if inspect.ismodule(module.__dict__.get('shutil')):
self._shutil_modules.add(module)
if 'tempfile' in module.__dict__:
if inspect.ismodule(module.__dict__.get('tempfile')):
self._tempfile_modules.add(module)
if 'io' in module.__dict__:
if inspect.ismodule(module.__dict__.get('io')):
self._io_modules.add(module)

def _refresh(self):
Expand Down

0 comments on commit f6fc906

Please sign in to comment.