mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Issue 8547 - detecting and reporting that modules have been imported from the wrong location under test discovery.
This commit is contained in:
		
							parent
							
								
									1a0ce685ab
								
							
						
					
					
						commit
						e6f5e22123
					
				
					 2 changed files with 58 additions and 3 deletions
				
			
		|  | @ -173,7 +173,10 @@ def discover(self, start_dir, pattern='test*.py', top_level_dir=None): | ||||||
| 
 | 
 | ||||||
|         if not top_level_dir in sys.path: |         if not top_level_dir in sys.path: | ||||||
|             # all test modules must be importable from the top level directory |             # all test modules must be importable from the top level directory | ||||||
|             sys.path.append(top_level_dir) |             # should we *unconditionally* put the start directory in first | ||||||
|  |             # in sys.path to minimise likelihood of conflicts between installed | ||||||
|  |             # modules and development versions? | ||||||
|  |             sys.path.insert(0, top_level_dir) | ||||||
|         self._top_level_dir = top_level_dir |         self._top_level_dir = top_level_dir | ||||||
| 
 | 
 | ||||||
|         is_not_importable = False |         is_not_importable = False | ||||||
|  | @ -246,6 +249,16 @@ def _find_tests(self, start_dir, pattern): | ||||||
|                     except: |                     except: | ||||||
|                         yield _make_failed_import_test(name, self.suiteClass) |                         yield _make_failed_import_test(name, self.suiteClass) | ||||||
|                     else: |                     else: | ||||||
|  |                         mod_file = os.path.abspath(getattr(module, '__file__', full_path)) | ||||||
|  |                         realpath = os.path.splitext(mod_file)[0] | ||||||
|  |                         fullpath_noext = os.path.splitext(full_path)[0] | ||||||
|  |                         if realpath.lower() != fullpath_noext.lower(): | ||||||
|  |                             module_dir = os.path.dirname(realpath) | ||||||
|  |                             mod_name = os.path.splitext(os.path.basename(full_path))[0] | ||||||
|  |                             expected_dir = os.path.dirname(full_path) | ||||||
|  |                             msg = ("%r module incorrectly imported from %r. Expected %r. " | ||||||
|  |                                    "Is this module globally installed?") | ||||||
|  |                             raise ImportError(msg % (mod_name, module_dir, expected_dir)) | ||||||
|                         yield self.loadTestsFromModule(module) |                         yield self.loadTestsFromModule(module) | ||||||
|             elif os.path.isdir(full_path): |             elif os.path.isdir(full_path): | ||||||
|                 if not os.path.isfile(os.path.join(full_path, '__init__.py')): |                 if not os.path.isfile(os.path.join(full_path, '__init__.py')): | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| import os | import os | ||||||
|  | import re | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
| import unittest | import unittest | ||||||
|  | @ -54,8 +55,9 @@ def isfile(path): | ||||||
|         loader._get_module_from_name = lambda path: path + ' module' |         loader._get_module_from_name = lambda path: path + ' module' | ||||||
|         loader.loadTestsFromModule = lambda module: module + ' tests' |         loader.loadTestsFromModule = lambda module: module + ' tests' | ||||||
| 
 | 
 | ||||||
|         loader._top_level_dir = '/foo' |         top_level = os.path.abspath('/foo') | ||||||
|         suite = list(loader._find_tests('/foo', 'test*.py')) |         loader._top_level_dir = top_level | ||||||
|  |         suite = list(loader._find_tests(top_level, 'test*.py')) | ||||||
| 
 | 
 | ||||||
|         expected = [name + ' module tests' for name in |         expected = [name + ' module tests' for name in | ||||||
|                     ('test1', 'test2')] |                     ('test1', 'test2')] | ||||||
|  | @ -298,6 +300,46 @@ def discover(self, start_dir, pattern, top_level_dir): | ||||||
|         self.assertTrue(program.failfast) |         self.assertTrue(program.failfast) | ||||||
|         self.assertTrue(program.catchbreak) |         self.assertTrue(program.catchbreak) | ||||||
| 
 | 
 | ||||||
|  |     def test_detect_module_clash(self): | ||||||
|  |         class Module(object): | ||||||
|  |             __file__ = 'bar/foo.py' | ||||||
|  |         sys.modules['foo'] = Module | ||||||
|  |         full_path = os.path.abspath('foo') | ||||||
|  |         original_listdir = os.listdir | ||||||
|  |         original_isfile = os.path.isfile | ||||||
|  |         original_isdir = os.path.isdir | ||||||
|  | 
 | ||||||
|  |         def cleanup(): | ||||||
|  |             os.listdir = original_listdir | ||||||
|  |             os.path.isfile = original_isfile | ||||||
|  |             os.path.isdir = original_isdir | ||||||
|  |             del sys.modules['foo'] | ||||||
|  |             if full_path in sys.path: | ||||||
|  |                 sys.path.remove(full_path) | ||||||
|  |         self.addCleanup(cleanup) | ||||||
|  | 
 | ||||||
|  |         def listdir(_): | ||||||
|  |             return ['foo.py'] | ||||||
|  |         def isfile(_): | ||||||
|  |             return True | ||||||
|  |         def isdir(_): | ||||||
|  |             return True | ||||||
|  |         os.listdir = listdir | ||||||
|  |         os.path.isfile = isfile | ||||||
|  |         os.path.isdir = isdir | ||||||
|  | 
 | ||||||
|  |         loader = unittest.TestLoader() | ||||||
|  | 
 | ||||||
|  |         mod_dir = os.path.abspath('bar') | ||||||
|  |         expected_dir = os.path.abspath('foo') | ||||||
|  |         msg = re.escape(r"'foo' module incorrectly imported from %r. Expected %r. " | ||||||
|  |                 "Is this module globally installed?" % (mod_dir, expected_dir)) | ||||||
|  |         self.assertRaisesRegexp( | ||||||
|  |             ImportError, '^%s$' % msg, loader.discover, | ||||||
|  |             start_dir='foo', pattern='foo.py' | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(sys.path[0], full_path) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     unittest.main() |     unittest.main() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Michael Foord
						Michael Foord