Source code for stress_test.html_generation

# Copyright (c) 2015 Intracom S.A. Telecom Solutions. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v1.0 which accompanies this distribution,
# and is available at http://www.eclipse.org/legal/epl-v10.html

"""
HTML generation functions """
import json
import optparse
import stress_test.report_spec
import util.html


[docs]def generate_html(report_spec, report_filename): """ Generates the test HTML report :param report_spec: report specification for this report :param report_filename: target HTML filename :type report_spec: ReportSpec :type report_filename: str """ # The following multiline variable contains Javascript functions # that are integrated into the html report. The specific ones make the # headers of tables scroll with the page javascript_functions = ''' <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"> </script> <script type="text/javascript"> //<![CDATA[ /** * Usage: Call ActivateFloatingHeader with a CSS selector(string) matching * table elements that should have a floating header * * $(document).ready(function() { * ActivateFloatingHeaders("table.tableWithFloatingHeader"); * }); */ function _UpdateTableHeadersScroll() { $("div.divTableWithFloatingHeader").each(function() { var originalHeaderRow = $(".tableFloatingHeaderOriginal", this); var floatingHeaderRow = $(".tableFloatingHeader", this); var offset = $(this).offset(); var scrollTop = $(window).scrollTop(); // check if floating header should be displayed if ((scrollTop > offset.top) && (scrollTop < offset.top + $(this).height() - originalHeaderRow.height())) { floatingHeaderRow.css("visibility", "visible"); floatingHeaderRow.css("left", -$(window).scrollLeft()); } else { floatingHeaderRow.css("visibility", "hidden"); } }); } function _UpdateTableHeadersResize() { $("div.divTableWithFloatingHeader").each(function() { var originalHeaderRow = $(".tableFloatingHeaderOriginal", this); var floatingHeaderRow = $(".tableFloatingHeader", this); // Copy cell widths from original header $("th", floatingHeaderRow).each(function(index) { var cellWidth = $("th", originalHeaderRow).eq(index).css('width'); $(this).css('width', cellWidth); }); // Copy row width from whole table floatingHeaderRow.css("width", Math.max(originalHeaderRow.width(), $(this).width()) + "px"); }); } function ActivateFloatingHeaders(selector_str){ $(selector_str).each(function() { $(this).wrap('<div class="divTableWithFloatingHeader" ' + 'style="position:relative"></div>'); // use first row as floating header by default var floatingHeaderSelector = "thead"; var explicitFloatingHeaderSelector = "thead.floating-header" if ($(explicitFloatingHeaderSelector, this).length){ floatingHeaderSelector = explicitFloatingHeaderSelector; } var originalHeaderRow = $(floatingHeaderSelector, this).first(); var clonedHeaderRow = originalHeaderRow.clone() originalHeaderRow.before(clonedHeaderRow); clonedHeaderRow.addClass("tableFloatingHeader"); clonedHeaderRow.css("position", "fixed"); // not sure why but 0px is used there is still some space in the top clonedHeaderRow.css("top", "-2px"); clonedHeaderRow.css("margin-left", $(this).offset().left+1); clonedHeaderRow.css("margin-right", $(this).offset().right+1); clonedHeaderRow.css("visibility", "hidden"); originalHeaderRow.addClass("tableFloatingHeaderOriginal"); }); _UpdateTableHeadersResize(); _UpdateTableHeadersScroll(); $(window).scroll(_UpdateTableHeadersScroll); $(window).resize(_UpdateTableHeadersResize); } //]]> </script> <script type="text/javascript"> //<![CDATA[ $(document).ready(function() { ActivateFloatingHeaders("table.tableWithFloatingHeader"); }); //]]> </script> ''' # In the following multiline variable, we keep the information about the # formating of the produced html document as a css string. default_css_styling = ''' body { margin:0; padding:20px; font:13px "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif; } /* ---- Resets ---- */ p, table, caption, td, tr, th { margin:0; padding:0; font-weight:normal; } /* ---- Paragraphs ---- */ p { margin-bottom:15px; } /* ---- Table ---- */ table { border-collapse:separate; border-spacing:0px; margin-bottom:15px; width:90%; border:1px solid #cccccc; } caption { text-align:left; font-size:15px; padding-bottom:10px; } table td, table th { padding:5px; border:1px solid #fff; border-width:0px 1px 1px 0px; vertical-align: middle; } thead th { background:#91c5d4; font-size: 17px; font-weight:bold; text-align:center; } thead th.table-title { font-size:19px; font-weight:bold; text-align:left; } thead th[colspan], thead th[rowspan] { background:#66a9bd; } tbody th, tfoot th { text-align:left; background:#91c5d4; } tbody td, tfoot td { text-align:left; background:#d5eaf0; font-size:16px; font-weight:normal; } tbody td.center { text-align:center; } tfoot th { background:#b0cc7f; } fieldset { width:30%; font-size:16px; border: 1px solid #000000; padding: 10px; } fieldset.left { float:left; margin-right:20px; } fieldset legend { font-size:17px; font-weight:bold; } tfoot td { background:#d7e1c5; font-weight:bold; } tbody tr.odd td { background:#bcd9e1; } img { width:49%; max-width:800px; min-width:640px; height:auto; border: 0; } img.graph-left{ float:left; margin-right:1px; } img.graph-right{ float:right; margin-left:1px; } div.graph-container{ float:left; width:100%; max-width:1605px; min-width:1285px; } div.float-cleaner{ clear:both; } ''' content = '' params = json.loads(open(report_spec.config_json).read()) # The content on the top of the html report html_head_content = '<h1>' + report_spec.title + '</h1><hr>' # Generating header of the report page content = content + util.html.generate_html_head(default_css_styling, javascript_functions, html_head_content) # Generating results parameters table content = content + generate_table(report_spec.config_tables) # Inserting plots inside the report page content = content + insert_plots(params['plots']) # Generating test results table content = content + generate_table(report_spec.results_table) content = content + util.html.generate_html_foot() repf = open(report_filename, 'w') repf.write(content) repf.close()
[docs]def generate_table(tables_specs): """ Gets a dictionary with tables specifications and generates the \ corresponded html code. :param tables_specs: Dictionary containing the specifications of a group \ of tables. :returns: html code of the table. :rtype: str :type tables_specs: <dictionary> """ table_html = '' for table_specs in tables_specs: table_data = json.loads(open(table_specs.source_json).read()) if table_specs.table_type == '1d': table_html = table_html + util.html.single_dict_to_html( table_data, 'Parameter', 'Value', table_specs.title, table_specs.keys) elif table_specs.table_type == '2d': table_html = table_html + util.html.multi_dict_to_html( table_data, table_specs.title, table_specs.keys, table_specs.ordering_key) table_html = table_html + '<br>' + '<hr>' return table_html
[docs]def insert_plots(plots_list): """ Gets a list of dictionaries that describes the plots of the report, and generates the corresponded html code. :param plots_list: A list of dictionaries with the plots description. :returns: The corresponded html code to insert the plots. :rtype: str :type plots_list: <list<dictionary>> """ num_plots = len(plots_list) plots_html = '' if num_plots: plots_html = plots_html + '<div class=\"graph-container\">' graph_float = 'left' for plot_id in list(range(0, num_plots)): if plots_list[plot_id]['plot_filename']: # Adding a graph image in document. plots_html = plots_html + \ '<img class=\"graph-' + graph_float + '\" src=\"' + \ str(plots_list[plot_id]['plot_filename']) + \ '.png\" alt=\"result graph\" />' # Changing the page alignment of the next inserted graph image. # Also place a content break to have images group of 2. if graph_float == 'right': plots_html = plots_html + \ '<div class=\"float-cleaner\"><br></div>' graph_float = 'left' else: graph_float = 'right' plots_html = plots_html + '</div>' plots_html = plots_html + '<div class=\"float-cleaner\"><br></div>' plots_html = plots_html + '<hr>' return plots_html
[docs]def self_test(): """ Used for self testing purposes """ opt_parser = optparse.OptionParser() opt_parser.add_option('--input-results', dest='RESULTS_JSON', action='store', default='results.json', help="pathname of the result json file to open") opt_parser.add_option('--input-conf', dest='PARAMETERS_JSON', action='store', default='conf.json', help='name of the parameter json file to open') opt_parser.add_option('--html-report', dest='report_filename', action='store', default='report.html', help='name of the filename of html report') json_opts = opt_parser.parse_args()[0] report_test = stress_test.report_spec.ReportSpec( json_opts.PARAMETERS_JSON, json_opts.RESULTS_JSON, 'test', [stress_test.report_spec.TableSpec( '1d', 'config', [('controller_start', 'Controller Start'), ('controller_stop', 'Controller Stop'), ('java_opts', 'Java Options')], json_opts.PARAMETERS_JSON)], [stress_test.report_spec.TableSpec( '2d', 'results', None, json_opts.RESULTS_JSON, 'generator_thread_creation_delay_ms')] ) generate_html(report_test, json_opts.report_filename)
# Used for self-testing purposes. if __name__ == '__main__': self_test()