def arguments_parse(): """Handle the command line arguments.""" parser = OptionParser(usage='usage: %prog [options] arguments') parser.add_option('-f', '--file', dest='filename', metavar='FILE', help='specify the input XML testcase file for testing (REQUIRED)') parser.add_option('-p', '--packages', dest='custompackages', metavar='FILE', help='specify the input file for custom package processing') parser.add_option('-o', '--out', dest='allpackages', metavar='FILE', help='specify the output file to print the list of packages in the input XML') (options, args) = parser.parse_args() # If no arguments are passed just print the help message if options.filename is None: print colorize("The input file (specified by the '-f' option) is mandatory.", 'red') parser.print_help() sys.exit(1) if len(args) != 0: parser.error('Invalid number of arguments.') sys.exit(1) # Either call -p or -o, but not both if options.custompackages and options.allpackages: print colorize("Error: Specify either the '-p' or the '-o' option, but not both.", 'red') sys.exit(1) # Since both cannot be true, check which is and return accordingly return options.filename, options.custompackages, options.allpackages
def custom_package_parse(infile): """Parse only the selected packages from a given file.""" try: return [line.rstrip() for line in open(os.path.abspath(infile))] except IOError: print colorize("Invalid package input file: \'{0}' " \ "or the file does not exist.", 'red').format(os.path.abspath(infile)) print colorize("Make sure that the input file " "contains packages seperated by a newline.", 'green') sys.exit(1)
def check_file(file): """Check for validity of the testcase file.""" fileExtension = os.path.splitext(file) fileAbsolutePath = os.path.abspath(file) if not os.path.isfile(file): print colorize("The file '{0}' is not a valid input file " \ "or the file does not exist.", 'red').format(file) sys.exit(1) if not '.xml' in fileExtension: print colorize("Only XML files are supported. The file '{0}' " \ "is an invalid testcase file.", 'red').format(file) sys.exit(1) print "Parsing file: '{0}'\n".format(fileAbsolutePath)
def output_package_list(self, outfile): """Print the list of packages in the XML file to an output file.""" packageList = self.print_package_list() outputFile = os.path.abspath(outfile) if os.path.isfile(outputFile): while True: choice = raw_input("The file '{0}' exists. Do you wish to " \ "overwrite (y / n)? : ".format(outputFile)) if choice in ('y', 'Y', 'yes', 'YES'): break else: print colorize('Aborting', 'red') sys.exit(1) try: writeFile = open(outputFile, 'w') output = '\n'.join(packageList) writeFile.write(output) writeFile.close() except IOError: print colorize('Error: An error occurred while trying to write ' \ 'the output package file.', 'red') print colorize('Solution: Please ensure that the output ' \ 'file name and path is valid.', 'green') sys.exit(1) print colorize("The list of packages has been written to: " \ "'{0}'", 'green').format(outputFile) sys.exit(1)
def download_file(self, file): """Download a file using wget.""" totalDownloads = len(file) counter = 0 print 'Downloading files, please wait ...' while counter < totalDownloads: downloadFile = ['wget'] + ['-N'] + file[counter].split() fileName = os.path.basename(''.join(file[counter])) startwget = subprocess.call(downloadFile, stderr=open(os.devnull, 'w')) if startwget == 0: print colorize('{0}', 'bold').format(fileName) self.report.append('{0} downloaded to: {1}'.format(fileName, os.getcwd())) else: print "The file {0} does not exist.".format(''.join(file[counter])) counter += 1
def test_automated_main(self): """Entry point for the testcase type automated.""" case = self.element.xpath('case') totalCases = len(case) counter = 0 print '' while counter < totalCases: print 'Case {0} of {1}'.format(counter+1, totalCases), self.report.append('') self.report.append('Case {0} of {1}'.format(counter+1, totalCases)) for text in case[counter].iter('text'): print colorize(text.text, 'bold') commandList = [] for command in case[counter].iter('command'): commandList.append(command.text) totalCommands = len(commandList) self.report.append('Total Commands: {0}'.format(totalCommands)) self.report.append('-') commandCounter = 0 while commandCounter < totalCommands: self.report.append('Command {0}: {1}'.format(commandCounter+1, commandList[commandCounter])) try: runCommand = subprocess.Popen(commandList[commandCounter].split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: self.report.append('Output: Invalid command or invalid option') commandCounter += 1 continue output, error = runCommand.communicate() if error: self.report.append('Error: {0}'.format(error.rstrip())) commandCounter += 1 continue self.report.append('Output: {0}'.format(output.rstrip())) commandCounter += 1 for expected in case[counter].iter('expected'): self.report.append('Expected: {0}'.format(expected.text)) if expected.text in output: self.summary.append('Success') else: self.summary.append('Failed') print '... Done' counter += 1
def download_file(self, file): """Download a file using wget.""" totalDownloads = len(file) counter = 0 print 'Downloading files, please wait ...' while counter < totalDownloads: downloadFile = ['wget'] + ['-N'] + file[counter].split() fileName = os.path.basename(''.join(file[counter])) startwget = subprocess.call(downloadFile, stderr=open(os.devnull, 'w')) if startwget == 0: print colorize('{0}', 'bold').format(fileName) self.report.append('{0} downloaded to: {1}'.format( fileName, os.getcwd())) else: print "The file {0} does not exist.".format(''.join( file[counter])) counter += 1
def main(): """Call the command line and the parser modules.""" print colorize('Pardus Testing Framework\n', 'bold') # Call the clarguments module filename, custompackages, allpackages = arguments_parse() # Check whether the file is valid or not check_file(filename) # Now check the conditions and create the object if custompackages is not None: customparsefile = XMLParser(os.path.abspath(filename), custom_package_parse(custompackages)) print "Custom parsing:\t'{0}'\n".format(os.path.abspath(custompackages)) customparsefile.parser_main() else: parsefile = XMLParser(os.path.abspath(filename), None) if allpackages is not None: parsefile.output_package_list(os.path.abspath(allpackages)) parsefile.parser_main()
def test_shell(self, element, packagelist, counter): """Call the module for testcase type SHELL.""" commandList = self.testcase_tag_parse(element, 'command') if not commandList: print colorize('No <command> tag found. Skipping test ...', 'red') self.testreport.append(None) return testshell_install = testinstall.TestInstall(packagelist, self.installed_packages(), self.available_packages()) testshell_install.test_install_main() packagelist = testshell_install.packagelist if testshell_install.failcode == 0: print colorize('Unable to install packages. Skipping test ...', 'red') self.testreport.append(None) return self.testreport.append(testshell.TestShell(element, packagelist)) self.testreport[counter].report.extend(testshell_install.report) self.testreport[counter].test_shell_main()
def parser_main(self): """The entry point for normal execution.""" totalTestcases = 0 # Get the total number of testcases in the file for element in self.tree.iter('testcase'): totalTestcases += 1 counter = 0 # If the -p option is true, parse only the packages present in that file # The ElementTree is modified at this stage, so as to ease the parsing if self.custompackage is not None: customCounter = 0 while customCounter < totalTestcases: element = self.rootelement[customCounter] for custom in element.iter('package'): # if the text is not in the tag, remove the tag if not custom.text in self.custompackage: element.remove(custom) customCounter += 1 # Run each testcase while counter < totalTestcases: element = self.rootelement[counter] # Based on the type of testcase, call the appropriate one elementText = element.get('test') print "Running test: ", colorize("{0} / {1}", 'bold').format( counter + 1, totalTestcases) print 'Type of test: {0}'.format(elementText) packageList = [] for packageTag in element.iter('package'): packageList.append(packageTag.text) # If no package tag is there, move on to the next testcase if not packageList: print colorize('Package testing skipped ...', 'red') print colorize('-', 'bold') self.testreport.append(None) counter += 1 continue # One line hack to call the appropriate method dict( install=self.test_install, automated=self.test_automated, gui=self.test_gui, shell=self.test_shell, )[elementText](element, packageList, counter) print colorize('Finished', 'green') print colorize('-', 'bold') counter += 1 self.generate_report(totalTestcases)
def parser_main(self): """The entry point for normal execution.""" totalTestcases = 0 # Get the total number of testcases in the file for element in self.tree.iter('testcase'): totalTestcases += 1 counter = 0 # If the -p option is true, parse only the packages present in that file # The ElementTree is modified at this stage, so as to ease the parsing if self.custompackage is not None: customCounter = 0 while customCounter < totalTestcases: element = self.rootelement[customCounter] for custom in element.iter('package'): # if the text is not in the tag, remove the tag if not custom.text in self.custompackage: element.remove(custom) customCounter += 1 # Run each testcase while counter < totalTestcases: element = self.rootelement[counter] # Based on the type of testcase, call the appropriate one elementText = element.get('test') print "Running test: ", colorize("{0} / {1}", 'bold').format(counter+1, totalTestcases) print 'Type of test: {0}'.format(elementText) packageList = [] for packageTag in element.iter('package'): packageList.append(packageTag.text) # If no package tag is there, move on to the next testcase if not packageList: print colorize('Package testing skipped ...', 'red') print colorize('-', 'bold') self.testreport.append(None) counter += 1 continue # One line hack to call the appropriate method dict( install=self.test_install, automated=self.test_automated, gui=self.test_gui, shell=self.test_shell, )[elementText](element, packageList, counter) print colorize('Finished', 'green') print colorize('-', 'bold') counter += 1 self.generate_report(totalTestcases)
def arguments_parse(): """Handle the command line arguments.""" parser = OptionParser(usage='usage: %prog [options] arguments') parser.add_option( '-f', '--file', dest='filename', metavar='FILE', help='specify the input XML testcase file for testing (REQUIRED)') parser.add_option( '-p', '--packages', dest='custompackages', metavar='FILE', help='specify the input file for custom package processing') parser.add_option( '-o', '--out', dest='allpackages', metavar='FILE', help= 'specify the output file to print the list of packages in the input XML' ) (options, args) = parser.parse_args() # If no arguments are passed just print the help message if options.filename is None: print colorize( "The input file (specified by the '-f' option) is mandatory.", 'red') parser.print_help() sys.exit(1) if len(args) != 0: parser.error('Invalid number of arguments.') sys.exit(1) # Either call -p or -o, but not both if options.custompackages and options.allpackages: print colorize( "Error: Specify either the '-p' or the '-o' option, but not both.", 'red') sys.exit(1) # Since both cannot be true, check which is and return accordingly return options.filename, options.custompackages, options.allpackages
def test_gui(self, element, packagelist, counter): """Call the module for testcase type GUI.""" caseList = self.testcase_tag_parse(element, 'case') if not caseList: print colorize('No <case> tag found. Skipping test ...', 'red') self.testreport.append(None) return testgui_install = testinstall.TestInstall(packagelist, self.installed_packages(), self.available_packages()) testgui_install.test_install_main() # Get the list of packages to parse packagelist = testgui_install.packagelist if testgui_install.failcode == 0: print colorize('Unable to install packages. Skipping test ...', 'red') self.testreport.append(None) return self.testreport.append(testgui.TestGUI(element, packagelist)) self.testreport[counter].report.extend(testgui_install.report) # Add the install report to the final report self.testreport[counter].test_gui_main()
def test_automated(self, element, packagelist, counter): """Call the module for testcase type AUTOMATED.""" expectedTextList = self.testcase_tag_parse(element, 'expected') if not expectedTextList: print colorize('No <expected> tag found. Skipping test ...', 'red') self.testreport.append(None) return # Do the same for the <command> tag commandTextList = self.testcase_tag_parse(element, 'command') if not commandTextList: print colorize('No <command> tag found. Skipping test ...', 'red') self.testreport.append(None) return testautomated_install = testinstall.TestInstall(packagelist, self.installed_packages(), self.available_packages()) testautomated_install.test_install_main() packagelist = testautomated_install.packagelist if testautomated_install.failcode == 0: print colorize('Unable to install packages. Skipping test ...', 'red') self.testreport.append(None) return self.testreport.append(testautomated.TestAutomated(packagelist, element)) self.testreport[counter].report.extend(testautomated_install.report) self.testreport[counter].test_automated_main()
def test_automated(self, element, packagelist, counter): """Call the module for testcase type AUTOMATED.""" expectedTextList = self.testcase_tag_parse(element, 'expected') if not expectedTextList: print colorize('No <expected> tag found. Skipping test ...', 'red') self.testreport.append(None) return # Do the same for the <command> tag commandTextList = self.testcase_tag_parse(element, 'command') if not commandTextList: print colorize('No <command> tag found. Skipping test ...', 'red') self.testreport.append(None) return testautomated_install = testinstall.TestInstall( packagelist, self.installed_packages(), self.available_packages()) testautomated_install.test_install_main() packagelist = testautomated_install.packagelist if testautomated_install.failcode == 0: print colorize('Unable to install packages. Skipping test ...', 'red') self.testreport.append(None) return self.testreport.append( testautomated.TestAutomated(packagelist, element)) self.testreport[counter].report.extend(testautomated_install.report) self.testreport[counter].test_automated_main()
def __init__(self, xmlfile, custompackage, tree=None, rootelement=None): self.xmlfile = xmlfile try: self.tree = etree.parse(self.xmlfile) except etree.XMLSyntaxError, detail: print colorize('Error: The testcase file cannot be executed ' \ 'due to an invalid syntax.', 'red') print colorize('Detail: {0}', 'bold').format(detail) print colorize('Solution: Request the testcase author ' \ 'for a new file or fix it manually.', 'green') sys.exit(1)
def test_install_main(self): """Check the conditions and call the Pisi API to install the packages""" # Packages in the testcase file but not installed packagestNotInstalled = list(set(self.packagelist) - set(self.installedpackages)) if not packagestNotInstalled: self.report.append('All the required packages are installed') self.summary.append('Success') return # Install only packages that are in all the available repositories packagesNotInRepo = list(set(packagestNotInstalled) - set((self.availablepackages))) if packagesNotInRepo: self.report.append('The following packages were not found in ' \ "the repository: '{0}'".format(', '.join(packagesNotInRepo))) # if none of the package to be installed was found in the repository # set the failcode to 0 and return. The installation won't continue if len(packagesNotInRepo) == len(self.packagelist): self.summary.append('Fail') self.failcode = 0 return # Modify the package list and remove the packages which are not in the # repository. this is done so self.packagelist = list(set(self.packagelist) - set(packagesNotInRepo)) # Only try installing those packages which are in the repository finalPackages = list(set(packagestNotInstalled) - set(packagesNotInRepo)) totalPackages = len(finalPackages) if totalPackages == 0: self.report.append('No packages were installed') self.summary.append('Success') return # Calculate the download size and display it in MiB downloadSize = calculate_download_size(finalPackages)[0]/(1024.0 * 1024.0) self.report.append('Number of packages to be installed: ' \ "'{0}', total size: '{1:.2f} MiB'".format(totalPackages, downloadSize)) print 'Installing packages, please wait ... ' \ 'Size:', colorize('{0:.2f} MiB', 'bold').format(downloadSize) counter = 0 while counter < totalPackages: # Pisi installs new packages by using a list. However if we pass all the # packages as a single list, we don't have much control over the errors. # That is why pass a single package as a list here package = finalPackages[counter] singlePackage = package.split() try: install(singlePackage) except PrivilegeError: # in case the user doesn't have permission self.report.append('Error: To install the packages, ' \ 'run the framework with root privileges') self.failcode = 0 # for the testcases gui, shell and automated print colorize('Failed: Privilege error. Run as root user.', 'red') self.summary.append('Fail') return counter += 1 self.report.append("Finished installing the following " \ "packages: '{0}'".format(', '.join(finalPackages))) self.summary.append('Success')
def test_install_main(self): """Check the conditions and call the Pisi API to install the packages""" # Packages in the testcase file but not installed packagestNotInstalled = list( set(self.packagelist) - set(self.installedpackages)) if not packagestNotInstalled: self.report.append('All the required packages are installed') self.summary.append('Success') return # Install only packages that are in all the available repositories packagesNotInRepo = list( set(packagestNotInstalled) - set((self.availablepackages))) if packagesNotInRepo: self.report.append('The following packages were not found in ' \ "the repository: '{0}'".format(', '.join(packagesNotInRepo))) # if none of the package to be installed was found in the repository # set the failcode to 0 and return. The installation won't continue if len(packagesNotInRepo) == len(self.packagelist): self.summary.append('Fail') self.failcode = 0 return # Modify the package list and remove the packages which are not in the # repository. this is done so self.packagelist = list(set(self.packagelist) - set(packagesNotInRepo)) # Only try installing those packages which are in the repository finalPackages = list( set(packagestNotInstalled) - set(packagesNotInRepo)) totalPackages = len(finalPackages) if totalPackages == 0: self.report.append('No packages were installed') self.summary.append('Success') return # Calculate the download size and display it in MiB downloadSize = calculate_download_size(finalPackages)[0] / (1024.0 * 1024.0) self.report.append('Number of packages to be installed: ' \ "'{0}', total size: '{1:.2f} MiB'".format(totalPackages, downloadSize)) print 'Installing packages, please wait ... ' \ 'Size:', colorize('{0:.2f} MiB', 'bold').format(downloadSize) counter = 0 while counter < totalPackages: # Pisi installs new packages by using a list. However if we pass all the # packages as a single list, we don't have much control over the errors. # That is why pass a single package as a list here package = finalPackages[counter] singlePackage = package.split() try: install(singlePackage) except PrivilegeError: # in case the user doesn't have permission self.report.append('Error: To install the packages, ' \ 'run the framework with root privileges') self.failcode = 0 # for the testcases gui, shell and automated print colorize('Failed: Privilege error. Run as root user.', 'red') self.summary.append('Fail') return counter += 1 self.report.append("Finished installing the following " \ "packages: '{0}'".format(', '.join(finalPackages))) self.summary.append('Success')