def moveImagesToCommonFolder(source = sikuli.getParentFolder(), destination = ""): if destination == "": destination = _myImagesPath for foldername, subfolders, filenames in os.walk(source): for filename in filenames: file = os.path.join(foldername,filename) if source == sikuli.getBundleFolder(): folderFilter = True else: folderFilter = foldername.endswith(".sikuli") if file.endswith(".png") and folderFilter: #print file myfilename = os.path.basename(file) myhash = getHash(file) newFile = os.path.join(destination, myfilename) newHash = getHash(file) if not os.path.exists(newFile): shutil.move(file, destination) else: print "----------", myfilename," is in ", destination if newHash == myhash: #print "duplicate found, removing it" os.remove(file) else: print "cannot move :", file
def user(message): if SikuliSettings.UserLogs: if Debug.printoutuser == None: if SikuliSettings.isMacApp: Debug.printoutuser = "******" else: Debug.printoutuser = sikuli.getBundleFolder()+ "UserLog.txt" with open(Debug.printoutuser, "a") as f: if SikuliSettings.UserLogTime: text = '[{} ({})] {}'.format(SikuliSettings.UserLogPrefix,'{:%m/%d/%y %I:%M:%S %p}'.format(datetime.datetime.now()).lstrip("0").replace(" 0", " "), message) else: text = '[{}] {}'.format(SikuliSettings.UserLogPrefix, message) f.write(text+"\n")
def _recapture_image_prompt(original_path, message): global _myEvent badKey = False na_path = os.path.join(_sitePackages, "image_not_captured_yet.png") temp_path = na_path three_buttons = ["Instant Capture", "User-Initiated Capture (CTRL+SHIFT+2)", "Show Capture", "Show Original", ] four_buttons = ["Instant Capture", "User-Initiated Capture (CTRL+SHIFT+2)", "Show Capture", "Show Original", "Move On"] icon = ImageIcon(original_path) while True: if temp_path == na_path: buttons = three_buttons else: buttons = four_buttons choice = JOptionPane().showOptionDialog(None, message , "Capture new image or close this window to retry the code.", JOptionPane.PLAIN_MESSAGE, 0, icon, buttons, buttons[0]) if choice == -1: #print "Image updater closed without doing anything." break #with this included the while loop will quit and the _screen_logger loop will retry the original image elif choice == 0: temp_path = sikuli.capture() if temp_path == None: temp_path = na_path icon = ImageIcon(original_path) else: icon = ImageIcon(temp_path) elif choice == 1: if not sikuli.Env.addHotkey("2", sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL, _capture_wait): badKey = True sikuli.Env.addHotkey(Key.F2, sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL, _capture_wait) _myEvent.clear() _myEvent.wait() temp_path = sikuli.SCREEN.capture() if temp_path == None: temp_path = na_path icon = ImageIcon(original_path) else: icon = ImageIcon(temp_path) if badKey: sikuli.Env.removeHotkey(Key.F2, sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL) else: sikuli.Env.removeHotkey("2", sikuli.KeyModifier.SHIFT + sikuli.KeyModifier.CTRL) elif choice == 2: icon = ImageIcon(temp_path) elif choice == 3: icon = ImageIcon(original_path) elif choice == 4: shutil.copyfile(temp_path, original_path) break else: #print "You added an extra button and it doesn't do anything." break
def _find_valid_image(img): if isinstance(img, sikuli.Pattern): img = img.getFilename() valid_extensions = ["png", "jpg", "jpeg"] split_result = img.split('.') # If no '.': not a file if len(split_result) <= 1: return "" # If there is only one '.' and nothing before it, not a file elif len(split_result) == 2 and split_result[0] == "": return "" # If it doesn't end in a valid extension, not an image file elif split_result[-1] not in valid_extensions: return "" # If it's an absolute path (that passed the file extension # tests), return it elif os.path.isfile(img): return img # Look in all the SIKULI_IMAGE_PATH dirs to see if it's there image_dirs = list(sikuli.getImagePath()) #image_dirs.insert(0, sikuli.getBundlePath()) my_frames = inspect.getouterframes(inspect.currentframe()) image_path = os.path.dirname(my_frames[-1][1]) image_dirs.insert(0, image_path) for dir in image_dirs: if not dir.endswith('/'): dir = dir + '/' if dir.startswith('/') and myOS == "W": dir = dir[1:] # If found, return the full path if os.path.isfile(os.path.join(dir, img)): return dir + img #No file handling if _imageUpdating: missing_file = os.path.join(_myImagesPath, img) #put in common imagepath print missing_file return missing_file return ""
def setUserLogFile(fileName, premake=True): if fileName == None: fileName = "" return False else: if "" == fileName: if SikuliSettings.isMacApp: Debug.printoutuser = "******" else: Debug.printoutuser = sikuli.getBundleFolder()+ "UserLog.txt" else: Debug.printoutuser = fileName if premake: try: with open(Debug.printoutuser, "a") as f: f.write("") return True except: Debug.printoutuser = None print "[Error] User logfile %s not accessible - check given path"% fileName return False
from __future__ import with_statement import org.sikuli.basics.SikuliXforJython from sikuli import * from sikuliwrapper import * from org.sikuli.script import App, Env from sikuli import Sikuli #add custom image library Sikuli.addImagePath(common.cfgImageLibrary) class Calculator(BaseLogger): ROBOT_LIBRARY_SCOPE = 'TEST SUITE' def __init__(self): self.appCoordinates = (0, 0, 1024, 768) def startApp(self): calcApp = App("Calculator") if not calcApp.window(): App.open("calc.exe"); wait(2) calcApp.focus(); wait(1) def verifyApp(self): # check application if exists("CalcApp.png"): self.log.passed("Calculator window appeared") else: self.log.failed("No calculator window") def performAction(self, *args):
def _init(): SikuliSettings.ActionLogs = False SikuliSettings.InfoLogs = False #SikuliSettings.DebugLogs = False #print "initializing" global myOS global _sitePackages global _logToFolder global _imageUpdating global _errorFile global _artifactFolder global _partialHTML global _myImagesPath global _showHeader global _textLog global _myEvent _myEvent = threading.Event() _myEvent.set() #OS-specific variables section my_OS = sikuli.Env.getOS() splitOSVersion = sikuli.Env.getOSVersion().split('.') my_OSVersion = splitOSVersion[0]+"."+splitOSVersion[1] if my_OS == sikuli.OS.LINUX: myOS = "L" _sikuliRepo = os.path.join(os.path.expanduser('~'),".Sikulix/") _vagrantFolder = "/vagrant/" _homeFolder = os.path.expanduser('~')+"/" os_options = { "3.2": "UbuntuPrecise", "3.13": "UbuntuTrusty", "4.4" : "UbuntuXenial", "3.8" : "Wasta12", "3.16": "Wasta14" } elif my_OS == sikuli.OS.WINDOWS: myOS = "W" _sikuliRepo = os.path.join(os.getenv('APPDATA'),"Sikulix\\") _vagrantFolder = "C:/vagrant/" _homeFolder = os.getenv('USERPROFILE')+"\\" os_options = { "6.0": "WindowsVista", "6.1":"Windows7", "6.2":"Windows8", "6.3":"Windows8.1", "10.0": "Windows10", } elif my_OS == OS.MAC: myOS = "M" _sikuliRepo = os.path.join(os.path.expanduser('~'),"Library/Application Support/Sikulix/") _homeFolder = os.path.expanduser('~')+"/" else: myOS = "N" print "Unsupported OS." exit(1) _sitePackages = os.path.join(_sikuliRepo, "Lib/site-packages") # Determine Logging Folder # A non-existent, empty, invalid logFolder.txt or one with "image_updater" keeps all logs in the .sikuli folder of each test. # A logFolder.txt with a valid path keeps all logs in one log in that folder. # A logFolder.txt with "vagrant" keeps all logs in the default vagrant folder. # Helper scripts logs are kept in the top level folder. try: with open(os.path.join(_sitePackages, "logFolder.txt"), "r") as f: rawLogFolder = os.path.normpath((f.readline()).strip()) except IOError: rawLogFolder = "." if "image_updater" in rawLogFolder: _logToFolder = sikuli.getBundleFolder() updateImages() #setFindFailedResponse(PROMPT) #Native support for capturing in 1.1.1 elif "vagrant" in rawLogFolder: _logToFolder = _vagrantFolder else: if rawLogFolder != "." and os.path.exists(rawLogFolder): _logToFolder = rawLogFolder else: if len(rawLogFolder)>1: print "ERROR: LogFolder.txt contents not usable. Using default behavior." _logToFolder = sikuli.getBundleFolder() Debug.setUserLogFile(os.path.join(_logToFolder, "UserLog.txt"), premake=False) try: myImagesFolder = os_options[my_OSVersion] except: sikuli.popup("The version of "+str(my_OS)+" is not supported yet.") #Determing where the common immage folders are and make them (default) if they are missing. parentPath = sikuli.getParentPath() parentFolder = os.path.basename(parentPath) if os.path.basename(parentPath) == "helpers": _myImagesPath = os.path.join(os.path.dirname(parentPath), "images", myImagesFolder) else: _myImagesPath = os.path.join(parentPath, "images", myImagesFolder) if not os.path.exists(_myImagesPath): error_message = "WARNING: The following Common Image Path is missing: "+_myImagesPath print error_message #sikuli.popup(error_message) if sikuli.Sikulix.prefLoad("cib") == "ASK": buttons = ["Make", "Cancel","Exit Program"] choice = JOptionPane().showOptionDialog(None, error_message , "Common Image Path Does Not Exist.", JOptionPane.PLAIN_MESSAGE, 0, None, buttons, buttons[0]) elif sikuli.Sikulix.prefLoad("cib") == "MAKE": choice = 0 elif sikuli.Sikulix.prefLoad("cib") == "SKIP": choice = 1 else: print "Common Image Behavior not correct." if choice == -1: pass #Window Closed elif choice == 0: #creat path try: os.makedirs(_myImagesPath) sikuli.addImagePath(_myImagesPath) except: sikuli.popup(_myImagesPath+" could not be created.") elif choice == 1: pass elif choice == 2: exit(1) else: #print "You added an extra button and it doesn't do anything." pass else: sikuli.addImagePath(_myImagesPath) #myProjectsPath = os.path.join(parentPath, "projects") # If a file with the given filename already exists, the Logger will # just keep writing to the end of that file. # *_errorFile* is the path to the text log. # *_logToFolder* is the path to the directory which stores the # html log and its assiocated images. _artifactFolder = os.path.join(_logToFolder, "log") _errorFile = os.path.join(_artifactFolder,"error_log") #with open(_errorFile, "a") as f: # f.write("") # Create the log folder if it doesn't exist if not os.path.exists(_artifactFolder): os.makedirs(_artifactFolder) _partialHTML = os.path.join(_artifactFolder, "mylog.log") # Otherwise, see if there's already a log file else: glob_result = glob.glob(_artifactFolder + "/*.log") if len(glob_result) == 1: _partialHTML = glob_result[0] else: _partialHTML = os.path.join(_artifactFolder, "mylog.log") # Add the CSS stylesheet to the log folder, if it's not there already. if not os.path.exists(os.path.join(_artifactFolder, "log.css")): shutil.copyfile(os.path.join(_sitePackages,"log.css"), os.path.join(_artifactFolder, "log.css")) if _showHeader: #if imported this header shows the filepath of the main script #if runScript this header shows the filepath of the helper script doc, tag, text = Doc().tagtext() with tag("tr"): with tag("td", style="text-align: center; background-color:lightskyblue", colspan="7"): text(time.strftime("%x %H:%M:%S")+": "+sikuli.getBundleFolder()) with open(_partialHTML, "a") as f: f.write(doc.getvalue()) _registerHTMLgenerator()
def _screen_logger_wrapper(*args, **kwargs): #print "Arguments were: %s %s | %s" % (func.__name__, args, kwargs) frames = inspect.getouterframes(inspect.currentframe()) scriptname = os.path.basename(frames[1][1])[:-3] count = 0 for frame in frames: if frame[3] == '_screen_logger_wrapper': count = count +1 # Sikuli uses find and wait internally, so the only versions of the # sikuli commands that should be decorated are those that are at the # highest level (i.e. those that are only wrapped once). if count == 1: fname = func.__name__ #frame = frames[1][0] #filename = frames[1][1] lineno = frames[1][2] #function = frames[1][3] code_context = frames[1][4][0] #index = frames[1][5] output = "[Line "+str(lineno)+"] "+str(code_context).rstrip() number_of_screens = sikuli.getNumberScreens() if isinstance(args[0],SikuliRegion): specific_area = True area = args[0] image = args[1] if fname == "wait" and _imageUpdating: targs = list(args) if len(args)==1: targs.append(0) elif len(args)>1: targs[2] = 0 args = targs elif fname == "dragDrop": extraImage = args[2] else: specific_area = False area = sikuli.SCREEN image = args[0] if fname == "wait" and _imageUpdating: targs = list(args) if len(args)==1: targs.append(0) elif len(args)>1: targs[1] = 0 args = targs elif fname == "dragDrop": extraImage = args[1] if fname == "dragDrop": display_order = "[start]" else: display_order = "" if isinstance(image, float) or isinstance(image, int): _textLog = True elif isinstance(image, sikuli.Pattern): _textLog = False imageName = os.path.basename(image.getFilename()) else: _textLog = False imageName = image if fname == "dragDrop": if isinstance(extraImage, sikuli.Pattern): extraImageName = os.path.basename(extraImage.getFilename()) else: extraImageName = extraImage ### TODO replace image in code_context with image for HTML log, consolidate columns while True: try: screenshot = sikuli.capture(area) if specific_area or fname == "type" or fname == "paste" or fname == "onChange" or fname == "observe" or _textLog: result = func(*args, **kwargs) else: failures = 0 for screen_id in range(number_of_screens): try: my_screen = sikuli.Screen(screen_id) screen_check_func = getattr(my_screen,func.__name__) result = screen_check_func(*args, **kwargs) break except sikuli.FindFailed: failures = failures +1 except: #print "base exception" raise if failures == number_of_screens: #print "both screens FindFailed" raise sikuli.FindFailed("Find Failed on both Screens") if fname =="exists" and result == None and _imageUpdating: raise sikuli.FindFailed("Exists() did not find anything.") if _logType == "SUCCESS" or _logType == "ALL": if _textLog: similarity ="N/A" else: similarity = str(simpleCompare(screenshot, image, 4)) _write_error("+++",scriptname, output+display_order+"[S:"+similarity+"]") _write_html_row(scriptname,func.__name__+display_order, image, "Success", screenshot, similarity) #if _imageUpdating: # if fname == "type" or fname == "paste" or fname == "onChange" or fname == "observe" or fname == "onVanish" or fname == "onAppear": # pass # elif specific_area: # specific_area.getLastMatch().highlight(1) # else: # my_screen.getLastMatch().highlight(1) return result except sikuli.FindFailed: if _textLog: similarity ="N/A" else: screenshot = area.getLastScreenImageFile(tempfile.gettempdir(), str(int(time.time()*1000))) similarity = str(simpleCompare(screenshot, image, 4)) error_text = traceback.format_exc() if fname == "dragDrop" and extraImageName in error_text: if _logType == "SUCCESS" or _logType == "ALL": _write_error("+++",scriptname, output+display_order+"[S:"+similarity+"]") _write_html_row(scriptname,func.__name__+display_order, image, "Success", screenshot, similarity) display_order = "[end]" image = extraImage similarity = str(simpleCompare(screenshot, image, 4)) if _imageUpdating: line_data = "\n"+frames[1][1]+"\nCurrent Similarity is: "+str(similarity)+"\n"+output+display_order if specific_area: area.highlight(1) _recapture_image_prompt(_find_valid_image(image), line_data) continue else: if _logType == "FAIL" or _logType == "ALL": _write_error("---",scriptname, output+display_order+"[S:"+similarity+"]") _write_html_row(scriptname,func.__name__+display_order, image, "Fail", screenshot, similarity) raise except: raise else: return func(*args, **kwargs)
def _write_html_row(script_name, action_type, expected, result_type, screenshot, similarity): doc, tag, text = Doc().tagtext() # Create the row # Status, Time and Date, Test name, Action, Expected, Screenshot, Similarity with tag("tr"): if result_type == "Success": with tag("td", ('bgcolor', 'green')): text("+++") elif result_type == "Fail": with tag("td", ('bgcolor', 'red')): text("---") else: with tag("td"): text("???") with tag("td"): text(time.strftime("%H:%M:%S %x")) with tag("td"): text(script_name) with tag("td"): text(action_type) with tag("td"): # If 'expected' is given, figure out what kind # of thing it is if expected: expected_path = "" # If it's a pattern, get the image if isinstance(expected, sikuli.Pattern): full_path = _find_valid_image(expected.getFilename()) expected_path = _copy_testfile(full_path) # If it's a match or a region, take a # screenshot of the area elif (isinstance(expected, sikuli.Match) or isinstance(expected, sikuli.Region)): screencap = sikuli.capture(expected) expected_path = _copy_testfile(screencap) elif isinstance(expected, sikuli.Location): # Create an area 50px around the location r = sikuli.Region(expected.getX(), expected.getY(), 0, 0) r = r.nearby() # take a screenshot screencap = sikuli.capture(r) expected_path = _copy_testfile(screencap) elif isinstance(expected, str): full_path = _find_valid_image(expected) # If a path was found, add a clickable image. # If not, add text. if full_path: expected_path = _copy_testfile(full_path) if expected_path == "": text(str(expected)) else: with tag("a", href="./log/"+expected_path): doc.stag("img", src="./log/"+expected_path) with tag("td"): screenshot_path = _copy_testfile(screenshot) with tag("a", href="./log/"+screenshot_path): doc.stag("img", src="./log/"+screenshot_path) with tag("td"): text(similarity) # Write the row to the partial html file with open(_partialHTML, "a") as f: f.write(doc.getvalue())