[Checkins]
SVN: zope.testbrowser/branches/benji-reduce-testing-dependencies/
rework zope.testbrowser testing;
will eventually allow the different flavors of
Benji York
benji at zope.com
Mon Sep 17 06:34:53 EDT 2007
Log message for revision 79707:
rework zope.testbrowser testing; will eventually allow the different flavors of
testbrowser to all run the same tests; also helps with the required packages
trimming
Changed:
U zope.testbrowser/branches/benji-reduce-testing-dependencies/README.txt
U zope.testbrowser/branches/benji-reduce-testing-dependencies/buildout.cfg
U zope.testbrowser/branches/benji-reduce-testing-dependencies/setup.py
U zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/README.txt
A zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/Zope.txt
U zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/browser.py
U zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/forms.html
A zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/index.html
U zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/navigate.html
D zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/simple.html
A zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/target.html
A zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/headers.txt
U zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/tests.py
A zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/zopetests.py
-=-
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/README.txt
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/README.txt 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/README.txt 2007-09-17 10:34:53 UTC (rev 79707)
@@ -1,11 +1,17 @@
Overview
========
-``zope.testbrowser`` provides an easy-to-use programmable web browser
-with special focus on testing. It is used in Zope, but it's not Zope
-specific at all. For instance, it can be used to test or otherwise
-interact with any web site.
+The zope.testbrowser package provides web user agents (browsers) with
+programmatic interfaces designed to be used for testing web applications,
+especially in conjunction with doctests. This project originates in the Zope 3
+community, but is not Zope-specific.
+There are currently three type of testbrowser provided. One for accessing web
+sites via HTTP (zope.testbrowser.browser), one for directly accessing a Zope 3
+application (zope.testbrowser.testing), and one that controls a Firefox web
+browser (zope.testbrowser.real).
+
+
Changes
=======
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/buildout.cfg
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/buildout.cfg 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/buildout.cfg 2007-09-17 10:34:53 UTC (rev 79707)
@@ -1,29 +1,34 @@
[buildout]
develop = .
-parts = test
+parts = test-zope test-no-zope
versions = versions
find-links = http://download.zope.org/distribution/
-[test]
+[test-zope]
recipe = zc.recipe.testrunner
-defaults = ['--tests-pattern', '^f?tests$']
+defaults = ['--tests-pattern', '^zopetests$', '-1', '--auto-color']
eggs = zope.testbrowser [zope]
+[test-no-zope]
+recipe = zc.recipe.testrunner
+defaults = ['-1', '--auto-color']
+eggs = zope.testbrowser
+
[versions]
ClientForm = 0.2.7
RestrictedPython = 3.4.2
-ZConfig = 2.4a6
+ZConfig = 2.5
ZODB3 = 3.9.0-dev-r77011
docutils = 0.4
mechanize = 0.1.7b
pytz = 2007f
-setuptools = 0.6c6
+setuptools = 0.6c7
zc.buildout = 1.0.0b30
zc.recipe.egg = 1.0.0b6
zc.recipe.testrunner = 1.0.0b8
zdaemon = 2.0.0
zodbcode = 3.4.0b1dev-r75670
-zope.annotation = 3.4.0b1.dev-r75758
+zope.annotation = 3.4.0
zope.app.applicationcontrol = 3.4-dev-r73715
zope.app.appsetup = 3.4.0a1
zope.app.authentication = 3.4.0b1
@@ -54,14 +59,14 @@
zope.app.securitypolicy = 3.4.0a1
zope.app.session = 3.5.0dev-r77333
zope.app.testing = 3.4.0b1-r78707
-zope.app.wsgi = 3.4.0b1dev-r75415
+zope.app.wsgi = 3.4.0
zope.app.zapi = 3.4.0a1
zope.app.zcmlfiles = 3.4.0a1
zope.app.zopeappgenerations = 3.4.0a1
-zope.cachedescriptors = 3.4.0b1-r75830
+zope.cachedescriptors = 3.4.0
zope.component = 3.4.0a1
zope.configuration = 3.4.0b1
-zope.contenttype = 3.4.0a1
+zope.contenttype = 3.4.0
zope.copypastemove = 3.4.0a1
zope.datetime = 3.4.0
zope.deferredimport = 3.4.0
@@ -76,9 +81,9 @@
zope.i18n = 3.4.0b5.dev-r78840
zope.i18nmessageid = 3.4.0
zope.interface = 3.4.0
-zope.lifecycleevent = 3.4.0a1
+zope.lifecycleevent = 3.4.0
zope.location = 3.4.0b2
-zope.minmax = 1.0b1
+zope.minmax = 1.0b2
zope.modulealias = 3.4.0a1
zope.pagetemplate = 3.4.0a1
zope.proxy = 3.4.0
@@ -86,7 +91,7 @@
zope.schema = 3.4.0b1dev-r77624
zope.security = 3.4.0b5
zope.size = 3.4.0
-zope.structuredtext = 3.4.0a1
+zope.structuredtext = 3.4.0
zope.tal = 3.4.0b1
zope.tales = 3.4.0a1
zope.testing = 3.5.1
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/setup.py
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/setup.py 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/setup.py 2007-09-17 10:34:53 UTC (rev 79707)
@@ -30,7 +30,8 @@
version = '3.4.2dev',
url = 'http://pypi.python.org/pypi/zope.testbrowser',
license = 'ZPL 2.1',
- description = 'Programmable browser for functional black-box tests',
+ description = 'Programmable browser for functional black-box tests'
+ ' (not Zope-specific)',
author = 'Zope Corporation and Contributors',
author_email = 'zope3-dev at zope.org',
long_description = long_description,
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/README.txt
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/README.txt 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/README.txt 2007-09-17 10:34:53 UTC (rev 79707)
@@ -1,42 +1,17 @@
Detailed Documentation
======================
-The ``zope.testbrowser.browser`` module exposes a ``Browser`` class that
-simulates a web browser similar to Mozilla Firefox or IE.
+Before being of much interest, we need to open a web page. ``Browser``
+instances have a ``base`` attribute that sets the URL from which ``open``ed
+URLs are relative. This lets you target tests at servers running in various,
+or even variable locations (like using randomly chosen ports).
- >>> from zope.testbrowser.browser import Browser
>>> browser = Browser()
-
-This version of the browser object can be used to access any web site just as
-you would do using a normal web browser.
-
-There is also a special version of the ``Browser`` class used to do functional
-testing of Zope 3 applications, it can be imported from
-``zope.testbrowser.testing``:
-
- >>> from zope.testbrowser.testing import Browser
- >>> browser = Browser()
-
-An initial page to load can be passed to the ``Browser`` constructor:
-
- >>> browser = Browser('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.base = 'http://localhost:%s/' % TEST_PORT
+ >>> browser.open('index.html')
>>> browser.url
- 'http://localhost/@@/testbrowser/simple.html'
+ 'http://localhost:.../index.html'
-The browser can send arbitrary headers; this is helpful for setting the
-"Authorization" header or a language value, so that your tests format values
-the way you expect in your tests, if you rely on zope.i18n locale-based
-formatting or a similar approach.
-
- >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
- >>> browser.addHeader('Accept-Language', 'en-US')
-
-An existing browser instance can also `open` web pages:
-
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
- >>> browser.url
- 'http://localhost/@@/testbrowser/simple.html'
-
Once you have opened a web page initially, best practice for writing
testbrowser doctests suggests using 'click' to navigate further (as discussed
below), except in unusual circumstances.
@@ -44,9 +19,9 @@
The test browser complies with the IBrowser interface; see
``zope.testbrowser.interfaces`` for full details on the interface.
- >>> from zope.testbrowser import interfaces
+ >>> import zope.testbrowser.interfaces
>>> from zope.interface.verify import verifyObject
- >>> verifyObject(interfaces.IBrowser, browser)
+ >>> verifyObject(zope.testbrowser.interfaces.IBrowser, browser)
True
@@ -85,90 +60,61 @@
Not all URLs return HTML. Of course our simple page does:
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
>>> browser.isHtml
True
But if we load an image (or other binary file), we do not get HTML:
- >>> browser.open('http://localhost/@@/testbrowser/zope3logo.gif')
+ >>> browser.open('zope3logo.gif')
>>> browser.isHtml
False
-
HTML Page Title
----------------
Another useful helper property is the title:
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.open('index.html')
>>> browser.title
'Simple Page'
If a page does not provide a title, it is simply ``None``:
- >>> browser.open('http://localhost/@@/testbrowser/notitle.html')
+ >>> browser.open('notitle.html')
>>> browser.title
However, if the output is not HTML, then an error will occur trying to access
the title:
- >>> browser.open('http://localhost/@@/testbrowser/zope3logo.gif')
+ >>> browser.open('zope3logo.gif')
>>> browser.title
Traceback (most recent call last):
...
BrowserStateError: not viewing HTML
-Headers
--------
-
-As you can see, the `contents` of the browser does not return any HTTP
-headers. The headers are accessible via a separate attribute, which is an
-``httplib.HTTPMessage`` instance (httplib is a part of Python's standard
-library):
-
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
- >>> browser.headers
- <httplib.HTTPMessage instance...>
-
-The headers can be accessed as a string:
-
- >>> print browser.headers
- Status: 200 OK
- Content-Length: 123
- Content-Type: text/html;charset=utf-8
- X-Powered-By: Zope (www.zope.org), Python (www.python.org)
-
-Or as a mapping:
-
- >>> browser.headers['content-type']
- 'text/html;charset=utf-8'
-
-
Navigation and Link Objects
---------------------------
-If you want to simulate clicking on a link, get the link and `click` on it.
-In the `navigate.html` file there are several links set up to demonstrate the
-capabilities of the link objects and their `click` method.
+If you want to simulate clicking on a link, get the link and call its `click`
+method. In the `navigate.html` file there are several links set up to
+demonstrate the capabilities of the link objects and their `click` method.
The simplest way to get a link is via the anchor text. In other words
the text you would see in a browser (text and url searches are substring
searches):
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> browser.contents
- '...<a href="navigate.html?message=By+Link+Text">Link Text</a>...'
+ '...<a href="target.html">Link Text</a>...'
>>> link = browser.getLink('Link Text')
>>> link
- <Link text='Link Text'
- url='http://localhost/@@/testbrowser/navigate.html?message=By+Link+Text'>
+ <Link text='Link Text' url='http://localhost:.../target.html'>
Link objects comply with the ILink interface.
- >>> verifyObject(interfaces.ILink, link)
+ >>> verifyObject(zope.testbrowser.interfaces.ILink, link)
True
Links expose several attributes for easy access.
@@ -177,22 +123,22 @@
'Link Text'
>>> link.tag # links can also be image maps.
'a'
- >>> link.url # it's normalized
- 'http://localhost/@@/testbrowser/navigate.html?message=By+Link+Text'
+ >>> link.url # normalized to an absolute URL
+ 'http://localhost:.../target.html'
>>> link.attrs
- {'href': 'navigate.html?message=By+Link+Text'}
+ {'href': 'target.html'}
Links can be "clicked" and the browser will navigate to the referenced URL.
>>> link.click()
>>> browser.url
- 'http://localhost/@@/testbrowser/navigate.html?message=By+Link+Text'
+ 'http://localhost:.../target.html'
>>> browser.contents
- '...Message: <em>By Link Text</em>...'
+ '...This page is the target of a link...'
When finding a link by its text, whitespace is normalized.
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> browser.contents
'...> Link Text \n with Whitespace\tNormalization (and parens) </...'
>>> link = browser.getLink('Link Text with Whitespace Normalization '
@@ -203,14 +149,13 @@
'Link Text with Whitespace Normalization (and parens)'
>>> link.click()
>>> browser.url
- 'http://localhost/@@/testbrowser/navigate.html?message=By+Link+Text+with+Normalization'
- >>> browser.contents
- '...Message: <em>By Link Text with Normalization</em>...'
+ 'http://localhost:.../target.html'
When a link text matches more than one link, by default the first one is
chosen. You can, however, specify the index of the link and thus retrieve a
later matching link:
+ >>> browser.open('navigate.html')
>>> browser.getLink('Link Text')
<Link text='Link Text' ...>
@@ -225,48 +170,38 @@
...
ExpiredError
-You can also find the link by its URL,
+You can also find links by URL,
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
- >>> browser.contents
- '...<a href="navigate.html?message=By+URL">Using the URL</a>...'
-
- >>> browser.getLink(url='?message=By+URL').click()
+ >>> browser.open('navigate.html')
+ >>> browser.getLink(url='target.html').click()
>>> browser.url
- 'http://localhost/@@/testbrowser/navigate.html?message=By+URL'
- >>> browser.contents
- '...Message: <em>By URL</em>...'
+ 'http://localhost:.../target.html'
or its id:
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> browser.contents
- '...<a href="navigate.html?message=By+Id"
- id="anchorid">By Anchor Id</a>...'
+ '...<a href="target.html" id="anchorid">By Anchor Id</a>...'
>>> browser.getLink(id='anchorid').click()
>>> browser.url
- 'http://localhost/@@/testbrowser/navigate.html?message=By+Id'
- >>> browser.contents
- '...Message: <em>By Id</em>...'
+ 'http://localhost:.../target.html'
You thought we were done here? Not so quickly. The `getLink` method also
supports image maps, though not by specifying the coordinates, but using the
area's id:
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> link = browser.getLink(id='zope3')
>>> link.tag
'area'
>>> link.click()
>>> browser.url
- 'http://localhost/@@/testbrowser/navigate.html?message=Zope+3+Name'
- >>> browser.contents
- '...Message: <em>Zope 3 Name</em>...'
+ 'http://localhost:.../target.html'
Getting a nonexistent link raises an exception.
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> browser.getLink('This does not exist')
Traceback (most recent call last):
...
@@ -278,21 +213,21 @@
Like in any normal browser, you can reload a page:
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.open('index.html')
>>> browser.url
- 'http://localhost/@@/testbrowser/simple.html'
+ 'http://localhost:.../index.html'
>>> browser.reload()
>>> browser.url
- 'http://localhost/@@/testbrowser/simple.html'
+ 'http://localhost:.../index.html'
You can also go back:
- >>> browser.open('http://localhost/@@/testbrowser/notitle.html')
+ >>> browser.open('notitle.html')
>>> browser.url
- 'http://localhost/@@/testbrowser/notitle.html'
+ 'http://localhost:.../notitle.html'
>>> browser.goBack()
>>> browser.url
- 'http://localhost/@@/testbrowser/simple.html'
+ 'http://localhost:.../index.html'
Controls
@@ -302,7 +237,7 @@
and fill in values for the controls of input forms. To do so, let's first open
a page that has a bunch of controls:
- >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+ >>> browser.open('controls.html')
Obtaining a Control
~~~~~~~~~~~~~~~~~~~
@@ -449,7 +384,7 @@
>>> ctrl = browser.getControl('Text Control')
>>> ctrl
<Control name='text-value' type='text'>
- >>> verifyObject(interfaces.IControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IControl, ctrl)
True
They have several useful attributes:
@@ -492,7 +427,7 @@
False
>>> ctrl.multiple
True
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
- 'options' lists all available value options.
@@ -562,7 +497,8 @@
'2'
>>> browser.getControl('Zwei').selected
True
- >>> verifyObject(interfaces.IItemControl, browser.getControl('Zwei'))
+ >>> verifyObject(zope.testbrowser.interfaces.IItemControl,
+ ... browser.getControl('Zwei'))
True
>>> browser.getControl('Ein').selected = True
>>> browser.getControl('Ein').selected
@@ -594,7 +530,7 @@
>>> ctrl = browser.getControl('Password Control')
>>> ctrl
<Control name='password-value' type='password'>
- >>> verifyObject(interfaces.IControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IControl, ctrl)
True
>>> ctrl.value
'Password'
@@ -611,7 +547,7 @@
>>> ctrl = browser.getControl(name='hidden-value')
>>> ctrl
<Control name='hidden-value' type='hidden'>
- >>> verifyObject(interfaces.IControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IControl, ctrl)
True
>>> ctrl.value
'Hidden'
@@ -626,7 +562,7 @@
>>> ctrl = browser.getControl('Text Area Control')
>>> ctrl
<Control name='textarea-value' type='textarea'>
- >>> verifyObject(interfaces.IControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IControl, ctrl)
True
>>> ctrl.value
' Text inside\n area!\n '
@@ -650,7 +586,7 @@
>>> ctrl = browser.getControl('File Control')
>>> ctrl
<Control name='file-value' type='file'>
- >>> verifyObject(interfaces.IControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IControl, ctrl)
True
>>> ctrl.value is None
True
@@ -672,7 +608,7 @@
>>> ctrl = browser.getControl('Single Select Control')
>>> ctrl
<ListControl name='single-select-value' type='select'>
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
>>> ctrl.value
['1']
@@ -708,7 +644,7 @@
>>> ctrl = browser.getControl(name='single-unvalued-checkbox-value')
>>> ctrl
<ListControl name='single-unvalued-checkbox-value' type='checkbox'>
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
>>> ctrl.value
True
@@ -724,7 +660,7 @@
>>> ctrl.displayValue
[]
>>> verifyObject(
- ... interfaces.IItemControl,
+ ... zope.testbrowser.interfaces.IItemControl,
... browser.getControl('Single Unvalued Checkbox'))
True
>>> browser.getControl('Single Unvalued Checkbox').optionValue
@@ -750,7 +686,7 @@
>>> ctrl = browser.getControl(name='single-valued-checkbox-value')
>>> ctrl
<ListControl name='single-valued-checkbox-value' type='checkbox'>
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
>>> ctrl.value
['1']
@@ -766,7 +702,7 @@
>>> ctrl.displayValue
[]
>>> verifyObject(
- ... interfaces.IItemControl,
+ ... zope.testbrowser.interfaces.IItemControl,
... browser.getControl('Single Valued Checkbox'))
True
>>> browser.getControl('Single Valued Checkbox').selected
@@ -789,7 +725,7 @@
>>> ctrl = browser.getControl(name='multi-checkbox-value')
>>> ctrl
<ListControl name='multi-checkbox-value' type='checkbox'>
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
>>> ctrl.value
['1', '3']
@@ -811,7 +747,8 @@
'2'
>>> browser.getControl('Two').selected
True
- >>> verifyObject(interfaces.IItemControl, browser.getControl('Two'))
+ >>> verifyObject(zope.testbrowser.interfaces.IItemControl,
+ ... browser.getControl('Two'))
True
>>> browser.getControl('Three').selected = True
>>> browser.getControl('Three').selected
@@ -861,7 +798,7 @@
>>> ctrl
<ListControl name='radio-value' type='radio'>
- >>> verifyObject(interfaces.IListControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IListControl, ctrl)
True
>>> ctrl.disabled
False
@@ -884,7 +821,7 @@
>>> ctrl = browser.getControl(name='image-value')
>>> ctrl
<ImageControl name='image-value' type='image'>
- >>> verifyObject(interfaces.IImageSubmitControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.IImageSubmitControl, ctrl)
True
>>> ctrl.value
''
@@ -904,7 +841,7 @@
<SubmitControl name='submit-value' type='submit'>
>>> browser.getControl('Submit') # multiple labels, but same control
<SubmitControl name='submit-value' type='submit'>
- >>> verifyObject(interfaces.ISubmitControl, ctrl)
+ >>> verifyObject(zope.testbrowser.interfaces.ISubmitControl, ctrl)
True
>>> ctrl.value
'Submit This'
@@ -920,21 +857,13 @@
>>> browser.getControl('Text Control').value = 'Other Text'
>>> browser.getControl('Submit').click()
- >>> print browser.contents
- <html>
- ...
- <em>Other Text</em>
- <input type="text" name="text-value" id="text-value" value="Some Text" />
- ...
- <em>Submit This</em>
- <input type="submit" name="submit-value" id="submit-value" value="Submit This" />
- ...
- </html>
+ >>> browser.contents
+ "...'text-value': ['Other Text']..."
Note that if you click a submit object after the associated page has expired,
you will get an error.
- >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+ >>> browser.open('controls.html')
>>> ctrl = browser.getControl('Submit')
>>> ctrl.click()
>>> ctrl.click()
@@ -944,23 +873,13 @@
All the above also holds true for the image control:
- >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+ >>> browser.open('controls.html')
>>> browser.getControl('Text Control').value = 'Other Text'
>>> browser.getControl(name='image-value').click()
- >>> print browser.contents
- <html>
- ...
- <em>Other Text</em>
- <input type="text" name="text-value" id="text-value" value="Some Text" />
- ...
- <em>1</em>
- <em>1</em>
- <input type="image" name="image-value" id="image-value"
- src="zope3logo.gif" />
- ...
- </html>
+ >>> browser.contents
+ "...'text-value': ['Other Text']..."
- >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+ >>> browser.open('controls.html')
>>> ctrl = browser.getControl(name='image-value')
>>> ctrl.click()
>>> ctrl.click()
@@ -970,19 +889,11 @@
But when sending an image, you can also specify the coordinate you clicked:
- >>> browser.open('http://localhost/@@/testbrowser/controls.html')
+ >>> browser.open('controls.html')
>>> browser.getControl(name='image-value').click((50,25))
- >>> print browser.contents
- <html>
- ...
- <em>50</em>
- <em>25</em>
- <input type="image" name="image-value" id="image-value"
- src="zope3logo.gif" />
- ...
- </html>
+ >>> browser.contents
+ "...'image-value.x': ['50']...'image-value.y': ['25']..."
-
Forms
-----
@@ -991,12 +902,12 @@
be used to do so. The key value is the form's name or id. If more than one
form has the same name or id, the first one will be returned.
- >>> browser.open('http://localhost/@@/testbrowser/forms.html')
+ >>> browser.open('forms.html')
>>> form = browser.getForm(name='one')
Form instances conform to the IForm interface.
- >>> verifyObject(interfaces.IForm, form)
+ >>> verifyObject(zope.testbrowser.interfaces.IForm, form)
True
The form exposes several attributes related to forms:
@@ -1014,7 +925,7 @@
- The action (target URL) when the form is submitted:
>>> form.action
- 'http://localhost/@@/testbrowser/forms.html'
+ 'http://localhost:.../forms.html'
- The method (HTTP verb) used to transmit the form data:
@@ -1024,7 +935,7 @@
- The encoding type of the form data:
>>> form.enctype
- 'multipart/form-data'
+ 'application/x-www-form-urlencoded'
Besides those attributes, you have also a couple of methods. Like for the
browser, you can get control objects, but limited to the current form...
@@ -1035,12 +946,8 @@
...and submit the form.
>>> form.submit('Submit')
- >>> print browser.contents
- <html>
- ...
- <em>First Text</em>
- ...
- </html>
+ >>> browser.contents
+ "...'text-value': ['First Text']..."
Submitting also works without specifying a control, as shown below, which is
it's primary reason for existing in competition with the control submission
@@ -1050,6 +957,7 @@
the `forms.html` template, we have four forms all having a text control named
`text-value`. Now, if I use the browser's `get` method,
+ >>> browser.open('forms.html')
>>> browser.getControl(name='text-value')
Traceback (most recent call last):
...
@@ -1068,11 +976,13 @@
'Second Text'
>>> form.submit('Submit')
>>> browser.contents
- '...<em>Second Text</em>...'
+ "...'text-value': ['Second Text']..."
+ >>> browser.open('forms.html')
>>> form = browser.getForm('2')
>>> form.getControl('Submit').click()
>>> browser.contents
- '...<em>Second Text</em>...'
+ "...'text-value': ['Second Text']..."
+ >>> browser.open('forms.html')
>>> browser.getForm('3').getControl('Text Control').value
'Third Text'
@@ -1083,10 +993,11 @@
>>> form = browser.getForm(index=3)
>>> form.submit()
>>> browser.contents
- '...<em>Fourth Text</em>...<em>Submitted without the submit button.</em>...'
+ "...'text-value': ['Fourth Text']..."
If a form is requested that does not exists, an exception will be raised.
+ >>> browser.open('forms.html')
>>> form = browser.getForm('does-not-exist')
Traceback (most recent call last):
LookupError
@@ -1094,13 +1005,14 @@
If the HTML page contains only one form, no arguments to `getForm` are
needed:
- >>> oneform = Browser()
- >>> oneform.open('http://localhost/@@/testbrowser/oneform.html')
- >>> form = oneform.getForm()
+ >>> browser.open('oneform.html')
+ >>> browser.getForm()
+ <zope.testbrowser...Form object at ...>
If the HTML page contains more than one form, `index` is needed to
disambiguate if no other arguments are provided:
+ >>> browser.open('forms.html')
>>> browser.getForm()
Traceback (most recent call last):
ValueError: if no other arguments are given, index is required.
@@ -1114,81 +1026,13 @@
Be very careful using raw seconds, cross-machine differences can be huge,
pystones is usually a better choice.
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.open('index.html')
>>> browser.lastRequestSeconds < 10 # really big number for safety
True
>>> browser.lastRequestPystones < 10000 # really big number for safety
True
-Handling Errors when using Zope 3's Publisher
----------------------------------------------
-
-A very useful feature of the publisher is the automatic graceful handling of
-application errors, such as invalid URLs:
-
- >>> browser.open('http://localhost/invalid')
- Traceback (most recent call last):
- ...
- HTTPError: HTTP Error 404: Not Found
-
-Note that the above error was thrown by ``urllib2`` and not by the
-publisher. For debugging purposes, however, it can be very useful to see the
-original exception caused by the application. In those cases you can set the
-``handleErrors`` property of the browser to ``False``. It is defaulted to
-``True``:
-
- >>> browser.handleErrors
- True
-
-So when we tell the publisher not to handle the errors,
-
- >>> browser.handleErrors = False
-
-we get a different, Zope internal error:
-
- >>> browser.open('http://localhost/invalid')
- Traceback (most recent call last):
- ...
- NotFound: Object: <zope.app.folder.folder.Folder object at ...>,
- name: u'invalid'
-
-NB: Setting the handleErrors attribute to False will only change
- anything if the http server you're testing is using Zope 3's
- publisher or can otherwise respond appropriately to an
- 'X-zope-handle-errors' header in requests.
-
-When the testbrowser is raising HttpErrors, the errors still hit the test.
-Sometimes we don't want that to happen, in situations where there are edge
-cases that will cause the error to be predictabley but infrequently raised.
-Time is a primary cause of this.
-
-To get around this, one can set the raiseHttpErrors to False.
-
- >>> browser.handleErrors = True
- >>> browser.raiseHttpErrors = False
-
-This will cause HttpErrors not to propagate.
-
- >>> browser.open('http://localhost/invalid')
-
-The headers are still there, though.
-
- >>> '404 Not Found' in str(browser.headers)
- True
-
-If we don't handle the errors, and allow internal ones to propagate, however,
-this flage doesn't affect things.
-
- >>> browser.handleErrors = False
- >>> browser.open('http://localhost/invalid')
- Traceback (most recent call last):
- ...
- NotFound: Object: <zope.app.folder.folder.Folder object at ...>,
- name: u'invalid'
-
- >>> browser.raiseHttpErrors = True
-
Hand-Holding
------------
@@ -1228,7 +1072,7 @@
When URLs have spaces in them, they're handled correctly (before the bug was
fixed, you'd get "ValueError: too many values to unpack"):
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> browser.getLink('Spaces in the URL').click()
.goBack() Truncation
@@ -1236,11 +1080,11 @@
The .goBack() method used to truncate the .contents.
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
+ >>> browser.open('navigate.html')
>>> actual_length = len(browser.contents)
- >>> browser.open('http://localhost/@@/testbrowser/navigate.html')
- >>> browser.open('http://localhost/@@/testbrowser/simple.html')
+ >>> browser.open('navigate.html')
+ >>> browser.open('index.html')
>>> browser.goBack()
>>> len(browser.contents) == actual_length
True
Added: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/Zope.txt
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/Zope.txt (rev 0)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/Zope.txt 2007-09-17 10:34:53 UTC (rev 79707)
@@ -0,0 +1,67 @@
+Handling Errors when using Zope 3's Publisher
+---------------------------------------------
+
+A very useful feature of the publisher is the automatic graceful handling of
+application errors, such as invalid URLs:
+
+ >>> browser.open('http://localhost/invalid')
+ Traceback (most recent call last):
+ ...
+ HTTPError: HTTP Error 404: Not Found
+
+Note that the above error was thrown by ``urllib2`` and not by the
+publisher. For debugging purposes, however, it can be very useful to see the
+original exception caused by the application. In those cases you can set the
+``handleErrors`` property of the browser to ``False``. It is defaulted to
+``True``:
+
+ >>> browser.handleErrors
+ True
+
+So when we tell the publisher not to handle the errors,
+
+ >>> browser.handleErrors = False
+
+we get a different, Zope internal error:
+
+ >>> browser.open('http://localhost/invalid')
+ Traceback (most recent call last):
+ ...
+ NotFound: Object: <zope.app.folder.folder.Folder object at ...>,
+ name: u'invalid'
+
+NB: Setting the handleErrors attribute to False will only change
+ anything if the http server you're testing is using Zope 3's
+ publisher or can otherwise respond appropriately to an
+ 'X-zope-handle-errors' header in requests.
+
+When the testbrowser is raising HttpErrors, the errors still hit the test.
+Sometimes we don't want that to happen, in situations where there are edge
+cases that will cause the error to be predictabley but infrequently raised.
+Time is a primary cause of this.
+
+To get around this, one can set the raiseHttpErrors to False.
+
+ >>> browser.handleErrors = True
+ >>> browser.raiseHttpErrors = False
+
+This will cause HttpErrors not to propagate.
+
+ >>> browser.open('http://localhost/invalid')
+
+The headers are still there, though.
+
+ >>> '404 Not Found' in str(browser.headers)
+ True
+
+If we don't handle the errors, and allow internal ones to propagate, however,
+this flage doesn't affect things.
+
+ >>> browser.handleErrors = False
+ >>> browser.open('http://localhost/invalid')
+ Traceback (most recent call last):
+ ...
+ NotFound: Object: <zope.app.folder.folder.Folder object at ...>,
+ name: u'invalid'
+
+ >>> browser.raiseHttpErrors = True
Property changes on: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/Zope.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/browser.py
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/browser.py 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/browser.py 2007-09-17 10:34:53 UTC (rev 79707)
@@ -16,15 +16,17 @@
$Id$
"""
__docformat__ = "reStructuredText"
+
+from cStringIO import StringIO
from zope.testbrowser import interfaces
import ClientForm
-from cStringIO import StringIO
import mechanize
import operator
import re
import sys
import time
import urllib2
+import urlparse
try:
from zope import interface
@@ -150,6 +152,7 @@
"""A web user agent."""
interface.implements(interfaces.IBrowser)
+ base = None
_contents = None
_counter = 0
@@ -218,6 +221,8 @@
def open(self, url, data=None):
"""See zope.testbrowser.interfaces.IBrowser"""
+ if self.base is not None:
+ url = urlparse.urljoin(self.base, url)
self._start_timer()
try:
try:
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/forms.html
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/forms.html 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/forms.html 2007-09-17 10:34:53 UTC (rev 79707)
@@ -6,26 +6,25 @@
<em tal:condition="request/text-value|nothing"
tal:content="request/text-value" />
- <form id="1" name="one" action="forms.html"
- enctype="multipart/form-data" method="post">
+ <form id="1" name="one" action="forms.html" method="post">
<input type="text" name="text-value" value="First Text" />
<input type="image" name="image-1" src="zope3logo.gif" />
<input type="submit" name="submit-1" value="Submit" />
</form>
- <form id="2" name="two" action="forms.html">
+ <form id="2" name="two" action="forms.html" method="post">
<input type="text" name="text-value" value="Second Text" />
<input type="submit" name="submit-2" value="Submit" />
</form>
- <form id="3" name="three" action="forms.html">
+ <form id="3" name="three" action="forms.html" method="post">
<label for="text-value-3">Text Control</label>
<input type="text" name="text-value" id="text-value-3"
value="Third Text" />
<input type="submit" name="submit-3" value="Submit" />
</form>
- <form action="forms.html">
+ <form action="forms.html" method="post">
<label for="text-value-4">Text Control</label>
<input type="text" name="text-value" id="text-value-4"
value="Fourth Text" />
Copied: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/index.html (from rev 79609, zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/simple.html)
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/index.html (rev 0)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/index.html 2007-09-17 10:34:53 UTC (rev 79707)
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Simple Page</title>
+ </head>
+ <body>
+ <h1>Simple Page</h1>
+ </body>
+</html>
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/navigate.html
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/navigate.html 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/navigate.html 2007-09-17 10:34:53 UTC (rev 79707)
@@ -7,19 +7,15 @@
Message: <em tal:content="request/message">Message</em>
</p>
- <a href="navigate.html?message=By+Link+Text">Link Text</a>
+ <a href="target.html">Link Text</a>
- <a href="navigate.html?message=By+Link+Text+with+Normalization"> Link Text
+ <a href="target.html"> Link Text
with Whitespace Normalization (and parens) </a>
- <a href="navigate.html?message=By+URL">Using the URL</a>
+ <a href="target.html" id="anchorid">By Anchor Id</a>
- <a href="navigate.html?message=By+Name" name="anchorname">By Anchor Name</a>
+ <a href="target.html">Spaces in the URL</a>
- <a href="navigate.html?message=By+Id" id="anchorid">By Anchor Id</a>
-
- <a href="navigate.html?message=Spaces in URL">Spaces in the URL</a>
-
<form action="navigate.html" method="post">
<input name="message" value="By Form Submit" />
<input type="submit" name="submit-form" value="Submit" />
@@ -27,11 +23,11 @@
<img src="./zope3logo.gif" usemap="#zope3logo" />
<map name="zope3logo">
- <area shape="rect" alt="Zope3"
- href="navigate.html?message=Zope+3+Name" id="zope3" title="Zope 3"
+ <area shape="rect" alt="Zope3"
+ href="target.html" id="zope3" title="Zope 3"
coords="44,7,134,33" />
- <area shape="circle" alt="Logo"
- href="navigate.html?message=Logo" id="logo" title="Logo"
+ <area shape="circle" alt="Logo"
+ href="navigate.html?message=Logo" id="logo" title="Logo"
coords="23,21,18" />
</map>
Deleted: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/simple.html
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/simple.html 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/simple.html 2007-09-17 10:34:53 UTC (rev 79707)
@@ -1,8 +0,0 @@
-<html>
- <head>
- <title>Simple Page</title>
- </head>
- <body>
- <h1>Simple Page</h1>
- </body>
-</html>
Added: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/target.html
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/target.html (rev 0)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/ftests/target.html 2007-09-17 10:34:53 UTC (rev 79707)
@@ -0,0 +1,8 @@
+<html>
+ <head>
+ <title>Target Page</title>
+ </head>
+ <body>
+ This page is the target of a link.
+ </body>
+</html>
Added: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/headers.txt
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/headers.txt (rev 0)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/headers.txt 2007-09-17 10:34:53 UTC (rev 79707)
@@ -0,0 +1,25 @@
+Headers
+-------
+
+As you can see, the `contents` of the browser does not return any HTTP
+headers. The headers are accessible via a separate attribute, which is an
+``httplib.HTTPMessage`` instance (httplib is a part of Python's standard
+library):
+
+ >>> browser.base = 'http://localhost:%s/' % TEST_PORT
+ >>> browser.open('index.html')
+ >>> browser.headers
+ <httplib.HTTPMessage instance...>
+
+The headers can be accessed as a string:
+
+ >>> print browser.headers
+ Server: BaseHTTP/0.3 Python/2.4.4
+ Date: Mon, 17 Sep 2007 10:05:42 GMT
+ Connection: close
+ Content-type: text/html
+
+Or as a mapping:
+
+ >>> browser.headers['content-type']
+ 'text/html'
Property changes on: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/headers.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/tests.py
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/tests.py 2007-09-17 07:18:31 UTC (rev 79706)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/tests.py 2007-09-17 10:34:53 UTC (rev 79707)
@@ -17,19 +17,72 @@
"""
from cStringIO import StringIO
-from zope.app.testing import functional
-from zope.app.testing.functional import FunctionalDocFileSuite
from zope.testbrowser import browser
from zope.testing import renormalizing, doctest
+import BaseHTTPServer
+import cgi
import httplib
import mechanize
-import os
+import os.path
+import pprint
+import random
import re
+import string
+import threading
import unittest
-import unittest
+import urllib
import urllib2
+import zope.testbrowser.browser
+try:
+ from zope.app.testing import functional
+except:
+ functional = None
+web_server_base_path = os.path.join(os.path.split(__file__)[0], 'ftests')
+
+class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+
+ def date_time_string(self):
+ return 'Mon, 17 Sep 2007 10:05:42 GMT'
+
+ def do_GET(self):
+ if self.path.endswith('robots.txt'):
+ self.send_response(404)
+ self.send_header('Connection', 'close')
+ return
+
+ try:
+ f = open(web_server_base_path + self.path)
+ except IOError:
+ self.send_response(500)
+ self.send_header('Connection', 'close')
+ return
+
+ self.send_response(200)
+ self.send_header('Connection', 'close')
+ if self.path.endswith('.gif'):
+ self.send_header('Content-type', 'image/gif')
+ else:
+ self.send_header('Content-type', 'text/html')
+
+ self.end_headers()
+ self.wfile.write(f.read())
+ f.close()
+
+ def do_POST(self):
+ body = self.rfile.read(int(self.headers['content-length']))
+ values = cgi.parse_qs(body)
+ self.wfile
+ self.send_response(200)
+ self.send_header('Content-type', 'text/plain')
+ self.end_headers()
+ pprint.pprint(values, self.wfile)
+
+ def log_request(self, *args, **kws):
+ pass
+
+
def set_next_response(body, headers=None, status='200', reason='OK'):
global next_response_body
global next_response_headers
@@ -376,20 +429,55 @@
(re.compile(r'Content-Type: '), 'Content-type: '),
])
-TestBrowserLayer = functional.ZCMLLayer(
- os.path.join(os.path.split(__file__)[0], 'ftests/ftesting.zcml'),
- __name__, 'TestBrowserLayer', allow_teardown=True)
+def serve_requests(server):
+ global server_stopped
+ global server_stop
+ server_stop = False
+ while not server_stop:
+ server.handle_request()
+ server.socket.close()
+def setUpServer(test):
+ port = random.randint(20000,30000)
+ test.globs['TEST_PORT'] = port
+ server = BaseHTTPServer.HTTPServer(('localhost', port), TestHandler)
+ thread = threading.Thread(target=serve_requests, args=[server])
+ thread.setDaemon(True)
+ thread.start()
+ test.globs['web_server_thread'] = thread
+
+def tearDownServer(test):
+ global server_stop
+ server_stop = True
+ # make a request, so the last call to `handle_one_request` will return
+ urllib.urlretrieve('http://localhost:%d/' % test.globs['TEST_PORT'])
+ test.globs['web_server_thread'].join()
+
+def setUpWire(test):
+ test.globs['Browser'] = zope.testbrowser.browser.Browser
+ setUpServer(test)
+
+def tearDownWire(test):
+ tearDownServer(test)
+
+def setUpHeaders(test):
+ setUpServer(test)
+ test.globs['browser'] = zope.testbrowser.browser.Browser()
+
+def tearDownHeaders(test):
+ tearDownServer(test)
+
def test_suite():
flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
- readme = FunctionalDocFileSuite('README.txt', optionflags=flags,
- checker=checker)
- readme.layer = TestBrowserLayer
- wire = doctest.DocFileSuite('over_the_wire.txt', optionflags=flags)
- wire.level = 2
+
+ readme = doctest.DocFileSuite('README.txt', optionflags=flags,
+ checker=checker, setUp=setUpWire, tearDown=tearDownWire)
+
+ headers = doctest.DocFileSuite('headers.txt', optionflags=flags,
+ setUp=setUpHeaders, tearDown=tearDownHeaders)
+
this_file = doctest.DocTestSuite(checker=checker)
- return unittest.TestSuite((this_file, readme, wire))
+ return unittest.TestSuite((this_file, readme, headers))
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Copied: zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/zopetests.py (from rev 79613, zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/tests.py)
===================================================================
--- zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/zopetests.py (rev 0)
+++ zope.testbrowser/branches/benji-reduce-testing-dependencies/src/zope/testbrowser/zopetests.py 2007-09-17 10:34:53 UTC (rev 79707)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+"""Real test for file-upload and beginning of a better internal test framework
+
+$Id$
+"""
+
+from zope.testing import doctest
+import os.path
+import unittest
+import zope.app.testing.functional
+import zope.testbrowser.testing
+import zope.testbrowser.tests
+
+TestBrowserLayer = zope.app.testing.functional.ZCMLLayer(
+ os.path.join(os.path.split(__file__)[0], 'ftests/ftesting.zcml'),
+ __name__, 'TestBrowserLayer', allow_teardown=True)
+
+def setUp(test):
+ test.globs['browser'] = zope.testbrowser.testing.Browser()
+
+def test_suite():
+ flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
+
+ readme = zope.app.testing.functional.FunctionalDocFileSuite('Zope.txt',
+ optionflags=flags, checker=zope.testbrowser.tests.checker, setUp=setUp)
+ readme.layer = TestBrowserLayer
+
+ return unittest.TestSuite((readme,))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
More information about the Checkins
mailing list