def runTestsCB(self): """Execute all of the tests in our suite. """ trace.into('ProctorGUI', 'runTestsCB') if self.tests and self.state == 'running': # # We are already running, do nothing. # pass elif self.tests: # # The user hit Go after hitting Stop, # so resume where we left off. # self.resumeTests() else: # # Starting from scratch. # self.runTests() trace.outof() return
def __getitem__(self, key): """The key might be a full or partial module path. In all cases, it is assumed to be relative from the current point in the module tree. """ trace.into('ModuleTree', '__getitem__', key=key, outputLevel=self.TRACE_LEVEL) key_parts = self._getKeyParts(key) try: # # The first part of the key should be our child. # child_node = self.data[key_parts[0]] # # If there is a remaining part of the key, it is # the name of a node under the child node. # if len(key_parts) > 1: item = child_node['.'.join(key_parts[1:])] else: item = child_node except KeyError: trace.outof('not found', outputLevel=self.TRACE_LEVEL) raise else: trace.outof(item, outputLevel=self.TRACE_LEVEL) return item
def savePrefsCB(self, *args): trace.into('ProctorGUI', 'savePrefsCB', arguments=args) self.component('testcanvas').configure( canvas_background=self.user_preferences['background'], ) self.configureTestIconsFromPrefs() trace.outof() return
def _changeScanDirectoryVariableCB(self, *args): """Callback executed when variable containing scan directory changes. """ trace.into('ProctorGUI', '_changeScanDirectoryCB', args=args) self._buildScanner() trace.outof() return
def _getKeyParts(self, key): trace.into('ModuleTree', '_getKeyParts', key=key, outputLevel=self.TRACE_LEVEL) key_parts = key.split('.') trace.outof(key_parts, outputLevel=self.TRACE_LEVEL) return key_parts
def resetTestButtons(self): """Clear button colors """ trace.into('ProctorGUI', 'resetTestButtons') for button in self.test_buttons.values(): #button.configure(bg=self.PENDING_COLOR) button.setState('pending') trace.outof() return
def stopTest(self, test): trace.into('ProctorTestResult', 'stopTest', test=test) unittest.TestResult.stopTest(self, test) try: self._showGarbage() except Exception, err: print 'GC ERROR: ', err
def addFailure(self, test, err): trace.into('TestResult', 'addFailure', test=test, err=err) unittest.TestResult.addFailure(self, test, err) STDOUT.write('FAIL in %s\n' % test.id()) STDOUT.write(self._exc_info_to_string(err, test)) STDOUT.write('\n') STDOUT.flush() trace.outof() return
def addSuccess(self, test): trace.into('TestResult', 'addSuccess', test=test) unittest.TestResult.addSuccess(self, test) STDOUT.write('ok\n') STDOUT.flush() trace.outof() return
def __init__(self, testSuite, verbosity): trace.into('ProctorTestResult', '__init__') self.num_tests = testSuite.countTestCases() self.num_tests_run = 0 self.verbosity = verbosity unittest.TestResult.__init__(self) trace.outof() return
def resetTestsCB(self): """Reset the UI and clear all test results. """ trace.into('ProctorGUI', 'resetTestsCB') self.tests = [] self.result = None self.resetTestButtons() self.setState('idle') self.showTestOutput(None) self.updateProgress(0) trace.outof() return
def _setTestButtonColor(self, testId, color): """Set the test button to the specified color. """ trace.into('ProctorGUI', '_setTestButtonColor', testId=testId, color=color) button = self.test_buttons[testId] button.configure(bg=color) self.update_idletasks() trace.outof() return
def scan(self, directoryName): trace.into('ModuleScanner', 'scan', directoryName=directoryName, outputLevel=self.TRACE_LEVEL) if os.path.isdir(directoryName): os.path.walk(directoryName, self.walkCallback, None) else: self.walkCallback(None, os.path.dirname(directoryName), [os.path.basename(directoryName)]) trace.outof(outputLevel=self.TRACE_LEVEL) return
def _makeTestButtons(self, node, data=None): """Create a button for each test. This method is called as part of walking the module tree. """ trace.into('ProctorGUI', '_makeTestButtons') # # Get the tests # test_suite = node.getTestSuite() tests = self._flattenTestSuite(test_suite) spacing = self.user_preferences['spacing'] # # Create the buttons # for test in tests: trace.into('', 'tests', row=self._row, col=self._col) ulx = (self._button_width + spacing) * self._col uly = (self._button_height + spacing) * self._row trace.writeVar(ulx=ulx, uly=uly) command = lambda b, e, s=self, t=test.id(): s.testButtonCB(testId=t ) new_button = TestIcon( canvas=self.canvas, name=test.id(), command=command, balloonHelp=test.id(), balloonFcn=self.showTestBalloonCB, width=self._button_width, height=self._button_height, ulx=ulx, uly=uly, ) self.test_buttons[test.id()] = new_button # # Increment our position counter. # self._col += 1 if self._col == self._num_per_row: self._col = 0 self._row += 1 trace.outof() trace.outof() return
def rescanTestsCB(self): """Reload and rescan all modules looking for tests. """ trace.into('ProctorGUI', 'rescanTestsCB') if self.state == 'idle': self.busyStart() self._buildScanner() self._updateTestButtons() self.busyEnd() else: self.showError('Cannot rescan during a test run. Reset first.') trace.outof() return
def _buildScanner(self): trace.into('ProctorGUI', '_buildScanner') scan_directory = os.path.join(self.scan_directory_parent, self.scan_directory.get()) trace.write('variable: %s' % scan_directory) self.scanner = ModuleScanner() self.showMessage('busy', 'Scanning...') self.busyStart() self.scanner.scan(scan_directory) self.busyEnd() self.showMessage('busy', '') trace.outof() return
def _ignoreModule(self, module): trace.into('ModuleTree', '_ignoreModule', outputLevel=self.TRACE_LEVEL) if not module: trace.write('No module') return trace.outof(True, outputLevel=self.TRACE_LEVEL) if hasattr(module, '__proctor_ignore_module__' ) and module.__proctor_ignore_module__: trace.write('Found ignore flag') return trace.outof(True, outputLevel=self.TRACE_LEVEL) return trace.outof(False, outputLevel=self.TRACE_LEVEL)
def _loadTests(self): trace.into('ModuleTree', '_loadTests', outputLevel=self.TRACE_LEVEL) self.test_suites = {} if self._ignoreModule(self.module): trace.write('No module', outputLevel=self.TRACE_LEVEL) self.test_loader = None else: trace.write('Loading tests', outputLevel=self.TRACE_LEVEL) self.test_loader = unittest.TestLoader() self.test_loader.suiteClass = self._addTestsToSuite self.test_loader.loadTestsFromModule(self.module) #trace.writeVar(self_test_suite=self.test_suite, # outputLevel=self.TRACE_LEVEL) trace.outof(outputLevel=self.TRACE_LEVEL) return
def setState(self, newState): trace.into('ProctorGUI', 'setState', newState=newState) if newState == 'idle': self.updateProgress(0) self.showMessage('busy') self.busyEnd() enable_widgets = [ self.component('changescandirectorybtn'), self.go_button, self.rescan_button, self.reset_button, ] disable_widgets = [self.stop_button] elif newState == 'running': self.busyStart() enable_widgets = [self.stop_button] disable_widgets = [ self.component('changescandirectorybtn'), self.go_button, self.rescan_button, self.reset_button, ] elif newState == 'paused': self.busyEnd() enable_widgets = [ self.go_button, self.reset_button, ] disable_widgets = [ self.component('changescandirectorybtn'), self.rescan_button, self.stop_button, ] for w in disable_widgets: w.configure(state='disabled') for w in enable_widgets: w.configure(state='normal') self.state = newState trace.outof() return
def startTest(self, test): trace.into('ProctorTestResult', 'startTest', test=test) unittest.TestResult.startTest(self, test) desc = test.id() progress_line = '%3d/%3d %s ...' % ( self.num_tests_run + 1, self.num_tests, desc, ) STDOUT.write(progress_line) STDOUT.flush() self.num_tests_run += 1 trace.outof() return
def __init__(self, name='', parent=None): trace.into('ModuleTree', '__init__', name=name, parent=parent, outputLevel=self.TRACE_LEVEL) self.name = name self.parent = parent self.data = {} self.module = None if parent: parent.reload() self.reload() trace.outof(outputLevel=self.TRACE_LEVEL) return
def changeScanDirectoryCB(self, *args): """Callback to bring up change directory dialog. """ trace.into('ProctorGUI', 'changeScanDirectoryCB', args=args) if self.state == 'idle': file_name = tkFileDialog.askopenfilename( title='Select a file in the directory to scan...') trace.writeVar(file_name=file_name) directory_name = os.path.dirname(file_name) trace.writeVar(directory_name=directory_name) if directory_name: prefix = os.path.commonprefix( (self.scan_directory_parent, directory_name)) remainder = directory_name[len(prefix) + 1:] self.scan_directory.set(remainder) else: self.showError('Cannot rescan during a test run. Reset first.') trace.outof() return
def getTestSuite(self, full=0, category='All'): trace.into('ModuleTree', 'getTestSuite', outputLevel=self.TRACE_LEVEL) test_suite = unittest.TestSuite() # # Add our own suite of local tests # category_test_suite = self._getTestSuite(category) if category_test_suite.countTestCases(): test_suite.addTest(category_test_suite) # # Get suites from our children # if full: children = self.data.items() #children.sort() for child_name, child_node in children: child_tests = child_node.getTestSuite(full=full, category=category) if child_tests.countTestCases(): test_suite.addTest(child_tests) return trace.outof(test_suite, outputLevel=self.TRACE_LEVEL)
def __setitem__(self, key, value): trace.into('ModuleTree', '__setitem__', key=key, value=value, outputLevel=self.TRACE_LEVEL) key_parts = self._getKeyParts(key) trace.writeVar(key_parts=key_parts, outputLevel=self.TRACE_LEVEL) # # Separate the part of the key that is the name of the # value from the path to the key. # value_name = key_parts[-1] key_parts = key_parts[:-1] trace.writeVar(value_name=value_name, key_parts=key_parts, outputLevel=self.TRACE_LEVEL) # # Create intermediate nodes, if necessary. # child_node = self for node_name in key_parts: trace.write('handling node name %s' % node_name, outputLevel=self.TRACE_LEVEL) try: trace.write('looking for %s' % node_name, outputLevel=self.TRACE_LEVEL) child_node = child_node[node_name] trace.write('got %s' % node_name, outputLevel=self.TRACE_LEVEL) except KeyError: trace.write('creating child node', outputLevel=self.TRACE_LEVEL) new_child_node = child_node.newNode(name=node_name) child_node.data[node_name] = new_child_node child_node = new_child_node trace.write('created %s' % node_name, outputLevel=self.TRACE_LEVEL) child_node.data[value_name] = child_node.newNode(value_name) trace.outof(outputLevel=self.TRACE_LEVEL) return
def _updateTestButtons(self): """Update the actual test buttons. Remove any existing buttons, and make new buttons to correspond to each test. """ trace.into('ProctorGUI', '_updateTestButtons') # # Remove any existing buttons # for name, button in self.test_buttons.items(): button.delete() del self.test_buttons[name] self.update_idletasks() # # Make the new buttons # if self.scanner: module_tree = self.scanner.getModuleTree() self.test_buttons = {} self._createAllTestButtons(module_tree) trace.outof() return
def _importModule(self): trace.into('ModuleTree', '_importModule', outputLevel=self.TRACE_LEVEL) if self.name: try: full_name = self.getName() path_name = full_name.replace('.', '/') directory, module_base = os.path.split(path_name) trace.write('find_module(%s, [%s])' % (module_base, directory), outputLevel=self.TRACE_LEVEL) module = None global _module_cache try: module = _module_cache[(module_base, directory)] trace.write('Found module %s.%s in cache' % ( directory, module_base, )) except KeyError: if self.parent and self.parent.module: trace.write('using parent search path') search_path = self.parent.module.__path__ else: trace.write( 'using directory from filename for search path') search_path = [directory] trace.write('Searching for %s in %s' % (module_base, search_path)) fp, pathname, description = imp.find_module( module_base, search_path) trace.writeVar(module_base=module_base, fp=fp, pathname=pathname, description=description, outputLevel=self.TRACE_LEVEL) try: # HACK ALERT: # Add a fake prefix to the module so we effectivly import it # into our own namespace. That prevents errors if the # test module wants to import other modules from the # same package which we might not have already imported, # since the sys.modules lookup will not return the module # we imported for testing purposes. load_module_args = ('test: %s' % full_name, fp, pathname, description) trace.write('load_module%s' % str(load_module_args), outputLevel=self.TRACE_LEVEL) try: module = imp.load_module(*load_module_args) except Exception, msg: trace.write('ImportError(%s)' % str(msg)) trace.showTraceback() raise ImportError(str(msg)) else: trace.write('Imported %s (%s)' % (str(module), id(module))) trace.write('Updating cache') _module_cache[(module_base, directory)] = module finally: if fp: fp.close()
def __init__(self, verboseLevel=0): trace.into('ModuleScanner', '__init__', outputLevel=self.TRACE_LEVEL) self.verbose_level = verboseLevel self.module_tree = ModuleTree() trace.outof(outputLevel=self.TRACE_LEVEL) return
def walkCallback(self, arg, dirname, filenames): trace.into('ModuleScanner', 'walkCallback', arg=arg, dirname=dirname, filenames=filenames, outputLevel=self.TRACE_LEVEL) if self.verbose_level: print 'Scanning: %s' % (dirname or '.') sys.stdout.flush() # # Create a local copy of the names to skip, then add # .cvsignore content to it if the file exists. # skip_names = list(self.SKIP_NAMES[:]) if '.cvsignore' in filenames: try: ignore_file = open(os.path.join(dirname, '.cvsignore'), 'r') except IOError: trace.write('Unable to open .cvsignore file in %s' % dirname) else: ignore_files = ignore_file.readlines() ignore_file.close() ignore_files = [f.strip() for f in ignore_files] skip_names = skip_names + ignore_files # # Update the local copy of the names to skip # with .proctor configuration if the file exists. # if '.proctor' in filenames: try: proctor_file = open(os.path.join(dirname, '.proctor'), 'r') except IOError: trace.write('Unable to open .proctor file in %s' % dirname) else: proctor_file_body = proctor_file.read() proctor_file.close() global_namespace = {} local_namespace = {} try: exec proctor_file_body in global_namespace, local_namespace except: import traceback sys.stderr.write( '\n--- Config File Error %s/.proctor ---\n' % dirname) traceback.print_exc() sys.stderr.write( '--------------------------------------------\n\n') else: skip_names = skip_names + list(local_namespace['ignore']) # # First, skip over directories we are not interested in # scanning. # for skip_name in skip_names: if skip_name in filenames: trace.write('Skipping %s' % skip_name, outputLevel=self.TRACE_LEVEL) del filenames[filenames.index(skip_name)] # # Clean up the directory name # normalized_dirname = os.path.normpath(dirname) trace.write('normalized path=%s' % normalized_dirname, outputLevel=self.TRACE_LEVEL) # # Get the relative path # common_prefix = os.path.commonprefix((os.getcwd(), normalized_dirname)) if common_prefix: prefix_len = len(common_prefix) + len(os.sep) normalized_dirname = normalized_dirname[prefix_len:] # # Convert the directory name to a module path # dirname_parts = normalized_dirname.split(os.sep) package_path = '.'.join(dirname_parts) trace.writeVar(package_path=package_path, outputLevel=self.TRACE_LEVEL) for filename in filenames: # # Skip files with bad extensions or prefixes. # base_filename, extension = os.path.splitext(filename) extension = extension[1:] if extension in self.SKIP_FILE_EXTENSIONS: trace.write('Skipping file %s/%s' % (normalized_dirname, filename), outputLevel=self.TRACE_LEVEL) elif filename[0] == '.': trace.write('Skipping file %s/%s' % (normalized_dirname, filename), outputLevel=self.TRACE_LEVEL) elif extension == 'py': # # If we are looking in ., put the new module # at the root of the module tree. Otherwise, # build the import path to the module as the # key. # if package_path == os.curdir: module_path = base_filename else: module_path = '%s.%s' % (package_path, base_filename) trace.write('Adding %s' % module_path, outputLevel=self.TRACE_LEVEL) self.module_tree[module_path] = module_path else: trace.write('Skipping file %s/%s' % (normalized_dirname, filename), outputLevel=self.TRACE_LEVEL) trace.outof(outputLevel=self.TRACE_LEVEL) return
def _createAllTestButtons(self, moduleTree=None): trace.into('ProctorGUI', '_createAllTestButtons') all_tests = moduleTree.getTestSuite(1) num_tests = all_tests.countTestCases() self.showMessage('userevent', '%d tests' % num_tests) trace.writeVar(num_tests=num_tests) # # Get preferences # width = self.user_preferences['width'] height = self.user_preferences['height'] spacing = self.user_preferences['spacing'] # # Do some math to figure out how big to make the buttons. # Lean towards a more horizontal layout. # canvas_height = self.canvas.winfo_height() canvas_width = self.canvas.winfo_width() trace.writeVar( canvas_height=canvas_height, canvas_width=canvas_width, ) num_per_row = ((canvas_width / (width + spacing)) or 1) num_rows = (num_tests / num_per_row) if (num_tests % num_per_row): num_rows += 1 # # Store values for use later # self._button_height = height self._button_width = width self._num_per_row = num_per_row self._row = 0 self._col = 0 # # Resize the canvas (height only) # required_height = num_rows * (self._button_height + spacing) trace.writeVar(required_height=required_height) if canvas_height > (required_height + self._button_height): trace.write('resizing down') do_resize = 1 elif canvas_height < required_height: trace.write('resizing up') do_resize = 1 else: do_resize = 0 if do_resize: canvas = self.component('testcanvas') hull = canvas.component('hull') hull.configure(height=required_height) moduleTree.walk(self._makeTestButtons) trace.outof() return