Revision: 78eb5f07de3a
Author: Janne Härkönen <[email protected]>
Date: Wed Feb 22 15:01:14 2012
Log: first version of testdoc
http://code.google.com/p/robotframework/source/detail?r=78eb5f07de3a
Added:
/src/robot/testdoc.py
/src/robot/webcontent/testdoc.html
=======================================
--- /dev/null
+++ /src/robot/testdoc.py Wed Feb 22 15:01:14 2012
@@ -0,0 +1,155 @@
+#!/usr/bin/env python
+
+# Copyright 2008-2011 Nokia Siemens Networks Oyj
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+USAGE = """Robot Framework Test Data Documentation Tool
+
+Usage: testdoc.py [options] data_sources
+
+This tool generates a high level test documentation from a given test data.
+Generated documentation includes the names, documentations and other
metadata
+of each test suite and test case, as well as the top-level keywords and
their
+arguments. Most of the options accepted by this tool have exactly same
+semantics as same options have when executing test cases.
+
+Options:
+ -T --title title Set the title of the generated documentation.
+ Underscores in the title are converted to spaces.
+ -N --name name Set the name of the top level test suite.
+ -D --doc document Set the document of the top level test suite.
+ -M --metadata name:value * Set metadata of the top level test suite.
+ -G --settag tag * Set given tag(s) to all test cases.
+ -t --test name * Include test cases by name.
+ -s --suite name * Include test suites by name.
+ -i --include tag * Include test cases by tags.
+ -e --exclude tag * Exclude test cases by tags.
+ -h --help Print this help.
+
+Examples:
+ $ testdoc.py mytestcases.html testdoc.html
+ $ testdoc.py --name smoke_test_plan --include smoke path/to/my_tests/
doc.html
+"""
+import sys
+import os
+import codecs
+
+if 'robot' not in sys.modules:
+ import pythonpathsetter # running testdoc.py as script
+
+from robot import utils, version
+from robot.running import TestSuite, Keyword
+from robot.conf import RobotSettings
+from robot.parsing import populators
+from robot.reporting.htmlfilewriter import HtmlFileWriter, ModelWriter
+from robot.reporting.jsonwriter import JsonWriter
+
+populators.PROCESS_CURDIR = False
+
+class TestDoc(utils.Application):
+
+ def __init__(self):
+ utils.Application.__init__(self, USAGE, arg_limits=(2,),
auto_version=False)
+
+ def main(self, args, title=None, **opts):
+ datasources = args[0:-1]
+ outfile = args[-1]
+ suite = TestSuite(datasources, RobotSettings(opts))
+ self._write_test_doc(suite, outfile, title)
+
+ def _write_test_doc(self, suite, outfile, title):
+ output = codecs.open(outfile, 'w', 'UTF-8')
+ model_writer = TestdocModelWriter(output, suite)
+ HtmlFileWriter(output, model_writer).write('testdoc.html')
+ output.close()
+
+
+class TestdocModelWriter(ModelWriter):
+
+ def __init__(self, output, suite):
+ self._output = output
+ self._suite = suite
+
+ def write(self, line):
+ self._output.write('<script type="text/javascript">' + os.linesep)
+ self._write_data()
+ self._output.write('</script>' + os.linesep)
+
+ def _write_data(self):
+ json = JsonConverter().convert(self._suite)
+ JsonWriter(self._output).write_json('suite = ', json)
+
+
+class JsonConverter(object):
+
+ def convert(self, suite):
+ return self._convert_suite(suite, 's-0')
+
+ def _convert_suite(self, suite, suite_id, index=None):
+ suite_id = suite_id + '-s-%d' % index if index is not None else
suite_id
+ return {'name': suite.name,
+ 'fullName': suite.longname,
+ 'source': suite.source,
+ 'doc': suite.doc,
+ 'id': suite_id,
+ 'metadata': dict(suite.metadata),
+ 'numberOfTests': suite.get_test_count(),
+ 'suites': self._convert_suites(suite, suite_id),
+ 'tests': self._convert_tests(suite, suite_id),
+ 'keywords': self._get_suite_keywords(suite, suite_id)
+ }
+
+ def _get_suite_keywords(self, suite, suite_id):
+ kws = []
+ if suite.setup.name:
+ kws.append(self._convert_keyword(suite.setup, suite_id,
0, 'SETUP'))
+ if suite.teardown.name:
+ kws.append(self._convert_keyword(suite.teardown, suite_id,
1, 'TEARDOWN'))
+ return kws
+
+ def _convert_suites(self, suite, suite_id):
+ return [self._convert_suite(suite, suite_id, index)
+ for index, suite in enumerate(suite.suites)]
+
+ def _convert_tests(self, suite, suite_id):
+ return [self._convert_test(test, suite_id, index)
+ for index, test in enumerate(suite.tests)]
+
+ def _convert_test(self, test, suite_id, index):
+ test_id = suite_id + '-t-%d' % index
+ return {'name': test.name,
+ 'fullName': test.longname,
+ 'id': test_id,
+ 'doc': test.doc,
+ 'tags': test.tags,
+ 'keywords': self._convert_keywords(test, test_id)}
+
+ def _convert_keywords(self, test, test_id):
+ return [self._convert_keyword(k, test_id, index, 'KEYWORD')
+ for index, k in enumerate(test.keywords)]
+
+ def _convert_keyword(self, kw, test_id, index, type):
+ return {'name': kw.name,
+ 'id': test_id + '-k-%d' % index,
+ 'arguments': ', '.join(kw.args),
+ 'type': type
+ }
+
+
+def testdoc_cli(args):
+ TestDoc().execute_cli(args)
+
+if __name__ == '__main__':
+ testdoc_cli(sys.argv[1:])
+
=======================================
--- /dev/null
+++ /src/robot/webcontent/testdoc.html Wed Feb 22 15:01:14 2012
@@ -0,0 +1,176 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01
Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<meta http-equiv="Pragma" content="no-cache">
+<meta http-equiv="Expires" content="-1">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="Generator" content="">
+<link rel="icon" type="image/x-icon"
href="data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAIAAAAAAAAAAAAAEAAAAAAAAAAAAAAAJEBoACtnfgA5cYYAERsiAEx2lAAbKkQAcazBACZCVwAcM1cAK0ucAAMDBQAnQncASG+FABkoVQAyWmgA6f8SgvH/Ij99+GLyIinyJfn/Yi//KSLzUy9iZogpIld3/4JVVTkid7vyUjNVNVJEAGOZ6Z7pXwAABpmZkRiLAAAGiJZpmGAAAEEt3SXdxAAATC7o/u3EAAC8MRZpjasAAAY1VVVTYAAABKqqqqpAAAAADKqq4AAAAAAAv4sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMADAADgAwAA4AcAAOAHAADgBwAAwAcAAOAHAADgDwAA8A8AAPg/AAD+fwAA">
+<link rel="stylesheet" type="text/css" href="log.css" media="all">
+<link rel="stylesheet" type="text/css" href="common.css" media="all">
+<link rel="stylesheet" type="text/css" href="print.css" media="print">
+<script type="text/javascript" src="lib/jquery.min.js"></script>
+<script type="text/javascript" src="lib/jquery.tmpl.min.js"></script>
+<script type="text/javascript" src="lib/jsxcompressor.js"></script>
+<script type="text/javascript" src="view.js"></script>
+<script type="text/javascript" src="log.js"></script>
+<!-- JS MODEL --><script type="text/javascript"
src="testdata/testdoc.js"></script>
+<title></title>
+</head>
+<body>
+<div id="javascript_disabled">
+ <h1>Opening test suite documentation failed</h1>
+ <ul>
+ <li>Verify that you have <b>JavaScript enabled</b> in your
browser.</li>
+ <li>Make sure you are using a <b>modern enough browser</b>. Firefox
3.5, IE 8, or equivalent is required, newer browsers are recommended.</li>
+ <li>Check are there messages in your browser's <b>JavaScript error
log</b>. Please report the problem if you suspect you have encountered a
bug.</li>
+ </ul>
+</div>
+<script type="text/javascript">
+ // Not using jQuery here for speed and to support ancient browsers.
+ document.getElementById('javascript_disabled').style.display = 'none';
+</script>
+
+<div class="header" id="header_div"></div>
+<div id="statistics_container"></div>
+
+<script type="text/javascript">
+$(document).ready(function(){
+ setTitle(window.suite);
+ parseTemplates();
+ addSuite(window.suite);
+ expandSuite(window.suite);
+});
+
+function setTitle(suite) {
+ var givenTitle = suite.title;
+ document.title = givenTitle ? givenTitle : 'Documentation for ' +
suite.name;
+ $.tmpl('<h1>' + document.title + '</h1>').appendTo($('body'))
+}
+
+function addSuite(suite) {
+ var root = $.tmpl('suiteTemplate', suite);
+ root.appendTo($('body'));
+ addKeywords(suite);
+ addSuites(suite);
+ addTests(suite);
+}
+
+function addSuites(suite) {
+ $.map(suite.suites, function (s, _) {
+ $.tmpl('suiteTemplate', s).appendTo($('#' + suite.id
+ '_children'));
+ addKeywords(s);
+ addSuites(s);
+ addTests(s);
+ });
+}
+function addTests(suite) {
+ $.map(suite.tests, function (test, _) {
+ $.tmpl('testTemplate', test).appendTo($('#' + suite.id
+ '_children'));
+ addKeywords(test);
+ });
+}
+
+function addKeywords(parent) {
+ $.map(parent.keywords, function (kw, _) {
+ $.tmpl('keywordTemplate', kw).appendTo($('#' + parent.id
+ '_children'));
+ });
+}
+</script>
+
+<script type="text/x-jquery-tmpl" id="suiteTemplate">
+ <div id="${id}" class="suite">
+ <div id="${id}_elementheader" class="elementheader"
+ onclick="toggleSuite('${id}');" title="${fullName}">
+ <div id="${id}_foldingbutton" class="foldingbutton">+</div>
+ <span class="not_run">TEST SUITE:</span>
+ <span class="name">${name}</span>
+ <a class="expandall" href="javascript:expandAllChildren('${id}')"
+ onclick="stopPropagation(event);">Expand All</a>
+ </div>
+ <div id="${id}_children" style="display: none;">
+ <table class="metadata">
+ <tr>
+ <th>Full Name:</th>
+ <td>${fullName}</td>
+ </tr>
+ {{if doc}}
+ <tr>
+ <th>Documentation:</th>
+ <td>{{html doc}}</td>
+ </tr>
+ {{/if}}
+ {{each metadata}}
+ <tr>
+ <th>${$value[0]}:</th>
+ <td>{{html $value[1]}}</td>
+ </tr>
+ {{/each}}
+ {{if source}}
+ <tr>
+ <th>Source:</th>
+ {{if relativeSource}}
+ <td><a href="${relativeSource}">${source}</a></td>
+ {{else}}
+ <td>${source}</td>
+ {{/if}}
+ </tr>
+ {{/if}}
+ <tr>
+ <th>Number of Tests:</th>
+ <td>${numberOfTests}</td>
+ </tr>
+ </table>
+ </div>
+ </div>
+</script>
+
+<script type="text/x-jquery-tmpl" id="testTemplate">
+ <div id="${id}" class="test">
+ <div id="${id}_elementheader" onclick="toggleTest('${id}');"
+ class="elementheader" title="${fullName}">
+ <div id="${id}_foldingbutton" class="foldingbutton">+</div>
+ <span class="not_run">TEST CASE: </span>
+ <span class="name">${name}</span>
+ <a class="expandall" href="javascript:expandAllChildren('${id}')"
+ onclick="stopPropagation(event);">Expand All</a>
+ </div>
+ <div id="${id}_children" style="display: none;">
+ <table class="metadata">
+ <tr>
+ <th>Full Name:</th>
+ <td>${fullName}</td>
+ </tr>
+ {{if doc}}
+ <tr>
+ <th>Documentation:</th>
+ <td>{{html doc}}</td>
+ </tr>
+ {{/if}}
+ <tr>
+ <th>Tags:</th>
+ <td>${tags}</td>
+ </tr>
+ {{if timeout}}
+ <tr>
+ <th>Timeout:</th>
+ <td>${timeout}</td>
+ </tr>
+ {{/if}}
+ </table>
+ </div>
+ </div>
+</script>
+
+<script type="text/x-jquery-tmpl" id="keywordTemplate">
+ <div id="${id}" class="keyword">
+ <span class="not_run">${type}: </span>
+ <span class="name">${name}</span>
+ <span class="arg">${arguments}</span>
+ </div>
+</script>
+
+
+</body>
+</html>