Browse Source

UI_Automation codes with user manual after code cleanup

Clindo 7 years ago
parent
commit
2a165ad332

BIN
UI_Automation_Codes/Automation_User_Manual.pdf


+ 88 - 0
UI_Automation_Codes/Camtasia_UIAUtomation.py

@@ -0,0 +1,88 @@
+#This file contains the basic workflow of Camtasia UI Automation
+
+from helper import Automate
+from Render_video import render_video
+from conf import Config
+from logger import log
+import sys
+import os, time
+
+#Initialization
+#Creates an instane of logger class.
+log = log()
+
+#Creates an instane of Automate class.
+#which contains the helper functions.
+Auto = Automate()
+#Reads the configuration.xml to get configuration parameters
+Auto.readConfig()
+
+log.logger.info('Automate initialized')
+#Creates an instance of render_video class.
+#Which is done by pywinauto library
+bi = render_video()
+
+#Get the files already present in the watch directory
+if os.path.exists(Auto.__configuration__.Original_Path):
+    before = dict([(f, None) for f in os.listdir(Auto.__configuration__.Original_Path)])
+    log.logger.info("Already existing files:")
+    log.logger.info(before)
+else:
+    log.logger.error("-------> Trec file path is invalid. Recheck the configuration.xml, and RESTART THE APP ----->")
+    sys.exit() #Exits the automation app if configuration is not correct
+
+#Infinite loop to watch file changes in the WatchFolder
+while 1:
+
+    fileNames = []
+    #Checking wether files currently present are already rendered successfully.
+    with open("SuccessfullyRenderedFiles.txt") as file:
+        for line in file:
+            line = line.strip()
+            fileNames.append(line)
+    differenceList= list(set(before.keys())-set(fileNames))
+    differenceJSON =dict([(f, None) for f in differenceList])
+
+
+    #Check new added files after Polling_time
+    time.sleep (Auto.__configuration__.Polling_time)
+    #Get the new added trec files
+    if os.path.exists(Auto.__configuration__.Original_Path):
+        after = dict ([(f, None) for f in os.listdir (Auto.__configuration__.Original_Path)])
+        added = [f for f in after if not f in before]
+        added+=differenceJSON
+        # print  " addedJSON"+added
+    else:
+        log.logger.info("Trec file path does not exists!")
+        sys.exit()
+
+    if added:
+        log.logger.info("Files added:")
+        log.logger.info(added)
+        for file in added:
+            log.logger.info(file)
+            rendered_file_name = bi.convert_files(file)
+            if rendered_file_name :
+                log.logger.info('Rendering Successful')
+                backslash = "\\"
+                full_path_of_rendered_file = Auto.__configuration__.Saved_Path+backslash+rendered_file_name
+                rendered_html_file = rendered_file_name+".html"
+
+                if os.path.exists(full_path_of_rendered_file):
+                    status = Auto.renameFile(full_path_of_rendered_file,rendered_html_file)
+                    #If the file is renamed successfully, then we are adding it to the SuccessfullyRenderedFiles.txt
+                    if status == 1:
+                        renderedFileList= open("SuccessfullyRenderedFiles.txt","a+")
+                        # print rendered_file_name
+                        renderedFileList.write("%s.trec\n" % rendered_file_name)
+                        renderedFileList.close()
+                        log.logger.info("Renaming Successful!")
+                    else:
+                        log.logger.info("Renaming not Successful!")
+                else:
+                    log.logger.info("Rendered file does not exists!")
+                    sys.exit()
+            else:
+                log.logger.info('Rendering not successful')
+
+    before = after

+ 130 - 0
UI_Automation_Codes/Render_video.py

@@ -0,0 +1,130 @@
+#This file contains render video logic using pywin auto library.
+
+from conf import Config
+from pywinauto.application import Application ,ProcessNotFoundError
+from pywinauto.findwindows import WindowAmbiguousError, WindowNotFoundError
+from pywinauto.findbestmatch import MatchError
+from logger import log
+from helper import Automate
+import time
+import os
+import datetime
+import time
+import sys
+
+class render_video:
+
+    def convert_files(self,file):
+        _config = Config()
+        backslash = "\\"
+        app_path = _config.Original_Path+backslash+file
+        #print(app_path)
+        Auto=Automate()
+        renderTime=Auto.renderTime(app_path,_config.Rendering_wait_time)
+        IsFileCopied=Auto.IsCopyFinished(app_path)
+        if IsFileCopied ==0:
+            return
+        if os.path.exists(app_path):
+            os.startfile(app_path)
+        else:
+            log.logger.info("Trec file does not exists")
+            return
+        time.sleep(_config.App_time)
+        # print("Sleep End!!!")
+
+        try:
+            if os.path.exists(_config.Camtasia_Path):
+                app = Application().connect(path=_config.Camtasia_Path)
+            else:
+                log.logger.info("Camtasia executable not found!")
+                return
+
+            # To bring the Camtasia window to the focus.
+            app_dialog = app.top_window_()
+            app_dialog.Minimize()
+            app_dialog.Restore()
+        except(ProcessNotFoundError):
+            log.logger.info("Not Camtasia process found... Exiting App")
+            return
+        except(WindowNotFoundError):
+            log.logger.info("Not found Camtasia... Exiting App")
+            app.kill()
+            return
+        except(WindowAmbiguousError):
+            log.logger.info("There are too many Camtasia windows found... Exiting App")
+            app.kill()
+            return
+
+        if os.path.exists(app_path):
+            os.startfile(app_path)
+        else:
+            log.logger.info("Trec file does not exists... Exiting App")
+            app.kill()
+            return
+
+        #for TRIAL
+        if _config.Trial == 'YES':
+            try:
+                app.Window_(best_match='Dialog', top_level_only=True).ChildWindow(best_match='Finish').Click()
+            except(MatchError):
+                # print ' Not found Finish Dialog'
+                log.logger.info("Not found Finish Dialog... Exiting App")
+                app.kill()
+                return
+
+        time.sleep(_config.Dialog_wait_time)
+        #end for TRIAL
+        child_elements = app[_config.App_Name]
+        #for clicking the share button
+        child_elements.ClickInput(coords=(_config.Share_Btn_X, _config.Share_Btn_Y))
+        child_elements.TypeKeys("{DOWN}")
+        child_elements.TypeKeys("{ENTER}")
+        time.sleep(_config.Dialog_wait_time)
+
+        #for TRIAL
+        if _config.Trial == 'YES':
+            #for clicking the water mark button
+            child_elements.Wait('visible',timeout=20)
+            child_elements.ClickInput(coords=(_config.Water_Mark_Btn_X, _config.Water_Mark_Btn_Y))
+            time.sleep(_config.Dialog_wait_time)
+        #end for TRIAL
+        for i in range(_config.Dialogs):
+            time.sleep(2)
+            child_elements.Wait('visible',timeout=20)
+
+            try:
+                app.Window_(best_match='Dialog', top_level_only=True).ChildWindow(best_match='Next').Click()
+            except(MatchError):
+                # print ' Not found Dialog to click the first Next. Check if coordinates are mentioned correctly in configuration.xml'
+                log.logger.info("Not found Dialog to click the first Next. Check if coordinates are mentioned correctly in configuration.xml. Exiting App")
+                app.kill()
+                return
+
+
+        stripped_file_name = os.path.splitext(os.path.basename(file))[0]
+        dup_dir = Auto.check_duplicate(stripped_file_name,_config.Saved_Path);
+        if dup_dir == 1:
+            log.logger.info("Duplicate exists.The rendering will overwrite the existing directory")
+
+        try:
+            app.Window_(best_match='Dialog', top_level_only=True).ChildWindow(title="Untitled Project",class_name="Edit").SetText(stripped_file_name)
+        except(MatchError):
+            # print ' Not found Dialog to rename the project'
+            log.logger.info("Not found Dialog to rename the project... Exiting App")
+            app.kill()
+            return
+        try:
+            app.Window_(best_match='Dialog', top_level_only=True).ChildWindow(best_match='Finish').Click()
+        except(MatchError):
+            # print ' Not found Dialog to click Finish'
+            log.logger.info("Not found Dialog to click Finish... Exiting App")
+            app.kill()
+            return
+
+        time.sleep(renderTime)
+        app.kill_()
+        time.sleep(_config.Dialog_wait_time)
+        #print("Rendering Succcessful")
+
+        return stripped_file_name
+        #Finish rendering

+ 0 - 0
UI_Automation_Codes/SuccessfullyRenderedFiles.txt


+ 136 - 0
UI_Automation_Codes/conf.py

@@ -0,0 +1,136 @@
+#This file is for reading the configuration.xml
+
+import xml.etree.ElementTree as ET
+from logger import log
+
+class Config:
+    'Configuration Class for File Paths'
+    Original_Path = ""
+    Camtasia_Path = ""
+    App_Name = ""
+    Saved_Path = ""
+    Dialogs = 0
+    Trial = ""
+    Share_Btn_X = 0
+    Share_Btn_Y = 0
+    Water_Mark_Btn_X = 0
+    Water_Mark_Btn_Y = 0
+    App_time = 0
+    Dialog_wait_time = 0
+    Rendering_wait_time = 0
+    Polling_time = 0
+    log = log()
+
+    #Function to read the configuration.xml
+    def read_config(self):
+        log.logger.info('Reading configuration file')
+        tree = ET.parse('configuration.xml')
+        root = tree.getroot()
+        #Get the folder path where the files are present
+        path = root.find('WatchFolder')
+        if path == "":
+            log.logger.info('Failed to read the file path attribute')
+            return 0
+
+        Config.Original_Path = path.get('path1')
+        if Config.Original_Path == "":
+            log.logger.info('Failed to read the file path')
+            return 0
+
+        #Get the folder path where files are to be moved
+        camtasia_path = root.find('CamtasiaPath')
+        if camtasia_path == "":
+            log.logger.info('Failed to read the Camtasia file path attribute')
+            return 0
+
+        Config.Camtasia_Path = camtasia_path.get('path2')
+        if Config.Camtasia_Path == "":
+            log.logger.info('Failed to read the Camtasia file path')
+            return 0
+
+        app_name = root.find('APP_NAME')
+        if app_name == "":
+            log.logger.info('Failed to read the App name attribute')
+            return 0
+
+        Config.App_Name = app_name.get('app_name')
+        if Config.App_Name == "":
+            log.logger.info('Failed to read App name')
+            return 0
+
+        #Get the folder path where files are to be saved after rendering
+        saved_path = root.find('SAVING_PATH')
+        if saved_path == "":
+            log.logger.info('Failed to read the saved file path attribute')
+            return 0
+
+        Config.Saved_Path = saved_path.get('path3')
+        if Config.Saved_Path == "":
+            log.logger.info('Failed to read the saving path')
+            return 0
+
+        #Get the no. of dialogs screens during coversion
+        no_screens = root.find('No_Screens')
+        if no_screens == "":
+            log.logger.error('Failed to read the no. of dialog box attribute')
+            return 0
+
+        Config.Dialogs = no_screens.get('dialog')
+        if Config.Dialogs == "":
+            log.logger.error('Failed to read the no. of dialog boxes')
+            return 0
+
+        Config.Dialogs = int(Config.Dialogs)
+
+        #Get if Camtasia has Trial license
+        trial = root.find('TRIAL')
+        if trial == "":
+            log.logger.error('Failed to read the trial license attribute')
+            return 0
+        Config.Trial = trial.get('trial')
+        if Config.Trial == "":
+            log.logger.error('Failed to read the trial license value')
+            return 0
+
+        #Get the co-ordinates of the share button
+        share_btn = root.find('Share_BTN_COOR')
+        Config.Share_Btn_X = share_btn.get('x')
+        Config.Share_Btn_X = int(Config.Share_Btn_X)
+        Config.Share_Btn_Y = share_btn.get('y')
+        Config.Share_Btn_Y = int(Config.Share_Btn_Y)
+        #Get the co-ordinates Watermark
+        watermark_btn = root.find('WATER_MARK_COOR')
+        Config.Water_Mark_Btn_X = watermark_btn.get('x')
+        Config.Water_Mark_Btn_X = int(Config.Water_Mark_Btn_X)
+        Config.Water_Mark_Btn_Y = watermark_btn.get('y')
+        Config.Water_Mark_Btn_Y = int(Config.Water_Mark_Btn_Y)
+        #Get the sleep time for Camtasia app to start
+        app_time = root.find('APP_START_TIME')
+        Config.App_time = app_time.get('time')
+        Config.App_time = int(Config.App_time)
+
+        #Get the wait time for Dialog box
+        dialog_wait_time = root.find('DIALOG_WAIT_TIME')
+        Config.Dialog_wait_time = dialog_wait_time.get('time2')
+        Config.Dialog_wait_time = float(Config.Dialog_wait_time)
+
+
+        #Get the rendering wait time
+        rendering_wait_time = root.find('REND_WAIT_TIME')
+        Config.Rendering_wait_time = rendering_wait_time.get('time3')
+        Config.Rendering_wait_time = float(Config.Rendering_wait_time)
+
+        #Get the watch folder polling time
+        polling_time = root.find('POLLING_TIME')
+        Config.Polling_time = polling_time.get('time4')
+        Config.Polling_time = int(Config.Polling_time)
+        return 1
+
+
+
+    def get_Moved_Path(self):
+        return Config.Moved_Path
+
+    def get_Original_Path(self):
+        return Config.Original_Path
+

+ 15 - 0
UI_Automation_Codes/configuration.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<RootPath>
+    <WatchFolder path1="D:\Master Studies\WS16-17\TKPraktikum\AutoHotHeyScripts\Test\watch"> </WatchFolder>
+    <CamtasiaPath path2="C:\Program Files\TechSmith\Camtasia 9\CamtasiaStudio.exe"> </CamtasiaPath>
+    <APP_NAME app_name="Camtasia 9"></APP_NAME>
+    <SAVING_PATH path3="D:\Master Studies\WS16-17\TKPraktikum\AutoHotHeyScripts\Test\saveFolder"></SAVING_PATH>
+    <No_Screens dialog="4"> </No_Screens>
+    <TRIAL trial="YES"> </TRIAL>
+    <Share_BTN_COOR x="200" y="20"> </Share_BTN_COOR>
+    <WATER_MARK_COOR x="400" y="600"></WATER_MARK_COOR>
+    <APP_START_TIME time="50"></APP_START_TIME>
+    <DIALOG_WAIT_TIME time2="3"></DIALOG_WAIT_TIME>
+    <REND_WAIT_TIME time3="3300"></REND_WAIT_TIME>
+    <POLLING_TIME time4="10"></POLLING_TIME>
+</RootPath>

+ 94 - 0
UI_Automation_Codes/helper.py

@@ -0,0 +1,94 @@
+#This file has the helper functions for automation.
+
+from conf import Config
+import os,io,time
+import shutil
+from logger import log
+import sys
+
+#Initialization Class for Automation
+class Automate:
+
+    #Initialize logging
+    log = log()
+
+    #Helper function to initialize configuration parameters
+    def readConfig(self):
+        self.__configuration__ = Config()
+        status = self.__configuration__.read_config()
+        if status == 1:
+            log.logger.info("Configuration read success")
+        else:
+            log.logger.info("Configuration read not successful! Exiting automation script")
+            sys.exit()
+
+    #Helper function to get the files from a directory
+    def GetFiles(self, paths):
+        files = []
+        for file in os.listdir(paths):
+            files.append(file)
+        return files
+
+    #Helper function to copy files from a src dir to dest dir
+    def copyFiles(self, src_folder,dest_folder,added):
+        if src_folder == "" or dest_folder == "":
+            log.logger.error('Source or Destination Folder does not exists')
+            return 0
+
+        if not os.listdir(src_folder):
+            log.logger.error('No files found in src folder')
+            return 0
+
+        #for file in os.listdir(src_folder):
+        for file in added:
+            # print ("File being moved -----> " + file)
+            full_file_name = os.path.join( src_folder, file )
+            if os.path.isfile(full_file_name):
+                try:
+                    shutil.copy( full_file_name, dest_folder )
+                except shutil.Error as e:
+                    log.logger.error('Could not copy the files %s',e)
+                    return 0
+        return 1
+
+    #Helper function to rename the rendered trec file embedded HTML to index.html
+    def renameFile(self,path,tochangefilename):
+        fileName = os.listdir(path)
+        for files in fileName:
+            if(files == tochangefilename):
+                os.rename(path+"\\"+tochangefilename, path+"\\"+"index.html")
+                return 1
+        return 0
+
+    #Helper function to calculate wait time for rendering based on File Size
+    def renderTime(self, file, renderingPerMB):
+        st = os.stat(file)
+        sizeBytes = st.st_size
+        sizeBytes /= (1024 * 1024)
+        renderTime = sizeBytes * renderingPerMB
+        renderTime /= 1000
+        return renderTime
+
+    #Helper function Check is a duplicate exists and delete the duplicate folder
+    def check_duplicate(self,filename,filePath):
+        directories = os.listdir(filePath)
+        for dir in directories:
+            if dir == filename:
+                shutil.rmtree(filePath+'\\'+filename)
+                return 1
+        return 0
+
+    #Helper function Check if the file to render is copied completely before rendering
+    def IsCopyFinished(self,fileName):
+        timeout = 3600   # [seconds]
+        timeout_start = time.time()
+        if os.path.exists(fileName):
+            while time.time() < timeout_start + timeout:
+                try:
+                    with io.FileIO(fileName, "r+") as fileObj:
+                        log.logger.info("File loading completed.")
+                        return 1
+                except IOError as ioe:
+                    pass
+        log.logger.info("Issue with file.")
+        return 0

+ 12 - 0
UI_Automation_Codes/logger.py

@@ -0,0 +1,12 @@
+#This file contains logger initialization
+
+import logging
+
+class log:
+    #Initialize logger
+    logger = logging.getLogger('Camtasia UI Automation')
+    hdlr = logging.FileHandler('App.log',mode='w')
+    formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s %(message)s')
+    hdlr.setFormatter(formatter)
+    logger.addHandler(hdlr)
+    logger.setLevel(logging.DEBUG)