[Checkins] SVN: Zelenium/trunk/ Move code to Launchpad, due to non-ZPL status of the included selenium-core JS.
Tres Seaver
tseaver at palladion.com
Wed Apr 7 14:21:23 EDT 2010
Log message for revision 110604:
Move code to Launchpad, due to non-ZPL status of the included selenium-core JS.
Changed:
D Zelenium/trunk/CHANGES.txt
D Zelenium/trunk/COPYRIGHT.txt
D Zelenium/trunk/LICENSE.txt
U Zelenium/trunk/README.txt
D Zelenium/trunk/__init__.py
D Zelenium/trunk/configure.zcml
D Zelenium/trunk/exclude.txt
D Zelenium/trunk/generator.py
D Zelenium/trunk/interfaces.py
D Zelenium/trunk/permissions.py
D Zelenium/trunk/scripts/
D Zelenium/trunk/selenium/
D Zelenium/trunk/tests/
D Zelenium/trunk/version.txt
D Zelenium/trunk/www/
D Zelenium/trunk/zuite.py
-=-
Deleted: Zelenium/trunk/CHANGES.txt
===================================================================
--- Zelenium/trunk/CHANGES.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/CHANGES.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,181 +0,0 @@
-Zelenium Product Changelog
-
- After Zelenium 0.8
-
- - Applied a fix from Rob Miller to make Zelenium Zuite objects functional
- in the presence of 'five:traverse', making 'index_html' the explicit
- default view.
-
- - Corrected the documentation in the README for capturing results of a test
- run ('auto=1' -> 'auto=true', in line with the Selenium documentation).
- Thanks to Yoshinori Okuji for pointing this out.
-
- Zelenium 0.8 (2006/05/16)
-
- - SVN tag: svn+ssh://svn.zope.org/repos/main/Zelenium/tags/0.8
-
- - Fixed unit tests by wrapping filesystem objects that are rendered
- during ZIP file creation - code in OFS.Image wants to acquire
- REQUEST and use RESPONSE.
-
- - Found how to make the dependency on ExternalEditor optional (thanks
- to Andreas Jung for the bug report).
-
- - Stripped empty filenames out of manifest, to avoid infinite
- recursion.
-
- - Added the testsuite_name property that allows multiple test
- suites to be built up from test cases within a single filesystem
- directory.
-
- - Upgrade to selenium version 0.6
-
- - Suites now recurse through all "folderish" subobjects, looking
- for tests (allows, for instance, tests to be loaded from disk via
- CMF's FileSystemDirectoryView). Thanks to Malcom Cleaton for the
- patch!
-
- - Define zelenium_globals in __init__.py to be able to
- register the 'selenium' directory for use as a CMF skin directory.
-
- - If debug-mode is set to "on" in zope.conf, filesystem-based testcases
- files are reloaded every time they are used, to ease development of
- filesystem-based test suites. This behavior emulates what the CMF
- Filesystem Directory Views do with debug-mode on.
-
- - Moved repository to Subversion:
- svn+ssh://svn.zope.org/repos/main/Zelenium/
-
- Zelenium-0.7 (2005/06/07)
-
- - CVS tag: 'Zelenium-0_7'
-
- - Upgrade to use the Selenium "core application" from Selenium 0.4.0.
- See http://selenium.thoughtworks.com/release-notes.html for a summary
- of changes.
-
- o **N.B.**: the semantics of 'click' have changed; that command
- no longer waits by default, and the 'nowait' modifier is no longer
- meaningful. Use 'clickAndWait' to get the desired semantics.
-
- Zelenium-0.6 (2005/05/09)
-
- - CVS tag: 'Zelenium-0_6'
-
- - Add ability to suppress inclusion of Selenium support files in
- snapshot / download.
-
- - Add support for returning testcases from a mapped directory path,
- including recursion through subdirectories of that path. Currently,
- the implementation has the following issues:
-
- o It only creates OFS.Image.File objects for test cases (no templates,
- scripts, etc.)
-
- - Add unit tests for Zuite.__getitem__ behavior, including support files.
-
- Zelenium-0.5.1 (2005/05/07)
-
- - CVS tag: 'Zelenium-0_5_1'
-
- - Make passing / failing test cases in results view more obvious in
- printed representation by adding icons. N.B.: at the moment, we do
- this by sniffing the HTML of the test case for the "pink" backgrounds.
-
- - Apply patch from the selenium-devel list to fix regression in
- testcase HTML extraction in 'postTestResults'.
-
- - Make the posted results folder into its own class, derived from
- Folder (moving the template out to a PageTemplateFile).
-
- - Further repaired recursive ZIPfile generation, including normalizing
- URLs in generated HTML.
-
- - Extended zuite unittests to test 'listTestCases' and
- 'manage_createSnapshot', as well as recursive ZIPfile generation.
-
- Zelenium-0.5 (2005/05/04)
-
- - CVS tag: 'Zelenium-0_5'
-
- - Updated to use the "TestRunner core" from Selenium version 0.3.0.
- See http://selenium.thoughtworks.com/release-notes.html for more
- information.
-
- - Add unit tests for Zuite class.
-
- - Make ZIPfile generation work with nested suites.
-
- Zelenium-0.4.1 (2005/05/02)
-
- - CVS tag: 'Zelenium-0_4_1'
-
- - Repair breakage of ExternalEditor link in 'manage_main'.
-
- - Compensate in display of test tables for non-padded integers
- in the IDs (make them sort properly).
-
- Zelenium-0.4 (2005/04/27)
-
- - CVS tag: 'Zelenium-0_4'
-
- - Make Zuite instances recursively include their Zuite children's
- test cases (to allow easier organization of the test cases in a
- hierarchy).
-
- - Allow indiviual zuites to override the list of metatypes which
- can be test cases, via a new 'testcase_metatypes' property.
-
- - Force Zuite objects to show order support, even in the presence of
- ExternalEditor, whose monkey patching seems to trip it up. Surface
- the EE icon, if the product is available
-
- Note: we are *forking* OFS/dtml/main.dtml and the version in
- ExteranalEditor/manage_main.dtml to surface order support, which
- is a pretty brutal hack. We should probably get ExteranalEditor
- fixed, instead, and rip out the forked copy.
-
- Zelenium-0.3.1 (2005/04/26)
-
- - CVS tag: 'Zelenium-0_3_1'
-
- - Record server-side data during 'postResults': Zope version string,
- product names and versions.
-
- - Captured additional request parameters in 'postResults': user agent,
- HTTP host, remote address).
-
- Zelenium-0.3 (2005/04/25)
-
- - CVS tag: 'Zelenium-0_3'
-
- - Added 'postResults' handling code to capture results as a sub-
- folder of the suite.
-
- Zelenium-0.2.1 (2005/04/21)
-
- - CVS tag: 'Zelenium-0_2_1'
-
- - Correct the emitted HTML for input widgets (close the tr tag).
-
- - Fix unpack bug in code which punts on requests to "foreign" hosts.
-
- - Punt on handling XML-RPC requests (e.g., Epoz calls back to the
- server to run Tidy).
-
- Zelenium-0.2 (2005/04/20)
-
- - CVS tag: 'Zelenium-0_2'
-
- - Added script, 'generator.py', to create Selenium testcase files
- from the request / response logfiles created by tcpwatch.
-
- - Allowed test cases to be PageTemplates, as well as Files, to permit
- indirecting through properties of the test suite (e.g., for
- user id / password).
-
- Zelenium-0.1 (2005/04/15)
-
- - CVS tag: 'Zelenium-0_1'
-
- - Initial release
Deleted: Zelenium/trunk/COPYRIGHT.txt
===================================================================
--- Zelenium/trunk/COPYRIGHT.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/COPYRIGHT.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,15 +0,0 @@
-Zelenium Zope Product
----------------------
-
-Copyright (c) 2005 Zope Corporation and Contributors.
-All Rights Reserved.
-
-This software is subject to the provisions of the Zope Public License,
-Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-FOR A PARTICULAR PURPOSE.
-
-(See selenium/COPYRIGHT.txt for the license pertaining to files in that
-directory).
Deleted: Zelenium/trunk/LICENSE.txt
===================================================================
--- Zelenium/trunk/LICENSE.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/LICENSE.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,58 +0,0 @@
-Zope Public License (ZPL) Version 2.1
-=====================================
-
-A copyright notice accompanies this license document that
-identifies the copyright holders.
-
-This license has been certified as open source. It has also
-been designated as GPL compatible by the Free Software
-Foundation (FSF).
-
-Redistribution and use in source and binary forms, with or
-without modification, are permitted provided that the
-following conditions are met:
-
- - Redistributions in source code must retain the
- accompanying copyright notice, this list of conditions,
- and the following disclaimer.
-
- - Redistributions in binary form must reproduce the accompanying
- copyright notice, this list of conditions, and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
-
- - Names of the copyright holders must not be used to
- endorse or promote products derived from this software
- without prior written permission from the copyright
- holders.
-
- - The right to distribute this software or to use it for
- any purpose does not give you the right to use
- Servicemarks (sm) or Trademarks (tm) of the copyright
- holders. Use of them is covered by separate agreement
- with the copyright holders.
-
- - If any files are modified, you must cause the modified
- files to carry prominent notices stating that you changed
- the files and the date of any change.
-
-Disclaimer
-----------
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS''
-AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
-NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
-NO EVENT SHALL THE COPYRIGHT HOLDERS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-(See selenium/LICENSE.txt for the license pertaining to files in that
-directory).
Modified: Zelenium/trunk/README.txt
===================================================================
--- Zelenium/trunk/README.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/README.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,174 +1,15 @@
Zelenium Product README
+=======================
- Overview
+Overview
+--------
- This product allows developers to create TTW Selenium test suites
- inside their Zope instance, in order to do browser-based functional
- testing of their site.
+This product allows developers to create TTW Selenium test suites
+inside their Zope instance, in order to do browser-based functional
+testing of their site.
+Because it contains third-party code (the Selenium Javascript libraries,
+in particular), licensed under non-ZPL licenses, the trunk of the project
+has moved its development to Launchpad. To check it out::
- Installing the Product
-
- 1. Unpack the tarball in a temporary location.
-
- 2. Copy or move the 'Zelenium' directory to the 'Products' directory
- of your INSTANCE_HOME.
-
- 3. Restart Zope.
-
-
- Using Zelenium
-
- You can add a 'Zuite' object at any location within your Zope
- site. It behaves as a standard ordered folder, with a couple of
- differences:
-
- - It's 'index_html' is the "TestRunner.html" view familiar
- from Selenium.
-
- - It derives the test suite (in the upper left corner iframe)
- from all OFS.Image.File objects whose names start with 'test'.
- You can use the OrderedFolder support to modify the order in
- which the test case files are run.
-
- - It provides a "Zip" action, which allows you to export the
- test suite, all test cases, and the supporting Selenium
- Javascript / CSS files as a single, self-contained zipfile.
-
-
- Reporting Bugs against Zelenium
-
- Please use the "collector",
- http://www.zope.org/Members/tseaver/Zelenium/issues
- to report any bugs you find against the product, as well as to
- submit patches, request features, etc.
-
-
- Adding Tests
-
- Tests are just 'File' instances whose names begin with 'test'.
- They should have a content type of 'text/html', and should contain
- a table which defines the steps which make up the test case.
-
- See http://selenium.thoughtworks.com/testrunner.html for documentation
- on the table structure and the Selenese language.
-
-
- Using Additional Metatypes as Test Cases
-
- On the "Properties" tab of your test suite, you can add / modify
- the list of meta_types which the suite will allow as test cases.
- Adding "Script (Python)", for instance, allows you to define
- test cases in PythonScripts.
-
-
- Nesting Test Suites
-
- Each test suite automatically includes the test cases of any
- suite it contains. You can take advantage of this feature to
- organize your test cases in a hierarchy, running them in separate
- segments, or all at once.
-
- Including Tests from the Filesystem
-
- Test suites now have a property, 'filesystem_path'; if set, the
- suite will recursively load testcases from files in / under the
- directory pointed to by that path.
-
- The list of files to be included is computed via the following
- rules:
-
- - If the testsuite_name property contains the name of a file that
- exists in the directory, it is presumed to contain a list of
- files containing tests, one per line. The test cases will be
- presented in the order indicated in the file, and test cases
- may be included more than once.
-
- - If the testsuite_name property is empty but the directory
- contains a file, '.objects', it is presumed to
- contain a list of files to be included, one per line; only those
- files / subdirectories (if present) will be included. In this case,
- the test cases will be presented in the order indicated in the file,
- followed by any test cases from subdirectories.
-
- - Otherwise, if the suite's property, 'filename_glob' is non-empty,
- it will be expanded (via Python's 'glob.glob') to compute the list
- of filenames. The test cases will be presented in alphabetical
- order, followed by any test cases from subdirectories.
-
- - Otherwise, any file will be considered a testcase. The test cases
- will be presented in alphabetical order, followed by any test cases
- from subdirectories.
-
- Exporting an Archive
-
- On the "Zip" tab, supply a filename and click the "Download" button.
- The Zuite object will construct a zip file with the following
- contents:
-
- 'index.html' -- the "TestRunner.html" framework page
-
- 'TestSuite.html' -- the list of test case files (rendered as
- static HTML)
-
- 'test*" -- your test case files (appending '.html' if the IDs
- do not have extensions)
-
- Each of the supporting '.js' and '.css' files which drive the
- browserbot.
-
-
- Creating a Snapshot
-
- On the "Zip" tab, supply a filename and click the "Download" button.
- The Zuite object will construct a zip file with the same contents
- described above, and then save it as a File object in its own contents.
-
-
- Generating Testcases using tcpwatch
-
- 1. Download the 'tcpwatch' product from Shane Hathaway's site:
-
- http://hathawaymix.org/Software/TCPWatch
-
- 2. Unpack and run tcpwatch in its "HTTP proxy" mode, with recoring
- turned on. E.g., the following command runs the proxy on
- port 9999, recording the request / response data to the directory
- '/tmp/recorded_scenario'::
-
- $ python /path/to/tcpwatch/ tcpwatch.py \
- -p 9999 -r /tmp/recorded_scenario
-
- 3. Configure your browser to use an HTTP proxy on localhost, port 9999.
-
- 4. Click through your site, exercising the features you are testing.
-
- 5. Stop the proxy. Run the 'generator.py' script, pointing to the
- directory where tcpwatch was recording::
-
- $ python /path/to/Zelenium/generator.py \
- --logfile-directory=/tmp/recorded_scenario \
- --output-file=test_case_name.html
-
- 6. Edit the generated test case, removing / correcting the various
- steps.
-
- 7. Upload the test case to a Zelenium Zuite and run it.
-
-
- Capturing Results from the Test Run
-
- Selenium has a feature which allows the testrunner to upload
- result data from an automated test run to the server.
-
- Invoke the test suite from your browser as usual, but append the
- query string '?auto=true', to the URL, e.g.::
-
- http://localhost:8080/test_suite?auto=true
-
- Selenium will run all test cases, and then upload its result data
- to the 'postResults' method of your suite. (Note that you no longer
- need the 'postResults' PythonScript in the root of your site, because
- the latest version of Selenium posts to that name relative to the
- test suite).
-
+ $ bzr co lp:~tseaver/zelenium/trunk
Deleted: Zelenium/trunk/__init__.py
===================================================================
--- Zelenium/trunk/__init__.py 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/__init__.py 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,21 +0,0 @@
-""" Zelenium product initialization
-
-This product uses the Selenium javascript to run browser-driven tests.
-
-$Id$
-"""
-
-import zuite
-import permissions
-
-zelenium_globals = globals()
-
-def initialize(context):
-
- context.registerClass( zuite.Zuite
- , permission=permissions.ManageSeleniumTestCases
- , constructors=( zuite.manage_addZuiteForm
- , zuite.manage_addZuite
- )
- , icon='www/check.gif'
- )
Deleted: Zelenium/trunk/configure.zcml
===================================================================
--- Zelenium/trunk/configure.zcml 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/configure.zcml 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,16 +0,0 @@
-<configure xmlns="http://namespaces.zope.org/zope"
- xmlns:browser="http://namespaces.zope.org/browser">
-
- <browser:defaultView
- for=".interfaces.IZuite"
- name="index_html"
- />
-
- <browser:page
- for=".interfaces.IZuite"
- name="index_html"
- template="www/suiteView.zpt"
- permission="zope2.View"/>
-
-</configure>
-
Deleted: Zelenium/trunk/exclude.txt
===================================================================
--- Zelenium/trunk/exclude.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/exclude.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,5 +0,0 @@
-.css
-.gif
-.ico
-/misc_
-/p_
\ No newline at end of file
Deleted: Zelenium/trunk/generator.py
===================================================================
--- Zelenium/trunk/generator.py 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/generator.py 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,495 +0,0 @@
-""" Script: generator
-
-Generate a Selenium testcase using request / response logiles from tcpwatch.
-
-$Id$
-"""
-
-import sys
-import re
-import getopt
-import glob
-import cgi
-import mimetools
-import urllib
-import urlparse
-import multifile
-import StringIO
-
-_TEST_CASE_HEADER = """\
-<html>
-<head>
-<title>%(TEST_CASE_TITLE)s</title>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
- <tbody>
- <tr>
- <td rowspan="1" colspan="3">%(TEST_CASE_TITLE)s<br>
- </td>
- </tr>
-"""
-
-_TEST_CASE_FOOTER = """
- </tbody>
-</table>
-</body>
-</html>
-"""
-
-_GET_REQUEST_SKELETON = """
- <tr>
- <td>open</td>
- <td>%(REQUEST_URI)s</td>
- <td> </td>
- </tr>
-"""
-
-_POST_REQUEST_SKELETON = """
- <tr>
- <td>click</td>
- <td>submit</td>
- <td> </td>
- </tr>
-"""
-
-_REDIRECT_SKELETON = """
- <tr>
- <td>verifyLocation</td>
- <td>%(REDIRECTED_URL)s</td>
- <td> </td>
- </tr>
-"""
-
-_INPUT_FIELD_SKELETON = """
- <tr>
- <td>type</td>
- <td>%(FIELD_NAME)s</td>
- <td>%(FIELD_VALUE)s</td>
- </tr>
-"""
-
-_SELECT_FIELD_SKELETON = """
- <tr>
- <td>select</td>
- <td>%(FIELD_NAME)s</td>
- <td>%(FIELD_VALUE)s</td>
- </tr>
-"""
-
-class ScenarioGenerator:
- """
- Convert a series of HTTP requests files (as generated by
- LoggingProxy) into a scenario file (to be consumed by
- FT_Runner).
- """
- _verbosity = 1
- _logfile_directory = '/tmp'
- _logfile_prefix = 'watch'
- _logfile_extension_req = 'request'
- _logfile_extension_resp = 'response'
- _output_file = None
- _exclude_patterns = []
- _exclude_file = None
- _exclude_regex = None
- _site_host = None
- _site_path = None
- _test_case_title = None
-
- def __init__( self, args ):
-
- self.parseOptions( args )
-
- def printUsage( self, msg=None ):
- """
- Dump a help message, and bail out.
- """
- sys.stderr.write( """
- %(GENERATOR_EXE)s [-?vq] \\
- [-l log_dir] [-f log_prefix] [-e log_extension] \\
- [-o file] [-x pattern] [-X file] \\
- [-h site_host] [-r site_path]
-
- -?, --help Print this help message
-
- -v, --verbose Increment verbosity (default is '1')
-
- -q, --quiet Set verbosity to '0'
-
- -l, --logfile-directory Directory from which to read log files
- (default '%(LOGFILE_DIRECTORY)s')
-
- -f, --logfile-prefix Prefix for log file names
- (default '%(LOGFILE_PREFIX)s')
-
- -e, --logfile-extension Extension for log file request names
- (default '%(LOGFILE_EXTENSION_REQ)s')
-
- -E, --logfile-response Extension for log file response names
- (default '%(LOGFILE_EXTENSION_RESP)s')
-
- -o, --output-file Write to 'file', instead of default
- (%(LOGFILE_PREFIX)s.zft).
- Use '-' to write to stdout.
-
- -x, --exclude-pattern Exclude requests which match 'pattern'
- (e.g., to suppress stylesheet or images).
-
- -X, --exclude-file Exclude requests which match any pattern
- read from 'file' (one pattern per line).
-
- -h, --site-host Specify the host / port of the site being
- tested.
-
- -p, --site-path Specify the path to the "base" of the
- site being tested.
-
-%(MESSAGE)s\n""" % { 'GENERATOR_EXE' : sys.argv[0]
- , 'LOGFILE_DIRECTORY' : self._logfile_directory
- , 'LOGFILE_PREFIX' : self._logfile_prefix
- , 'LOGFILE_EXTENSION_REQ' : self._logfile_extension_req
- , 'LOGFILE_EXTENSION_RESP' : self._logfile_extension_resp
- , 'MESSAGE' : msg or ''
- } )
- sys.exit( 1 )
-
- def parseOptions( self, args ):
- """
- Parse command-line options.
- """
- verbosity = self._verbosity
- logfile_directory = logfile_prefix = None
- logfile_extension_req = logfile_extension_resp = None
- output_file = exclude_file = site_host = site_path = None
- test_case_title = None
-
- try:
- opts, ignored = getopt.getopt( args
- , "?vql:f:e:E:o:x:X:h:p:T:"
- , [ 'help'
- , 'verbose'
- , 'quiet'
- , 'logfile-directory='
- , 'logfile-prefix='
- , 'logfile-extension='
- , 'logfile-extension-response='
- , 'output-file='
- , 'exclude-pattern'
- , 'exclude-file'
- , 'site-host='
- , 'site-path='
- , 'test-case-title='
- ]
- )
- except getopt.GetoptError, msg:
- self.printUsage( msg=msg)
-
- for o, v in opts:
-
- if o == '-?' or o == '--help':
- self.printUsage()
-
- if o == '-v' or o == '--verbose':
- verbosity = verbosity + 1
-
- if o == '-q' or o == '--quiet':
- verbosity = 0
-
- if o == '-l' or o == '--logfile-directory':
- logfile_directory = v
-
- if o == '-f' or o == '--logfile-prefix':
- logfile_prefix = v
-
- if o == '-e' or o == '--logfile-extension':
- logfile_extension_req = v
-
- if o == '-E' or o == '--logfile-extension-response':
- logfile_extension_resp = v
-
- if o == '-o' or o == '--output-file':
- output_file = v
-
- if o == '-x' or o == '--exclude-pattern':
- self._addExcludePattern( v )
-
- if o == '-X' or o == '--exclude-file':
- exclude_file = v
-
- if o == '-h' or o == '--site-host':
- site_host = v
-
- if o == '-p' or o == '--site-path':
- site_path = v
-
- if o == '-T' or o == '--test-case-title':
- test_case_title = v
-
- self._verbosity = verbosity
-
- if logfile_directory is not None:
- self._logfile_directory = logfile_directory
-
- if logfile_prefix is not None:
- self._logfile_prefix = logfile_prefix
-
- if logfile_extension_req is not None:
- self._logfile_extension_req = logfile_extension_req
-
- if logfile_extension_resp is not None:
- self._logfile_extension_resp = logfile_extension_resp
-
- if site_host is not None:
- self._site_host = site_host
-
- if site_path is not None:
- self._site_path = site_path
-
- if test_case_title is not None:
- self._test_case_title = test_case_title
-
- if output_file == '-':
- self._output_file = sys.stdout
- elif output_file is not None:
- self._output_file = open( output_file, 'w' )
- else:
- self._output_file = sys.stdout
-
- if exclude_file is not None:
- self._exclude_file = exclude_file
-
- def _log( self, msg, level ):
- """
- Write a note to stderr (if verbosity enabled).
- """
- if level <= self._verbosity:
- sys.stderr.write( "%s\n" % msg )
-
- def _print( self, fmt, **kw ):
- """
- Dump the appropriately-formatted values to our output
- file.
- """
- self._output_file.write( fmt % kw )
-
-
- def _addExcludePattern( self, pattern ):
- """
- Add a pattern to our list of excluded patterns.
- """
- self._exclude_patterns.append( r'(%s)' % pattern )
- self._exclude_regex = None
-
- def _getExcludeRegex( self
- ):
- """
- Return a regex which, if matched, indicates that we should
- skip the file.
- """
- if self._exclude_regex is None:
-
- if self._exclude_file:
- f = open( self._exclude_file )
- for line in f.readlines():
- line = line.strip()
- self._addExcludePattern( line )
-
- if self._exclude_patterns:
- self._exclude_regex = re.compile(
- '|'.join( self._exclude_patterns ) )
- return self._exclude_regex
-
- def _stripSitePath(self, uri, parms):
- """
- Strip off our site-host and site-path from 'uri'.
- """
- ( scheme
- , netloc
- , path
- , url_parm
- , query
- , fragment
- ) = urlparse.urlparse( uri )
-
- site_host = urlparse.urlunparse( ( scheme, netloc, '', '', '', '' ) )
-
- if scheme and parms.get( 'site_host' ) is None:
- parms[ 'site_host' ] = site_host
-
- if site_host != parms[ 'site_host' ]: # XXX foreign site! Punt!
- return None, None
-
- if self._site_path and path.startswith( self._site_path ):
- path = path[ len( self._site_path ) : ]
-
- uri = urlparse.urlunparse(
- ( '', '', path, url_parm, query, fragment ) )
-
- return uri, query
-
- def processFile( self
- , infilename
- , outfilename
- , parms={}
- , REQUEST_LINE=re.compile( r'^([^\s]+)\s+'
- r'([^\s]+)\s+'
- r'([^\s]+)$' )
- , RESPONSE_LINE=re.compile( r'^([^\s]+)\s+'
- r'([0-9][0-9][0-9])\s+'
- r'(.*)$' )
- ):
- """
- Process a single request file; record global context
- in parms.
- """
- self._log( 'Scanning request file: %s' % infilename, 1 )
-
- parms[ 'content_type' ] = None
-
- f = open( infilename )
- all_text = f.read()
- body_end = f.tell()
- f.seek( 0 )
-
- exclude = self._getExcludeRegex()
- if exclude is not None and exclude.search( all_text ):
- self._log( '** matches exclude regex, skipping', 1 )
- return
-
- request = f.readline().rstrip()
- match = REQUEST_LINE.match( request )
-
- if not match:
- self._log( 'Invalid request line: %s' % request, 0 )
- return
-
- http_verb, uri, http_version = match.groups()
-
- uri, query = self._stripSitePath( uri, parms )
-
- if uri is None:
- return # XXX foreign site
-
- headers = mimetools.Message( f )
-
- body_start = f.tell()
- content_length = body_end - body_start
-
- content_type = parms[ 'content_type' ] = headers.gettype()
- parms[ 'encoding' ] = headers.getencoding()
-
- cgi_environ = { 'REQUEST_METHOD' : http_verb
- , 'QUERY_STRING' : query
- , 'CONTENT_TYPE' : headers.typeheader
- , 'CONTENT_LENGTH' : content_length
- }
-
- if http_verb == 'POST':
-
- if content_type == 'text/xml': # XXX XML-RPC, punt!
- return
-
- form_data = cgi.FieldStorage( fp=f
- , environ=cgi_environ
- , keep_blank_values=1
- # , headers=headers.dict XXX
- )
- for k in form_data.keys():
-
- v = form_data.getvalue( k )
-
- # TODO: handle uploaded files.
-
- self._print( _INPUT_FIELD_SKELETON
- , FIELD_NAME=k
- , FIELD_VALUE=v
- )
-
- payload = f.read()
- f.close()
-
- self._print( _POST_REQUEST_SKELETON
- , REQUEST_URI=uri
- )
- else:
- self._print( _GET_REQUEST_SKELETON
- , REQUEST_URI=uri
- )
-
- if outfilename:
- self._log( 'Scanning response file: %s' % outfilename, 1 )
- response_file = open( outfilename )
- # could exclude here as well
- status = response_file.readline().rstrip()
- match = RESPONSE_LINE.match( status )
- http_verb, code, reason = match.groups()
- response_headers = mimetools.Message( response_file )
- response_file.close()
- else:
- code = 200
-
- if code in ('301', '302', '307'):
- response_location = response_headers[ 'Location' ]
- response_uri, query = self._stripSitePath( response_location
- , parms
- )
- self._print( _REDIRECT_SKELETON
- , REDIRECTED_URL=response_uri
- )
-
-
- return
-
- def processScenario( self ):
- """
- Read all files in '_logfile_directory' whose prefix
- matches '_logfile_prefix', '_logfile_extension_req', and
- '_logfile_extension_resp';
- create a scenario file with one section per request file,
- dumping to specified output file.
- """
- self._print( _TEST_CASE_HEADER
- , TEST_CASE_TITLE=self._test_case_title or 'TEST CASE'
- )
-
- glob__in_pattern = '%s/%s*.%s' % ( self._logfile_directory
- , self._logfile_prefix
- , self._logfile_extension_req
- )
-
- glob__out_pattern = '%s/%s*.%s' % ( self._logfile_directory
- , self._logfile_prefix
- , self._logfile_extension_resp
- )
-
- parms = { 'site_host' : self._site_host
- , 'site_path' : self._site_path
- }
-
- infilenames = glob.glob( glob__in_pattern )
- infilenames.sort()
- outfilenames = glob.glob( glob__out_pattern )
- outfilenames.sort()
- for infilename in infilenames:
- # find the response file name that matches this request file
- outfilename = re.sub( self._logfile_extension_req + '$'
- , self._logfile_extension_resp
- , infilename
- )
- # XXX error if missing? Optional outfile processing?
- if outfilename in outfilenames:
- self.processFile( infilename
- , outfilename
- , parms
- )
- else:
- self.processFile( infilename
- , None
- , parms
- )
-
- self._print( _TEST_CASE_FOOTER )
-
-if __name__ == '__main__':
-
- ScenarioGenerator( sys.argv[1:] ).processScenario()
Deleted: Zelenium/trunk/interfaces.py
===================================================================
--- Zelenium/trunk/interfaces.py 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/interfaces.py 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,9 +0,0 @@
-""" Zelenium interfaces
-
-$Id$
-"""
-from zope.interface import Interface
-
-class IZuite(Interface):
- """ Marker interface for IZuite objects.
- """
Deleted: Zelenium/trunk/permissions.py
===================================================================
--- Zelenium/trunk/permissions.py 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/permissions.py 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,8 +0,0 @@
-""" Zelenium product permissions
-
-$Id$
-"""
-
-from AccessControl.Permissions import view as View
-
-ManageSeleniumTestCases = 'Manage Selenium test cases'
Deleted: Zelenium/trunk/version.txt
===================================================================
--- Zelenium/trunk/version.txt 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/version.txt 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1 +0,0 @@
-Zelenium-0.8+
Deleted: Zelenium/trunk/zuite.py
===================================================================
--- Zelenium/trunk/zuite.py 2010-04-07 17:22:16 UTC (rev 110603)
+++ Zelenium/trunk/zuite.py 2010-04-07 18:21:23 UTC (rev 110604)
@@ -1,740 +0,0 @@
-""" Classes: Zuite
-
-Zuite instances are collections of Zelenium test cases.
-
-$Id$
-"""
-import glob
-import logging
-import os
-import re
-from urllib import unquote
-import zipfile
-import StringIO
-import types
-
-from zope.interface import implements
-
-from AccessControl.SecurityInfo import ClassSecurityInfo
-from App.special_dtml import DTMLFile
-from App.ImageFile import ImageFile
-from App.config import getConfiguration
-from DateTime.DateTime import DateTime
-from Globals import package_home
-from Globals import InitializeClass
-from OFS.Folder import Folder
-from OFS.Image import File
-from OFS.OrderedFolder import OrderedFolder
-from Products.PageTemplates.PageTemplateFile import PageTemplateFile
-
-from interfaces import IZuite
-from permissions import ManageSeleniumTestCases
-from permissions import View
-
-logger = logging.getLogger('event.Zelenium')
-
-_NOW = None # set only for testing
-
-_PINK_BACKGROUND = re.compile('bgcolor="#ffcfcf"')
-
-_EXCLUDE_NAMES = ( 'CVS', '.svn', '.objects' )
-
-#winzip awaits latin1
-_DEFAULTENCODING = 'latin1'
-
-
-def _getNow():
- if _NOW is not None:
- return _NOW
-
- return DateTime()
-
-_WWW_DIR = os.path.join( package_home( globals() ), 'www' )
-
-#
-# Selenium support files.
-#
-_SUPPORT_DIR = os.path.join( package_home( globals() ), 'selenium' )
-_SUPPORT_FILES = {}
-
-def _makeFile(filename, prefix=None, id=None):
-
- if prefix:
- path = os.path.join( prefix, filename )
- else:
- path = filename
-
- if id is None:
- id = os.path.split( path )[ 1 ]
-
- return File( id=id, title='', file=open(path).read() )
-
-
-def registerFiles(directory, prefix):
- for filename in os.listdir(directory):
- ignored, extension = os.path.splitext(filename)
-
- if extension.lower() in ('.js', '.html', '.css', '.png'):
- _SUPPORT_FILES['%s_%s' % (prefix, filename)] = _makeFile( filename, prefix=directory)
-
-_MARKER = object()
-
-
-def _recurseFSTestCases( result, prefix, fsobjs ):
-
- test_cases = dict( [ ( x.getId(), x )
- for x in fsobjs.get( 'testcases', () ) ] )
- subdirs = fsobjs.get( 'subdirs', {} )
-
- for name in fsobjs.get( 'ordered', [] ):
-
- if name in test_cases:
- test_case = test_cases[ name ]
- name = test_case.getId()
- path = '/'.join( prefix + ( name, ) )
- result.append( { 'id' : name
- , 'title' : test_case.title_or_id()
- , 'url' : path
- , 'path' : path
- , 'test_case' : test_case
- } )
-
- if name in subdirs:
- info = subdirs[ name ]
- _recurseFSTestCases( result
- , prefix + ( name, )
- , info
- )
-
-class Zuite( OrderedFolder ):
- """ TTW-manageable browser test suite
-
- A Zuite instance is an ordered folder, whose 'index_html' provides the
- typical "TestRunner.html" view from Selenium. It generates the
- "TestSuite.html" view from its 'objectItems' list (which allows the
- user to control ordering), selecting File and PageTemplate objects
- whose names start with 'test'.
- """
- meta_type = 'Zuite'
-
- manage_options = ( OrderedFolder.manage_options
- + ( { 'label' : 'Zip', 'action' : 'manage_zipfile' },
- )
- )
-
- implements(IZuite)
-
- test_case_metatypes = ( 'File'
- , 'Page Template'
- )
- filesystem_path = ''
- filename_glob = ''
- testsuite_name = ''
- _v_filesystem_objects = None
- _v_selenium_objects = None
-
- _properties = ( { 'id' : 'test_case_metatypes'
- , 'type' : 'lines'
- , 'mode' : 'w'
- }
- , { 'id' : 'filesystem_path'
- , 'type' : 'string'
- , 'mode' : 'w'
- }
- , { 'id' : 'filename_glob'
- , 'type' : 'string'
- , 'mode' : 'w'
- }
- , { 'id' : 'testsuite_name'
- , 'type' : 'string'
- , 'mode' : 'w'
- }
- )
-
- security = ClassSecurityInfo()
- security.declareObjectProtected( View )
-
- security.declareProtected( ManageSeleniumTestCases, 'manage_main' )
- manage_main = DTMLFile( 'suiteMain', _WWW_DIR )
-
- security.declareProtected( View, 'index_html' )
- index_html = PageTemplateFile( 'suiteView', _WWW_DIR )
-
- security.declareProtected( View, 'test_suite_html' )
- test_suite_html = PageTemplateFile( 'suiteTests', _WWW_DIR )
-
- security.declareProtected( View, 'splash_html' )
- splash_html = PageTemplateFile( 'suiteSplash', _WWW_DIR )
-
- security.declareProtected( View, 'test_prompt_html' )
- test_prompt_html = PageTemplateFile( 'testPrompt', _WWW_DIR )
-
- security.declareProtected(ManageSeleniumTestCases, 'manage_zipfile')
- manage_zipfile = PageTemplateFile( 'suiteZipFile', _WWW_DIR )
-
-
- def __getitem__( self, key, default=_MARKER ):
-
- if key in self.objectIds():
- return self._getOb( key )
-
- if key in _SUPPORT_FILES.keys():
- return _SUPPORT_FILES[ key ].__of__( self )
-
- proxy = _FilesystemProxy( key
- , self._listFilesystemObjects()
- ).__of__( self )
-
- localdefault = object()
-
- value = proxy.get( key, localdefault )
-
- if value is not localdefault:
- return value
-
- proxy = _FilesystemProxy( key
- , self._listSeleniumObjects()
- ).__of__( self )
-
- value = proxy.get( key, default )
-
- if value is not _MARKER:
- return value
-
- raise KeyError, key
-
-
- security.declareProtected( View, 'listTestCases' )
- def listTestCases( self, prefix=() ):
- """ Return a list of our contents which qualify as test cases.
- """
- result = []
- self._recurseListTestCases(result, prefix, self)
- return result
-
- def _recurseListTestCases( self, result, prefix, ob ):
- for tcid, test_case in ob.objectItems():
- if isinstance( test_case, self.__class__ ):
- result.extend( test_case.listTestCases(
- prefix=prefix + ( tcid, ) ) )
- elif test_case.isPrincipiaFolderish:
- self._recurseListTestCases(result, prefix+(tcid,), test_case)
- elif test_case.meta_type in self.test_case_metatypes:
- path = '/'.join( prefix + ( tcid, ) )
- result.append( { 'id' : tcid
- , 'title' : test_case.title_or_id()
- , 'url' : path
- , 'path' : path
- , 'test_case' : test_case
- } )
-
- fsobjs = self._listFilesystemObjects()
-
- _recurseFSTestCases( result, prefix, fsobjs )
-
-
- security.declareProtected(ManageSeleniumTestCases, 'getZipFileName')
- def getZipFileName(self):
- """ Generate a suitable name for the zip file.
- """
- now = _getNow()
- now_str = now.ISO()[:10]
- return '%s-%s.zip' % ( self.getId(), now_str )
-
-
- security.declareProtected(ManageSeleniumTestCases, 'manage_getZipFile')
- def manage_getZipFile( self
- , archive_name=None
- , include_selenium=True
- , RESPONSE=None
- ):
- """ Export the test suite as a zip file.
- """
- if archive_name is None or archive_name.strip() == '':
- archive_name = self.getZipFileName()
-
- bits = self._getZipFile( include_selenium )
-
- if RESPONSE is None:
- return bits
-
- RESPONSE.setHeader('Content-type', 'application/zip')
- RESPONSE.setHeader('Content-length', str( len( bits ) ) )
- RESPONSE.setHeader('Content-disposition',
- 'inline;filename=%s' % archive_name )
- RESPONSE.write(bits)
-
-
- security.declareProtected(ManageSeleniumTestCases, 'manage_createSnapshot')
- def manage_createSnapshot( self
- , archive_name=None
- , include_selenium=True
- , RESPONSE=None
- ):
- """ Save the test suite as a zip file *in the zuite*.
- """
- if archive_name is None or archive_name.strip() == '':
- archive_name = self.getZipFileName()
-
- archive = File( archive_name
- , title=''
- , file=self._getZipFile( include_selenium )
- )
- self._setObject( archive_name, archive )
-
- if RESPONSE is not None:
- RESPONSE.redirect( '%s/manage_main?manage_tabs_message=%s'
- % ( self.absolute_url()
- , 'Snapshot+added'
- ) )
-
-
- security.declarePublic('postResults')
- def postResults(self, REQUEST):
- """ Record the results of a test run.
-
- o Create a folder with properties representing the summary results,
- and files containing the suite and the individual test runs.
-
- o REQUEST will have the following form fields:
-
- result -- one of "failed" or "passed"
-
- totalTime -- time in floating point seconds for the run
-
- numTestPasses -- count of test runs which passed
-
- numTestFailures -- count of test runs which failed
-
- numCommandPasses -- count of commands which passed
-
- numCommandFailures -- count of commands which failed
-
- numCommandErrors -- count of commands raising non-assert errors
-
- suite -- Colorized HTML of the suite table
-
- testTable.<n> -- Colorized HTML of each test run
- """
- completed = DateTime()
- result_id = 'result_%s' % completed.strftime( '%Y%m%d_%H%M%S' )
- self._setObject( result_id, ZuiteResults( result_id ) )
- result = self._getOb( result_id )
- rfg = REQUEST.form.get
- reg = REQUEST.environ.get
-
- result._updateProperty( 'completed'
- , completed
- )
-
- result._updateProperty( 'passed'
- , rfg( 'result' ).lower() == 'passed'
- )
-
- result._updateProperty( 'time_secs'
- , float( rfg( 'totalTime', 0 ) )
- )
-
- result._updateProperty( 'tests_passed'
- , int( rfg( 'numTestPasses', 0 ) )
- )
-
- result._updateProperty( 'tests_failed'
- , int( rfg( 'numTestFailures', 0 ) )
- )
-
- result._updateProperty( 'commands_passed'
- , int( rfg( 'numCommandPasses', 0 ) )
- )
-
- result._updateProperty( 'commands_failed'
- , int( rfg( 'numCommandFailures', 0 ) )
- )
-
- result._updateProperty( 'commands_with_errors'
- , int( rfg( 'numCommandErrors', 0 ) )
- )
-
- result._updateProperty( 'user_agent'
- , reg( 'HTTP_USER_AGENT', 'unknown' )
- )
-
- result._updateProperty( 'remote_addr'
- , reg( 'REMOTE_ADDR', 'unknown' )
- )
-
- result._updateProperty( 'http_host'
- , reg( 'HTTP_HOST', 'unknown' )
- )
-
- result._updateProperty( 'server_software'
- , reg( 'SERVER_SOFTWARE', 'unknown' )
- )
-
- result._updateProperty( 'product_info'
- , self._listProductInfo()
- )
-
- result._setObject( 'suite.html'
- , File( 'suite.html'
- , 'Test Suite'
- , unquote( rfg( 'suite' ) )
- , 'text/html'
- )
- )
-
- test_ids = [ x for x in REQUEST.form.keys()
- if x.startswith( 'testTable' ) ]
- test_ids.sort()
-
- for test_id in test_ids:
- body = unquote( rfg( test_id ) )
- result._setObject( test_id
- , File( test_id
- , 'Test case: %s' % test_id
- , body
- , 'text/html'
- ) )
- testcase = result._getOb( test_id )
-
- # XXX: this is silly, but we have no other metadata.
- testcase._setProperty( 'passed'
- , _PINK_BACKGROUND.search( body ) is None
- , 'boolean'
- )
-
-
- #
- # Helper methods
- #
- security.declarePrivate('_listFilesystemObjects')
- def _listFilesystemObjects( self ):
- """ Return a mapping of any filesystem objects we "hold".
- """
- if ( self._v_filesystem_objects is not None and
- not getConfiguration().debug_mode ):
- return self._v_filesystem_objects
-
- if not self.filesystem_path:
- return { 'testcases' : (), 'subdirs' : {} }
-
- path = os.path.abspath( self.filesystem_path )
-
- self._v_filesystem_objects = self._grubFilesystem( path )
- return self._v_filesystem_objects
-
- security.declarePrivate('_listSeleniumObjects')
- def _listSeleniumObjects( self ):
- """ Return a mapping of any filesystem objects we "hold".
- """
- if ( self._v_selenium_objects is not None and
- not getConfiguration().debug_mode ):
- return self._v_selenium_objects
-
- self._v_selenium_objects = self._grubFilesystem(_SUPPORT_DIR)
- return self._v_selenium_objects
-
- security.declarePrivate('_grubFilesystem')
- def _grubFilesystem( self, path ):
-
- info = { 'testcases' : (), 'subdirs' : {} }
-
- # Look for a specified test suite
- # or a '.objects' file with an explicit manifiest
- manifest = os.path.join( path, self.testsuite_name or '.objects' )
-
- if os.path.isfile( manifest ):
- filenames = filter(None,[ x.strip() for x in open( manifest ).readlines() ])
-
- elif self.filename_glob:
- globbed = glob.glob( os.path.join( path, self.filename_glob ) )
- filenames = [ os.path.split( x )[ 1 ] for x in globbed ]
-
- else: # guess
- filenames = [ x for x in os.listdir( path )
- if x not in _EXCLUDE_NAMES ]
- filenames.sort()
-
- info[ 'ordered' ] = filenames
-
- for name in filenames:
-
- fqfn = os.path.join( path, name )
-
- if os.path.isfile( fqfn ):
- testcase = _makeFile( fqfn )
- info[ 'testcases' ] += ( testcase, )
-
- elif os.path.isdir( fqfn ):
- info[ 'subdirs' ][ name ] = self._grubFilesystem( fqfn )
-
- else:
-
- logger.warning(
- '%r was neither a file nor directory and so has been ignored',
- fqfn
- )
-
- return info
-
-
- security.declarePrivate('_getFilename')
- def _getFilename(self, name):
- """ Convert 'name' to a suitable filename, if needed.
- """
- if '.' not in name:
- return '%s.html' % name
-
- return name
-
-
- security.declarePrivate( '_getZipFile' )
- def _getZipFile( self, include_selenium=True ):
- """ Generate a zip file containing both tests and scaffolding.
- """
- stream = StringIO.StringIO()
- archive = zipfile.ZipFile( stream, 'w' )
-
-
- def convertToBytes(body):
- if isinstance(body, types.UnicodeType):
- return body.encode(_DEFAULTENCODING)
- else:
- return body
-
- archive.writestr( 'index.html'
- , convertToBytes(self.index_html( suite_name='testSuite.html' ) ) )
-
- test_cases = self.listTestCases()
-
- paths = { '' : [] }
-
- def _ensurePath( prefix, element ):
- elements = paths.setdefault( prefix, [] )
- if element not in elements:
- elements.append( element )
-
- for info in test_cases:
- # ensure suffixes
- path = self._getFilename( info[ 'path' ] )
- info[ 'path' ] = path
- info[ 'url' ] = self._getFilename( info[ 'url' ] )
-
- elements = path.split( os.path.sep )
- _ensurePath( '', elements[ 0 ] )
-
- for i in range( 1, len( elements ) ):
- prefix = '/'.join( elements[ : i ] )
- _ensurePath( prefix, elements[ i ] )
-
- archive.writestr( 'testSuite.html'
- , convertToBytes(self.test_suite_html( test_cases=test_cases ) ) )
-
- for pathname, filenames in paths.items():
-
- if pathname == '':
- filename = '.objects'
- else:
- filename = '%s/.objects' % pathname
-
- archive.writestr( convertToBytes(filename)
- , convertToBytes(u'\n'.join( filenames ) ) )
-
- for info in test_cases:
- test_case = info[ 'test_case' ]
-
- if getattr( test_case, '__call__', None ) is not None:
- body = test_case() # XXX: DTML?
- else:
- body = test_case.manage_FTPget()
-
- archive.writestr( convertToBytes(info[ 'path' ])
- , convertToBytes(body) )
-
- if include_selenium:
-
- for k, v in _SUPPORT_FILES.items():
- archive.writestr( convertToBytes(k),
- convertToBytes(v.__of__(self).manage_FTPget() ) )
-
- archive.close()
- return stream.getvalue()
-
- security.declarePrivate('_listProductInfo')
- def _listProductInfo( self ):
- """ Return a list of strings of form '%(name)s %(version)s'.
-
- o Each line describes one product installed in the Control_Panel.
- """
- result = []
- cp = self.getPhysicalRoot().Control_Panel
- products = cp.Products.objectItems()
- products.sort()
-
- for product_name, product in products:
- version = product.version or 'unreleased'
- result.append( '%s %s' % ( product_name, version ) )
-
- return result
-
-
-InitializeClass( Zuite )
-
-
-class ZuiteResults( Folder ):
-
- security = ClassSecurityInfo()
- meta_type = 'Zuite Results'
-
- _properties = ( { 'id' : 'test_case_metatypes'
- , 'type' : 'lines'
- , 'mode' : 'w'
- },
- { 'id' : 'completed'
- , 'type' : 'date'
- , 'mode' : 'w'
- },
- { 'id' : 'passed'
- , 'type' : 'boolean'
- , 'mode' : 'w'
- },
- { 'id' : 'time_secs'
- , 'type' : 'float'
- , 'mode' : 'w'
- },
- { 'id' : 'tests_passed'
- , 'type' : 'int'
- , 'mode' : 'w'
- },
- { 'id' : 'tests_failed'
- , 'type' : 'int'
- , 'mode' : 'w'
- },
- { 'id' : 'commands_passed'
- , 'type' : 'int'
- , 'mode' : 'w'
- },
- { 'id' : 'commands_failed'
- , 'type' : 'int'
- , 'mode' : 'w'
- },
- { 'id' : 'commands_with_errors'
- , 'type' : 'int'
- , 'mode' : 'w'
- },
- { 'id' : 'user_agent'
- , 'type' : 'string'
- , 'mode' : 'w'
- },
- { 'id' : 'remote_addr'
- , 'type' : 'string'
- , 'mode' : 'w'
- },
- { 'id' : 'http_host'
- , 'type' : 'string'
- , 'mode' : 'w'
- },
- { 'id' : 'server_software'
- , 'type' : 'string'
- , 'mode' : 'w'
- },
- { 'id' : 'product_info'
- , 'type' : 'lines'
- , 'mode' : 'w'
- },
- )
-
- security.declareObjectProtected( View )
-
- security.declarePublic( 'index_html' )
- index_html = PageTemplateFile( 'resultsView', _WWW_DIR )
-
- security.declareProtected( View, 'error_icon' )
- error_icon = ImageFile( 'error.gif', _WWW_DIR )
-
- security.declareProtected( View, 'check_icon' )
- check_icon = ImageFile( 'check.gif', _WWW_DIR )
-
-
- def __getitem__( self, key, default=_MARKER ):
-
- if key in self.objectIds():
- return self._getOb( key )
-
- if key == 'error.gif':
- return self.error_icon
-
- if key == 'check.gif':
- return self.check_icon
-
- if default is not _MARKER:
- return default
-
- raise KeyError, key
-
-InitializeClass( ZuiteResults )
-
-class _FilesystemProxy( Folder ):
-
- security = ClassSecurityInfo()
-
- def __init__( self, id, fsobjs ):
-
- self._setId( id )
- self._fsobjs = fsobjs
-
- def __getitem__( self, key ):
-
- return self.get( key )
-
- security.declareProtected( View, 'index_html' )
- index_html = PageTemplateFile( 'suiteView', _WWW_DIR )
-
- security.declareProtected( View, 'test_suite_html' )
- test_suite_html = PageTemplateFile( 'suiteTests', _WWW_DIR )
-
- security.declareProtected( View, 'get' )
- def get( self, key, default=_MARKER ):
-
- for tc in self._fsobjs[ 'testcases' ]:
- if tc.getId() == key:
- return tc.__of__( self.aq_parent )
-
- if key in self._fsobjs[ 'subdirs' ]:
- return self.__class__( key, self._fsobjs[ 'subdirs' ][ key ]
- ).__of__( self.aq_parent )
-
- if key in _SUPPORT_FILES.keys():
- return _SUPPORT_FILES[ key ].__of__( self )
-
- if default is not _MARKER:
- return default
-
- raise KeyError, key
-
- security.declareProtected( View, 'listTestCases' )
- def listTestCases( self, prefix=() ):
- """ Return a list of our contents which qualify as test cases.
- """
- result = []
- _recurseFSTestCases( result, prefix, self._fsobjs )
- return result
-
-InitializeClass( _FilesystemProxy )
-
-#
-# Factory methods
-#
-manage_addZuiteForm = PageTemplateFile( 'addZuite', _WWW_DIR )
-
-def manage_addZuite(dispatcher, id, title='', REQUEST=None):
- """ Add a new Zuite to dispatcher's objects.
- """
- zuite = Zuite(id)
- zuite.title = title
- dispatcher._setObject(id, zuite)
- zuite = dispatcher._getOb(id)
-
- if REQUEST is not None:
- REQUEST['RESPONSE'].redirect('%s/manage_main'
- % zuite.absolute_url() )
More information about the checkins
mailing list