def stats_by_keywords(inpath):
    
    result = ExecutionResult(inpath)
    visitor = ExecutionKeywordStats()    
    result.visit(visitor)
    for kw in sorted(visitor.elapsed_by_kw, key=visitor.elapsed_by_kw.get, reverse=True):
      print kw, visitor.elapsed_by_kw[kw]
Example #2
0
 def run(self, args, opts):
     """Sub command 'check' runner"""
     if not opts.cases:
         raise UsageError("case path must be set with -c or --cases!")
     print " Syntax Checking ".center(70, '*')
     print '...'
     log_level = 'TRACE'
     cases_path = opts.cases
     tmp_path = tempfile.gettempdir()
     xml_result = os.path.join(tmp_path, "check_result.xml")
     output_file = os.path.join(tmp_path, "stdout.txt")
     with open(output_file, 'w') as stdout:
         dryrun_result = run(cases_path,
                             dryrun=True,
                             loglevel=log_level,
                             log='NONE',
                             report='NONE',
                             output=xml_result,
                             stdout=stdout)
     detail_result = ExecutionResult(xml_result)
     if opts.is_tcms:
         if not opts.plan_id:
             raise UsageError("plan id must be set with -p or --planid!")
         plan_id = opts.plan_id
         tcms = TCMS()
         ids = tcms.get_plan_case_ids(plan_id)
         detail_result.visit(ResultChecker(ids, plan_id))
     elif dryrun_result == 0:
         print 'Contratulations, no syntax error'
     else:
         detail_result.visit(DryRunChecker())
     print '\n( No news is good news:) )'
     print 'checing result is in the file: %s' % output_file
     print ' DONE '.center(70, '*')
Example #3
0
def get_suite_names(output_file):
    if not os.path.isfile(output_file):
       return []
    try:
       e = ExecutionResult(output_file)
       gatherer = GatherSuiteNames()
       e.visit(gatherer)
       return gatherer.result
    except:
       return []
Example #4
0
def get_suite_names(output_file):
    if not os.path.isfile(output_file):
        print "get_suite_names: output_file='%s' does not exist" % output_file
        return []
    try:
        e = ExecutionResult(output_file)
        gatherer = GatherSuiteNames()
        e.visit(gatherer)
        return gatherer.result
    except:
        print "Exception in get_suite_names!"
        return []
 def __init__(self, workspace_dir, include_keywords = True):
     #self._verbose = Logger('Parser', verbose_stream)
     self._include_keywords = include_keywords
     self._workspace_dir = workspace_dir
     self._pyro_test_results = []
     
     for dirname in os.walk(self._workspace_dir).next()[1]:    
         testspace_path = os.path.join(os.path.abspath(self._workspace_dir),dirname)
         for xml_file in os.listdir(testspace_path):
             if xml_file.endswith(".xml"):
                 xml_path = (os.path.join(testspace_path,xml_file))
                 #print xml_path
                 try:
                     result = ExecutionResult(xml_path, include_keywords=True)
                 except DataError:
                     print "EMPTY SUITE FOUND, TRYING TO REBOUND: %s " % xml_path
                     self._pyro_test_results.append(PyroTestResult().empty_testsuite(xml_path))
                     #continue
                 else:
                     pyro_result = PyroTestResult()
                     result.visit(TestResultChecker(pyro_result))                        
                     self._pyro_test_results.append(pyro_result)
Example #6
0
        updateResultInTestLink(self.tls,
                               self.result_dict['testLinkTestProjectName'],
                               self.result_dict['testLinkTestPlanName'],
                               self.build, test.name.strip(":"),
                               testCaseStatus,
                               self.result_dict['testLinkPlatform'])


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description="IVTREE ROBOT FRAMEWORK")
    parser.add_argument("-b", action="store", default="False", dest="build_id")
    command_args = parser.parse_args()
    try:

        if command_args.build_id:
            print "running"
            run_robot('True', command_args.build_id)
        else:
            run_robot()

    finally:
        print "finally"
        complete_dir_path = os.path.join(
            os.getcwd(), "logs" + os.sep + command_args.build_id)
        complete_xml_path = os.path.join(complete_dir_path, "output.xml")
        print complete_xml_path
        result = ExecutionResult(complete_xml_path)
        result.suite.visit(PrintTestInfo(command_args.build_id))
def parse_output_xml(xml_file_path, csv_dir_path, version_id, platform, level):
    r"""
    Parse the robot-generated output.xml file and extract various test
    output data. Put the extracted information into a csv file in the "dest"
    folder.

    Description of argument(s):
    xml_file_path                   The path to a Robot-generated output.xml
                                    file.
    csv_dir_path                    The path to the directory that is to
                                    contain the .csv files generated by
                                    this function.
    version_id                      Version of the openbmc firmware
                                    (e.g. "v2.1-215-g6e7eacb").
    platform                        Platform of the openbmc system.
    level                           Release level of the OpenBMC system
                                    (e.g. "OBMC920").
    """

    result = ExecutionResult(xml_file_path)
    result.configure(stat_config={'suite_stat_level': 2,
                                  'tag_stat_combine': 'tagANDanother'})

    stats = result.statistics
    print("--------------------------------------")
    total_tc = stats.total.critical.passed + stats.total.critical.failed
    print("Total Test Count:\t %d" % total_tc)
    print("Total Test Failed:\t %d" % stats.total.critical.failed)
    print("Total Test Passed:\t %d" % stats.total.critical.passed)
    print("Test Start Time:\t %s" % result.suite.starttime)
    print("Test End Time:\t\t %s" % result.suite.endtime)
    print("--------------------------------------")

    # Use ResultVisitor object and save off the test data info
    class TestResult(ResultVisitor):
        def __init__(self):
            self.testData = []

        def visit_test(self, test):
            self.testData += [test]

    collectDataObj = TestResult()
    result.visit(collectDataObj)

    # Write the result statistics attributes to CSV file
    l_csvlist = []

    # Default Test data
    l_subsys = 'OPENBMC'
    l_test_type = 'FTC'

    l_pse_rel = 'OBMC910'
    if level:
        l_pse_rel = level

    l_env = 'HW'
    l_proc = 'P9'
    l_platform_type = ""
    l_func_area = ""

    # System data from XML meta data
    # l_system_info = get_system_details(xml_file_path)

    # First let us try to collect information from keyboard input
    # If keyboard input cannot give both information, then find from xml file.
    if version_id and platform:
        l_driver = version_id
        l_platform_type = platform
        print("BMC Version_id:%s" % version_id)
        print("BMC Platform:%s" % platform)
    else:
        # System data from XML meta data
        l_system_info = get_system_details(xml_file_path)
        l_driver = l_system_info[0]
        l_platform_type = l_system_info[1]

    # Driver version id and platform are mandatorily required for CSV file
    # generation. If any one is not avaulable, exit CSV file generation
    # process.
    if l_driver and l_platform_type:
        print("Driver and system info set.")
    else:
        print("Both driver and system info need to be set.\
                CSV file is not generated.")
        sys.exit()

    # Default header
    l_header = ['test_start', 'test_end', 'subsys', 'test_type',
                'test_result', 'test_name', 'pse_rel', 'driver',
                'env', 'proc', 'platform_type', 'test_func_area']

    l_csvlist.append(l_header)

    # Generate CSV file onto the path with current time stamp
    l_base_dir = csv_dir_path
    l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
    # Example: 2017-02-20-08-47-22_Witherspoon.csv
    l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"

    print("Writing data into csv file:%s" % l_csvfile)

    for testcase in collectDataObj.testData:
        # Functional Area: Suite Name
        # Test Name: Test Case Name
        l_func_area = str(testcase.parent).split(' ', 1)[1]
        l_test_name = str(testcase)

        # Test Result pass=0 fail=1
        if testcase.status == 'PASS':
            l_test_result = 0
        else:
            l_test_result = 1

        # Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
        l_stime = xml_to_csv_time(testcase.starttime)
        l_etime = xml_to_csv_time(testcase.endtime)
        # Data Sequence: test_start,test_end,subsys,test_type,
        #                test_result,test_name,pse_rel,driver,
        #                env,proc,platform_tyep,test_func_area,
        l_data = [l_stime, l_etime, l_subsys, l_test_type, l_test_result,
                  l_test_name, l_pse_rel, l_driver, l_env, l_proc,
                  l_platform_type, l_func_area]
        l_csvlist.append(l_data)

    # Open the file and write to the CSV file
    l_file = open(l_csvfile, "w")
    l_writer = csv.writer(l_file, lineterminator='\n')
    l_writer.writerows(l_csvlist)
    l_file.close()
Example #8
0
 def check_tests(self):
     result = ExecutionResult(self.report)
     result.visit(ExecutionTimeChecker(self.report))
     return suit_list
 def process_output(self, inpath, outpath=None):
     result = ExecutionResult(inpath)
     result.suite.visit(self)
     result.save(outpath)
     return result
Example #10
0
def get_result_data(xml_robot_output):
    """ Creates a result visitor from Robot API and accesses data from last Robot test run  """
    result = ExecutionResult(xml_robot_output)
    visitor = TestRailResultVisitor()
    result.visit(visitor)
    return visitor.suite_list, visitor.testcase_list
Example #11
0
 def get_suite_status(inpath):
     result = ExecutionResult(inpath)
     result.visit(SuiteStatus())
     suites_object["suites"] = suite_list
     return suites_object
Example #12
0
    shown = 0
    for k in s:
        if shown == shown_keywords:
            break
        if limit is not None and k.stdev_per_avgtime > limit:
            continue
        shown += 1
        print str(k.elapsed).rjust(14)+' | '+str(k.calls).rjust(7)+ ' | ' + \
                str(k.average_time).rjust(12) + ' | ' + str(k.median_time).rjust(15) + \
                ' | ' + str(k.standard_deviation).rjust(9) + ' | ' + str(k.stdev_per_avgtime).rjust(16) + (' | "%s"' % k.name)
    print 'Showing %d of total keywords %d' % (shown, len(times.keywords))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--limit', '-l', type=float, help='Filter out keywords with larger percentage'
            ' of stdev/avg time than LIMIT. This helps by filtering out most used "primitive" keywords'
            ' such as Sleep and Run Keyword If etc. and let\'s you focus on the keywords that very often'
            ' take a lot of time to execute (in other words are most fruitful places to focus optimisation effort).')
    parser.add_argument('--show', '-s', default=100, type=int, help='Max number of shown keywords. Default is 100.')
    parser.add_argument('source', help='output from a Robot Framework execution to analyze')
    args = parser.parse_args()
    try:
      resu = ExecutionResult(args.source)
      times = KeywordTimes()
      resu.visit(times)
      _print_results(times, args.show, args.limit)
    except:
        print __doc__
        raise
def generate_report(opts):
    writer = sys.stdout.write

    group = Group() if not FAILED_IMPORT else ''

    # ======================== START OF CUSTOMIZE REPORT ================================== #

    # URL or filepath of your company logo
    logo = opts.logo

    # Ignores following library keywords in metrics report
    ignore_library = IGNORE_LIBRARIES
    if opts.ignore:
        ignore_library.extend(opts.ignore)

    # Ignores following type keywords in metrics report
    ignore_type = IGNORE_TYPES
    if opts.ignoretype:
        ignore_type.extend(opts.ignoretype)

    # ======================== END OF CUSTOMIZE REPORT ================================== #

    # Report to support file location as arguments
    # Source Code Contributed By : Ruud Prijs

    # input directory
    path = os.path.abspath(os.path.expanduser(opts.path))

    # output.xml file
    output_name = os.path.join(path, opts.output)

    # report.html file
    report_name = opts.report_name

    # log.html file
    log_name = opts.log_name

    required_files = (
        output_name,
        # report_name,
        # log_name,
    )
    missing_files = [
        filename for filename in required_files if not os.path.exists(filename)
    ]
    if missing_files:
        # We have files missing.
        # writer("The following files are missing: {}\n".format(", ".join(missing_files)))
        writer("output.xml file is missing: {}".format(
            ", ".join(missing_files)))
        exit(1)

    # email status
    send_email = opts.email

    mtTime = datetime.now().strftime('%Y%m%d-%H%M%S')
    # Output result file location
    result_file_name = 'metrics-' + mtTime + '.html'
    result_file = os.path.join(path, result_file_name)

    # Read output.xml file
    result = ExecutionResult(output_name)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    writer("Converting .xml to .html file. This may take few minutes...")

    # ======= START OF EMAIL SETUP CONTENT ====== #
    if send_email:
        server = smtplib.SMTP('smtp.gmail.com:587')

    msg = MIMEMultipart()
    msg['Subject'] = 'Robotframework Automation Status'

    sender = opts.sender

    recipients = opts.to.split(',') if opts.to else ''

    ccrecipients = opts.cc.split(',') if opts.cc else ''

    msg['From'] = sender
    msg['To'] = ", ".join(recipients)
    msg['Cc'] = ", ".join(ccrecipients)
    password = opts.pwd
    msg.add_header('Content-Type', 'text/html')

    # ======= END OF EMAIL SETUP CONTENT ====== #

    head_content = """
    <!doctype html>
    <html lang="en">
    
    <head>
        <link rel="shortcut icon" href="https://png.icons8.com/windows/50/000000/bot.png" type="image/x-icon" />
        <title>RF Metrics Report</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
        <link href="https://cdn.datatables.net/buttons/1.5.2/css/buttons.dataTables.min.css" rel="stylesheet"/>
    
        <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
        
       <script src="https://code.jquery.com/jquery-3.3.1.js" type="text/javascript"></script>
       
        <!-- Bootstrap core Googleccharts -->
       <script src="https://www.gstatic.com/charts/loader.js" type="text/javascript"></script>
       <script type="text/javascript">google.charts.load('current', {packages: ['corechart']});</script>
    
       <!-- Bootstrap core Datatable-->
        <script src="https://code.jquery.com/jquery-3.3.1.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/dataTables.buttons.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.flash.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.html5.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.print.min.js" type="text/javascript"></script>
    
        <style>        
            .sidebar {
              position: fixed;
              top: 0;
              bottom: 0;
              left: 0;
              z-index: 100; /* Behind the navbar */
              box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
            }
            
            .sidebar-sticky {
              position: relative;
              top: 0;
              height: calc(100vh - 48px);
              padding-top: .5rem;
              overflow-x: hidden;
              overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
            }
            
            @supports ((position: -webkit-sticky) or (position: sticky)) {
              .sidebar-sticky {
                position: -webkit-sticky;
                position: sticky;
              }
            }
            
            .sidebar .nav-link {
              color: black;
            }
            
            .sidebar .nav-link.active {
              color: #007bff;
            }
            
            .sidebar .nav-link:hover .feather,
            .sidebar .nav-link.active .feather {
              color: inherit;
            }
    
            [role="main"] {
              padding-top: 8px;
            }
            
            /* Set height of body and the document to 100% */
            body {
                height: 100%;
                margin: 0;
                //font-family:  Comic Sans MS;
                background-color: white;
            }
    
            /* Style tab links */
            .tablinkLog {
                cursor: pointer;
            }
            
            @import url(https://fonts.googleapis.com/css?family=Droid+Sans);
            .loader {
                position: fixed;
                left: 0px;
                top: 0px;
                width: 100%;
                height: 100%;
                z-index: 9999;
                background: url('http://www.downgraf.com/wp-content/uploads/2014/09/01-progress.gif?e44397') 50% 50% no-repeat rgb(249,249,249);
            }
    
            /* TILES */
            .tile {
              width: 100%;
              float: left;
              margin: 0px;
              list-style: none;
              font-size: 30px;
              color: #FFF;
              -moz-border-radius: 5px;
              -webkit-border-radius: 5px;
              margin-bottom: 5px;
              position: relative;
              text-align: center;
              color: white!important;
            }
    
            .tile.tile-fail {
              background: #f44336!important;
            }
            .tile.tile-pass {
              background: #4CAF50!important;
            }
            .tile.tile-info {
              background: #009688!important;
            }
            .tile.tile-head {
              background: #616161!important;
            }
            .dt-buttons {
                margin-left: 5px;
            }
        </style>
    </head>
    """

    soup = BeautifulSoup(head_content, "html.parser")

    body = soup.new_tag('body')
    soup.insert(20, body)

    icons_txt = """
    <div class="loader"></div>
     <div class="container-fluid">
            <div class="row">
                <nav class="col-md-2 d-none d-md-block bg-light sidebar" style="font-size:16px;">
                    <div class="sidebar-sticky">
                        <ul class="nav flex-column">                            
                      <img src="%s" style="height:18vh!important;width:95%%;"/>
                    
                    <br>
                    
                    <h6 class="sidebar-heading d-flex justify-content-between align-items-center text-muted">
                            <span>Metrics</span>
                            <a class="d-flex align-items-center text-muted" href="#"></a>
                        </h6>
    
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" id="defaultOpen" onclick="openPage('dashboard', this, 'orange')">
                                    <i class="fa fa-dashboard"></i> Dashboard
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" onclick="openPage('suiteMetrics', this, 'orange');executeDataTable('#sm',5)" >
                                    <i class="fa fa-th-large"></i> Suite Metrics
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" onclick="openPage('testMetrics', this, 'orange');executeDataTable('#tm',3)">
                                  <i class="fa fa-list-alt"></i> Test Metrics
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" onclick="openPage('keywordMetrics', this, 'orange');executeDataTable('#km',3)">
                                  <i class="fa fa-table"></i> Keyword Metrics
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" onclick="openPage('log', this, 'orange');">
                                  <i class="fa fa-wpforms"></i> Robot Logs
                                </a>
                            </li>
                            <li class="nav-item">
                                <a class="tablink nav-link" href="#" onclick="openPage('statistics', this, 'orange');">
                                  <i class="fa fa-envelope-o"></i> Email Metrics
                                </a>
                            </li>
                        </ul>
                        <h6 class="sidebar-heading d-flex justify-content-between align-items-center text-muted">
                            <span>Project</span>
                            <a class="d-flex align-items-center text-muted" href="#"></a>
                        </h6>
                        <ul class="nav flex-column mb-2">
                            <li class="nav-item">
                                <a style="color:blue;" class="tablink nav-link" target="_blank" href="https://www.github.com">
                                  <i class="fa fa-external-link"></i> Git Hub
                                </a>
                            </li>
                            <li class="nav-item">
                                <a style="color:blue;" class="tablink nav-link" target="_blank" href="https://www.jira.com">
                                  <i class="fa fa-external-link"></i> JIRA
                                </a>
                            </li>
                        </ul>
                    </div>
                </nav>
            </div>
    """ % (logo)

    body.append(BeautifulSoup(icons_txt, 'html.parser'))

    page_content_div = soup.new_tag('div')
    page_content_div["role"] = "main"
    page_content_div["class"] = "col-md-9 ml-sm-auto col-lg-10 px-4"
    body.insert(50, page_content_div)

    writer("\n1 of 6: Capturing dashboard content...")
    ### ============================ START OF DASHBOARD ======================================= ####
    test_stats = TestStats()
    result.visit(test_stats)

    total_suite = test_stats.total_suite
    passed_suite = test_stats.passed_suite
    failed_suite = test_stats.failed_suite

    suitepp = math.ceil(passed_suite * 100.0 / total_suite)

    elapsedtime = datetime(
        1970, 1, 1) + timedelta(milliseconds=result.suite.elapsedtime)
    elapsedtime = elapsedtime.strftime("%X")

    myResult = result.generated_by_robot

    if myResult:
        generator = "Robot"
    else:
        generator = "Rebot"

    stats = result.statistics
    total = stats.total.all.total
    passed = stats.total.all.passed
    failed = stats.total.all.failed

    testpp = round(passed * 100.0 / total, 2)

    kw_stats = KeywordStats(ignore_library, ignore_type)
    result.visit(kw_stats)

    total_keywords = kw_stats.total_keywords
    passed_keywords = kw_stats.passed_keywords
    failed_keywords = kw_stats.failed_keywords

    # Handling ZeroDivisionError exception when no keywords are found
    if total_keywords > 0:
        kwpp = round(passed_keywords * 100.0 / total_keywords, 2)
    else:
        kwpp = 0

    dashboard_content = """
    <div class="tabcontent" id="dashboard">
                
                    <div class="d-flex flex-column flex-md-row align-items-center p-1 mb-3 bg-light border-bottom shadow-sm">
                      <h5 class="my-0 mr-md-auto font-weight-normal"><i class="fa fa-dashboard"></i> Dashboard</h5>
                      <nav class="my-2 my-md-0 mr-md-3" style="color:red">
                        <a class="p-2"><b style="color:black;">Execution Time: </b>%s h</a>
                        <a class="p-2"><b style="color:black;cursor: pointer;" data-toggle="tooltip" title=".xml file is created by">Generated By: </b>%s</a>
                      </nav>                  
                    </div>
                
                    <div class="row">
                        <div class="col-md-3"  onclick="openPage('suiteMetrics', this, '')" data-toggle="tooltip" title="Click to view Suite metrics" style="cursor: pointer;">                        
                            <a class="tile tile-head">
                                Suite
                                <p style="font-size:12px">Statistics</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-info">
                                %s
                                <p style="font-size:12px">Total</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-pass">
                                %s
                                <p style="font-size:12px">Pass</p>
                            </a>
                        </div>						
                        <div class="col-md-3">                        
                            <a class="tile tile-fail">
                                %s
                                <p style="font-size:12px">Fail</p>
                            </a>
                        </div>
                    </div>
                    
                    <div class="row">
                        <div class="col-md-3"  onclick="openPage('testMetrics', this, '')" data-toggle="tooltip" title="Click to view Test metrics" style="cursor: pointer;">                        
                            <a class="tile tile-head">
                                Test
                                <p style="font-size:12px">Statistics</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-info">
                                %s
                                <p style="font-size:12px">Total</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-pass">
                                %s
                                <p style="font-size:12px">Pass</p>
                            </a>
                        </div>						
                        <div class="col-md-3">                        
                            <a class="tile tile-fail">
                                %s
                                <p style="font-size:12px">Fail</p>
                            </a>
                        </div>
                    </div>
                    
                    <div class="row">
                        <div class="col-md-3"  onclick="openPage('keywordMetrics', this, '')" data-toggle="tooltip" title="Click to view Keyword metrics" style="cursor: pointer;">                        
                            <a class="tile tile-head">
                                Keyword
                                <p style="font-size:12px">Statistics</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-info">
                                %s
                                <p style="font-size:12px">Total</p>
                            </a>
                        </div>
                        <div class="col-md-3">                        
                            <a class="tile tile-pass">
                                %s
                                <p style="font-size:12px">Pass</p>
                            </a>
                        </div>						
                        <div class="col-md-3">                        
                            <a class="tile tile-fail">
                                %s
                                <p style="font-size:12px">Fail</p>
                            </a>
                        </div>
                    </div>
                    
                    <hr></hr>
                    <div class="row">
                        <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                            <span style="font-weight:bold">Suite Status:</span>
                            <div id="suiteChartID" style="height:250px;width:auto;"></div>
                        </div>
                        <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                            <span style="font-weight:bold">Test Status:</span>
                            <div id="testChartID" style="height:250px;width:auto;"></div>
                        </div>
                        <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                            <span style="font-weight:bold">Keyword Status:</span>
                            <div id="keywordChartID" style="height:250px;width:auto;"></div>
                        </div>
                    </div>
    
                    <hr></hr>
                    <div class="row">
                        <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                            <span style="font-weight:bold">Top 10 Suite Performance(sec):</span>
                            <div id="suiteBarID" style="height:400px;width:auto;"></div>
                        </div>
                        <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                            <span style="font-weight:bold">Top 10 Test Performance(sec):</span>
                            <div id="testsBarID" style="height:400px;width:auto;"></div>
                        </div>
                        <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                            <span style="font-weight:bold">Top 10 Keywords Performance(sec):</span>
                            <div id="keywordsBarID" style="height:400px;width:auto;"></div>
                        </div>
                    </div>
                    <div class="row">
                    <div class="col-md-12" style="height:25px;width:auto;">
                        <p class="text-muted" style="text-align:center;font-size:9px">robotframework-metrics</p>
                    </div>
                    </div>
       
       <script>
        window.onload = function(){
        executeDataTable('#sm',5);
        executeDataTable('#tm',3);
        executeDataTable('#km',3);
        createPieChart(%s,%s,'suiteChartID','Suite Status:');
        createBarGraph('#sm',0,5,10,'suiteBarID','Elapsed Time(s): ','Suite');	
        createPieChart(%s,%s,'testChartID','Tests Status:');	
        createBarGraph('#tm',1,3,10,'testsBarID','Elapsed Time(s): ','Test'); 
        createPieChart(%s,%s,'keywordChartID','Keywords Status:');
        createBarGraph('#km',1,3,10,'keywordsBarID','Elapsed Time(s): ','Keyword');
        };
       </script>
       <script>
    function openInNewTab(url,element_id) {
      var element_id= element_id;
      var win = window.open(url, '_blank');
      win.focus();
      $('body').scrollTo(element_id); 
    }
    </script>
      </div>
    """ % (elapsedtime, generator, total_suite, passed_suite, failed_suite,
           total, passed, failed, total_keywords, passed_keywords,
           failed_keywords, passed_suite, failed_suite, passed, failed,
           passed_keywords, failed_keywords)
    page_content_div.append(BeautifulSoup(dashboard_content, 'html.parser'))

    ### ============================ END OF DASHBOARD ============================================ ####
    writer("\n2 of 6: Capturing suite metrics...")
    ### ============================ START OF SUITE METRICS ======================================= ####

    # Tests div
    suite_div = soup.new_tag('div')
    suite_div["id"] = "suiteMetrics"
    suite_div["class"] = "tabcontent"
    page_content_div.insert(50, suite_div)

    test_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Suite Metrics</b></h4>
    <hr></hr>
    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "sm"
    table["class"] = "table table-striped table-bordered"
    suite_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Total"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Pass"
    tr.insert(3, th)

    th = soup.new_tag('th')
    th.string = "Fail"
    tr.insert(4, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(5, th)

    suite_tbody = soup.new_tag('tbody')
    table.insert(11, suite_tbody)

    ### =============== GET SUITE METRICS =============== ###
    if group:
        group.spawn(result.visit, SuiteResults(soup, suite_tbody, log_name))
    else:
        result.visit(SuiteResults(soup, suite_tbody, log_name))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))
    ### ============================ END OF SUITE METRICS ============================================ ####
    writer("\n3 of 6: Capturing test metrics...")
    ### ============================ START OF TEST METRICS ======================================= ####
    # Tests div
    tm_div = soup.new_tag('div')
    tm_div["id"] = "testMetrics"
    tm_div["class"] = "tabcontent"
    page_content_div.insert(100, tm_div)

    test_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Test Metrics</b></h4>
    <hr></hr>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "tm"
    table["class"] = "table table-striped table-bordered"
    tm_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    test_tbody = soup.new_tag('tbody')
    table.insert(11, test_tbody)

    ### =============== GET TEST METRICS =============== ###
    if group:
        group.spawn(result.visit, TestResults(soup, test_tbody, log_name))
    else:
        result.visit(TestResults(soup, test_tbody, log_name))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))
    ### ============================ END OF TEST METRICS ============================================ ####
    writer("\n4 of 6: Capturing keyword metrics...")
    ### ============================ START OF KEYWORD METRICS ======================================= ####

    # Keywords div
    km_div = soup.new_tag('div')
    km_div["id"] = "keywordMetrics"
    km_div["class"] = "tabcontent"
    page_content_div.insert(150, km_div)

    keyword_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Keyword Metrics</b></h4>
      <hr></hr>
    """
    km_div.append(BeautifulSoup(keyword_icon_txt, 'html.parser'))

    # Create table tag
    # <table id="myTable">
    table = soup.new_tag('table')
    table["id"] = "km"
    table["class"] = "table table-striped table-bordered"
    km_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Keyword"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    kw_tbody = soup.new_tag('tbody')
    table.insert(1, kw_tbody)

    if group:
        group.spawn(
            result.visit,
            KeywordResults(soup, kw_tbody, ignore_library, ignore_type))
        group.join()
    else:
        result.visit(
            KeywordResults(soup, kw_tbody, ignore_library, ignore_type))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    km_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))
    ### ============================ END OF KEYWORD METRICS ======================================= ####

    ### ============================ START OF LOGS ====================================== ###

    # Logs div
    log_div = soup.new_tag('div')
    log_div["id"] = "log"
    log_div["class"] = "tabcontent"
    page_content_div.insert(200, log_div)

    test_icon_txt = """
        <p style="text-align:right">** <b>Report.html</b> and <b>Log.html</b> need to be in current folder in order to display here</p>
      <div class="embed-responsive embed-responsive-4by3">
        <iframe class="embed-responsive-item" src=%s></iframe>
      </div>
    """ % (log_name)
    log_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    ### ============================ END OF LOGS ======================================= ####

    ### ============================ EMAIL STATISTICS ================================== ###
    # Statistics div
    statisitcs_div = soup.new_tag('div')
    statisitcs_div["id"] = "statistics"
    statisitcs_div["class"] = "tabcontent"
    page_content_div.insert(300, statisitcs_div)

    emailStatistics = """
    <h4><b><i class="fa fa-envelope-o"></i> Email Statistics</b></h4>
    <hr></hr>
    <button id="create" class="btn btn-primary active inner" role="button" onclick="updateTextArea();this.style.visibility= 'hidden';"><i class="fa fa-cogs"></i> Generate Statistics Email</button>
    <a download="message.eml" class="btn btn-primary active inner" role="button" id="downloadlink" style="display: none; width: 300px;"><i class="fa fa-download"></i> Click Here To Download Email</a>
    <script>
    function updateTextArea() {
        var suite = "<b>Top 10 Suite Performance:</b><br><br>" + $("#suiteBarID table")[0].outerHTML;
        var test = "<b>Top 10 Test Performance:</b><br><br>" + $("#testsBarID table")[0].outerHTML;
        var keyword ="<b>Top 10 Keyword Performance:</b><br><br>" + $("#keywordsBarID table")[0].outerHTML;
        var saluation="<pre><br>Please refer RF Metrics Report for detailed statistics.<br><br>Regards,<br>QA Team</pre></body></html>";
        document.getElementById("textbox").value += "<br>" + suite + "<br>" + test + "<br>" + keyword + saluation;
        $("#create").click(function(){
        $(this).remove();
        });
    }
    </script>
    
<textarea id="textbox" class="col-md-12" style="height: 400px; padding:1em;">
To: [email protected]
Subject: Automation Execution Status
X-Unsent: 1
Content-Type: text/html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test Email Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0 " />
        <style>
            body {
                background-color:#F2F2F2; 
            }
            body, html, table,pre,b {
                font-family: Calibri, Arial, sans-serif;
                font-size: 1em; 
            }
            .pastdue { color: crimson; }
            table {
                border: 1px solid silver;
                padding: 6px;
                margin-left: 30px;
                width: 600px;
            }
            thead {
                text-align: center;
                font-size: 1.1em;        
                background-color: #B0C4DE;
                font-weight: bold;
                color: #2D2C2C;
            }
            tbody {
            text-align: center;
            }
            th {
            width: 25%%;
            word-wrap:break-word;
            }
        </style>
    </head>
    <body><pre>Hi Team,
Following are the last build execution statistics.

<b>Metrics:<b>

</pre>
        <table>
            <thead>
            <th style="width: 25%%;">Statistics</th>
            <th style="width: 25%%;">Total</th>
            <th style="width: 25%%;">Pass</th>
            <th style="width: 25%%;">Fail</th>
            </thead>
            <tbody>
            <tr>
                <td style="text-align: left;font-weight: bold;"> SUITE </td>
                <td style="background-color: #F5DEB3;text-align: center;">%s</td>
                <td style="background-color: #90EE90;text-align: center;">%s</td>
                <td style="background-color: #F08080;text-align: center;">%s</td>
            </tr>
            <tr>
                <td style="text-align: left;font-weight: bold;"> TESTS </td>
                <td style="background-color: #F5DEB3;text-align: center;">%s</td>
                <td style="background-color: #90EE90;text-align: center;">%s</td>
                <td style="background-color: #F08080;text-align: center;">%s</td>
            </tr>
            <tr>
                <td style="text-align: left;font-weight: bold;"> KEYWORDS </td>
                <td style="background-color: #F5DEB3;text-align: center;">%s</td>
                <td style="background-color: #90EE90;text-align: center;">%s</td>
                <td style="background-color: #F08080;text-align: center;">%s</td>
            </tr>
            </tbody>
        </table>


</textarea>
    
    """ % (total_suite, passed_suite, failed_suite, total, passed, failed,
           total_keywords, passed_keywords, failed_keywords)
    statisitcs_div.append(BeautifulSoup(emailStatistics, 'html.parser'))

    ### ============================ END OF EMAIL STATISTICS ================================== ###

    script_text = """
    
        <script>
            (function () {
            var textFile = null,
              makeTextFile = function (text) {
                var data = new Blob([text], {type: 'text/plain'});
                if (textFile !== null) {
                  window.URL.revokeObjectURL(textFile);
                }
                textFile = window.URL.createObjectURL(data);
                return textFile;
              };
            
              var create = document.getElementById('create'),
                textbox = document.getElementById('textbox');
              create.addEventListener('click', function () {
                var link = document.getElementById('downloadlink');
                link.href = makeTextFile(textbox.value);
                link.style.display = 'block';
              }, false);
            })();
        </script>
        <script>
            function createPieChart(passed_count,failed_count,ChartID,ChartName){
            var status = [];
            status.push(['Status', 'Percentage']);
            status.push(['PASS',parseInt(passed_count)],['FAIL',parseInt(failed_count)]);
            var data = google.visualization.arrayToDataTable(status);
    
            var options = {
            pieHole: 0.6,
            legend: 'none',
            chartArea: {width: "95%",height: "90%"},
            colors: ['green', 'red'],
            };
    
            var chart = new google.visualization.PieChart(document.getElementById(ChartID));
            chart.draw(data, options);
        }
        </script>
        <script>
           function createBarGraph(tableID,keyword_column,time_column,limit,ChartID,Label,type){
            var status = [];
            css_selector_locator = tableID + ' tbody >tr'
            var rows = $(css_selector_locator);
            var columns;
            var myColors = [
                '#4F81BC',
                '#C0504E',
                '#9BBB58',
                '#24BEAA',
                '#8064A1',
                '#4AACC5',
                '#F79647',
                '#815E86',
                '#76A032',
                '#34558B'
            ];
            status.push([type, Label,{ role: 'annotation'}, {role: 'style'}]);
            for (var i = 0; i < rows.length; i++) {
                if (i == Number(limit)){
                    break;
                }
                //status = [];
                name_value = $(rows[i]).find('td'); 
              
                time=($(name_value[Number(time_column)]).html()).trim();
                keyword=($(name_value[Number(keyword_column)]).html()).trim();
                status.push([keyword,parseFloat(time),parseFloat(time),myColors[i]]);
              }
              var data = google.visualization.arrayToDataTable(status);
    
              var options = {
                legend: 'none',
                chartArea: {width: "92%",height: "75%"},
                bar: {
                    groupWidth: '90%'
                },
                annotations: {
                    alwaysOutside: true,
                    textStyle: {
                    fontName: 'Comic Sans MS',
                    fontSize: 13,
                    bold: true,
                    italic: true,
                    color: "black",     // The color of the text.
                    },
                },
                hAxis: {
                    textStyle: {
                        fontName: 'Arial',
                        fontSize: 10,
                    }
                },
                vAxis: {
                    gridlines: { count: 10 },
                    textStyle: {                    
                        fontName: 'Comic Sans MS',
                        fontSize: 10,
                    }
                },
              };  
    
                // Instantiate and draw the chart.
                var chart = new google.visualization.ColumnChart(document.getElementById(ChartID));
                chart.draw(data, options);
             }
    
        </script>
    
     <script>
      function executeDataTable(tabname,sortCol) {
        var fileTitle;
        switch(tabname) {
            case "#sm":
                fileTitle = "SuiteMetrics";
                break;
            case "#tm":
                fileTitle =  "TestMetrics";
                break;
            case "#km":
                fileTitle =  "KeywordMetrics";
                break;
            default:
                fileTitle =  "metrics";
        }
    
        $(tabname).DataTable(
            {
                retrieve: true,
                "order": [[ Number(sortCol), "desc" ]],
                dom: 'l<".margin" B>frtip',
                buttons: [
                    'copy',
                    {
                        extend: 'csv',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'excel',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'pdf',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'print',
                        title : '',
                    },
                ],
            } 
        );
    }
     </script>
     <script>
      function openPage(pageName,elmnt,color) {
        var i, tabcontent, tablinks;
        tabcontent = document.getElementsByClassName("tabcontent");
        for (i = 0; i < tabcontent.length; i++) {
            tabcontent[i].style.display = "none";
        }
        tablinks = document.getElementsByClassName("tablink");
        for (i = 0; i < tablinks.length; i++) {
            tablinks[i].style.backgroundColor = "";
        }
        document.getElementById(pageName).style.display = "block";
        elmnt.style.backgroundColor = color;
    
    }
    // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
     </script>
     <script>
     // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
     </script>
     <script>
    $(window).on('load',function(){$('.loader').fadeOut();});
    </script>
    """

    body.append(BeautifulSoup(script_text, 'html.parser'))

    ### ====== WRITE TO RF_METRICS_REPORT.HTML ===== ###

    # Write output as html file
    with open(result_file, 'w') as outfile:
        outfile.write(soup.prettify())

    # Wait for 2 seconds - File is generated
    time.sleep(2)

    # ====== EMAIL CONTENT ========== #

    email_content = """
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Robotframework Metrics</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0 " />
          <style>
             body {
                 background-color:#F2F2F2; 
             }
             body, html, table,span,b {
                 font-family: Calibri, Arial, sans-serif;
                 font-size: 1em; 
             }
             .pastdue { color: crimson; }
             table {
                 border: 1px solid silver;
                 padding: 6px;
                 margin-left: 30px;
                 width: 600px;
             }
             thead {
                 text-align: center;
                 font-size: 1.1em;        
                 background-color: #B0C4DE;
                 font-weight: bold;
                 color: #2D2C2C;
             }
             tbody {
                text-align: center;
             }
             th {
                word-wrap:break-word;
             }
             td {
                height: 25px;
             }
            .dt-buttons {
                margin-left: 30px;
            }
          </style>
       </head>
       <body>
       <span>Hi Team,<br>Following are the last build execution status.<br><br><b>Metrics:<b><br><br></span>
          <table>
             <thead>
                <th style="width: 25vh;"> Stats </th>
                <th style="width: 20vh;"> Total </th>
                <th style="width: 20vh;"> Pass </th>
                <th style="width: 20vh;"> Fail </th>
                      <th style="width: 15vh;"> Perc (%%)</th>
             </thead>
             <tbody>
                <tr>
                   <td style="text-align: left;font-weight: bold;"> SUITE </td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                         <td style="text-align: center;">%s</td>
                </tr>
                <tr>
                   <td style="text-align: left;font-weight: bold;"> TESTS </td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                         <td style="text-align: center;">%s</td>
                </tr>
                <tr>
                   <td style="text-align: left;font-weight: bold;"> KEYWORDS </td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                   <td style="text-align: center;">%s</td>
                         <td style="text-align: center;">%s</td>
                </tr>
             </tbody>
          </table>
    
    <span><br><b>Info:<b><br><br></span>
     <table>
             <tbody>
                <tr>
                   <td style="text-align: left;font-weight: normal;width: 30vh;"> Execution Time </td>
                   <td style="text-align: center;font-weight: normal;">%s h</td>
                </tr>
                <tr>
                   <td style="text-align: left;font-weight: normal;width: 50vh;"> Generated By </td>
                   <td style="text-align: center;font-weight: normal;">%s</td>
                </tr>
             </tbody>
          </table>
    
    <span style="text-align: left;font-weight: normal;"><br>Please refer robotframework-metrics report for detailed info.<br><br>Regards,<br>QA Team</span>
    
    </body></html> 
    """ % (total_suite, passed_suite, failed_suite, suitepp, total, passed,
           failed, testpp, total_keywords, passed_keywords, failed_keywords,
           kwpp, elapsedtime, generator)

    #msg.set_payload(email_content)
    msg.attach(MIMEText(email_content, 'html'))

    # Attach robotframework file
    rfmetrics = MIMEBase('application', "octet-stream")
    rfmetrics.set_payload(open(result_file, "rb").read())
    encoders.encode_base64(rfmetrics)
    attachmentName = 'attachment; filename=%s' % (result_file_name)
    rfmetrics.add_header('Content-Disposition', attachmentName)
    msg.attach(rfmetrics)

    if send_email:
        # Start server
        server.starttls()
        writer("\n5 of 6: Sending email with robotmetrics.html...")
        # Login Credentials for sending the mail
        server.login(msg['From'], password)

        server.sendmail(sender, recipients, msg.as_string())
        writer("\n6 of 6: Email sent successfully!")
    else:
        writer("\n6 of 6: Skipping step 5 (send email)!")

    writer(
        "\nResults file created successfully and can be found at {}\n".format(
            result_file))
Example #14
0
def check_tests(seconds, inpath, outpath=None):
    result = ExecutionResult(inpath)
    result.visit(ExecutionTimeChecker(float(seconds)))
    result.save(outpath)
Example #15
0
def check_tests(seconds, inpath, outpath=None):
    result = ExecutionResult(inpath)
    result.visit(ExecutionTimeChecker(float(seconds)))
    result.save(outpath)
Example #16
0
Usage as a script:
    {tool} path/to/output.xml max_seconds

Usage as a modifier:
    robot --prerebotmodifier {tool}:max_seconds path/to/tests.robot
    rebot --prerebotmodifier {tool}:max_seconds path/to/output.xml
"""

import sys
from robot.api import SuiteVisitor, ExecutionResult


class FailSlowTests(SuiteVisitor):
    def __init__(self, max_seconds):
        self.max_seconds = float(max_seconds)

    def visit_test(self, test):
        if test.passed and test.elapsedtime > self.max_seconds * 1000:
            test.status = 'FAIL'
            test.message = 'Test was slower than %0.3f s.' % self.max_seconds


if __name__ == '__main__':
    if len(sys.argv) != 3:
        sys.exit(__doc__.format(tool=sys.argv[0]))
    path, max_time = sys.argv[1:]
    result = ExecutionResult(path)
    result.suite.visit(FailSlowTests(max_time))
    result.save()
    sys.exit(result.return_code)
def generate_report(opts):
    logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
    group = Group() if not FAILED_IMPORT else ''

    # START OF CUSTOMIZE REPORT
    # URL or filepath of your company logo
    logo = opts.logo

    # Ignores following library keywords in metrics report
    ignore_library = IGNORE_LIBRARIES
    if opts.ignore:
        ignore_library.extend(opts.ignore)

    # Ignores following type keywords in metrics report
    ignore_type = IGNORE_TYPES
    if opts.ignoretype:
        ignore_type.extend(opts.ignoretype)

    # END OF CUSTOMIZE REPORT
    # Report to support file location as arguments
    # Source Code Contributed By : Ruud Prijs
    # input directory
    path = os.path.abspath(os.path.expanduser(opts.path))

    # output.xml files
    output_names = []
    # support "*.xml" of output files
    if (opts.output == "*.xml"):
        for item in os.listdir(path):
            if os.path.isfile(item) and item.endswith('.xml'):
                output_names.append(item)
    else:
        for curr_name in opts.output.split(","):
            curr_path = os.path.join(path, curr_name)
            output_names.append(curr_path)

    # log.html file
    log_name = opts.log_name

    # copy the list of output_names onto the one of required_files; the latter may (in the future)
    # contain files that should not be processed as output_names
    required_files = list(output_names)
    missing_files = [
        filename for filename in required_files if not os.path.exists(filename)
    ]
    if missing_files:
        # We have files missing.
        exit("output.xml file is missing: {}".format(", ".join(missing_files)))

    mt_time = datetime.now().strftime('%Y%m%d-%H%M%S')

    # Output result file location
    if opts.metrics_report_name:
        result_file_name = opts.metrics_report_name
    else:
        result_file_name = 'metrics-' + mt_time + '.html'
    result_file = os.path.join(path, result_file_name)

    # Read output.xml file
    result = ExecutionResult(*output_names)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    logging.info("Converting .xml to .html file. This may take few minutes...")

    head_content = """
    <!doctype html><html lang="en">
    <head>
        <link rel="shortcut icon" href="https://png.icons8.com/windows/50/000000/bot.png" type="image/x-icon" />
        <title>RF Metrics</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet"/>
        <link href="https://cdn.datatables.net/buttons/1.5.2/css/buttons.dataTables.min.css" rel="stylesheet"/>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

       <script src="https://code.jquery.com/jquery-3.3.1.js" type="text/javascript"></script>

        <!-- Bootstrap core Googleccharts -->
       <script src="https://www.gstatic.com/charts/loader.js" type="text/javascript"></script>
       <script type="text/javascript">google.charts.load('current', {packages: ['corechart']});</script>

       <!-- Bootstrap core Datatable-->
        <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/dataTables.buttons.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.flash.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.html5.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.print.min.js" type="text/javascript"></script>

        <style>
            body {
                font-family: -apple-system,sans-serif;
            }

            .sidenav {
                height: 100%;
                width: 220px;
                position: fixed;
                z-index: 1;
                top: 0;
                left: 0;
                background-color: white;
                overflow-x: hidden;
                border-style: ridge;
            }

            .sidenav a {
                padding: 12px 10px 8px 12px;
                text-decoration: none;
                font-size: 18px;
                color: Black;
                display: block;
            }

            .main {
                padding-top: 10px;
            }

            @media screen and (max-height: 450px) {
                .sidenav {padding-top: 15px;}
                .sidenav a {font-size: 18px;}
            }

            .tile {
                width: 100%;
                float: left;
                margin: 0px;
                list-style: none;
                font-size: 30px;
                color: #FFF;
                -moz-border-radius: 5px;
                -webkit-border-radius: 5px;
                margin-bottom: 5px;
                position: relative;
                text-align: center;
                color: white!important;
            }

            .tile.tile-fail {
                background: #f44336!important;
            }
            .tile.tile-pass {
                background: #4CAF50!important;
            }
            .tile.tile-info {
                background: #009688!important;
            }
            .tile.tile-head {
                background: #616161!important;
            }
            .dt-buttons {
                margin-left: 5px;
            }
            
            .loader {
                position: fixed;
                left: 0px;
                top: 0px;
                width: 100%;
                height: 100%;
                z-index: 9999;
                background: url('https://www.downgraf.com/wp-content/uploads/2014/09/02-loading-blossom-2x.gif') 
                    50% 50% no-repeat rgb(249,249,249);
            }

        </style>
    </head>
    """

    soup = BeautifulSoup(head_content, "html.parser")
    body = soup.new_tag('body')
    soup.insert(20, body)
    icons_txt = """
    <div class="loader"></div>
    <div class="sidenav">
        <a> <img src="%s" style="height:20vh;max-width:98%%;"/> </a>
        <a class="tablink" href="#" id="defaultOpen" onclick="openPage('dashboard', this, 'orange')"><i class="fa fa-dashboard"></i> Dashboard</a>
        <a class="tablink" href="#" onclick="openPage('suiteMetrics', this, 'orange'); executeDataTable('#sm',5)"><i class="fa fa-th-large"></i> Suite Metrics</a>
        <a class="tablink" href="#" onclick="openPage('testMetrics', this, 'orange'); executeDataTable('#tm',3)"><i class="fa fa-list-alt"></i> Test Metrics</a>
        <a class="tablink" href="#" onclick="openPage('keywordMetrics', this, 'orange'); executeDataTable('#km',3)"><i class="fa fa-table"></i> Keyword Metrics</a>
        <a class="tablink" href="#" onclick="openPage('log', this, 'orange');"><i class="fa fa-wpforms"></i> Logs</a>
        <a class="tablink" href="#" onclick="openPage('statistics', this, 'orange');"><i class="fa fa-envelope-o"></i> Email</a>
    </div>
    """ % logo

    body.append(BeautifulSoup(icons_txt, 'html.parser'))

    page_content_div = soup.new_tag('div')
    page_content_div["class"] = "main col-md-9 ml-sm-auto col-lg-10 px-4"
    body.insert(50, page_content_div)

    logging.info("1 of 4: Capturing dashboard content...")
    test_stats = TestStats()
    result.visit(test_stats)

    total_suite = test_stats.total_suite
    passed_suite = test_stats.passed_suite
    failed_suite = test_stats.failed_suite

    suitepp = round(passed_suite * 100.0 / total_suite, 1)
    suitefp = round(failed_suite * 100.0 / total_suite, 1)
    elapsedtime = datetime(
        1970, 1, 1) + timedelta(milliseconds=result.suite.elapsedtime)
    elapsedtime = elapsedtime.strftime("%X")
    my_results = result.generated_by_robot

    if my_results:
        generator = "Robot"
    else:
        generator = "Rebot"

    stats = result.statistics
    total = stats.total.all.total
    passed = stats.total.all.passed
    failed = stats.total.all.failed

    testpp = round(passed * 100.0 / total, 1)
    testfp = round(failed * 100.0 / total, 1)

    kw_stats = KeywordStats(ignore_library, ignore_type)
    result.visit(kw_stats)

    total_keywords = kw_stats.total_keywords
    passed_keywords = kw_stats.passed_keywords
    failed_keywords = kw_stats.failed_keywords

    # Handling ZeroDivisionError exception when no keywords are found
    if total_keywords > 0:
        kwpp = round(passed_keywords * 100.0 / total_keywords, 1)
        kwfp = round(failed_keywords * 100.0 / total_keywords, 1)
    else:
        kwpp = 0
        kwfp = 0

    dashboard_content = """
    <div class="tabcontent" id="dashboard">
        <div id="stats_screenshot_area">
        <div class="d-flex flex-column flex-md-row align-items-center p-1 mb-3 bg-light 
            border-bottom shadow-sm">
            <h5 class="my-0 mr-md-auto font-weight-normal"><i class="fa fa-dashboard"></i> Dashboard</h5>
            <nav class="my-2 my-md-0 mr-md-3" style="color:red">
            <a class="p-2"><b style="color:black;">Execution Time: </b>%s h</a>
            <a class="p-2"><b style="color:black;cursor: pointer;" data-toggle="tooltip" title=".xml file is created by">Generated By: </b>%s</a>
            </nav>                  
        </div>

        <div class="row">
            <div class="col-md-3"  onclick="openPage('suiteMetrics', this, '')" data-toggle="tooltip" 
                title="Click to view Suite metrics" style="cursor: pointer;">                        
                <a class="tile tile-head">
                    Suite
                    <p style="font-size:12px">Statistics</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-info">
                    %s
                    <p style="font-size:12px">Total</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-pass">
                    %s
                    <p style="font-size:12px">Pass</p>
                </a>
            </div>						
            <div class="col-md-3">                        
                <a class="tile tile-fail">
                    %s
                    <p style="font-size:12px">Fail</p>
                </a>
            </div>
        </div>

        <div class="row">
            <div class="col-md-3"  onclick="openPage('testMetrics', this, '')" data-toggle="tooltip" 
            title="Click to view Test metrics" style="cursor: pointer;">                        
                <a class="tile tile-head">
                    Test
                    <p style="font-size:12px">Statistics</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-info">
                    %s
                    <p style="font-size:12px">Total</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-pass">
                    %s
                    <p style="font-size:12px">Pass</p>
                </a>
            </div>						
            <div class="col-md-3">                        
                <a class="tile tile-fail">
                    %s
                    <p style="font-size:12px">Fail</p>
                </a>
            </div>
        </div>

        <div class="row">
            <div class="col-md-3"  onclick="openPage('keywordMetrics', this, '')" data-toggle="tooltip" 
                title="Click to view Keyword metrics" style="cursor: pointer;">                        
                <a class="tile tile-head">
                    Keyword
                    <p style="font-size:12px">Statistics</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-info">
                    %s
                    <p style="font-size:12px">Total</p>
                </a>
            </div>
            <div class="col-md-3">                        
                <a class="tile tile-pass">
                    %s
                    <p style="font-size:12px">Pass</p>
                </a>
            </div>						
            <div class="col-md-3">                        
                <a class="tile tile-fail">
                    %s
                    <p style="font-size:12px">Fail</p>
                </a>
            </div>
        </div>

        <hr></hr>
        <div class="row">
            <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                <span style="font-weight:bold">Suite Status:</span>
                <div id="suiteChartID" style="height:250px;width:auto;"></div>
            </div>
            <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                <span style="font-weight:bold">Test Status:</span>
                <div id="testChartID" style="height:250px;width:auto;"></div>
            </div>
            <div class="col-md-4" style="background-color:white;height:280px;width:auto;border:groove;">
                <span style="font-weight:bold">Keyword Status:</span>
                <div id="keywordChartID" style="height:250px;width:auto;"></div>
            </div>
        </div>
        </div>
        <hr></hr>
        <div class="row">
            <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                <span style="font-weight:bold">Top 10 Suite Performance(sec):</span>
                <div id="suiteBarID" style="height:400px;width:auto;"></div>
            </div>
            <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                <span style="font-weight:bold">Top 10 Test Performance(sec):</span>
                <div id="testsBarID" style="height:400px;width:auto;"></div>
            </div>
            <div class="col-md-12" style="background-color:white;height:450px;width:auto;border:groove;">
                <span style="font-weight:bold">Top 10 Keywords Performance(sec):</span>
                <div id="keywordsBarID" style="height:400px;width:auto;"></div>
            </div>
        </div>
        <div class="row">
        <div class="col-md-12" style="height:25px;width:auto;">
            <p class="text-muted" style="text-align:center;font-size:9px">
                <a target="_blank" href="https://github.com/adiralashiva8/robotframework-metrics"> robotframework-metrics </a>
            </p>
        </div>
        </div>

       <script>
        window.onload = function(){
        executeDataTable('#sm',5);
        executeDataTable('#tm',3);
        executeDataTable('#km',3);
        createPieChart(%s,%s,'suiteChartID','Suite Status:');
        createBarGraph('#sm',0,5,10,'suiteBarID','Elapsed Time (s) ','Suite');	
        createPieChart(%s,%s,'testChartID','Tests Status:');	
        createBarGraph('#tm',1,3,10,'testsBarID','Elapsed Time (s) ','Test'); 
        createPieChart(%s,%s,'keywordChartID','Keywords Status:');
        createBarGraph('#km',1,3,10,'keywordsBarID','Elapsed Time (s) ','Keyword');
        };
       </script>
       <script>
    function openInNewTab(url,element_id) {
      var element_id= element_id;
      var win = window.open(url, '_blank');
      win.focus();
      $('body').scrollTo(element_id); 
    }
    </script>
      </div>
    """ % (elapsedtime, generator, total_suite, passed_suite, failed_suite,
           total, passed, failed, total_keywords, passed_keywords,
           failed_keywords, passed_suite, failed_suite, passed, failed,
           passed_keywords, failed_keywords)

    page_content_div.append(BeautifulSoup(dashboard_content, 'html.parser'))

    ### ============================ END OF DASHBOARD ============================================ ####
    logging.info("2 of 4: Capturing suite metrics...")
    ### ============================ START OF SUITE METRICS ======================================= ####

    # Tests div
    suite_div = soup.new_tag('div')
    suite_div["id"] = "suiteMetrics"
    suite_div["class"] = "tabcontent"
    page_content_div.insert(50, suite_div)

    test_icon_txt = """
                    <h4><b><i class="fa fa-table"></i> Suite Metrics</b></h4>
                    <hr></hr>
                    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "sm"
    table["class"] = "table table-striped table-bordered"
    suite_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Total"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Pass"
    tr.insert(3, th)

    th = soup.new_tag('th')
    th.string = "Fail"
    tr.insert(4, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(5, th)

    suite_tbody = soup.new_tag('tbody')
    table.insert(11, suite_tbody)

    # GET SUITE METRICS
    if group:
        group.spawn(result.visit, SuiteResults(soup, suite_tbody, log_name))
    else:
        result.visit(SuiteResults(soup, suite_tbody, log_name))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    ### ============================ END OF SUITE METRICS ============================================ ####
    logging.info("3 of 4: Capturing test metrics...")
    ### ============================ START OF TEST METRICS ======================================= ####

    # Tests div
    tm_div = soup.new_tag('div')
    tm_div["id"] = "testMetrics"
    tm_div["class"] = "tabcontent"
    page_content_div.insert(100, tm_div)

    test_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Test Metrics</b></h4>
    <hr></hr>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "tm"
    table["class"] = "table table-striped table-bordered"
    tm_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    th = soup.new_tag('th')
    th.string = "Error Message"
    tr.insert(4, th)

    test_tbody = soup.new_tag('tbody')
    table.insert(11, test_tbody)

    # GET TEST METRICS
    if group:
        group.spawn(result.visit, TestResults(soup, test_tbody, log_name))
    else:
        result.visit(TestResults(soup, test_tbody, log_name))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    ### ============================ END OF TEST METRICS ============================================ ####
    logging.info("4 of 4: Capturing keyword metrics...")
    ### ============================ START OF KEYWORD METRICS ======================================= ####

    # Keywords div
    km_div = soup.new_tag('div')
    km_div["id"] = "keywordMetrics"
    km_div["class"] = "tabcontent"
    page_content_div.insert(150, km_div)

    keyword_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Keyword Metrics</b></h4>
      <hr></hr>
    """
    km_div.append(BeautifulSoup(keyword_icon_txt, 'html.parser'))

    # Create table tag
    # <table id="myTable">
    table = soup.new_tag('table')
    table["id"] = "km"
    table["class"] = "table table-striped table-bordered"
    km_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Keyword"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    kw_tbody = soup.new_tag('tbody')
    table.insert(1, kw_tbody)

    if group:
        group.spawn(
            result.visit,
            KeywordResults(soup, kw_tbody, ignore_library, ignore_type))
        group.join()
    else:
        result.visit(
            KeywordResults(soup, kw_tbody, ignore_library, ignore_type))

    test_icon_txt = """
    <div class="row">
    <div class="col-md-12" style="height:25px;width:auto;">
    </div>
    </div>
    """
    km_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))
    # END OF KEYWORD METRICS

    # START OF LOGS

    # Logs div
    log_div = soup.new_tag('div')
    log_div["id"] = "log"
    log_div["class"] = "tabcontent"
    page_content_div.insert(200, log_div)

    test_icon_txt = """
        <p style="text-align:right">** <b>Report.html</b> and <b>Log.html</b> need to be in current folder in 
        order to display here</p>
      <div class="embed-responsive embed-responsive-4by3">
        <iframe class="embed-responsive-item" src=%s></iframe>
      </div>
    """ % log_name
    log_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # END OF LOGS

    # EMAIL STATISTICS
    # Statistics div
    statisitcs_div = soup.new_tag('div')
    statisitcs_div["id"] = "statistics"
    statisitcs_div["class"] = "tabcontent"
    page_content_div.insert(300, statisitcs_div)

    emailStatistics = """
    <h4><b><i class="fa fa-envelope-o"></i> Email Statistics</b></h4>
    <hr></hr>
    <button id="create" class="btn btn-primary active inner" role="button" onclick="this.style.visibility= 'hidden';"><i class="fa fa-cogs"></i> Generate Statistics Email</button>
    <a download="message.eml" class="btn btn-primary active inner" role="button" id="downloadlink" style="display: none; width: 300px;"><i class="fa fa-download"></i> Click Here To Download Email</a>   
<textarea id="textbox" class="col-md-12" style="height: 400px; padding:1em;">
To: [email protected]
Subject: Automation Execution Status
X-Unsent: 1
Content-Type: text/html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test Email Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0 " />
    <style>
        body {
            background-color:#F2F2F2; 
        }
        body, html, table {
            font-family: Courier New, Arial, sans-serif;
            font-size: 1em; 
        }
        .pastdue { color: crimson; }
        table {
            padding: 5px;
            margin-left: 30px;
            width: 800px;
        }
        thead {
            text-align: center;
            font-size: 1.1em;        
            background-color: #B0C4DE;
            font-weight: bold;
            color: #2D2C2C;
        }
        tbody {
            text-align: center;
        }
        th {
            width: 25%;
            word-wrap:break-word;
        }
    </style>
</head>
<body>
    <p>Hi Team,</p>
    <p>Following are the last build execution status</p>
    <p></p>
    <table>
        <tbody>
            <tr>
                <td style="text-align:left; padding-left:5px;color:#0b6690;">
                    <h2>Test Automation Report</h2>
                </td>
                <td style="text-align:right; padding-right:10px;color:#0b6690;">
                    <h3>Duration: elapsed_time</h3>
                </td>
            </tr>
        </tbody>
    </table>
    <table>
        <tr>
            <td></td>
        </tr>
    </table>
    <table>
        <tbody>
        <tr>
            <td style="background-color:#616161; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">Suite</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Statistics</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#009688; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">suite_total</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Total</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#4CAF50; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">suite_pass</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Pass</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#f44336; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">suite_fail</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Fail</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
        <tr>
            <td style="background-color:#616161; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">Test</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Statistics</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#009688; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">test_total</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Total</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#4CAF50; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">test_pass</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Pass</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#f44336; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">test_fail</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Fail</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
        <tr>
            <td style="background-color:#616161; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">Keyword</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Statistics</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#009688; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">keyword_total</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Total</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#4CAF50; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">keyword_pass</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Pass</td>
                        </tr>
                    </tbody>
                </table>
            </td>
            <td style="background-color:#f44336; color:white; width:25%">
                <table style="width:100%;">
                    <tbody>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 30px;">keyword_fail</td>
                        </tr>
                        <tr>
                            <td style="text-align:center; color:white;font-size: 12px;">Fail</td>
                        </tr>
                    </tbody>
                </table>
            </td>
        </tr>
        </tbody>
    </table>
    <table>
        <tr>
            <td></td>
        </tr>
    </table>
    <table>
        <tbody>
            <tr>
                <td style="width:33%;color:#0b6690;"><h3>Suite Status</h3></td>
                <td style="width:33%;color:#0b6690;"><h3>Test Status</h3></td>
                <td style="width:33%;color:#0b6690;"><h3>Keyword Status</h3></td>
            </tr>
            <tr>
                <td>
                    <img src='https://chart.googleapis.com/chart?cht=p3&chd=t:suite-pass-perc,suite-fail-perc&chs=250x200&chco=3BB032|bc2d29&chdl=suite-pass-perc-pass|suite-fail-perc-fail'/>
                </td>
                <td>
                    <img src='https://chart.googleapis.com/chart?cht=p3&chd=t:test-pass-perc,test-fail-perc&chs=250x200&chco=3BB032|bc2d29&chdl=test-pass-perc-pass|test-fail-perc-fail'/>
                </td>
                <td>
                    <img src='https://chart.googleapis.com/chart?cht=p3&chd=t:keyword-pass-perc,keyword-fail-perc&chs=250x200&chco=3BB032|bc2d29&chdl=keyword-pass-perc-pass|keyword-fail-perc-fail'/>
                </td>
            </tr>
        </tbody>
    </table>
    <p>Please refer RF Metrics report for detailed statistics.<p>
    <strong>Team QA</strong>
</body></html></textarea>

    """

    emailStatistics = emailStatistics.replace("suite_total", str(total_suite))
    emailStatistics = emailStatistics.replace("suite_pass", str(passed_suite))
    emailStatistics = emailStatistics.replace("suite_fail", str(failed_suite))
    emailStatistics = emailStatistics.replace("test_total", str(total))
    emailStatistics = emailStatistics.replace("test_pass", str(passed))
    emailStatistics = emailStatistics.replace("test_fail", str(failed))
    emailStatistics = emailStatistics.replace("keyword_total",
                                              str(total_keywords))
    emailStatistics = emailStatistics.replace("keyword_pass",
                                              str(passed_keywords))
    emailStatistics = emailStatistics.replace("keyword_fail",
                                              str(failed_keywords))
    emailStatistics = emailStatistics.replace("elapsed_time", str(elapsedtime))
    emailStatistics = emailStatistics.replace("suite-pass-perc", str(suitepp))
    emailStatistics = emailStatistics.replace("suite-fail-perc", str(suitefp))
    emailStatistics = emailStatistics.replace("test-pass-perc", str(testpp))
    emailStatistics = emailStatistics.replace("test-fail-perc", str(testfp))
    emailStatistics = emailStatistics.replace("keyword-pass-perc", str(kwpp))
    emailStatistics = emailStatistics.replace("keyword-fail-perc", str(kwfp))

    statisitcs_div.append(BeautifulSoup(emailStatistics, 'html.parser'))

    # END OF EMAIL STATISTICS
    script_text = """
        <script>
            (function () {
            var textFile = null,
              makeTextFile = function (text) {
                var data = new Blob([text], {type: 'text/plain'});
                if (textFile !== null) {
                  window.URL.revokeObjectURL(textFile);
                }
                textFile = window.URL.createObjectURL(data);
                return textFile;
              };

              var create = document.getElementById('create'),
                textbox = document.getElementById('textbox');
              create.addEventListener('click', function () {
                var link = document.getElementById('downloadlink');
                link.href = makeTextFile(textbox.value);
                link.style.display = 'block';
              }, false);
            })();
        </script>
        <script>
            function createPieChart(passed_count,failed_count,ChartID,ChartName){
            var status = [];
            status.push(['Status', 'Percentage']);
            status.push(['PASS',parseInt(passed_count)],['FAIL',parseInt(failed_count)]);
            var data = google.visualization.arrayToDataTable(status);

            var options = {
            pieHole: 0.6,
            legend: 'none',
            chartArea: {width: "95%",height: "90%"},
            colors: ['green', 'red'],
            };

            var chart = new google.visualization.PieChart(document.getElementById(ChartID));
            chart.draw(data, options);
        }
        </script>
        <script>
           function createBarGraph(tableID,keyword_column,time_column,limit,ChartID,Label,type){
            var status = [];
            css_selector_locator = tableID + ' tbody >tr'
            var rows = $(css_selector_locator);
            var columns;
            var myColors = [
                '#4F81BC',
                '#C0504E',
                '#9BBB58',
                '#24BEAA',
                '#8064A1',
                '#4AACC5',
                '#F79647',
                '#815E86',
                '#76A032',
                '#34558B'
            ];
            status.push([type, Label,{ role: 'annotation'}, {role: 'style'}]);
            for (var i = 0; i < rows.length; i++) {
                if (i == Number(limit)){
                    break;
                }
                //status = [];
                name_value = $(rows[i]).find('td'); 

                time=($(name_value[Number(time_column)]).html()).trim();
                keyword=($(name_value[Number(keyword_column)]).html()).trim();
                status.push([keyword,parseFloat(time),parseFloat(time),myColors[i]]);
              }
              var data = google.visualization.arrayToDataTable(status);

              var options = {
                legend: 'none',
                chartArea: {width: "92%",height: "75%"},
                bar: {
                    groupWidth: '90%'
                },
                annotations: {
                    alwaysOutside: true,
                    textStyle: {
                    fontName: 'Comic Sans MS',
                    fontSize: 13,
                    bold: true,
                    italic: true,
                    color: "black",     // The color of the text.
                    },
                },
                hAxis: {
                    textStyle: {
                        fontName: 'Arial',
                        fontSize: 10,
                    }
                },
                vAxis: {
                    gridlines: { count: 10 },
                    textStyle: {                    
                        fontName: 'Comic Sans MS',
                        fontSize: 10,
                    }
                },
              };  

                // Instantiate and draw the chart.
                var chart = new google.visualization.ColumnChart(document.getElementById(ChartID));
                chart.draw(data, options);
             }

        </script>

     <script>
      function executeDataTable(tabname,sortCol) {
        var fileTitle;
        switch(tabname) {
            case "#sm":
                fileTitle = "SuiteMetrics";
                break;
            case "#tm":
                fileTitle =  "TestMetrics";
                break;
            case "#km":
                fileTitle =  "KeywordMetrics";
                break;
            default:
                fileTitle =  "metrics";
        }

        $(tabname).DataTable(
            {
                retrieve: true,
                "order": [[ Number(sortCol), "desc" ]],
                dom: 'l<".margin" B>frtip',
                buttons: [
                    'copy',
                    {
                        extend: 'csv',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'excel',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'pdf',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        title : '',
                    },
                    {
                        extend: 'print',
                        title : '',
                    },
                ],
            } 
        );
    }
     </script>
     <script>
      function openPage(pageName,elmnt,color) {
        var i, tabcontent, tablinks;
        tabcontent = document.getElementsByClassName("tabcontent");
        for (i = 0; i < tabcontent.length; i++) {
            tabcontent[i].style.display = "none";
        }
        tablinks = document.getElementsByClassName("tablink");
        for (i = 0; i < tablinks.length; i++) {
            tablinks[i].style.backgroundColor = "";
        }
        document.getElementById(pageName).style.display = "block";
        elmnt.style.backgroundColor = color;

    }
    // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
     </script>
     <script>
     // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
     </script>
     <script>
    $(window).on('load',function(){$('.loader').fadeOut();});
    </script>
    """

    body.append(BeautifulSoup(script_text, 'html.parser'))

    # WRITE TO RF_METRICS_REPORT.HTML

    # Write output as html file
    with open(result_file, 'w') as outfile:
        outfile.write(soup.prettify())

    logging.info(
        "Results file created successfully and can be found at {}".format(
            result_file))
 def output_file(self, path):
     result = ExecutionResult(path)
     result.visit(OxygenVisitor(self.run_time_data))
     result.save()
from robot.api import ExecutionResult, ResultVisitor
from robot.utils import timestamp_to_secs as ts, secs_to_timestamp as st

res = ExecutionResult('output.xml')


class SuiteAndTestTimes(ResultVisitor):
    def __init__(self):
        self.result_by_start_time = []
        self.result_by_end_time = []
        self.suite_names = set()

    def visit_test(self, test):
        self.suite_names.add(test.parent.longname)
        self.result_by_start_time.append(
            [ts(test.starttime), test.parent.longname, test.longname])
        self.result_by_end_time.append(
            [ts(test.endtime), test.parent.longname, test.longname])


test_times = SuiteAndTestTimes()
res.visit(test_times)

result_by_start_time = sorted(test_times.result_by_start_time)
result_by_end_time = sorted(test_times.result_by_end_time)

starting, result_by_start_time = result_by_start_time[0], result_by_start_time[
    1:]
ending, result_by_end_time = result_by_end_time[0], result_by_end_time[1:]
currenttime = starting[0]
Example #20
0
def process(infile="output.xml"):
    visitor = result_visitor.RobotResultsVisitor()
    test_run = ExecutionResult(infile)
    test_run.visit(visitor)
Example #21
0
def get_testcases(xml_robotfwk_output):
    """ Return the list of Testcase ID with status """
    result = ExecutionResult(xml_robotfwk_output)
    visitor = TestRailResultVisitor()
    result.visit(visitor)
    return visitor.result_testcase_list
Example #22
0
def lastResults(request):
    try:
        os.environ['TEST_PATH']
    except:
        with open('settings.yml', 'r') as outfile:
            stngs = yaml.load(outfile)
            os.environ["TEST_PATH"] = str(stngs["TestPath"])
            print "Path updated!"
    try:
        path = os.path.join(os.environ['TEST_PATH'], "results")
        dir_list = next(os.walk(path))[1]
        test_dir_results = reversed(sorted(dir_list))
        results_files = {}
        for folder in test_dir_results:
            run_results_path = os.path.join(path, folder)
            results_files[folder] = {}
            if os.path.isdir(run_results_path):
                for result_file in os.listdir(run_results_path):
                    if os.path.splitext(result_file)[1] == ".html" and "Report" not in os.path.splitext(result_file)[0]: 
                        results_files[folder][os.path.splitext(result_file)[0]]=[]
                        xml_file = os.path.splitext(result_file)[0]+'.xml'
                        xml_file_path = os.path.join(path, folder, xml_file)
                        results_files[folder][os.path.splitext(result_file)[0]].append({'failed' : ExecutionResult(xml_file_path).statistics.total.critical.failed })
                        results_files[folder][os.path.splitext(result_file)[0]].append({'passed' : ExecutionResult(xml_file_path).statistics.total.critical.passed })
        sorted_results = reversed(sorted(results_files.items()))
    except:
        sorted_results = []

    return render(request, 'lastresults.html', {"folders":sorted_results,})
def parse_output_xml(xml_file_path, csv_dir_path):
    result = ExecutionResult(xml_file_path)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    stats = result.statistics
    print "--------------------------------------"
    print "Total Test Count:\t",\
          stats.total.critical.passed + stats.total.critical.failed
    print "Total Test Failed:\t", stats.total.critical.failed
    print "Total Test Passed:\t", stats.total.critical.passed
    print "Test Start Time:\t", result.suite.starttime
    print "Test End Time:\t\t", result.suite.endtime
    print "--------------------------------------"

    # Use ResultVisitor object and save off the test data info
    class TestResult(ResultVisitor):
        def __init__(self):
            self.testData = []

        def visit_test(self, test):
            self.testData += [test]

    collectDataObj = TestResult()
    result.visit(collectDataObj)

    # Write the result statistics attributes to CSV file
    l_csvlist = []

    # Default Test data
    l_subsys = 'OPENBMC'
    l_test_type = 'FTC'
    l_pse_rel = 'OBMC910'
    l_env = 'HW'
    l_proc = 'P9'
    l_platform_type = ""
    l_func_area = ""

    # System data from XML meta data
    l_system_info = get_system_details(xml_file_path)
    l_driver = l_system_info[0]
    if l_system_info[1]:
        l_platform_type = l_system_info[1]
    else:
        print "System model is not set"
        sys.exit()

    # Default header
    l_header = [
        'test_start', 'test_end', 'subsys', 'test_type', 'test_result',
        'test_name', 'pse_rel', 'driver', 'env', 'proc', 'platform_type',
        'test_func_area'
    ]

    l_csvlist.append(l_header)

    # Generate CSV file onto the path with current time stamp
    l_base_dir = csv_dir_path
    l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
    # Example: 2017-02-20-08-47-22_Witherspoon.csv
    l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"

    print "Writing data into csv file:", l_csvfile

    for testcase in collectDataObj.testData:
        # Functional Area: Suite Name
        # Test Name: Test Case Name
        l_func_area = str(testcase.parent).split(' ', 1)[1]
        l_test_name = str(testcase)

        # Test Result pass=0 fail=1
        if testcase.status == 'PASS':
            l_test_result = 0
        else:
            l_test_result = 1

        # Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
        l_stime = xml_to_csv_time(testcase.starttime)
        l_etime = xml_to_csv_time(testcase.endtime)
        # Data Sequence: test_start,test_end,subsys,test_type,
        #                test_result,test_name,pse_rel,driver,
        #                env,proc,platform_tyep,test_func_area,
        l_data = [
            l_stime, l_etime, l_subsys, l_test_type, l_test_result,
            l_test_name, l_pse_rel, l_driver, l_env, l_proc, l_platform_type,
            l_func_area
        ]
        l_csvlist.append(l_data)

    # Open the file and write to the CSV file
    l_file = open(l_csvfile, "w")
    l_writer = csv.writer(l_file, lineterminator='\n')
    l_writer.writerows(l_csvlist)
    l_file.close()
        print('You can also mail it to mailto:[email protected].\n')
        print('Thanks you very much for your support!')
        print('Your Browser-Team (Mikko, Tatu, Kerkko, Janne and René)')


    def print_stats(self, kw_calls):
        longest_keyword = 0
        for kw_name in kw_calls:
            current_length = len(kw_name)
            longest_keyword = current_length \
                if current_length > longest_keyword \
                else longest_keyword
        print(f'+-{"".ljust(longest_keyword, "-")       }-+-------+---------+')
        print(f'| {"Keyword".ljust(longest_keyword, " ")} | count | parents |')
        print(f'+-{"".ljust(longest_keyword, "-")       }-+-------+---------+')
        for kw_name in kw_calls:
            print(f'| {kw_name.ljust(longest_keyword , " ")} |'
                  f' {str(kw_calls[kw_name]["call_count"]).ljust(5," ")} |'
                  f' {str(kw_calls[kw_name]["parent_count"]).ljust(7, " ")} |')
        print(f'+-{"".ljust(longest_keyword, "-")}-+-------+---------+')


if __name__ == "__main__":
    if len(sys.argv) > 1:
        original_output_xml = sys.argv[1]
        if not os.path.isfile(original_output_xml):
            raise FileNotFoundError(f'{original_output_xml} is no file')
        print(f'reading results from: {os.path.abspath(original_output_xml)}')
        ExecutionResult(original_output_xml).visit(ResultAnalyzer())
    else:
        print('Use the path to a output.xml as first arguemnt.  Example:  python -m SeleniumStats ../output.xml')
Example #25
0
def _suites_from_outputxml(outputxml):
    res = ExecutionResult(outputxml)
    suite_times = SuiteNotPassingsAndTimes()
    res.visit(suite_times)
    return [suite for (_, _, suite) in reversed(sorted(suite_times.suites))]
Example #26
0
    print('Showing %d of total keywords %d' % (shown, len(times.keywords)))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        '--limit',
        '-l',
        type=float,
        help='Filter out keywords with larger percentage'
        ' of stdev/avg time than LIMIT. This helps by filtering out most used "primitive" keywords'
        ' such as Sleep and Run Keyword If etc. and let\'s you focus on the keywords that very often'
        ' take a lot of time to execute (in other words are most fruitful places to focus optimisation effort).'
    )
    parser.add_argument('--show',
                        '-s',
                        default=100,
                        type=int,
                        help='Max number of shown keywords. Default is 100.')
    parser.add_argument(
        'source', help='output from a Robot Framework execution to analyze')
    args = parser.parse_args()
    try:
        resu = ExecutionResult(args.source)
        times = KeywordTimes()
        resu.visit(times)
        _print_results(times, args.show, args.limit)
    except:
        print(__doc__)
        raise
def generate_report(opts):

    path = os.path.abspath(os.path.expanduser(opts.path))

    # output.xml files
    output_names = []
    # support "*.xml" of output files
    if (opts.output == "*.xml"):
        for item in os.listdir(path):
            if os.path.isfile(item) and item.endswith('.xml'):
                output_names.append(item)
    else:
        for curr_name in opts.output.split(","):
            curr_path = os.path.join(path, curr_name)
            output_names.append(curr_path)

    required_files = list(output_names)
    missing_files = [
        filename for filename in required_files if not os.path.exists(filename)
    ]
    if missing_files:
        # We have files missing.
        exit("output.xml file is missing: {}".format(", ".join(missing_files)))

    # Read output.xml file
    result = ExecutionResult(*output_names)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    print("Capturing execution results, This may take few minutes...")

    # connect to database
    mydb = connect_to_mysql_db(opts.host, opts.port, opts.username,
                               opts.password, opts.projectname)
    rootdb = connect_to_mysql_db(opts.host, opts.port, opts.username,
                                 opts.password, 'robothistoric')

    test_stats = SuiteStats()
    result.visit(test_stats)

    stotal = test_stats.total_suite
    spass = test_stats.passed_suite
    sfail = test_stats.failed_suite

    stats = result.statistics
    total = stats.total.all.total
    passed = stats.total.all.passed
    failed = stats.total.all.failed

    elapsedtime = datetime.datetime(
        1970, 1, 1) + datetime.timedelta(milliseconds=result.suite.elapsedtime)
    elapsedtime = get_time_in_min(elapsedtime.strftime("%X"))
    elapsedtime = float("{0:.2f}".format(elapsedtime))

    # insert test results info into db
    result_id = insert_into_execution_table(mydb, rootdb, opts.executionname,
                                            total, passed, failed, elapsedtime,
                                            stotal, spass, sfail,
                                            opts.projectname)

    print("INFO: Capturing suite results")
    result.visit(SuiteResults(mydb, result_id))
    print("INFO: Capturing test results")
    result.visit(TestMetrics(mydb, result_id))

    print("INFO: Writing execution results")
    commit_and_close_db(mydb)
 def output_file(self, path):
     result = ExecutionResult(path)
     result.visit(ScreenShotVisitor(self.keywords, self.args[0]))
     result.save(path)
Example #29
0
def get_task_list(app, username, project):
    job_path = app.config["AUTO_HOME"] + "/jobs/%s/%s" % (username, project)
    next_build = 0
    task = []
    if exists_path(job_path):
        next_build = get_next_build_number(job_path)
        if next_build != 0:
            # 遍历所有任务结果
            # 判断最近一个任务状态
            icons = {
                "running": url_for('static', filename='img/running.gif'),
                "success": url_for('static', filename='img/success.png'),
                "fail": url_for('static', filename='img/fail.png'),
                "exception": url_for('static', filename='img/exception.png')
            }

            #if exists_path(job_path + "/%s" % (next_build - 1)):
            running = False
            lock = threading.Lock()
            lock.acquire()
            remove_robot(app)
            for p in app.config["AUTO_ROBOT"]:
                if p["name"] == project:
                    running = True
                    break
            lock.release()
            if running:
                task.append({
                    "status": icons["running"],
                    "name": "%s_#%s" % (project, next_build - 1),
                    "success": "",
                    "fail": ""
                })
            last = 1
            if running:
                last = 2
            for i in range(next_build - last, -1, -1):
                if exists_path(job_path + "/%s" % i):
                    try:
                        suite = ExecutionResult(job_path +
                                                "/%s/output.xml" % i).suite
                        stat = suite.statistics.critical
                        if stat.failed != 0:
                            status = icons["fail"]
                        else:
                            status = icons['success']
                        task.append({
                            "task_no":
                            i,
                            "status":
                            status,
                            "name":
                            "<a href='/view_report/%s/%s' target='_blank'>%s_#%s</a>"
                            % (project, i, project, i),
                            "success":
                            stat.passed,
                            "fail":
                            stat.failed,
                            "starttime":
                            suite.starttime,
                            "endtime":
                            suite.endtime,
                            "elapsedtime":
                            suite.elapsedtime,
                            "note":
                            ""
                        })
                    except:
                        status = icons["exception"]
                        if i == next_build - last:
                            status = icons["running"]
                        task.append({
                            "task_no": i,
                            "status": status,
                            "name": "%s_#%s" % (project, i),
                            "success": "-",
                            "fail": "-",
                            "starttime": "-",
                            "endtime": "-",
                            "elapsedtime": "-",
                            "note": "异常"
                        })

    return {"total": next_build - 1, "rows": task}
Example #30
0
def _suites_from_outputxml(outputxml):
    res = ExecutionResult(outputxml)
    suite_times = SuiteNotPassingsAndTimes()
    res.visit(suite_times)
    return [suite for (_, _, suite) in reversed(sorted(suite_times.suites))]
def parse_output_xml(xml_file_path, csv_dir_path):
    result = ExecutionResult(xml_file_path)
    result.configure(stat_config={'suite_stat_level': 2,
                                  'tag_stat_combine': 'tagANDanother'})

    stats = result.statistics
    print "--------------------------------------"
    print "Total Test Count:\t",\
          stats.total.critical.passed + stats.total.critical.failed
    print "Total Test Failed:\t", stats.total.critical.failed
    print "Total Test Passed:\t", stats.total.critical.passed
    print "Test Start Time:\t", result.suite.starttime
    print "Test End Time:\t\t", result.suite.endtime
    print "--------------------------------------"

    # Use ResultVisitor object and save off the test data info
    class TestResult(ResultVisitor):
        def __init__(self):
            self.testData = []

        def visit_test(self, test):
            self.testData += [test]

    collectDataObj = TestResult()
    result.visit(collectDataObj)

    # Write the result statistics attributes to CSV file
    l_csvlist = []

    # Default Test data
    l_subsys = 'OPENBMC'
    l_test_type = 'FTC'
    l_pse_rel = 'OBMC910'
    l_env = 'HW'
    l_proc = 'P9'
    l_platform_type = ""
    l_func_area = ""

    # System data from XML meta data
    l_system_info = get_system_details(xml_file_path)
    l_driver = l_system_info[0]
    if l_system_info[1]:
        l_platform_type = l_system_info[1]
    else:
        print "System model is not set"
        sys.exit()

    # Default header
    l_header = ['test_start', 'test_end', 'subsys', 'test_type',
                'test_result', 'test_name', 'pse_rel', 'driver',
                'env', 'proc', 'platform_type', 'test_func_area']

    l_csvlist.append(l_header)

    # Generate CSV file onto the path with current time stamp
    l_base_dir = csv_dir_path
    l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
    # Example: 2017-02-20-08-47-22_Witherspoon.csv
    l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"

    print "Writing data into csv file:", l_csvfile

    for testcase in collectDataObj.testData:
        # Functional Area: Suite Name
        # Test Name: Test Case Name
        l_func_area = str(testcase.parent).split(' ', 1)[1]
        l_test_name = str(testcase)

        # Test Result pass=0 fail=1
        if testcase.status == 'PASS':
            l_test_result = 0
        else:
            l_test_result = 1

        # Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
        l_stime = xml_to_csv_time(testcase.starttime)
        l_etime = xml_to_csv_time(testcase.endtime)
        # Data Sequence: test_start,test_end,subsys,test_type,
        #                test_result,test_name,pse_rel,driver,
        #                env,proc,platform_tyep,test_func_area,
        l_data = [l_stime, l_etime, l_subsys, l_test_type, l_test_result,
                  l_test_name, l_pse_rel, l_driver, l_env, l_proc,
                  l_platform_type, l_func_area]
        l_csvlist.append(l_data)

    # Open the file and write to the CSV file
    l_file = open(l_csvfile, "w")
    l_writer = csv.writer(l_file, lineterminator='\n')
    l_writer.writerows(l_csvlist)
    l_file.close()
Example #32
0
 def generate_dependency(self):
     output = "./output.xml"
     result = ExecutionResult(output)
     visitor = FileDependencyVisitor()
     result.visit(visitor)
     self.dependency = visitor.dependency
def parse_output_xml(xml_file_path, csv_dir_path, version_id, platform, level):
    r"""
    Parse the robot-generated output.xml file and extract various test
    output data. Put the extracted information into a csv file in the "dest"
    folder.

    Description of argument(s):
    xml_file_path                   The path to a Robot-generated output.xml
                                    file.
    csv_dir_path                    The path to the directory that is to
                                    contain the .csv files generated by
                                    this function.
    version_id                      Version of the openbmc firmware
                                    (e.g. "v2.1-215-g6e7eacb").
    platform                        Platform of the openbmc system.
    level                           Release level of the OpenBMC system
                                    (e.g. "OBMC920").
    """

    result = ExecutionResult(xml_file_path)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    stats = result.statistics
    print("--------------------------------------")
    total_tc = stats.total.critical.passed + stats.total.critical.failed
    print("Total Test Count:\t %d" % total_tc)
    print("Total Test Failed:\t %d" % stats.total.critical.failed)
    print("Total Test Passed:\t %d" % stats.total.critical.passed)
    print("Test Start Time:\t %s" % result.suite.starttime)
    print("Test End Time:\t\t %s" % result.suite.endtime)
    print("--------------------------------------")

    # Use ResultVisitor object and save off the test data info
    class TestResult(ResultVisitor):
        def __init__(self):
            self.testData = []

        def visit_test(self, test):
            self.testData += [test]

    collectDataObj = TestResult()
    result.visit(collectDataObj)

    # Write the result statistics attributes to CSV file
    l_csvlist = []

    # Default Test data
    l_subsys = 'OPENBMC'
    l_test_type = 'FTC'

    l_pse_rel = 'OBMC910'
    if level:
        l_pse_rel = level

    l_env = 'HW'
    l_proc = 'P9'
    l_platform_type = ""
    l_func_area = ""

    # System data from XML meta data
    # l_system_info = get_system_details(xml_file_path)

    # First let us try to collect information from keyboard input
    # If keyboard input cannot give both information, then find from xml file.
    if version_id and platform:
        l_driver = version_id
        l_platform_type = platform
        print("BMC Version_id:%s" % version_id)
        print("BMC Platform:%s" % platform)
    else:
        # System data from XML meta data
        l_system_info = get_system_details(xml_file_path)
        l_driver = l_system_info[0]
        l_platform_type = l_system_info[1]

    # Driver version id and platform are mandatorily required for CSV file
    # generation. If any one is not avaulable, exit CSV file generation
    # process.
    if l_driver and l_platform_type:
        print("Driver and system info set.")
    else:
        print("Both driver and system info need to be set.\
                CSV file is not generated.")
        sys.exit()

    # Default header
    l_header = [
        'test_start', 'test_end', 'subsys', 'test_type', 'test_result',
        'test_name', 'pse_rel', 'driver', 'env', 'proc', 'platform_type',
        'test_func_area'
    ]

    l_csvlist.append(l_header)

    # Generate CSV file onto the path with current time stamp
    l_base_dir = csv_dir_path
    l_timestamp = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
    # Example: 2017-02-20-08-47-22_Witherspoon.csv
    l_csvfile = l_base_dir + l_timestamp + "_" + l_platform_type + ".csv"

    print("Writing data into csv file:%s" % l_csvfile)

    for testcase in collectDataObj.testData:
        # Functional Area: Suite Name
        # Test Name: Test Case Name
        l_func_area = str(testcase.parent).split(' ', 1)[1]
        l_test_name = str(testcase)

        # Test Result pass=0 fail=1
        if testcase.status == 'PASS':
            l_test_result = 0
        else:
            l_test_result = 1

        # Format datetime from robot output.xml to "%Y-%m-%d-%H-%M-%S"
        l_stime = xml_to_csv_time(testcase.starttime)
        l_etime = xml_to_csv_time(testcase.endtime)
        # Data Sequence: test_start,test_end,subsys,test_type,
        #                test_result,test_name,pse_rel,driver,
        #                env,proc,platform_tyep,test_func_area,
        l_data = [
            l_stime, l_etime, l_subsys, l_test_type, l_test_result,
            l_test_name, l_pse_rel, l_driver, l_env, l_proc, l_platform_type,
            l_func_area
        ]
        l_csvlist.append(l_data)

    # Open the file and write to the CSV file
    l_file = open(l_csvfile, "w")
    l_writer = csv.writer(l_file, lineterminator='\n')
    l_writer.writerows(l_csvlist)
    l_file.close()
def generate_report(opts):
    logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
    group = Group() if not FAILED_IMPORT else ''

    # START OF CUSTOMIZE REPORT
    # URL or filepath of your company logo
    logo = opts.logo

    # Ignores following library keywords in metrics report
    ignore_library = IGNORE_LIBRARIES
    if opts.ignore:
        ignore_library.extend(opts.ignore)

    # Ignores following type keywords in metrics report
    ignore_type = IGNORE_TYPES
    if opts.ignoretype:
        ignore_type.extend(opts.ignoretype)

    # END OF CUSTOMIZE REPORT
    # Report to support file location as arguments
    # Source Code Contributed By : Ruud Prijs
    # input directory
    path = os.path.abspath(os.path.expanduser(opts.path))

    # output.xml files
    output_names = []
    # support "*.xml" of output files
    if (opts.output == "*.xml"):
        for item in os.listdir(path):
            item = os.path.join(path, item)
            if os.path.isfile(item) and item.endswith('.xml'):
                output_names.append(item)
    else:
        for curr_name in opts.output.split(","):
            curr_path = os.path.join(path, curr_name)
            output_names.append(curr_path)

    # log.html file
    log_name = opts.log_name

    # copy the list of output_names onto the one of required_files; the latter may (in the future)
    # contain files that should not be processed as output_names
    required_files = list(output_names)
    missing_files = [
        filename for filename in required_files if not os.path.exists(filename)
    ]
    if missing_files:
        # We have files missing.
        exit("output.xml file is missing: {}".format(", ".join(missing_files)))

    mt_time = datetime.now().strftime('%Y%m%d-%H%M%S')

    # Output result file location
    if opts.metrics_report_name:
        result_file_name = opts.metrics_report_name
    else:
        result_file_name = 'metrics-' + mt_time + '.html'
    result_file = os.path.join(path, result_file_name)

    # Read output.xml file
    result = ExecutionResult(*output_names)
    result.configure(stat_config={
        'suite_stat_level': 2,
        'tag_stat_combine': 'tagANDanother'
    })

    logging.info("Converting .xml to .html file. This may take few minutes...")

    head_content = """
    <!DOCTYPE doctype html>
    <html lang="en">

    <head>
        <link href="https://png.icons8.com/windows/50/000000/bot.png" rel="shortcut icon" type="image/x-icon" />
        <title>RF Metrics</title>
        <meta charset="utf-8" />
        <meta content="width=device-width, initial-scale=1" name="viewport" />
        <link href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet" />
        <link href="https://cdn.datatables.net/buttons/1.5.2/css/buttons.dataTables.min.css" rel="stylesheet" />
        <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
        <script src="https://code.jquery.com/jquery-3.3.1.js" type="text/javascript"/>
        <!-- Bootstrap core Googleccharts -->
        <script src="https://www.gstatic.com/charts/loader.js" type="text/javascript"/>
        <script type="text/javascript">
            google.charts.load('current', {
                packages: ['corechart']
            });
        </script>
        <!-- Bootstrap core Datatable-->
        <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/dataTables.buttons.min.js" type="text/javascript"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.html5.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.5.2/js/buttons.print.min.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/buttons/1.6.1/js/buttons.colVis.min.js" type="text/javascript"></script>

        <style>
            body {
                font-family: -apple-system, sans-serif;
                background-color: #eeeeee;
            }

            .sidenav {
                height: 100%;
                width: 220px;
                position: fixed;
                z-index: 1;
                top: 0;
                left: 0;
                background-color: white;
                overflow-x: hidden;
            }

            .sidenav a {
                padding: 12px 10px 8px 12px;
                text-decoration: none;
                font-size: 18px;
                color: Black;
                display: block;
            }

            .main {
                padding-top: 10px;
            }

            @media screen and (max-height: 450px) {
                .sidenav {
                    padding-top: 15px;
                }
                .sidenav a {
                    font-size: 18px;
                }
            }

            .wrimagecard {
                margin-top: 0;
                margin-bottom: 0.6rem;
                border-radius: 10px;
                transition: all 0.3s ease;
                background-color: #f8f9fa;
            }

            .rowcard {
                padding-top: 10px;
                box-shadow: 12px 15px 20px 0px rgba(46, 61, 73, 0.15);
                border-radius: 15px;
                transition: all 0.3s ease;
                background-color: white;
            }

            .tablecard {
                background-color: white;
                font-size: 14px;
            }

            tr {
                height: 40px;
            }

            .dt-buttons {
                margin-left: 5px;
            }

            th, td, tr {
                text-align:center;
                vertical-align: middle;
            }

            .loader {
                position: fixed;
                left: 0px;
                top: 0px;
                width: 100%;
                height: 100%;
                z-index: 9999;
                background: url('https://i.ibb.co/cXnKsNR/Cube-1s-200px.gif') 50% 50% no-repeat rgb(249, 249, 249);
            }
        </style>
    </head>
    """
    if opts.ignorekeywords == "True":
        hide_keyword = "hidden"
    else:
        hide_keyword = ""

    if opts.ignorelogs == "True":
        hide_logs = "hidden"
    else:
        hide_logs = ""

    soup = BeautifulSoup(head_content, "html.parser")
    body = soup.new_tag('body')
    soup.insert(20, body)
    icons_txt = """
    <div class="loader"></div>
    <div class="sidenav">
        <a> <img class="wrimagecard" src="%s" style="height:20vh;max-width:98%%;"/> </a>
        <a class="tablink" href="#" id="defaultOpen" onclick="openPage('dashboard', this, '#fc6666')"><i class="fa fa-dashboard" style="color:CORNFLOWERBLUE"></i> Dashboard</a>
        <a class="tablink" href="#" onclick="openPage('suiteMetrics', this, '#fc6666'); executeDataTable('#sm',5)"><i class="fa fa-th-large" style="color:CADETBLUE"></i> Suite Metrics</a>
        <a class="tablink" href="#" onclick="openPage('testMetrics', this, '#fc6666'); executeDataTable('#tm',3)"><i class="fa fa-list-alt" style="color:PALEVIOLETRED"></i> Test Metrics</a>
        <a %s class="tablink" href="#" onclick="openPage('keywordMetrics', this, '#fc6666'); executeDataTable('#km',3)"><i class="fa fa-table" style="color:STEELBLUE"></i> Keyword Metrics</a>
        <a %s class="tablink" href="#" onclick="openPage('log', this, '#fc6666');"><i class="fa fa-wpforms" style="color:CHOCOLATE"></i> Logs</a>
    </div>
    """ % (logo, hide_keyword, hide_logs)

    body.append(BeautifulSoup(icons_txt, 'html.parser'))

    page_content_div = soup.new_tag('div')
    page_content_div["class"] = "main col-md-9 ml-sm-auto col-lg-10 px-4"
    body.insert(50, page_content_div)

    logging.info("1 of 4: Capturing dashboard content...")
    test_stats = TestStats()
    result.visit(test_stats)

    try:
        test_stats_obj = test_stats.all
    except:
        test_stats_obj = test_stats
    total_suite = test_stats_obj.total_suite
    passed_suite = test_stats_obj.passed_suite
    failed_suite = test_stats_obj.failed_suite
    try:
        skipped_suite = test_stats_obj.skipped_suite
    except:
        skipped_suite = 0

    #suitepp = round(passed_suite * 100.0 / total_suite, 1)
    #suitefp = round(failed_suite * 100.0 / total_suite, 1)
    elapsedtime = datetime(
        1970, 1, 1) + timedelta(milliseconds=result.suite.elapsedtime)
    elapsedtime = elapsedtime.strftime("%X")
    my_results = result.generated_by_robot

    if my_results:
        generator = "Robot"
    else:
        generator = "Rebot"

    stats = result.statistics
    try:
        stats_obj = stats.total.all
    except:
        stats_obj = stats.total
    total = stats_obj.total
    passed = stats_obj.passed
    failed = stats_obj.failed
    try:
        skipped = stats_obj.skipped
    except:
        skipped = 0

    #testpp = round(passed * 100.0 / total, 1)
    #testfp = round(failed * 100.0 / total, 1)

    kw_stats = KeywordStats(ignore_library, ignore_type)
    result.visit(kw_stats)

    total_keywords = kw_stats.total_keywords
    passed_keywords = kw_stats.passed_keywords
    failed_keywords = kw_stats.failed_keywords
    try:
        skipped_keywords = kw_stats.skipped_keywords
    except:
        skipped_keywords = 0

    # Handling ZeroDivisionError exception when no keywords are found
    # if total_keywords > 0:
    #     kwpp = round(passed_keywords * 100.0 / total_keywords, 1)
    #     kwfp = round(failed_keywords * 100.0 / total_keywords, 1)
    # else:
    #     kwpp = 0
    #     kwfp = 0

    dashboard_content = """
    <div class="tabcontent" id="dashboard">
        <div id="stats_screenshot_area">
        <div class="d-flex flex-column flex-md-row align-items-center p-1 mb-3 bg-light border-bottom shadow-sm rowcard">
            <h5 class="my-0 mr-md-auto font-weight-normal"><i class="fa fa-dashboard"></i> Dashboard</h5>
            <nav class="my-2 my-md-0 mr-md-3" style="color:#fc6666">
            <a class="p-2"><b style="color:black;">Execution Time: </b>__TIME__ h</a>
            <a class="p-2"><b style="color:black;cursor: pointer;" data-toggle="tooltip" title=".xml file is created by">Generated By: </b>__GENERATED-BY__</a>
            </nav>
        </div>

        <div class="row rowcard">

            <div class="col-md-4 border-right" onclick="openPage('suiteMetrics', this, '')" data-toggle="tooltip" 
                title="Click to view Suite metrics" style="cursor: pointer;">
                <span style="font-weight:bold; padding-left:5px;color:gray">Suite Statistics:</span>
                <table style="width:100%;height:200px;text-align: center;">
                    <tbody>
                        <tr style="height:60%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:100%">
                                            <td style="font-size:60px; color:#2ecc71">__SPASS__</td>
                                        </tr>
                                        <tr>
                                            <td><span style="color: #999999;font-size:12px">Pass</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>

                        <tr style="height:25%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:70%;font-size:25px" align="center" valign="middle">
                                            <td style="width: 33%; color:brown">__STOTAL__</td>
                                            <td style="width: 33%; color:orange">__SSKIP__</td>
                                            <td style="width: 33%; color:#fc6666">__SFAIL__</td>
                                        </tr>
                                        <tr style="height:30%" align="center" valign="top">
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Total</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Skip</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Fail</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="col-md-4 borders" onclick="openPage('testMetrics', this, '')" data-toggle="tooltip" 
                            title="Click to view Test metrics" style="cursor: pointer;">
                <span style="font-weight:bold; padding-left:5px;color:gray">Test Statistics:</span>
                <table style="width:100%;height:200px;text-align: center;">
                    <tbody>
                        <tr style="height:60%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:100%">
                                            <td style="font-size:60px; color:#2ecc71">__TPASS__</td>
                                        </tr>
                                        <tr>
                                            <td><span style="color: #999999;font-size:12px">Pass</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>

                        <tr style="height:25%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:70%;font-size:25px" align="center" valign="middle">
                                            <td style="width: 33%; color:brown">__TTOTAL__</td>
                                            <td style="width: 33%; color:orange">__TSKIP__</td>
                                            <td style="width: 33%; color:#fc6666">__TFAIL__</td>
                                        </tr>
                                        <tr style="height:30%" align="center" valign="top">
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Total</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Skip</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Fail</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
            <div class="col-md-4 border-left" onclick="openPage('keywordMetrics', this, '')" data-toggle="tooltip" 
                            title="Click to view Keyword metrics" style="cursor: pointer;">
                <span style="font-weight:bold; padding-left:5px;color:gray">Keyword Statistics:</span>
                <table style="width:100%;height:200px;text-align: center;">
                    <tbody>
                        <tr style="height:60%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:100%">
                                            <td style="font-size:60px; color:#2ecc71">__KPASS__</td>
                                        </tr>
                                        <tr>
                                            <td><span style="color: #999999;font-size:12px">Pass</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>

                        <tr style="height:25%">
                            <td>
                                <table style="width:100%">
                                    <tbody>
                                        <tr style="height:70%;font-size:25px" align="center" valign="middle">
                                            <td style="width: 33%; color:brown">__KTOTAL__</td>
                                            <td style="width: 33%; color:orange">__KSKIP__</td>
                                            <td style="width: 33%; color:#fc6666">__KFAIL__</td>
                                        </tr>
                                        <tr style="height:30%" align="center" valign="top">
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Total</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Skip</span></td>
                                            <td style="width: 33%"><span style="color: #999999;font-size:10px">Fail</span></td>
                                        </tr>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>

        </div>
        <hr/>
        <div class="row rowcard">
            <div class="col-md-4" style="height:280px;width:auto;">
                <span style="font-weight:bold;color:gray">Suite Status:</span>
                <div id="suiteChartID" style="height:250px;width:auto;"></div>
            </div>
            <div class="col-md-4" style="height:280px;width:auto;">
                <span style="font-weight:bold;color:gray">Test Status:</span>
                <div id="testChartID" style="height:250px;width:auto;"></div>
            </div>
            <div class="col-md-4" style="height:280px;width:auto;">
                <span style="font-weight:bold;color:gray">Keyword Status:</span>
                <div id="keywordChartID" style="height:250px;width:auto;"></div>
            </div>
        </div>
        <hr/>
        <div class="row rowcard">
            <div class="col-md-12" style="height:450px;width:auto;">
                <span style="font-weight:bold;color:gray">Top 10 Suite Performance(sec):</span>
                <div id="suiteBarID" style="height:400px;width:auto;"></div>
            </div>
        </div>
        <hr/>
        <div class="row rowcard">
            <div class="col-md-12" style="height:450px;width:auto;">
                <span style="font-weight:bold;color:gray">Top 10 Test Performance(sec):</span>
                <div id="testsBarID" style="height:400px;width:auto;"> </div>
            </div>
        </div>
        <hr/>
        <div class="row rowcard" __KHIDE__>
            <div class="col-md-12" style="height:450px;width:auto;">
                <span style="font-weight:bold;color:gray">Top 10 Keywords Performance(sec):</span>
                <div id="keywordsBarID" style="height:400px;width:auto;"></div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12" style="height:25px;width:auto;">
                <p class="text-muted" style="text-align:center;font-size:9px">
                    <a href="https://github.com/adiralashiva8/robotframework-metrics" target="_blank" style="color:gray">robotframework-metrics</a>
                </p>
            </div>
        </div>

       <script>
            window.onload = function(){
                executeDataTable('#sm',6);
                executeDataTable('#tm',3);
                executeDataTable('#km',3);
                createPieChart(__SPASS__,__SFAIL__,__SSKIP__,'suiteChartID','Suite Status:');
                createBarGraph('#sm',0,6,10,'suiteBarID','Elapsed Time (s) ','Suite');
                createPieChart(__TPASS__,__TFAIL__,__TSKIP__,'testChartID','Tests Status:');
                createBarGraph('#tm',1,3,10,'testsBarID','Elapsed Time (s) ','Test');
                createPieChart(__KPASS__,__KFAIL__,__KSKIP__,'keywordChartID','Keywords Status:');
                createBarGraph('#km',1,3,10,'keywordsBarID','Elapsed Time (s) ','Keyword');
            };
       </script>
       <script>
            function openInNewTab(url,element_id) {
                var element_id= element_id;
                var win = window.open(url, '_blank');
                win.focus();
                $('body').scrollTo(element_id);
            }
        </script>
    </div>
    """

    dashboard_content = dashboard_content.replace("__TIME__", str(elapsedtime))
    dashboard_content = dashboard_content.replace("__GENERATED-BY__",
                                                  str(generator))
    dashboard_content = dashboard_content.replace("__STOTAL__",
                                                  str(total_suite))
    dashboard_content = dashboard_content.replace("__SPASS__",
                                                  str(passed_suite))
    dashboard_content = dashboard_content.replace("__SFAIL__",
                                                  str(failed_suite))
    dashboard_content = dashboard_content.replace("__SSKIP__",
                                                  str(skipped_suite))
    dashboard_content = dashboard_content.replace("__TTOTAL__", str(total))
    dashboard_content = dashboard_content.replace("__TPASS__", str(passed))
    dashboard_content = dashboard_content.replace("__TFAIL__", str(failed))
    dashboard_content = dashboard_content.replace("__TSKIP__", str(skipped))
    dashboard_content = dashboard_content.replace("__KTOTAL__",
                                                  str(total_keywords))
    dashboard_content = dashboard_content.replace("__KPASS__",
                                                  str(passed_keywords))
    dashboard_content = dashboard_content.replace("__KFAIL__",
                                                  str(failed_keywords))
    dashboard_content = dashboard_content.replace("__KSKIP__",
                                                  str(skipped_keywords))
    dashboard_content = dashboard_content.replace("__KHIDE__",
                                                  str(hide_keyword))

    page_content_div.append(BeautifulSoup(dashboard_content, 'html.parser'))

    ### ============================ END OF DASHBOARD ============================================ ####
    logging.info("2 of 4: Capturing suite metrics...")
    ### ============================ START OF SUITE METRICS ======================================= ####

    # Tests div
    suite_div = soup.new_tag('div')
    suite_div["id"] = "suiteMetrics"
    suite_div["class"] = "tabcontent"
    page_content_div.insert(50, suite_div)

    test_icon_txt = """
                    <h4><b><i class="fa fa-table"></i> Suite Metrics</b></h4>
                    <hr></hr>
                    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "sm"
    table["class"] = "table row-border tablecard"
    suite_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Total"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Pass"
    tr.insert(3, th)

    th = soup.new_tag('th')
    th.string = "Fail"
    tr.insert(4, th)

    th = soup.new_tag('th')
    th.string = "Fail"
    tr.insert(5, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(6, th)

    suite_tbody = soup.new_tag('tbody')
    table.insert(11, suite_tbody)

    result.visit(SuiteResults(soup, suite_tbody, log_name, opts.fullsuitename))

    test_icon_txt = """
    <div class="row">
        <div class="col-md-12" style="height:25px;width:auto;"></div>
    </div>
    """
    suite_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    ### ============================ END OF SUITE METRICS ============================================ ####
    logging.info("3 of 4: Capturing test metrics...")
    ### ============================ START OF TEST METRICS ======================================= ####

    # Tests div
    tm_div = soup.new_tag('div')
    tm_div["id"] = "testMetrics"
    tm_div["class"] = "tabcontent"
    page_content_div.insert(100, tm_div)

    test_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Test Metrics</b></h4>
    <hr></hr>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # Create table tag
    table = soup.new_tag('table')
    table["id"] = "tm"
    table["class"] = "table row-border tablecard"
    tm_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Suite Name"
    tr.insert(0, th)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    th = soup.new_tag('th')
    th.string = "Error Message"
    tr.insert(4, th)

    if opts.showtags == "True":
        th = soup.new_tag('th')
        th.string = "Tags"
        tr.insert(5, th)

    test_tbody = soup.new_tag('tbody')
    table.insert(11, test_tbody)

    # GET TEST METRICS
    result.visit(
        TestResults(soup, test_tbody, log_name, opts.fullsuitename,
                    opts.showtags))

    test_icon_txt = """
    <div class="row">
        <div class="col-md-12" style="height:25px;width:auto;"></div>
    </div>
    """
    tm_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    ### ============================ END OF TEST METRICS ============================================ ####
    logging.info("4 of 4: Capturing keyword metrics...")
    ### ============================ START OF KEYWORD METRICS ======================================= ####

    # Keywords div
    km_div = soup.new_tag('div')
    km_div["id"] = "keywordMetrics"
    km_div["class"] = "tabcontent"
    page_content_div.insert(150, km_div)

    keyword_icon_txt = """
    <h4><b><i class="fa fa-table"></i> Keyword Metrics</b></h4>
      <hr></hr>
    """
    km_div.append(BeautifulSoup(keyword_icon_txt, 'html.parser'))

    # Create table tag
    # <table id="myTable">
    table = soup.new_tag('table')
    table["id"] = "km"
    table["class"] = "table row-border tablecard"
    km_div.insert(10, table)

    thead = soup.new_tag('thead')
    table.insert(0, thead)

    tr = soup.new_tag('tr')
    thead.insert(0, tr)

    th = soup.new_tag('th')
    th.string = "Test Case"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Keyword"
    tr.insert(1, th)

    th = soup.new_tag('th')
    th.string = "Status"
    tr.insert(2, th)

    th = soup.new_tag('th')
    th.string = "Time (s)"
    tr.insert(3, th)

    kw_tbody = soup.new_tag('tbody')
    table.insert(1, kw_tbody)

    if opts.ignorekeywords == "True":
        pass
    else:
        if group:
            group.spawn(
                result.visit,
                KeywordResults(soup, kw_tbody, ignore_library, ignore_type))
            group.join()
        else:
            result.visit(
                KeywordResults(soup, kw_tbody, ignore_library, ignore_type))

    test_icon_txt = """
    <div class="row">
        <div class="col-md-12" style="height:25px;width:auto;"></div>
    </div>
    """
    km_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))
    # END OF KEYWORD METRICS

    # START OF LOGS

    # Logs div
    if opts.ignorelogs == "True":
        pass
    else:
        log_div = soup.new_tag('div')
        log_div["id"] = "log"
        log_div["class"] = "tabcontent"
        page_content_div.insert(200, log_div)

        test_icon_txt = """
            <p style="text-align:right">** <b>Report.html</b> and <b>Log.html</b> need to be in current folder in 
            order to display here</p>
        <div class="embed-responsive embed-responsive-4by3">
            <iframe class="embed-responsive-item" src=%s></iframe>
        </div>
        """ % log_name
        log_div.append(BeautifulSoup(test_icon_txt, 'html.parser'))

    # END OF LOGS
    script_text = """
        <script>
            function createPieChart(passed_count, failed_count, skipped_count, ChartID, ChartName){
            var status = [];
            status.push(['Status', 'Percentage']);
            status.push(['PASS',parseInt(passed_count)],['FAIL',parseInt(failed_count)],['SKIP',parseInt(skipped_count)]);
            var data = google.visualization.arrayToDataTable(status);

            var options = {
            pieHole: 0.6,
            legend: 'none',
            chartArea: {width: "95%",height: "90%"},
            colors: ['#2ecc71', '#fc6666', '#ffa500'],
            };

            var chart = new google.visualization.PieChart(document.getElementById(ChartID));
            chart.draw(data, options);
        }
        </script>
        <script>
           function createBarGraph(tableID,keyword_column,time_column,limit,ChartID,Label,type){
            var status = [];
            css_selector_locator = tableID + ' tbody >tr'
            var rows = $(css_selector_locator);
            var columns;
            var myColors = [
                '#4F81BC',
                '#C0504E',
                '#9BBB58',
                '#24BEAA',
                '#8064A1',
                '#4AACC5',
                '#F79647',
                '#815E86',
                '#76A032',
                '#34558B'
            ];
            status.push([type, Label,{ role: 'annotation'}, {role: 'style'}]);
            for (var i = 0; i < rows.length; i++) {
                if (i == Number(limit)){
                    break;
                }
                //status = [];
                name_value = $(rows[i]).find('td');

                time=($(name_value[Number(time_column)]).html()).trim();
                keyword=($(name_value[Number(keyword_column)]).html()).trim();
                status.push([keyword,parseFloat(time),parseFloat(time),myColors[i]]);
              }
              var data = google.visualization.arrayToDataTable(status);

              var options = {
                legend: 'none',
                chartArea: {width: "92%",height: "75%"},
                bar: {
                    groupWidth: '90%'
                },
                annotations: {
                    alwaysOutside: true,
                    textStyle: {
                    fontName: 'Comic Sans MS',
                    fontSize: 12,
                    //bold: true,
                    italic: true,
                    color: "black",     // The color of the text.
                    },
                },
                hAxis: {
                    textStyle: {
                        //fontName: 'Arial',
                        fontName: 'Comic Sans MS',
                        fontSize: 10,
                    }
                },
                vAxis: {
                    gridlines: { count: 10 },
                    textStyle: {
                        fontName: 'Comic Sans MS',
                        fontSize: 10,
                    }
                },
              };

                // Instantiate and draw the chart.
                var chart = new google.visualization.ColumnChart(document.getElementById(ChartID));
                chart.draw(data, options);
             }

        </script>

     <script>
      function executeDataTable(tabname,sortCol) {
        var fileTitle;
        switch(tabname) {
            case "#sm":
                fileTitle = "SuiteMetrics";
                break;
            case "#tm":
                fileTitle =  "TestMetrics";
                break;
            case "#km":
                fileTitle =  "KeywordMetrics";
                break;
            default:
                fileTitle =  "metrics";
        }

        $(tabname).DataTable(
            {
                retrieve: true,
                "order": [[ Number(sortCol), "desc" ]],
                dom: 'l<".margin" B>frtip',
                "aoColumnDefs": [ {
                    "aTargets": [ -1, -2 ],
                    "mRender": function ( data, type, full ) {
                        return $("<div/>").html(data).text(); 
                    }
                } ],
                buttons: [
                    {
                        extend:    'copyHtml5',
                        text:      '<i class="fa fa-files-o"></i>',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        titleAttr: 'Copy',
                        exportOptions: {
                            columns: ':visible'
                        }
					},

                    {
                        extend:    'csvHtml5',
                        text:      '<i class="fa fa-file-text-o"></i>',
                        titleAttr: 'CSV',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        exportOptions: {
                            columns: ':visible'
                        }
                    },

                    {
                        extend:    'excelHtml5',
                        text:      '<i class="fa fa-file-excel-o"></i>',
                        titleAttr: 'Excel',
                        filename: function() {
                            return fileTitle + '-' + new Date().toLocaleString();
                        },
                        exportOptions: {
                            columns: ':visible'
                        }
                    },
                    {
                        extend:    'print',
                        text:      '<i class="fa fa-print"></i>',
                        titleAttr: 'Print',
                        exportOptions: {
                            columns: ':visible',
                            alignment: 'left',
                        }
                    },
                    {
                        extend:    'colvis',
                        collectionLayout: 'fixed two-column',
                        text:      '<i class="fa fa-low-vision"></i>',
                        titleAttr: 'Hide Column',
                        exportOptions: {
                            columns: ':visible'
                        },
                        postfixButtons: [ 'colvisRestore' ]
                    },
                ],
                columnDefs: [ {
                    visible: false,
                } ]
            }
        );
    }
     </script>
    <script>
      function openPage(pageName,elmnt,color) {
        var i, tabcontent, tablinks;
        tabcontent = document.getElementsByClassName("tabcontent");
        for (i = 0; i < tabcontent.length; i++) {
            tabcontent[i].style.display = "none";
        }
        tablinks = document.getElementsByClassName("tablink");
        for (i = 0; i < tablinks.length; i++) {
            tablinks[i].style.color = "";
        }
        document.getElementById(pageName).style.display = "block";
        elmnt.style.color = color;

    }
    // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
     </script>
     <script>
     // Get the element with id="defaultOpen" and click on it
    document.getElementById("defaultOpen").click();
    </script>
    <script>
        $(window).on('load',function(){$('.loader').fadeOut();});
    </script>
    """

    body.append(BeautifulSoup(script_text, 'html.parser'))

    # WRITE TO RF_METRICS_REPORT.HTML

    # Write output as html file
    with open(result_file, 'w') as outfile:
        outfile.write(soup.prettify())

    logging.info(
        "Results file created successfully and can be found at {}".format(
            result_file))
Example #35
0
else:
    log_name = 'log.html'

# output.xml file
if '-output' in myargs:
    output_name = os.path.join(path, myargs['-output'][0])
else:
    output_name = os.path.join(path, 'output.xml')

mtTime = datetime.now().strftime('%Y%m%d-%H%M%S')
# Output result file location
result_file_name = 'metrics-' + mtTime + '.html'
result_file = os.path.join(path, result_file_name)

# Read output.xml file
result = ExecutionResult(output_name)
result.configure(stat_config={
    'suite_stat_level': 2,
    'tag_stat_combine': 'tagANDanother'
})

print("Converting .xml to .html file. This may take few minutes...")

head_content = """
<!doctype html>
<html lang="en">

<head>
    <link rel="shortcut icon" href="https://png.icons8.com/windows/50/000000/bot.png" type="image/x-icon" />
    <title>RF Metrics Report</title>
    <meta charset="utf-8">
def get_test_suite_names(output_xml_path):
    """"
    Parses an output.xml file and returns the names of test suites that contain tests that were executed
    """
    er = ExecutionResult(output_xml_path)
    return _recursively_list_test_suites(er.suite)
 def process_output(self, inpath, outpath=None):
     result = ExecutionResult(inpath)
     result.suite.visit(self)
     result.save(outpath)
     return result
Example #38
0
        half_low = int(math.floor(half))
        half_high = int(math.ceil(half))
        return round(float(s[half_low]+s[half_high])/2000, 3)

    @property
    def variance(self):
        squares = [(float(i)/1000)**2 for i in self.elapsedtimes]
        return sum(squares)/len(squares)-(self.elapsed/self.calls)**2

    @property
    def standard_deviation(self):
        return round(self.variance**0.5, 3)

    def __cmp__(self, other):
        return other.elapsed - self.elapsed


if __name__ == '__main__':
    import sys
    resu = ExecutionResult(sys.argv[1])
    times = KeywordTimes()
    resu.visit(times)
    s = sorted(times.keywords.values())
    shown_keywords = 100
    print 'Total time (s) | Number of calls | avg time (s) | median time (s) | standard deviation (s) | Keyword name'
    for k in s[:shown_keywords]:
        print str(k.elapsed).rjust(14)+' | '+str(k.calls).rjust(15)+ ' | ' + \
                str(k.average_time).rjust(12) + ' | ' + str(k.median_time).rjust(15) + \
                ' | ' + str(k.standard_deviation).rjust(22) + (' | "%s"' % k.name)
    print 'Showing %d of total keywords %d' % (shown_keywords, len(times.keywords))