[Checkins] SVN: z3c.etestbrowser/trunk/ added an ExtendedTestBrowser that speaks HTTP

Thomas Lotze tl at gocept.com
Thu Jul 8 12:25:22 EDT 2010


Log message for revision 114339:
  added an ExtendedTestBrowser that speaks HTTP

Changed:
  U   z3c.etestbrowser/trunk/CHANGES.txt
  U   z3c.etestbrowser/trunk/setup.py
  A   z3c.etestbrowser/trunk/src/z3c/etestbrowser/browser.py
  A   z3c.etestbrowser/trunk/src/z3c/etestbrowser/over_the_wire.txt
  U   z3c.etestbrowser/trunk/src/z3c/etestbrowser/testing.py
  U   z3c.etestbrowser/trunk/src/z3c/etestbrowser/tests.py

-=-
Modified: z3c.etestbrowser/trunk/CHANGES.txt
===================================================================
--- z3c.etestbrowser/trunk/CHANGES.txt	2010-07-08 16:22:41 UTC (rev 114338)
+++ z3c.etestbrowser/trunk/CHANGES.txt	2010-07-08 16:25:22 UTC (rev 114339)
@@ -2,13 +2,16 @@
 CHANGES
 =======
 
-1.3.2 (unreleased)
+1.4.0 (unreleased)
 ==================
 
 - Took zope.securitypolicy refactoring and zope.testing.doctest deprecation
   into account.
 
+- Added a variant of the ExtendedTestBrowser that speaks HTTP and has much
+  fewer dependencies than the existing one, which talks to the publisher.
 
+
 1.3.1 (2010-01-18)
 ==================
 

Modified: z3c.etestbrowser/trunk/setup.py
===================================================================
--- z3c.etestbrowser/trunk/setup.py	2010-07-08 16:22:41 UTC (rev 114338)
+++ z3c.etestbrowser/trunk/setup.py	2010-07-08 16:25:22 UTC (rev 114339)
@@ -22,7 +22,7 @@
     return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
 
 setup(name='z3c.etestbrowser',
-      version = '1.3.2dev',
+      version = '1.4.0dev',
       author='Christian Theune',
       author_email='ct at gocept.com',
       description='Extensions for zope.testbrowser',

Copied: z3c.etestbrowser/trunk/src/z3c/etestbrowser/browser.py (from rev 114331, z3c.etestbrowser/trunk/src/z3c/etestbrowser/testing.py)
===================================================================
--- z3c.etestbrowser/trunk/src/z3c/etestbrowser/browser.py	                        (rev 0)
+++ z3c.etestbrowser/trunk/src/z3c/etestbrowser/browser.py	2010-07-08 16:25:22 UTC (rev 114339)
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation 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.
+#
+##############################################################################
+"""Extensions for z3c.etestbrowser
+
+$Id$
+"""
+
+import re
+import htmllib
+import formatter
+
+import lxml.etree
+import lxml.html
+
+import zope.testbrowser.browser
+
+
+RE_CHARSET = re.compile('.*;charset=(.*)')
+
+
+def indent(elem, level=0):
+    i = "\n" + level*"  "
+    if len(elem):
+        if not elem.text or not elem.text.strip():
+            elem.text = i + "  "
+        for e in elem:
+            indent(e, level+1)
+            if not e.tail or not e.tail.strip():
+                e.tail = i + "  "
+        if not e.tail or not e.tail.strip():
+            e.tail = i
+    else:
+        if level and (not elem.tail or not elem.tail.strip()):
+            elem.tail = i
+
+
+class ExtendedTestBrowser(zope.testbrowser.browser.Browser):
+    """An extended testbrowser implementation.
+
+    Features:
+
+        - offers the content also as parsed etree
+
+    """
+
+    xml_strict = False
+
+    _etree = None
+    _normalized_contents = None
+
+    @property
+    def etree(self):
+        if self._etree is not None:
+            return self._etree
+        # I'm not using any internal knowledge about testbrowser
+        # here, to avoid breakage. Memory usage won't be a problem.
+        if self.xml_strict:
+            self._etree = lxml.etree.fromstring(
+                self.contents,
+                parser=lxml.etree.XMLParser(resolve_entities=False))
+        else:
+            # This is a workaround against the broken fallback for
+            # encoding detection of libxml2.
+            # We have a chance of knowing the encoding as Zope states this in
+            # the content-type response header.
+            content = self.contents
+            content_type = self.headers['content-type']
+            match = RE_CHARSET.match(content_type)
+            if match is not None:
+                charset = match.groups()[0]
+                content = content.decode(charset)
+            self._etree = lxml.etree.HTML(content)
+
+        return self._etree
+
+    @property
+    def normalized_contents(self):
+        if self._normalized_contents is None:
+            indent(self.etree)
+            self._normalized_contents = lxml.etree.tostring(
+                self.etree, pretty_print=True)
+        return self._normalized_contents
+
+    def _changed(self):
+        super(ExtendedTestBrowser, self)._changed()
+        self._etree = None
+        self._normalized_contents = None
+
+    def pretty_print(self):
+        """Print a pretty (formatted) version of the HTML content.
+
+        If the content is not text/html then it is just printed.
+        """
+        if not self.headers['content-type'].lower().startswith('text/html'):
+            print self.contents
+        else:
+            parser = htmllib.HTMLParser(
+                formatter.AbstractFormatter(formatter.DumbWriter()))
+            parser.feed(self.contents)
+            parser.close()

Added: z3c.etestbrowser/trunk/src/z3c/etestbrowser/over_the_wire.txt
===================================================================
--- z3c.etestbrowser/trunk/src/z3c/etestbrowser/over_the_wire.txt	                        (rev 0)
+++ z3c.etestbrowser/trunk/src/z3c/etestbrowser/over_the_wire.txt	2010-07-08 16:25:22 UTC (rev 114339)
@@ -0,0 +1,43 @@
+=================================
+Using testbrowser On the Internet
+=================================
+
+The ``z3c.etestbrowser`` module exposes an ``ExtendedTestBrowser`` class that
+simulates a web browser similar to Mozilla Firefox or IE.
+
+    >>> from z3c.etestbrowser.browser import ExtendedTestBrowser
+    >>> browser = ExtendedTestBrowser()
+
+It can send arbitrary headers; this is helpful for setting the 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('Accept-Language', 'en-US')
+
+The browser can `open` web pages:
+
+    >>> # This is tricky, since in Germany I am forwarded to google.de usually;
+    >>> # The `ncr` forces to really go to google.com.
+    >>> browser.open('http://google.com/ncr')
+    >>> browser.url
+    'http://www.google.com/'
+    >>> 'html' in browser.contents.lower()
+    True
+
+We can access the etree of the page .. contents:
+
+    >>> browser.etree.xpath('//body')
+    [<Element body at ...>]
+
+We'll put some text in the query box...
+
+    >>> browser.getControl(name='q').value = 'z3c.etestbrowser'
+
+...and then click the search button.
+
+    >>> browser.getControl('Google Search').click()
+    Traceback (most recent call last):
+    ...
+    RobotExclusionError: HTTP Error 403: request disallowed by robots.txt
+
+Oops!  Google doesn't let robots use their search engine.  Oh well.


Property changes on: z3c.etestbrowser/trunk/src/z3c/etestbrowser/over_the_wire.txt
___________________________________________________________________
Added: svn:keywords
   + Id Rev Date
Added: svn:eol-style
   + native

Modified: z3c.etestbrowser/trunk/src/z3c/etestbrowser/testing.py
===================================================================
--- z3c.etestbrowser/trunk/src/z3c/etestbrowser/testing.py	2010-07-08 16:22:41 UTC (rev 114338)
+++ z3c.etestbrowser/trunk/src/z3c/etestbrowser/testing.py	2010-07-08 16:25:22 UTC (rev 114339)
@@ -16,36 +16,12 @@
 $Id$
 """
 
-import re
-import StringIO
-import htmllib
-import formatter
-
-import lxml.etree, lxml.html
-
+import z3c.etestbrowser.browser
 import zope.testbrowser.testing
 
 
-RE_CHARSET = re.compile('.*;charset=(.*)')
-
-
-def indent(elem, level=0):
-    i = "\n" + level*"  "
-    if len(elem):
-        if not elem.text or not elem.text.strip():
-            elem.text = i + "  "
-        for e in elem:
-            indent(e, level+1)
-            if not e.tail or not e.tail.strip():
-                e.tail = i + "  "
-        if not e.tail or not e.tail.strip():
-            e.tail = i
-    else:
-        if level and (not elem.tail or not elem.tail.strip()):
-            elem.tail = i
-
-
-class ExtendedTestBrowser(zope.testbrowser.testing.Browser):
+class ExtendedTestBrowser(zope.testbrowser.testing.Browser,
+                          z3c.etestbrowser.browser.ExtendedTestBrowser):
     """An extended testbrowser implementation.
 
     Features:
@@ -53,59 +29,3 @@
         - offers the content also as parsed etree
 
     """
-
-    xml_strict = False
-
-    _etree = None
-    _normalized_contents = None
-
-    @property
-    def etree(self):
-        if self._etree is not None:
-            return self._etree
-        # I'm not using any internal knowledge about testbrowser
-        # here, to avoid breakage. Memory usage won't be a problem.
-        if self.xml_strict:
-            self._etree = lxml.etree.fromstring(
-                self.contents,
-                parser=lxml.etree.XMLParser(resolve_entities=False))
-        else:
-            # This is a workaround against the broken fallback for
-            # encoding detection of libxml2.
-            # We have a chance of knowing the encoding as Zope states this in
-            # the content-type response header.
-            content = self.contents
-            content_type = self.headers['content-type']
-            match = RE_CHARSET.match(content_type)
-            if match is not None:
-                charset = match.groups()[0]
-                content = content.decode(charset)
-            self._etree = lxml.etree.HTML(content)
-
-        return self._etree
-
-    @property
-    def normalized_contents(self):
-        if self._normalized_contents is None:
-            indent(self.etree)
-            self._normalized_contents = lxml.etree.tostring(
-                self.etree, pretty_print=True)
-        return self._normalized_contents
-
-    def _changed(self):
-        super(ExtendedTestBrowser, self)._changed()
-        self._etree = None
-        self._normalized_contents = None
-
-    def pretty_print(self):
-        """Print a pretty (formatted) version of the HTML content.
-
-        If the content is not text/html then it is just printed.
-        """
-        if not self.headers['content-type'].lower().startswith('text/html'):
-            print self.contents
-        else:
-            parser = htmllib.HTMLParser(
-                formatter.AbstractFormatter(formatter.DumbWriter()))
-            parser.feed(self.contents)
-            parser.close()

Modified: z3c.etestbrowser/trunk/src/z3c/etestbrowser/tests.py
===================================================================
--- z3c.etestbrowser/trunk/src/z3c/etestbrowser/tests.py	2010-07-08 16:22:41 UTC (rev 114338)
+++ z3c.etestbrowser/trunk/src/z3c/etestbrowser/tests.py	2010-07-08 16:25:22 UTC (rev 114339)
@@ -32,6 +32,7 @@
     suite = unittest.TestSuite()
     test = functional.FunctionalDocFileSuite(
         "README.txt",
+        "over_the_wire.txt",
         optionflags=doctest.REPORT_NDIFF|doctest.NORMALIZE_WHITESPACE|
         doctest.ELLIPSIS)
     test.layer = layer



More information about the checkins mailing list