From 8b6477c23d47472e06fbfe09807237ac5afb3e17 Mon Sep 17 00:00:00 2001 From: Wulian233 <71213467+Wulian233@users.noreply.github.com> Date: Sat, 25 May 2024 18:38:46 +0800 Subject: [PATCH] Delete my last PR files --- Tools/unittestgui/unittestgui.py | 480 ------------------------------- 1 file changed, 480 deletions(-) delete mode 100755 Tools/unittestgui/unittestgui.py diff --git a/Tools/unittestgui/unittestgui.py b/Tools/unittestgui/unittestgui.py deleted file mode 100755 index 70fff31754eb37..00000000000000 --- a/Tools/unittestgui/unittestgui.py +++ /dev/null @@ -1,480 +0,0 @@ -#!/usr/bin/env python3 -""" -GUI framework and application for use with Python unit testing framework. -Execute tests written using the framework provided by the 'unittest' module. - -Updated for unittest test discovery by Mark Roddy and Python 3 -support by Brian Curtin. - -Based on the original by Steve Purcell, from: - - http://pyunit.sourceforge.net/ - -Copyright (c) 1999, 2000, 2001 Steve Purcell -This module is free software, and you may redistribute it and/or modify -it under the same terms as Python itself, so long as this copyright message -and disclaimer are retained in their original form. - -IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, -SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF -THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - -THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, -AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, -SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -""" - -__author__ = "Steve Purcell (stephen_purcell@yahoo.com)" - -import sys -import traceback -import unittest - -import tkinter as tk -from tkinter import messagebox -from tkinter import filedialog -from tkinter import simpledialog - - -if sys.platform == 'win32': - from idlelib.util import fix_win_hidpi - fix_win_hidpi() - - -############################################################################## -# GUI framework classes -############################################################################## - -class BaseGUITestRunner(object): - """Subclass this class to create a GUI TestRunner that uses a specific - windowing toolkit. The class takes care of running tests in the correct - manner, and making callbacks to the derived class to obtain information - or signal that events have occurred. - """ - def __init__(self, *args, **kwargs): - self.currentResult = None - self.running = 0 - self.__rollbackImporter = RollbackImporter() - self.test_suite = None - - #test discovery variables - self.directory_to_read = '' - self.top_level_dir = '' - self.test_file_glob_pattern = 'test*.py' - - self.initGUI(*args, **kwargs) - - def errorDialog(self, title, message): - "Override to display an error arising from GUI usage" - pass - - def getDirectoryToDiscover(self): - "Override to prompt user for directory to perform test discovery" - pass - - def runClicked(self): - "To be called in response to user choosing to run a test" - if self.running: return - if not self.test_suite: - self.errorDialog("Test Discovery", "You discover some tests first!") - return - self.currentResult = GUITestResult(self) - self.totalTests = self.test_suite.countTestCases() - self.running = 1 - self.notifyRunning() - self.test_suite.run(self.currentResult) - self.running = 0 - self.notifyStopped() - - def stopClicked(self): - "To be called in response to user stopping the running of a test" - if self.currentResult: - self.currentResult.stop() - - def discoverClicked(self): - self.__rollbackImporter.rollbackImports() - directory = self.getDirectoryToDiscover() - if not directory: - return - self.directory_to_read = directory - try: - # Explicitly use 'None' value if no top level directory is - # specified (indicated by empty string) as discover() explicitly - # checks for a 'None' to determine if no tld has been specified - top_level_dir = self.top_level_dir or None - tests = unittest.defaultTestLoader.discover(directory, self.test_file_glob_pattern, top_level_dir) - self.test_suite = tests - except: - exc_type, exc_value, exc_tb = sys.exc_info() - traceback.print_exception(*sys.exc_info()) - self.errorDialog("Unable to run test '%s'" % directory, - "Error loading specified test: %s, %s" % (exc_type, exc_value)) - return - self.notifyTestsDiscovered(self.test_suite) - - # Required callbacks - - def notifyTestsDiscovered(self, test_suite): - "Override to display information about the suite of discovered tests" - pass - - def notifyRunning(self): - "Override to set GUI in 'running' mode, enabling 'stop' button etc." - pass - - def notifyStopped(self): - "Override to set GUI in 'stopped' mode, enabling 'run' button etc." - pass - - def notifyTestFailed(self, test, err): - "Override to indicate that a test has just failed" - pass - - def notifyTestErrored(self, test, err): - "Override to indicate that a test has just errored" - pass - - def notifyTestSkipped(self, test, reason): - "Override to indicate that test was skipped" - pass - - def notifyTestFailedExpectedly(self, test, err): - "Override to indicate that test has just failed expectedly" - pass - - def notifyTestStarted(self, test): - "Override to indicate that a test is about to run" - pass - - def notifyTestFinished(self, test): - """Override to indicate that a test has finished (it may already have - failed or errored)""" - pass - - -class GUITestResult(unittest.TestResult): - """A TestResult that makes callbacks to its associated GUI TestRunner. - Used by BaseGUITestRunner. Need not be created directly. - """ - def __init__(self, callback): - unittest.TestResult.__init__(self) - self.callback = callback - - def addError(self, test, err): - unittest.TestResult.addError(self, test, err) - self.callback.notifyTestErrored(test, err) - - def addFailure(self, test, err): - unittest.TestResult.addFailure(self, test, err) - self.callback.notifyTestFailed(test, err) - - def addSkip(self, test, reason): - super(GUITestResult,self).addSkip(test, reason) - self.callback.notifyTestSkipped(test, reason) - - def addExpectedFailure(self, test, err): - super(GUITestResult,self).addExpectedFailure(test, err) - self.callback.notifyTestFailedExpectedly(test, err) - - def stopTest(self, test): - unittest.TestResult.stopTest(self, test) - self.callback.notifyTestFinished(test) - - def startTest(self, test): - unittest.TestResult.startTest(self, test) - self.callback.notifyTestStarted(test) - - -class RollbackImporter: - """This tricky little class is used to make sure that modules under test - will be reloaded the next time they are imported. - """ - def __init__(self): - self.previousModules = sys.modules.copy() - - def rollbackImports(self): - for modname in sys.modules.copy().keys(): - if not modname in self.previousModules: - # Force reload when modname next imported - del(sys.modules[modname]) - - -############################################################################## -# Tkinter GUI -############################################################################## - -class DiscoverSettingsDialog(simpledialog.Dialog): - """ - Dialog box for prompting test discovery settings - """ - - def __init__(self, master, top_level_dir, test_file_glob_pattern, *args, **kwargs): - self.top_level_dir = top_level_dir - self.dirVar = tk.StringVar() - self.dirVar.set(top_level_dir) - - self.test_file_glob_pattern = test_file_glob_pattern - self.testPatternVar = tk.StringVar() - self.testPatternVar.set(test_file_glob_pattern) - - simpledialog.Dialog.__init__(self, master, title="Discover Settings", - *args, **kwargs) - - def body(self, master): - tk.Label(master, text="Top Level Directory").grid(row=0) - self.e1 = tk.Entry(master, textvariable=self.dirVar) - self.e1.grid(row = 0, column=1) - tk.Button(master, text="...", - command=lambda: self.selectDirClicked(master)).grid(row=0,column=3) - - tk.Label(master, text="Test File Pattern").grid(row=1) - self.e2 = tk.Entry(master, textvariable = self.testPatternVar) - self.e2.grid(row = 1, column=1) - return None - - def selectDirClicked(self, master): - dir_path = filedialog.askdirectory(parent=master) - if dir_path: - self.dirVar.set(dir_path) - - def apply(self): - self.top_level_dir = self.dirVar.get() - self.test_file_glob_pattern = self.testPatternVar.get() - -class TkTestRunner(BaseGUITestRunner): - """An implementation of BaseGUITestRunner using Tkinter. - """ - def initGUI(self, root, initialTestName): - """Set up the GUI inside the given root window. The test name entry - field will be pre-filled with the given initialTestName. - """ - self.root = root - - self.statusVar = tk.StringVar() - self.statusVar.set("Idle") - - #tk vars for tracking counts of test result types - self.runCountVar = tk.IntVar() - self.failCountVar = tk.IntVar() - self.errorCountVar = tk.IntVar() - self.skipCountVar = tk.IntVar() - self.expectFailCountVar = tk.IntVar() - self.remainingCountVar = tk.IntVar() - - self.top = tk.Frame() - self.top.pack(fill=tk.BOTH, expand=1) - self.createWidgets() - - def getDirectoryToDiscover(self): - return filedialog.askdirectory() - - def settingsClicked(self): - d = DiscoverSettingsDialog(self.top, self.top_level_dir, self.test_file_glob_pattern) - self.top_level_dir = d.top_level_dir - self.test_file_glob_pattern = d.test_file_glob_pattern - - def notifyTestsDiscovered(self, test_suite): - discovered = test_suite.countTestCases() - self.runCountVar.set(0) - self.failCountVar.set(0) - self.errorCountVar.set(0) - self.remainingCountVar.set(discovered) - self.progressBar.setProgressFraction(0.0) - self.errorListbox.delete(0, tk.END) - self.statusVar.set("Discovering tests from %s. Found: %s" % - (self.directory_to_read, discovered)) - self.stopGoButton['state'] = tk.NORMAL - - def createWidgets(self): - """Creates and packs the various widgets. - - Why is it that GUI code always ends up looking a mess, despite all the - best intentions to keep it tidy? Answers on a postcard, please. - """ - # Status bar - statusFrame = tk.Frame(self.top, relief=tk.SUNKEN, borderwidth=2) - statusFrame.pack(anchor=tk.SW, fill=tk.X, side=tk.BOTTOM) - tk.Label(statusFrame, width=1, textvariable=self.statusVar).pack(side=tk.TOP, fill=tk.X) - - # Area to enter name of test to run - leftFrame = tk.Frame(self.top, borderwidth=3) - leftFrame.pack(fill=tk.BOTH, side=tk.LEFT, anchor=tk.NW, expand=1) - suiteNameFrame = tk.Frame(leftFrame, borderwidth=3) - suiteNameFrame.pack(fill=tk.X) - - # Progress bar - progressFrame = tk.Frame(leftFrame, relief=tk.GROOVE, borderwidth=2) - progressFrame.pack(fill=tk.X, expand=0, anchor=tk.NW) - tk.Label(progressFrame, text="Progress:").pack(anchor=tk.W) - self.progressBar = ProgressBar(progressFrame, relief=tk.SUNKEN, - borderwidth=2) - self.progressBar.pack(fill=tk.X, expand=1) - - - # Area with buttons to start/stop tests and quit - buttonFrame = tk.Frame(self.top, borderwidth=3) - buttonFrame.pack(side=tk.LEFT, anchor=tk.NW, fill=tk.Y) - - tk.Button(buttonFrame, text="Discover Tests", - command=self.discoverClicked).pack(fill=tk.X) - - - self.stopGoButton = tk.Button(buttonFrame, text="Start", - command=self.runClicked, state=tk.DISABLED) - self.stopGoButton.pack(fill=tk.X) - - tk.Button(buttonFrame, text="Close", - command=self.top.quit).pack(side=tk.BOTTOM, fill=tk.X) - tk.Button(buttonFrame, text="Settings", - command=self.settingsClicked).pack(side=tk.BOTTOM, fill=tk.X) - - # Area with labels reporting results - for label, var in (('Run:', self.runCountVar), - ('Failures:', self.failCountVar), - ('Errors:', self.errorCountVar), - ('Skipped:', self.skipCountVar), - ('Expected Failures:', self.expectFailCountVar), - ('Remaining:', self.remainingCountVar), - ): - tk.Label(progressFrame, text=label).pack(side=tk.LEFT) - tk.Label(progressFrame, textvariable=var, - foreground="blue").pack(side=tk.LEFT, fill=tk.X, - expand=1, anchor=tk.W) - - # List box showing errors and failures - tk.Label(leftFrame, text="Failures and errors:").pack(anchor=tk.W) - listFrame = tk.Frame(leftFrame, relief=tk.SUNKEN, borderwidth=2) - listFrame.pack(fill=tk.BOTH, anchor=tk.NW, expand=1) - self.errorListbox = tk.Listbox(listFrame, foreground='red', - selectmode=tk.SINGLE, - selectborderwidth=0) - self.errorListbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=1, - anchor=tk.NW) - listScroll = tk.Scrollbar(listFrame, command=self.errorListbox.yview) - listScroll.pack(side=tk.LEFT, fill=tk.Y, anchor=tk.N) - self.errorListbox.bind("", - lambda e, self=self: self.showSelectedError()) - self.errorListbox.configure(yscrollcommand=listScroll.set) - - def errorDialog(self, title, message): - messagebox.showerror(parent=self.root, title=title, - message=message) - - def notifyRunning(self): - self.runCountVar.set(0) - self.failCountVar.set(0) - self.errorCountVar.set(0) - self.remainingCountVar.set(self.totalTests) - self.errorInfo = [] - while self.errorListbox.size(): - self.errorListbox.delete(0) - #Stopping seems not to work, so simply disable the start button - #self.stopGoButton.config(command=self.stopClicked, text="Stop") - self.stopGoButton.config(state=tk.DISABLED) - self.progressBar.setProgressFraction(0.0) - self.top.update_idletasks() - - def notifyStopped(self): - self.stopGoButton.config(state=tk.DISABLED) - #self.stopGoButton.config(command=self.runClicked, text="Start") - self.statusVar.set("Idle") - - def notifyTestStarted(self, test): - self.statusVar.set(str(test)) - self.top.update_idletasks() - - def notifyTestFailed(self, test, err): - self.failCountVar.set(1 + self.failCountVar.get()) - self.errorListbox.insert(tk.END, "Failure: %s" % test) - self.errorInfo.append((test,err)) - - def notifyTestErrored(self, test, err): - self.errorCountVar.set(1 + self.errorCountVar.get()) - self.errorListbox.insert(tk.END, "Error: %s" % test) - self.errorInfo.append((test,err)) - - def notifyTestSkipped(self, test, reason): - super(TkTestRunner, self).notifyTestSkipped(test, reason) - self.skipCountVar.set(1 + self.skipCountVar.get()) - - def notifyTestFailedExpectedly(self, test, err): - super(TkTestRunner, self).notifyTestFailedExpectedly(test, err) - self.expectFailCountVar.set(1 + self.expectFailCountVar.get()) - - - def notifyTestFinished(self, test): - self.remainingCountVar.set(self.remainingCountVar.get() - 1) - self.runCountVar.set(1 + self.runCountVar.get()) - fractionDone = float(self.runCountVar.get())/float(self.totalTests) - fillColor = len(self.errorInfo) and "red" or "green" - self.progressBar.setProgressFraction(fractionDone, fillColor) - - def showSelectedError(self): - selection = self.errorListbox.curselection() - if not selection: return - selected = int(selection[0]) - txt = self.errorListbox.get(selected) - window = tk.Toplevel(self.root) - window.title(txt) - window.protocol('WM_DELETE_WINDOW', window.quit) - test, error = self.errorInfo[selected] - tk.Label(window, text=str(test), - foreground="red", justify=tk.LEFT).pack(anchor=tk.W) - tracebackLines = traceback.format_exception(*error) - tracebackText = "".join(tracebackLines) - tk.Label(window, text=tracebackText, justify=tk.LEFT).pack() - tk.Button(window, text="Close", - command=window.quit).pack(side=tk.BOTTOM) - window.bind('', lambda e, w=window: w.quit()) - window.mainloop() - window.destroy() - - -class ProgressBar(tk.Frame): - """A simple progress bar that shows a percentage progress in - the given colour.""" - - def __init__(self, *args, **kwargs): - tk.Frame.__init__(self, *args, **kwargs) - self.canvas = tk.Canvas(self, height='20', width='60', - background='white', borderwidth=3) - self.canvas.pack(fill=tk.X, expand=1) - self.rect = self.text = None - self.canvas.bind('', self.paint) - self.setProgressFraction(0.0) - - def setProgressFraction(self, fraction, color='blue'): - self.fraction = fraction - self.color = color - self.paint() - self.canvas.update_idletasks() - - def paint(self, *args): - totalWidth = self.canvas.winfo_width() - width = int(self.fraction * float(totalWidth)) - height = self.canvas.winfo_height() - if self.rect is not None: self.canvas.delete(self.rect) - if self.text is not None: self.canvas.delete(self.text) - self.rect = self.canvas.create_rectangle(0, 0, width, height, - fill=self.color) - percentString = "%3.0f%%" % (100.0 * self.fraction) - self.text = self.canvas.create_text(totalWidth/2, height/2, - anchor=tk.CENTER, - text=percentString) - -def main(initialTestName=""): - root = tk.Tk() - root.title("PyUnit") - runner = TkTestRunner(root, initialTestName) - root.protocol('WM_DELETE_WINDOW', root.quit) - root.mainloop() - - -if __name__ == '__main__': - if len(sys.argv) == 2: - main(sys.argv[1]) - else: - main()