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: | ||||
|             # 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 | ||||
| 
 | ||||
|         is_not_importable = False | ||||
|  | @ -246,6 +249,16 @@ def _find_tests(self, start_dir, pattern): | |||
|                     except: | ||||
|                         yield _make_failed_import_test(name, self.suiteClass) | ||||
|                     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) | ||||
|             elif os.path.isdir(full_path): | ||||
|                 if not os.path.isfile(os.path.join(full_path, '__init__.py')): | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import os | ||||
| import re | ||||
| import sys | ||||
| 
 | ||||
| import unittest | ||||
|  | @ -54,8 +55,9 @@ def isfile(path): | |||
|         loader._get_module_from_name = lambda path: path + ' module' | ||||
|         loader.loadTestsFromModule = lambda module: module + ' tests' | ||||
| 
 | ||||
|         loader._top_level_dir = '/foo' | ||||
|         suite = list(loader._find_tests('/foo', 'test*.py')) | ||||
|         top_level = os.path.abspath('/foo') | ||||
|         loader._top_level_dir = top_level | ||||
|         suite = list(loader._find_tests(top_level, 'test*.py')) | ||||
| 
 | ||||
|         expected = [name + ' module tests' for name in | ||||
|                     ('test1', 'test2')] | ||||
|  | @ -298,6 +300,46 @@ def discover(self, start_dir, pattern, top_level_dir): | |||
|         self.assertTrue(program.failfast) | ||||
|         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__': | ||||
|     unittest.main() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Michael Foord
						Michael Foord