Source code for pysys.manual.ui

#!/usr/bin/env python
# PySys System Test Framework, Copyright (C) 2006-2018  M.B.Grieve

# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

# Contact: moraygrieve@users.sourceforge.net

import sys
try:
	if sys.version_info[0] == 2:
		from Tkinter import *
	else:
		from tkinter import *
except Exception:
	pass 

from pysys.xml.manual import *


[docs]class ManualTester(object):
[docs] def __init__(self, owner, filename, logname=None): self.parentContainer = None self.owner = owner self.isRunning = 1 self.intToRes = ["FAILED", "PASSED", "N/A"] self.logicMap = {"false" : 0, "true" : 1, "" : 1, 0 : "false", 1 : "true"} self.filename = filename self.steps = self.parseInputXML(self.filename) self.currentStep = -1 self.results = {} self.defect = ""
[docs] def build(self): self.parentContainer = Tk() self.parentContainer.protocol('WM_DELETE_WINDOW', self.quitPressed) self.parentContainer.wm_geometry("500x400") self.parentContainer.title("PySys Manual Tester - [%s]" % self.owner.descriptor.id) self.parentContainer.resizable(True, True) self.container = Frame(self.parentContainer) self.containerDetails = Frame(self.container) self.titleBox = Label(self.containerDetails, text="Test Title Here", font=("Verdana 10 "), anchor=W, wraplength=480) self.titleBox.pack(fill=X) self.messageBoxDetails = Text(self.containerDetails, wrap=WORD, width=1, height=1, padx=10, pady=10) self.messageBoxDetails.insert(INSERT, "Test Body Here") self.messageBoxDetails.pack(fill=BOTH, expand=YES, side=LEFT) self.yscrollbarDetails = Scrollbar(self.containerDetails, orient=VERTICAL) self.yscrollbarDetails.pack(fill=Y, side=LEFT) self.yscrollbarDetails.config(command=self.messageBoxDetails.yview) self.containerDetails.pack(fill=BOTH, expand=YES, padx=5, pady=5) self.messageBoxDetails.config(yscrollcommand=self.yscrollbarDetails.set, font=("Helvetica 10")) self.containerExpected = Frame(self.container) self.labelExpected = Label(self.containerExpected, text="Expected Result", font=("Verdana 10"), anchor=W) self.labelExpected.pack(fill=X) self.messageBoxExpected = Text(self.containerExpected, wrap=WORD, width=1, height=1, padx=10, pady=10) self.messageBoxExpected.insert(INSERT, "Test Body Here") self.messageBoxExpected.pack(fill=BOTH, expand=YES, side=LEFT) self.yscrollbarExpected = Scrollbar(self.containerExpected, orient=VERTICAL) self.yscrollbarExpected.pack(fill=Y, side=LEFT) self.yscrollbarExpected.config(command=self.messageBoxExpected.yview) self.containerExpected.pack(fill=BOTH, expand=YES, padx=5, pady=5) self.messageBoxExpected.config(yscrollcommand=self.yscrollbarExpected.set, font=("Helvetica 10")) self.container.pack(fill=BOTH, expand=YES, padx=5, pady=5) self.separator = Frame(height=2, bd=1, relief=SUNKEN) self.separator.pack(fill=X, pady=2) self.inputContainer = Frame(self.parentContainer, relief=GROOVE) self.quitButton = Button(self.inputContainer, text="Quit", command=self.quitPressed, pady=5, padx=5, font=("Verdana 9 bold")) self.quitButton.pack(side=LEFT, padx=5, pady=5) self.backButton = Button(self.inputContainer, text="< Back", command=self.backPressed, state=DISABLED, pady=5, padx=5, font=("Verdana 9 bold")) self.backButton.pack(side=LEFT, padx=5, pady=5) self.multiButton = Button(self.inputContainer, text="Start", command=self.multiPressed, default=ACTIVE, pady=5, padx=5, font=("Verdana 9 bold")) self.multiButton.pack(side=RIGHT, padx=5, pady=5) self.failButton = Button(self.inputContainer, text="Fail", command=self.failPressed, pady=5, padx=5, font=("Verdana 9 bold")) self.failButton.pack(side=RIGHT, padx=5, pady=5) self.inputContainer.pack(fill=X, padx=5, pady=5) self.doStep()
[docs] def quitPressed(self): self.owner.log.critical("Application terminated by user (BLOCKED)") self.owner.addOutcome(BLOCKED, 'Manual tester failed: Application terminated by user') self.stop()
[docs] def backPressed(self): if self.currentStep >= 0: self.currentStep = self.currentStep - 1 self.doStep()
[docs] def failPressed(self): if self.currentStep >= 0: self.results[self.currentStep] = 0 self.currentStep = self.currentStep + 1 self.doStep()
[docs] def multiPressed(self): if self.currentStep == len(self.steps): self.stop() return elif self.currentStep >= 0: if self.steps[self.currentStep].validate == 'true': self.results[self.currentStep] = 1 else: self.results[self.currentStep] = 2 self.currentStep = self.currentStep + 1 self.doStep()
[docs] def doStep(self): self.messageBoxDetails.config(state=NORMAL) self.messageBoxDetails.delete(1.0, END) self.messageBoxExpected.config(state=NORMAL) self.messageBoxExpected.delete(1.0, END) if self.currentStep < 0: self.multiButton.config(text="Start") self.backButton.config(state=DISABLED) self.failButton.forget() self.containerExpected.forget() self.messageBoxDetails.insert(INSERT, self.owner.descriptor.purpose) self.titleBox.config(text="Title - %s" % self.owner.descriptor.title) elif self.currentStep == len(self.steps): self.multiButton.config(text="Finish") self.containerExpected.forget() self.messageBoxDetails.insert(INSERT, self.reportToString()) self.titleBox.config(text="Test Complete - Summary Report") elif self.currentStep >= 0: self.backButton.config(state=NORMAL) self.failButton.pack(side=RIGHT, padx=5, pady=5) self.multiButton.config(text="Pass") self.failButton.config(text="Fail") self.messageBoxDetails.insert(INSERT, self.steps[self.currentStep].description) expectedResult = self.steps[self.currentStep].expectedResult if expectedResult != "": self.messageBoxExpected.insert(INSERT, expectedResult) self.containerExpected.pack(side=TOP, fill=BOTH, expand=YES, padx=5, pady=5) else: self.containerExpected.forget() self.titleBox.config(text="Step %s of %s - %s" % (self.currentStep + 1, len(self.steps), self.steps[self.currentStep].title)) if self.steps[self.currentStep].validate == 'false': self.multiButton.config(text="Next >") self.failButton.forget() self.messageBoxDetails.config(state=DISABLED) self.messageBoxExpected.config(state=DISABLED)
[docs] def dlgSavePressed(self): self.defect = self.dlgTextField.get() self.dlg.destroy()
[docs] def dlgNoPressed(self): self.dlg.destroy()
[docs] def reportToString(self): result = "" for r in range(len(self.steps)): try: result += "\nStep %s - %s: %s" % (r + 1, self.steps[r].title, self.intToRes[self.results[r]]) except Exception: pass if self.defect != "": result += "\n\nDefect - %s recorded with test failure" % self.defect return result
[docs] def logResults(self): for r in range(len(self.results)): if r < self.currentStep: try: self.owner.log.info("Step %s - %s: %s" % (r + 1, self.steps[r].title, self.intToRes[self.results[r]])) if self.results[r] == 0: self.owner.outcome.append(FAILED) elif self.results[r] == 1: self.owner.outcome.append(PASSED) except Exception: pass if self.defect != "": self.owner.log.info("Defect - %s recorded with test failure" % self.defect)
[docs] def start(self): # this runs on a background thread try: self.build() self.parentContainer.mainloop() except Exception as e: self.owner.addOutcome(BLOCKED, 'Manual tester failed: %s'%e) self.isRunning = 0 # can't log the exception here since pysys logger suppresses messages from other threads # but at least let the traceback go to stderr raise
[docs] def stop(self): """ Logs the results of the manual tester and ensures that it is not still running. This method may be called from the UI thread or another thread. """ self.logResults() self.isRunning = 0 if self.parentContainer != None: self.parentContainer.quit() self.parentContainer = None
[docs] def running(self): return self.isRunning
[docs] def parseInputXML(self, input): parser = XMLManualTestParser(input) steps = parser.getSteps() parser.unlink() return steps