[Checkins] SVN: z3c.testsetup/tags/0.2.0/ Prepare release.

Uli Fouquet uli at gnufix.de
Sat Feb 16 20:36:55 EST 2008


Log message for revision 83969:
  Prepare release.

Changed:
  A   z3c.testsetup/tags/0.2.0/
  D   z3c.testsetup/tags/0.2.0/CHANGES.txt
  A   z3c.testsetup/tags/0.2.0/CHANGES.txt
  D   z3c.testsetup/tags/0.2.0/setup.py
  A   z3c.testsetup/tags/0.2.0/setup.py
  D   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt
  A   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt
  D   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py
  A   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py
  D   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt
  A   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt
  A   z3c.testsetup/tags/0.2.0/src/z3c/testsetup/tests/cave_to_let/

-=-
Copied: z3c.testsetup/tags/0.2.0 (from rev 83862, z3c.testsetup/trunk)

Deleted: z3c.testsetup/tags/0.2.0/CHANGES.txt
===================================================================
--- z3c.testsetup/trunk/CHANGES.txt	2008-02-15 14:03:12 UTC (rev 83862)
+++ z3c.testsetup/tags/0.2.0/CHANGES.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -1,8 +0,0 @@
-=======
-CHANGES
-=======
-
-0.1.0 (2008-02-15)
-------------------
-
-- Initial Release

Copied: z3c.testsetup/tags/0.2.0/CHANGES.txt (from rev 83967, z3c.testsetup/trunk/CHANGES.txt)
===================================================================
--- z3c.testsetup/tags/0.2.0/CHANGES.txt	                        (rev 0)
+++ z3c.testsetup/tags/0.2.0/CHANGES.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -0,0 +1,23 @@
+CHANGES
+*******
+
+0.2 (unreleased)
+==================
+
+Feature Changes
+---------------
+
+* An `ftesting.zcml` in the root of a handled package is now taken as
+  default layer for functional doctests if it exists.
+
+Bug fixes
+---------
+
+
+0.1 (2008-02-15)
+================
+
+Feature changes
+---------------
+
+- Initial Release

Deleted: z3c.testsetup/tags/0.2.0/setup.py
===================================================================
--- z3c.testsetup/trunk/setup.py	2008-02-15 14:03:12 UTC (rev 83862)
+++ z3c.testsetup/tags/0.2.0/setup.py	2008-02-17 01:36:53 UTC (rev 83969)
@@ -1,49 +0,0 @@
-from setuptools import setup, find_packages
-import os
-
-def read(*rnames):
-    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
-
-long_description = (
-    read('README.txt')
-    + '\n\n'
-    + 'Detailed Documentation\n'
-    + '----------------------\n'
-    + read('src', 'z3c', 'testsetup', 'README.txt')
-    + '\n\n'
-    + read('CHANGES.txt')
-    + '\n\n'
-    )
-
-setup(
-    name='z3c.testsetup',
-    version='0.1.0',
-    author='Uli Fouquet and the Zope Community',
-    author_email='uli at gnufix.de',
-    url = 'http://pypi.python.org/pypi/z3c.testsetup',
-    description='Easier test setup for Zope 3 projects and '
-                'other Python packages.',
-    long_description=long_description,
-    license='ZPL 2.1',
-    keywords="zope3 zope tests unittest doctest testsetup",
-    classifiers=['Development Status :: 3 - Alpha',
-                 'Environment :: Web Environment',
-                 'Intended Audience :: Developers',
-                 'License :: OSI Approved :: Zope Public License',
-                 'Programming Language :: Python',
-                 'Operating System :: OS Independent',
-                 'Framework :: Zope3',
-                 ],
-
-    packages=find_packages('src'),
-    package_dir = {'': 'src'},
-    namespace_packages = ['z3c'],
-    include_package_data = True,
-    zip_safe=False,
-    install_requires=['setuptools',
-                      'zope.component',
-                      'zope.testing',
-                      'zope.app.testing',
-                      'martian',
-                      ],
-)

Copied: z3c.testsetup/tags/0.2.0/setup.py (from rev 83968, z3c.testsetup/trunk/setup.py)
===================================================================
--- z3c.testsetup/tags/0.2.0/setup.py	                        (rev 0)
+++ z3c.testsetup/tags/0.2.0/setup.py	2008-02-17 01:36:53 UTC (rev 83969)
@@ -0,0 +1,51 @@
+from setuptools import setup, find_packages
+import os
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+long_description = (
+    read('README.txt')
+    + '\n\n'
+    + 'Detailed Documentation\n'
+    + '**********************\n'
+    + read('src', 'z3c', 'testsetup', 'README.txt')
+    + '\n\n'
+    + read('CHANGES.txt')
+    + '\n\n'
+    + 'Download\n'
+    + '********\n'
+    )
+
+setup(
+    name='z3c.testsetup',
+    version='0.2dev',
+    author='Uli Fouquet and the Zope Community',
+    author_email='uli at gnufix.de',
+    url = 'http://pypi.python.org/pypi/z3c.testsetup',
+    description='Easier test setup for Zope 3 projects and '
+                'other Python packages.',
+    long_description=long_description,
+    license='ZPL 2.1',
+    keywords="zope3 zope tests unittest doctest testsetup",
+    classifiers=['Development Status :: 3 - Alpha',
+                 'Environment :: Web Environment',
+                 'Intended Audience :: Developers',
+                 'License :: OSI Approved :: Zope Public License',
+                 'Programming Language :: Python',
+                 'Operating System :: OS Independent',
+                 'Framework :: Zope3',
+                 ],
+
+    packages=find_packages('src'),
+    package_dir = {'': 'src'},
+    namespace_packages = ['z3c'],
+    include_package_data = True,
+    zip_safe=False,
+    install_requires=['setuptools',
+                      'zope.component',
+                      'zope.testing',
+                      'zope.app.testing',
+                      'martian',
+                      ],
+)

Deleted: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/README.txt	2008-02-15 14:03:12 UTC (rev 83862)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -1,526 +0,0 @@
-=============
-z3c.testsetup
-=============
-
-Easy testsetups for Zope 3 and Python projects.
-
-Setting up tests for Zope 3 projects sometimes tends to be
-cumbersome. ``z3c.testsetup`` jumps in here, to support much flatter
-test setups. The package supports three kinds of tests:
-
-- normal python tests: i.e. tests, that consist of python modules
-  which in turn contain ``unittest.TestCase`` classes.
-
-- unit doctests: i.e. tests, that are written as doctests, but require
-  no complicated layer setup etc.
-
-- functional doctests: i.e. tests, that are written as doctests, but
-  also require a more or less complex framework to test for example
-  browser requests.
-
-``z3c.testsetup`` is package-oriented. That means, it registers more or
-less automatically all the three kinds of tests mentioned above
-insofar they are part of a certain package.
-
-This is a general introduction to ``z3c.testsetup``. For setup
-examples you might see the ``cave`` package contained in the `tests/`
-directory. More details on special topics can be found in the
-appropriate .txt files in this directory.
-
-
-Basic Example
--------------
-
-The shortest test setup possible with ``z3c.testsetup`` looks like
-this::
-
-   >>> import z3c.testsetup
-   >>> test_suite = z3c.testsetup.register_all_tests(
-   ...                   'z3c.testsetup.tests.cave')
-
-It is sufficient to put this lines into a python module which is found
-by your testrunner (see `samplesetup_short` examples in the ``cave``
-package and `testrunner.txt`).
-
-To sum it up, testsetup with ``z3c.testsetup`` is done in two steps:
-
-1) Make sure your testfiles are named properly (.txt/.rst for
-   doctests, valid python modules for usual unit tests) and provide a
-   suitable marker string as explained below_.
-
-2) Write a test setup module which is named so that your testrunner
-   finds it and in this module call::
-
-      test_suite = z3c.testsetup.register_all_tests(<package>)
-
-   where `<package>` must be a package object. Instead of a package
-   object you can also pass the package's dotted name as string like
-   `'z3c.testsetup.tests.cave'`.
-
-Given that, this setup should find all doctests (unit and functional)
-as well as python tests in the package and register them.
-
-
-Customized Setups
------------------
-
-The `register_all_tests` function mentioned above accepts a bunch of
-keyword parameters::
-
-   register_all_tests(pkg_or_dotted_name, filter_func, extensions,
-                      encoding, checker,
-                      globs, setup, teardown, optionflags
-                      zcml_config, layer_name, layer)
-
-where all but the first parameter are keyword paramters and all but
-the package parameter are optional.
-
-While `filter_func` and `extensions` determine the set of testfiles to
-be found, the other paramters tell how to setup single tests.
-
-
-- `filter_func` (`ufilter_func`, `ffilter_func`): 
-
-  a function that takes an absolute filepath and returns `True` or
-  `False`, depending on whether the file should be included in the
-  test suite as doctest or not. `filter_func` applies only to
-  doctests.
-
-  We setup a few things to check that::
-
-     >>> import os
-     >>> import unittest
-     >>> suite = test_suite()
-     >>> suite.countTestCases()
-     4
-
-  Okay, the callable in `test_suite` we created above with
-  `register_all_tests` apparently delivered four testcases. This is
-  normally also the number of files involved, but let's check that
-  correctly.
-
-  We did setup a function `get_basenames_from_suite` in this testing
-  environment (as a `globs` entry) which determines the basenames of
-  the paths of all testcases contained in a `TestSuite`::
-
-     >>> get_basenames_from_suite(suite)
-     ['file1.py', 'file1.rst', 'file1.txt', 'subdirfile.txt']
-
-   Ah, okay. There are in fact four files, in which testcases were
-   found. Now, we define a plain filter function::
-
-      >>> def custom_file_filter(path):
-      ...     """Accept all txt files."""
-      ...     return path.endswith('.txt')
-
-   This one accepts all '.txt' files. We run `register_all_tests`
-   again, but this time with a `filter_func` parameter::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     filter_func=custom_file_filter)
-
-   To get the resulting test suite, we again call the returned
-   callable:: 
-
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.txt', 'file1.txt', 'subdirfile.txt',
-      'subdirfile.txt']
-
-   Compared with the first call to `register_all_tests` we got some
-   strange results here: there is a '.py' file, which should have been
-   refused by our filter function and the other two files appear
-   twice. What happened?
-
-   The python module is included, because python tests are not
-   filtered by `filter_func`. Instead this value applies only to
-   doctests.
-
-   The second strange result, that every .txt file appears twice in
-   the list, comes from the fact, that the filter is valid for unit
-   and functional doctests at the same time. In other words: the tests
-   in those .txt files are registered twice, as unittests and a second
-   time as functional tests as well.
-
-   If you want a filter function for functional doctests or unit
-   doctests only, then you can use `ffilter_func` and `ufilter_func`
-   respectively::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     ffilter_func=custom_file_filter,
-      ...     ufilter_func=lambda x: False)
-
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.txt', 'subdirfile.txt']
-
-    As expected, every .txt file was only registered once. The same
-    happens, when we switch and accept only unit doctests::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     ffilter_func=lambda x: False,
-      ...     ufilter_func=custom_file_filter)
-
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.txt', 'subdirfile.txt']
-
-    If you specify both, a `filter_func` and a more specialized
-    `ufilter_func` or `ffilter_func`, then this has the same effect as
-    passing both, `ufilter_func` and `ffilter_func`::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     ffilter_func=lambda x: False,
-      ...     filter_func=custom_file_filter)
-
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.txt', 'subdirfile.txt']
-
-
-- `pfilter_func`:
-
-    Does basically the same as the `filter_func`s above, but handles
-    Python modules instead of file paths. It therefore determines the
-    set of 'normal' Python tests accepted and does not touch the set
-    of doctests accepted.
-
-    We define a simple custom filter::
-
-      >>> def custom_module_filter(module):
-      ...     return 'Tests with real' in str(module.__doc__)
-
-    that checks for a certain string in modules' doc strings.
-
-    Now we start again with `pfilter_func` set::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     pfilter_func=custom_module_filter)
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.rst', 'file1.txt', 'notatest2.py', 'subdirfile.txt']
-
-    Because file1.py and notatest2.py in the cave package contain the
-    required string, this is correct. Because the default function
-    checks for the string `:Test-Layer: python`, the second module was
-    omitted by default.
-
-    Now let's use a filter, that refuses all modules::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     pfilter_func=lambda x: False)
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.rst', 'file1.txt', 'subdirfile.txt']
-
-    All Python modules vanished from the list.
-   
-    In case you wonder, why not all the other Python files of the
-    `cave` package (`__init__.py`, for example) appear in one of the
-    lists: we get only the result list, which contains only such
-    modules, which provide `unittest.TestCase` definitions. Because
-    most modules of the `cave` package don't define test cases, they
-    do not appear in the list. This automatism is driven by a
-    `unittest.TestLoader`. See
-    http://docs.python.org/lib/testloader-objects.html to learn more
-    about test loaders.
-
-
-- `extensions` (`uextensions`, `fextensions`):
-
-    a list of filename extensions to be considered during test
-    search. Default value is `['.txt', '.rst']`. Python tests are not
-    touched by this (they have to be regular Python modules with '.py'
-    extension).
-
-    Note, that the `extensions` attribute is used by the default
-    filter function. If you pass your own filter function using
-    `[u|f]filter_func`, then the extensions filtering won't work any
-    more. 
-
-    If we want to register .foo files, we can do so::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     extensions=['.foo'])
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'notatest1.foo', 'notatest1.foo']
-
-    Note, that only files that contain an appropriate marker are
-    found, regardless of the filename extension. The new .foo file
-    contains a marker for unit doctests and functional doctests, such
-    it is included twice in the list.
-
-    As we can see, the new file appears twice. This is, because it is
-    registered as functional doctest and unitdoctest as well.
-
-    To collect only functional doctests with a certain set of filename
-    extensions you can use: `fextensions`::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     fextensions=['.foo'])
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.rst', 'notatest1.foo']
-
-    Here the .rst file were registered as unit doctest, while the .foo
-    file was registered as functional doctest.
-
-    To collect only unit doctests with a different set of filename
-    extensions you can use `uextensions`::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     uextensions=['.foo'])
-      >>> suite = test_suite()
-      >>> get_basenames_from_suite(suite)
-      ['file1.py', 'file1.txt', 'notatest1.foo', 'subdirfile.txt']
-
-    Here the .foo file was registered as unit doctest and the .txt
-    files as functional ones.
-
-
-- `encoding`:   
-
-    the encoding of testfiles. 'utf-8' by default. Setting this to `None`
-    means using the default value. We've hidden one doctest file, that
-    contains umlauts. If we set the encoding to `ascii`, we get an
-    error::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     encoding='ascii')
-      >>> suite = test_suite()
-      Traceback (most recent call last):
-      ...
-      UnicodeDecodeError: 'ascii' codec can't decode ...: ordinal 
-      not in range(128)
-
-    While using 'latin-1' will work::
-
-      >>> test_suite = z3c.testsetup.register_all_tests(
-      ...     'z3c.testsetup.tests.cave',
-      ...     encoding='latin-1')
-      >>> suite = test_suite()
-      
-    No traceback here.
-
-    You can always overwrite an encoding setting for a certain file by
-    following PEP 0263 ( http://www.python.org/dev/peps/pep-0263/ ).
-
-
-- `checker`:
-
-    An output checker for functional doctests. `None` by default. A
-    typical output checker can be created like this::
-
-      >>> import re
-      >>> from zope.testing import renormalizing
-      >>> mychecker = renormalizing.RENormalizing([
-      ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
-      ...     '<SOME NUMBER OF> seconds'),
-      ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>'),
-      ... ])
-
-    This would match for example output like `0.123 seconds` if you
-    write in your doctest::
-
-      <SOME NUBMER OF> seconds
-
-    Please see ``testrunner.txt`` for examples of usage.
-
-    Checkers are applied to functional doctests only!
-
-- `globs`:
-
-    A dictionary of things that should be available immediately
-    (without imports) during tests. Defaults are::
-
-      dict(http=HTTPCaller(),
-           getRootFolder=getRootFolder,
-           sync=sync)
-
-    for functional doctests and an empty dict for unit
-    doctests. Python test globals can't be set this way.
-
-    If you want to register special globals for functional doctest or
-    unit doctests only, then you can use the `fglobs` and/or `uglobs`
-    keyword respectively. These keywords replace any `globs` value for
-    the respective kind of tests.
-
-    For more extensive examples see ``testrunner.txt``.
-
-- `setup`:
-
-    A function that takes a `test` argument and is executed before
-    every single doctest. By default it runs::
-
-      zope.app.testing.functional.FunctionalTestSetup().setUp()
-
-    for functional doctests and an empty function for unit
-    doctests. Python tests provide their own setups.
-
-    If you want to register special setup-functions for either
-    functional or unit doctests, then you can pass keyword parameters
-    `fsetup` or `usetup` respectively.
-
-- `teardown`:   
-
-    The equivalent to `setup`. Runs by default::
-
-      FunctionalTestSetup().tearDown()
-
-    for functional doctests and::
-
-      zope.testing.cleanup.cleanUp()
-
-    for unit doctests. Python tests have to provide their own teardown
-    functions in TestCases.
-
-- `optionflags`:
-
-    Optionflags influence the behaviour of the testrunner. They are
-    logically or'd so that you can add them arithmetically. See
-
-      http://svn.zope.org/zope.testing/trunk/src/zope/testing/doctest.py
-
-    for details.
-
-- `zcml_config`:
-
-    A filepath of a ZCML file which is registered with functional
-    doctests. In the ZCML file you can for example register principals
-    (users) usable by functional doctests.
-
-    By default an empty ZCML file of the z3c.testsetup package is
-    used (``ftesting.zcml``).
-
-    This parameter has no effect, if also a ``layer`` parameter is
-    given.
-
-- `layer_name`:
-
-    You can name your layer, to distinguish different setups of
-    functional doctests. The layer name can be an arbitrary string.
-
-    This parameter has no effect, if also a ``layer`` parameter is
-    given.
-
-- `layer`:
-
-    You can register a ZCML layer yourself and pass it as the
-    ``layer`` parameter. If you only have a filepath to the according
-    ZCML file, use the ``zcml_config`` paramter instead.
-
-    This parameter overrides any ``zcml_config`` and ``layer_name``
-    parameter.
-
-
-.. below:
-
-How to mark testfiles/modules
------------------------------
-
-To avoid non-wanted files and modules to be registered, you have to
-mark your wanted test files/modules with a special string explicitly:
-
-- python modules you want to register must provide a module docstring
-  that contains a line::
-
-    :Test-Layer: python
-
-  A module doctring is written at the top of file like this:
-
-  **Python Unit Test Example:**::
-
-    """
-    A module that tests things.
-
-    :Test-Layer: python
-
-    """
-    import unittest
-    class MyTest(unittest.TestCase):
-        def testFoo(self):
-            pass
-
-
-- doctest files that contain unit tests must provide a string::
-
-    :Test-Layer: unit
-
-  to be registered. Futhermore, their filename extension must be by
-  default '.txt' or '.rst'. A file `sampletest.txt` with a unit
-  doctest therefore might look like this:
-
-  **Unit Doctest Example 1:**::
-
-     ==========
-     My package
-     ==========
-
-     :Test-Layer: unit
-
-     This is documentation for the MyPackage package.
-
-        >>> 1+1
-        2
-
-  Also python modules which contain tests in doctests notation are
-  doctests. As rule of thumb you can say: if a module contains tests
-  that are written preceeded by '>>>', then this is a doctest. If
-  ``unittest.TestCase`` classes are defined, then it is a 'normal'
-  python testfile. Another valid unit doctest module therefore can
-  look like this:
-
-  **Unit Doctest Example 2:**::
-
-     """
-     ==========
-     My package
-     ==========
-
-     A package for doing things.
-
-     :Test-Layer: unit
-
-     We check for basic things::
-
-        >>> 1+1
-        2
-
-     """
-     class MyClass:
-         pass
-
-
-- files that contain functional doctests must provide a string::
-
-    :Test-Layer: functional
-
-  to be registered. Furthermore they must by default have a filename
-  extension `.txt` or `.rst`. A file `sampletest.txt` with functional
-  tests might look like this:
-
-  **Functional Doctest Example:**::
-
-     ==========
-     My package
-     ==========
-
-     :Test-Layer: functional
-
-     This is documentation for the MyPackage package.
-
-        >>> 1+1
-        2
-
-

Copied: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt (from rev 83968, z3c.testsetup/trunk/src/z3c/testsetup/README.txt)
===================================================================
--- z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt	                        (rev 0)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/README.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -0,0 +1,525 @@
+z3c.testsetup
+*************
+
+Easy testsetups for Zope 3 and Python projects.
+
+Setting up tests for Zope 3 projects sometimes tends to be
+cumbersome. ``z3c.testsetup`` jumps in here, to support much flatter
+test setups. The package supports three kinds of tests:
+
+- normal python tests: i.e. tests, that consist of python modules
+  which in turn contain ``unittest.TestCase`` classes.
+
+- unit doctests: i.e. tests, that are written as doctests, but require
+  no complicated layer setup etc.
+
+- functional doctests: i.e. tests, that are written as doctests, but
+  also require a more or less complex framework to test for example
+  browser requests.
+
+``z3c.testsetup`` is package-oriented. That means, it registers more or
+less automatically all the three kinds of tests mentioned above
+insofar they are part of a certain package.
+
+This is a general introduction to ``z3c.testsetup``. For setup
+examples you might see the ``cave`` package contained in the `tests/`
+directory. More details on special topics can be found in the
+appropriate .txt files in this directory.
+
+
+Basic Example
+=============
+
+The shortest test setup possible with ``z3c.testsetup`` looks like
+this::
+
+   >>> import z3c.testsetup
+   >>> test_suite = z3c.testsetup.register_all_tests(
+   ...                   'z3c.testsetup.tests.cave')
+
+It is sufficient to put this lines into a python module which is found
+by your testrunner (see `samplesetup_short` examples in the ``cave``
+package and ``testrunner.txt``).
+
+To sum it up, testsetup with ``z3c.testsetup`` is done in two steps:
+
+1) Make sure your testfiles are named properly (.txt/.rst for
+   doctests, valid python modules for usual unit tests) and provide a
+   suitable marker string as explained below (`How to mark
+   testfiles/modules`_).
+
+2) Write a test setup module which is named so that your testrunner
+   finds it and in this module call::
+
+      test_suite = z3c.testsetup.register_all_tests(<package>)
+
+   where ``<package>`` must be a package object. Instead of a package
+   object you can also pass the package's dotted name as string like
+   `'z3c.testsetup.tests.cave'`.
+
+Given that, this setup should find all doctests (unit and functional)
+as well as python tests in the package and register them.
+
+
+Customized Setups
+=================
+
+The `register_all_tests` function mentioned above accepts a bunch of
+keyword parameters::
+
+   register_all_tests(pkg_or_dotted_name, filter_func, extensions,
+                      encoding, checker,
+                      globs, setup, teardown, optionflags
+                      zcml_config, layer_name, layer)
+
+where all but the first parameter are keyword paramters and all but
+the package parameter are optional.
+
+While `filter_func` and `extensions` determine the set of testfiles to
+be found, the other paramters tell how to setup single tests.
+
+
+- **filter_func** (**ufilter_func**, **ffilter_func**)
+
+   a function that takes an absolute filepath and returns `True` or
+   `False`, depending on whether the file should be included in the
+   test suite as doctest or not. `filter_func` applies only to
+   doctests.
+
+   We setup a few things to check that::
+
+     >>> import os
+     >>> import unittest
+     >>> suite = test_suite()
+     >>> suite.countTestCases()
+     4
+
+   Okay, the callable in `test_suite` we created above with
+   `register_all_tests` apparently delivered four testcases. This is
+   normally also the number of files involved, but let's check that
+   correctly.
+
+   We did setup a function `get_basenames_from_suite` in this testing
+   environment (as a `globs` entry) which determines the basenames of
+   the paths of all testcases contained in a `TestSuite`::
+
+     >>> get_basenames_from_suite(suite)
+     ['file1.py', 'file1.rst', 'file1.txt', 'subdirfile.txt']
+
+   Ah, okay. There are in fact four files, in which testcases were
+   found. Now, we define a plain filter function::
+
+      >>> def custom_file_filter(path):
+      ...     """Accept all txt files."""
+      ...     return path.endswith('.txt')
+
+   This one accepts all '.txt' files. We run `register_all_tests`
+   again, but this time with a `filter_func` parameter::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     filter_func=custom_file_filter)
+
+   To get the resulting test suite, we again call the returned
+   callable::
+
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.txt', 'file1.txt', 'subdirfile.txt',
+      'subdirfile.txt']
+
+   Compared with the first call to `register_all_tests` we got some
+   strange results here: there is a '.py' file, which should have been
+   refused by our filter function and the other two files appear
+   twice. What happened?
+
+   The python module is included, because python tests are not
+   filtered by `filter_func`. Instead this value applies only to
+   doctests.
+
+   The second strange result, that every .txt file appears twice in
+   the list, comes from the fact, that the filter is valid for unit
+   and functional doctests at the same time. In other words: the tests
+   in those .txt files are registered twice, as unittests and a second
+   time as functional tests as well.
+
+   If you want a filter function for functional doctests or unit
+   doctests only, then you can use `ffilter_func` and `ufilter_func`
+   respectively::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     ffilter_func=custom_file_filter,
+      ...     ufilter_func=lambda x: False)
+
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.txt', 'subdirfile.txt']
+
+   As expected, every .txt file was only registered once. The same
+   happens, when we switch and accept only unit doctests::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     ffilter_func=lambda x: False,
+      ...     ufilter_func=custom_file_filter)
+
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.txt', 'subdirfile.txt']
+
+   If you specify both, a `filter_func` and a more specialized
+   `ufilter_func` or `ffilter_func`, then this has the same effect as
+   passing both, `ufilter_func` and `ffilter_func`::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     ffilter_func=lambda x: False,
+      ...     filter_func=custom_file_filter)
+
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.txt', 'subdirfile.txt']
+
+
+- **pfilter_func**:
+
+    Does basically the same as the ``filter_funcs`` above, but handles
+    Python modules instead of file paths. It therefore determines the
+    set of 'normal' Python tests accepted and does not touch the set
+    of doctests accepted.
+
+    We define a simple custom filter::
+
+      >>> def custom_module_filter(module):
+      ...     return 'Tests with real' in str(module.__doc__)
+
+    that checks for a certain string in modules' doc strings.
+
+    Now we start again with `pfilter_func` set::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     pfilter_func=custom_module_filter)
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.rst', 'file1.txt', 'notatest2.py', 'subdirfile.txt']
+
+    Because file1.py and notatest2.py in the cave package contain the
+    required string, this is correct. Because the default function
+    checks for the string `:Test-Layer: python`, the second module was
+    omitted by default.
+
+    Now let's use a filter, that refuses all modules::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     pfilter_func=lambda x: False)
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.rst', 'file1.txt', 'subdirfile.txt']
+
+    All Python modules vanished from the list.
+   
+    In case you wonder, why not all the other Python files of the
+    `cave` package (`__init__.py`, for example) appear in one of the
+    lists: we get only the result list, which contains only such
+    modules, which provide `unittest.TestCase` definitions. Because
+    most modules of the `cave` package don't define test cases, they
+    do not appear in the list. This automatism is driven by a
+    `unittest.TestLoader`. See
+    http://docs.python.org/lib/testloader-objects.html to learn more
+    about test loaders.
+
+
+- **extensions** (**uextensions**, **fextensions**):
+
+    a list of filename extensions to be considered during test
+    search. Default value is `['.txt', '.rst']`. Python tests are not
+    touched by this (they have to be regular Python modules with '.py'
+    extension).
+
+    Note, that the `extensions` attribute is used by the default
+    filter function. If you pass your own filter function using
+    `[u|f]filter_func`, then the extensions filtering won't work any
+    more. 
+
+    If we want to register .foo files, we can do so::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     extensions=['.foo'])
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'notatest1.foo', 'notatest1.foo']
+
+    Note, that only files that contain an appropriate marker are
+    found, regardless of the filename extension. The new .foo file
+    contains a marker for unit doctests and functional doctests, such
+    it is included twice in the list.
+
+    As we can see, the new file appears twice. This is, because it is
+    registered as functional doctest and unitdoctest as well.
+
+    To collect only functional doctests with a certain set of filename
+    extensions you can use: `fextensions`::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     fextensions=['.foo'])
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.rst', 'notatest1.foo']
+
+    Here the .rst file were registered as unit doctest, while the .foo
+    file was registered as functional doctest.
+
+    To collect only unit doctests with a different set of filename
+    extensions you can use `uextensions`::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     uextensions=['.foo'])
+      >>> suite = test_suite()
+      >>> get_basenames_from_suite(suite)
+      ['file1.py', 'file1.txt', 'notatest1.foo', 'subdirfile.txt']
+
+    Here the .foo file was registered as unit doctest and the .txt
+    files as functional ones.
+
+
+- **encoding**:   
+
+    the encoding of testfiles. 'utf-8' by default. Setting this to `None`
+    means using the default value. We've hidden one doctest file, that
+    contains umlauts. If we set the encoding to `ascii`, we get an
+    error::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     encoding='ascii')
+      >>> suite = test_suite()
+      Traceback (most recent call last):
+      ...
+      UnicodeDecodeError: 'ascii' codec can't decode ...: ordinal 
+      not in range(128)
+
+    While using 'latin-1' will work::
+
+      >>> test_suite = z3c.testsetup.register_all_tests(
+      ...     'z3c.testsetup.tests.cave',
+      ...     encoding='latin-1')
+      >>> suite = test_suite()
+      
+    No traceback here.
+
+    You can always overwrite an encoding setting for a certain file by
+    following PEP 0263 ( http://www.python.org/dev/peps/pep-0263/ ).
+
+
+- **checker**:
+
+    An output checker for functional doctests. `None` by default. A
+    typical output checker can be created like this::
+
+      >>> import re
+      >>> from zope.testing import renormalizing
+      >>> mychecker = renormalizing.RENormalizing([
+      ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
+      ...     '<SOME NUMBER OF> seconds'),
+      ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>'),
+      ... ])
+
+    This would match for example output like `0.123 seconds` if you
+    write in your doctest::
+
+      <SOME NUBMER OF> seconds
+
+    Please see ``testrunner.txt`` for examples of usage.
+
+    Checkers are applied to functional doctests only!
+
+- **globs**:
+
+    A dictionary of things that should be available immediately
+    (without imports) during tests. Defaults are::
+
+      dict(http=HTTPCaller(),
+           getRootFolder=getRootFolder,
+           sync=sync)
+
+    for functional doctests and an empty dict for unit
+    doctests. Python test globals can't be set this way.
+
+    If you want to register special globals for functional doctest or
+    unit doctests only, then you can use the `fglobs` and/or `uglobs`
+    keyword respectively. These keywords replace any `globs` value for
+    the respective kind of tests.
+
+    For more extensive examples see ``testrunner.txt``.
+
+- **setup**:
+
+    A function that takes a `test` argument and is executed before
+    every single doctest. By default it runs::
+
+      zope.app.testing.functional.FunctionalTestSetup().setUp()
+
+    for functional doctests and an empty function for unit
+    doctests. Python tests provide their own setups.
+
+    If you want to register special setup-functions for either
+    functional or unit doctests, then you can pass keyword parameters
+    `fsetup` or `usetup` respectively.
+
+- **teardown**:   
+
+    The equivalent to `setup`. Runs by default::
+
+      FunctionalTestSetup().tearDown()
+
+    for functional doctests and::
+
+      zope.testing.cleanup.cleanUp()
+
+    for unit doctests. Python tests have to provide their own teardown
+    functions in TestCases.
+
+- **optionflags**:
+
+    Optionflags influence the behaviour of the testrunner. They are
+    logically or'd so that you can add them arithmetically. See
+
+      http://svn.zope.org/zope.testing/trunk/src/zope/testing/doctest.py
+
+    for details.
+
+- **zcml_config**:
+
+    A filepath of a ZCML file which is registered with functional
+    doctests. In the ZCML file you can for example register principals
+    (users) usable by functional doctests.
+
+    By default any `ftesting.zcml` file from the root of the given
+    package is taken. If this does not exist, an empty ZCML file of
+    the z3c.testsetup package is used (``ftesting.zcml``).
+
+    This parameter has no effect, if also a ``layer`` parameter is
+    given.
+
+- **layer_name**:
+
+    You can name your layer, to distinguish different setups of
+    functional doctests. The layer name can be an arbitrary string.
+
+    This parameter has no effect, if also a ``layer`` parameter is
+    given.
+
+- **layer**:
+
+    You can register a ZCML layer yourself and pass it as the
+    ``layer`` parameter. If you only have a filepath to the according
+    ZCML file, use the ``zcml_config`` paramter instead.
+
+    This parameter overrides any ``zcml_config`` and ``layer_name``
+    parameter.
+
+
+How to mark testfiles/modules
+=============================
+
+To avoid non-wanted files and modules to be registered, you have to
+mark your wanted test files/modules with a special string explicitly:
+
+- python modules you want to register must provide a module docstring
+  that contains a line::
+
+    :Test-Layer: python
+
+  A module doctring is written at the top of file like this:
+
+  **Python Unit Test Example:**::
+
+    """
+    A module that tests things.
+
+    :Test-Layer: python
+
+    """
+    import unittest
+    class MyTest(unittest.TestCase):
+        def testFoo(self):
+            pass
+
+
+- doctest files that contain unit tests must provide a string::
+
+    :Test-Layer: unit
+
+  to be registered. Futhermore, their filename extension must be by
+  default '.txt' or '.rst'. A file `sampletest.txt` with a unit
+  doctest therefore might look like this:
+
+  **Unit Doctest Example 1:**::
+
+     ==========
+     My package
+     ==========
+
+     :Test-Layer: unit
+
+     This is documentation for the MyPackage package.
+
+        >>> 1+1
+        2
+
+  Also python modules which contain tests in doctests notation are
+  doctests. As rule of thumb you can say: if a module contains tests
+  that are written preceeded by '>>>', then this is a doctest. If
+  ``unittest.TestCase`` classes are defined, then it is a 'normal'
+  python testfile. Another valid unit doctest module therefore can
+  look like this:
+
+  **Unit Doctest Example 2:**::
+
+     """
+     ==========
+     My package
+     ==========
+
+     A package for doing things.
+
+     :Test-Layer: unit
+
+     We check for basic things::
+
+        >>> 1+1
+        2
+
+     """
+     class MyClass:
+         pass
+
+
+- files that contain functional doctests must provide a string::
+
+    :Test-Layer: functional
+
+  to be registered. Furthermore they must by default have a filename
+  extension `.txt` or `.rst`. A file `sampletest.txt` with functional
+  tests might look like this:
+
+  **Functional Doctest Example:**::
+
+     ==========
+     My package
+     ==========
+
+     :Test-Layer: functional
+
+     This is documentation for the MyPackage package.
+
+        >>> 1+1
+        2
+
+

Deleted: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/doctesting.py	2008-02-15 14:03:12 UTC (rev 83862)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py	2008-02-17 01:36:53 UTC (rev 83969)
@@ -1,183 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007-2008 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.
-#
-##############################################################################
-"""Test setup helpers for doctests.
-"""
-import unittest
-import os.path
-from zope.testing import doctest, cleanup
-from zope.app.testing.functional import (
-    HTTPCaller, getRootFolder, sync, ZCMLLayer, FunctionalDocFileSuite,
-    FunctionalTestSetup)
-from z3c.testsetup.base import BasicTestSetup
-from z3c.testsetup.util import get_package
-
-class DocTestSetup(BasicTestSetup):
-    """A test setup for doctests."""
-
-    globs = {}
-
-    optionflags = (doctest.ELLIPSIS+
-                   doctest.NORMALIZE_WHITESPACE+
-                   doctest.REPORT_NDIFF)
-
-    encoding = 'utf-8'
-
-    def __init__(self, package, setup=None, teardown=None, globs=None,
-                 optionflags=None, encoding=None, **kw):
-        BasicTestSetup.__init__(self, package, **kw)
-        self.setUp = setup or self.setUp
-        self.tearDown = teardown or self.tearDown
-        self.encoding = encoding or self.encoding
-        if globs is not None:
-            self.globs = globs
-        if optionflags is not None:
-            self.optionflags = optionflags
-        
-
-class UnitDocTestSetup(DocTestSetup):
-    """A unit test setup for packages.
-
-    A collection of methods to search for appropriate doctest files in
-    a given package. ``UnitTestSetup`` is also able to 'register' the
-    tests found and to deliver them as a ready-to-use
-    ``unittest.TestSuite`` instance.
-
-    While the functionality to search for testfiles is mostly
-    inherited from the base class, the focus here is to setup the
-    tests correctly.
-
-    See file `unittestsetup.py` in the tests/testsetup directory to
-    learn more about ``UnitTestSetup``.
-    """
-
-    optionflags = (doctest.ELLIPSIS+
-                   doctest.NORMALIZE_WHITESPACE+
-                   doctest.REPORT_NDIFF)
-
-    regexp_list = [
-        '^\s*:(T|t)est-(L|l)ayer:\s*(unit)\s*',
-        ]
-
-    globs = dict()
-
-    def setUp(self, test):
-        pass
-
-    def tearDown(self, test):
-        cleanup.cleanUp()
-
-    def getTestSuite(self):
-        docfiles = self.getDocTestFiles(package=self.package)
-        suite = unittest.TestSuite()
-        for name in docfiles:
-            if os.path.isabs(name):
-                # We get absolute pathnames, but we need relative ones...
-                common_prefix = os.path.commonprefix([self.package.__file__,
-                                                      name])
-                name = name[len(common_prefix):]
-            suite.addTest(
-                doctest.DocFileSuite(
-                name,
-                package=self.package,
-                setUp=self.setUp,
-                tearDown=self.tearDown,
-                globs=self.globs,
-                optionflags=self.optionflags,
-                **self.additional_options
-                ))
-        return suite
-
-
-class FunctionalDocTestSetup(DocTestSetup):
-    """A functional test setup for packages.
-
-    A collection of methods to search for appropriate doctest files in
-    a given package. ``FunctionalTestSetup`` is also able to
-    'register' the tests found and to deliver them as a ready-to-use
-    ``unittest.TestSuite`` instance.
-
-    While the functionality to search for testfiles is mostly
-    inherited from the base class, the focus here is to setup the
-    tests correctly.
-    """
-    ftesting_zcml = os.path.join(os.path.dirname(__file__),
-                                 'ftesting.zcml')
-    layer = ZCMLLayer(ftesting_zcml, __name__,
-                      'FunctionalLayer')
-
-    globs=dict(http=HTTPCaller(),
-               getRootFolder=getRootFolder,
-               sync=sync
-               )
-
-    optionflags = (doctest.ELLIPSIS+
-                   doctest.NORMALIZE_WHITESPACE+
-                   doctest.REPORT_NDIFF)
-
-    regexp_list = [
-        '^\s*:(T|t)est-(L|l)ayer:\s*(functional)\s*',
-        ]
-
-    checker = None
-
-    def __init__(self, package, checker=None, zcml_config = None,
-                 layer_name='FunctionalLayer', layer=None, **kw):
-        DocTestSetup.__init__(self, package, **kw)
-        self.checker = checker
-        # Setup a new layer if specified in params...
-        if zcml_config is not None and layer is None:
-            if not os.path.isfile(zcml_config):
-                zcml_config = os.path.join(
-                    os.path.dirname(self.package.__file__),
-                    zcml_config)
-            self.layer = ZCMLLayer(zcml_config, self.package.__name__,
-                                   layer_name)
-        # Passing a ready-for-use layer overrides layer specified by
-        # zcml_config...
-        if layer is not None:
-            self.layer = layer
-        return
-        
-    def setUp(self, test):
-        FunctionalTestSetup().setUp()
-
-    def tearDown(self, test):
-        FunctionalTestSetup().tearDown()
-
-    def suiteFromFile(self, name):
-        suite = unittest.TestSuite()
-        if os.path.isabs(name):
-            # We get absolute pathnames, but we need relative ones...
-            common_prefix = os.path.commonprefix([self.package.__file__, name])
-            name = name[len(common_prefix):]
-        test = FunctionalDocFileSuite(
-            name, package=self.package,
-            setUp=self.setUp, tearDown=self.tearDown,
-            globs=self.globs,
-            optionflags=self.optionflags,
-            encoding=self.encoding,
-            checker=self.checker,
-            **self.additional_options
-            )
-        test.layer = self.layer
-        suite.addTest(test)
-        return suite
-
-    def getTestSuite(self):
-        docfiles = self.getDocTestFiles(package=self.package)
-        suite = unittest.TestSuite()
-        for name in docfiles:
-            suite.addTest(self.suiteFromFile(name))
-        return suite
-

Copied: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py (from rev 83965, z3c.testsetup/trunk/src/z3c/testsetup/doctesting.py)
===================================================================
--- z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py	                        (rev 0)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/doctesting.py	2008-02-17 01:36:53 UTC (rev 83969)
@@ -0,0 +1,190 @@
+##############################################################################
+#
+# Copyright (c) 2007-2008 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.
+#
+##############################################################################
+"""Test setup helpers for doctests.
+"""
+import unittest
+import os.path
+from zope.testing import doctest, cleanup
+from zope.app.testing.functional import (
+    HTTPCaller, getRootFolder, sync, ZCMLLayer, FunctionalDocFileSuite,
+    FunctionalTestSetup)
+from z3c.testsetup.base import BasicTestSetup
+from z3c.testsetup.util import get_package
+
+class DocTestSetup(BasicTestSetup):
+    """A test setup for doctests."""
+
+    globs = {}
+
+    optionflags = (doctest.ELLIPSIS+
+                   doctest.NORMALIZE_WHITESPACE+
+                   doctest.REPORT_NDIFF)
+
+    encoding = 'utf-8'
+
+    def __init__(self, package, setup=None, teardown=None, globs=None,
+                 optionflags=None, encoding=None, **kw):
+        BasicTestSetup.__init__(self, package, **kw)
+        self.setUp = setup or self.setUp
+        self.tearDown = teardown or self.tearDown
+        self.encoding = encoding or self.encoding
+        if globs is not None:
+            self.globs = globs
+        if optionflags is not None:
+            self.optionflags = optionflags
+        
+
+class UnitDocTestSetup(DocTestSetup):
+    """A unit test setup for packages.
+
+    A collection of methods to search for appropriate doctest files in
+    a given package. ``UnitTestSetup`` is also able to 'register' the
+    tests found and to deliver them as a ready-to-use
+    ``unittest.TestSuite`` instance.
+
+    While the functionality to search for testfiles is mostly
+    inherited from the base class, the focus here is to setup the
+    tests correctly.
+
+    See file `unittestsetup.py` in the tests/testsetup directory to
+    learn more about ``UnitTestSetup``.
+    """
+
+    optionflags = (doctest.ELLIPSIS+
+                   doctest.NORMALIZE_WHITESPACE+
+                   doctest.REPORT_NDIFF)
+
+    regexp_list = [
+        '^\s*:(T|t)est-(L|l)ayer:\s*(unit)\s*',
+        ]
+
+    globs = dict()
+
+    def setUp(self, test):
+        pass
+
+    def tearDown(self, test):
+        cleanup.cleanUp()
+
+    def getTestSuite(self):
+        docfiles = self.getDocTestFiles(package=self.package)
+        suite = unittest.TestSuite()
+        for name in docfiles:
+            if os.path.isabs(name):
+                # We get absolute pathnames, but we need relative ones...
+                common_prefix = os.path.commonprefix([self.package.__file__,
+                                                      name])
+                name = name[len(common_prefix):]
+            suite.addTest(
+                doctest.DocFileSuite(
+                name,
+                package=self.package,
+                setUp=self.setUp,
+                tearDown=self.tearDown,
+                globs=self.globs,
+                optionflags=self.optionflags,
+                **self.additional_options
+                ))
+        return suite
+
+
+class FunctionalDocTestSetup(DocTestSetup):
+    """A functional test setup for packages.
+
+    A collection of methods to search for appropriate doctest files in
+    a given package. ``FunctionalTestSetup`` is also able to
+    'register' the tests found and to deliver them as a ready-to-use
+    ``unittest.TestSuite`` instance.
+
+    While the functionality to search for testfiles is mostly
+    inherited from the base class, the focus here is to setup the
+    tests correctly.
+    """
+    ftesting_zcml = os.path.join(os.path.dirname(__file__),
+                                 'ftesting.zcml')
+    layer = ZCMLLayer(ftesting_zcml, __name__,
+                      'FunctionalLayer')
+
+    globs=dict(http=HTTPCaller(),
+               getRootFolder=getRootFolder,
+               sync=sync
+               )
+
+    optionflags = (doctest.ELLIPSIS+
+                   doctest.NORMALIZE_WHITESPACE+
+                   doctest.REPORT_NDIFF)
+
+    regexp_list = [
+        '^\s*:(T|t)est-(L|l)ayer:\s*(functional)\s*',
+        ]
+
+    checker = None
+
+    def __init__(self, package, checker=None, zcml_config = None,
+                 layer_name='FunctionalLayer', layer=None, **kw):
+        DocTestSetup.__init__(self, package, **kw)
+        self.checker = checker
+        # Setup a new layer if specified in params...
+        if zcml_config is not None and layer is None:
+            if not os.path.isfile(zcml_config):
+                zcml_config = os.path.join(
+                    os.path.dirname(self.package.__file__),
+                    zcml_config)
+            self.layer = ZCMLLayer(zcml_config, self.package.__name__,
+                                   layer_name)
+        elif layer is None:
+            # Look for ftesting.zcml in pkg-root...
+            pkg_ftesting_zcml = os.path.join(
+                os.path.dirname(self.package.__file__), 'ftesting.zcml')
+            if os.path.isfile(pkg_ftesting_zcml):
+                self.layer = ZCMLLayer(pkg_ftesting_zcml,
+                                       self.package.__name__, layer_name)
+        # Passing a ready-for-use layer overrides layer specified by
+        # zcml_config...
+        if layer is not None:
+            self.layer = layer
+        return
+        
+    def setUp(self, test):
+        FunctionalTestSetup().setUp()
+
+    def tearDown(self, test):
+        FunctionalTestSetup().tearDown()
+
+    def suiteFromFile(self, name):
+        suite = unittest.TestSuite()
+        if os.path.isabs(name):
+            # We get absolute pathnames, but we need relative ones...
+            common_prefix = os.path.commonprefix([self.package.__file__, name])
+            name = name[len(common_prefix):]
+        test = FunctionalDocFileSuite(
+            name, package=self.package,
+            setUp=self.setUp, tearDown=self.tearDown,
+            globs=self.globs,
+            optionflags=self.optionflags,
+            encoding=self.encoding,
+            checker=self.checker,
+            **self.additional_options
+            )
+        test.layer = self.layer
+        suite.addTest(test)
+        return suite
+
+    def getTestSuite(self):
+        docfiles = self.getDocTestFiles(package=self.package)
+        suite = unittest.TestSuite()
+        for name in docfiles:
+            suite.addTest(self.suiteFromFile(name))
+        return suite
+

Deleted: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/functionaldoctestsetup.txt	2008-02-15 14:03:12 UTC (rev 83862)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -1,448 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2008 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.
-#
-##############################################################################
-"""
-=========================
-Functional Doc Test Setup
-=========================
-
-``FunctionalDocTestSetup`` helps to find and setup functional doctests
-contained in a package. The most important method therefore might be
-``getTestSuite()``, which searches a given package for doctest files
-and returns all tests found as a suite of functional doctests.
-
-Functional doctest setups find and register only doctests. Those tests
-can also be Python modules but if you defined real `unttest.TestCase`
-classes in your tests, then you most likely have 'normal' Python unit
-tests. Please see 'pythontestsetup.txt' in this case. For simple unit
-doctests, that do not require a more or less complex framework setup
-to be done for each test, the setups described in
-'unitdoctestsetup.txt' might suit your needs better.
-
-There are also real 'oneliners' possible, that wrap around the classes
-described here. See 'README.txt' to learn more about that.
-
-The work is done mainly in two stages:
-
-1) The package is searched for appropriate docfiles, based on the
-   settings of instance attributes.
-
-2) The tests contained in the found docfiles are setup as functional
-   tests and added to a ``unittest.TestSuite`` instance.
-
-There are plenty of default values active, if you use instances of
-this class without further modifications. Therefore we will first
-discuss the default behaviour and afterwards show, how you can modify
-this behaviour to suit your special expectations on the tests.
-
-
-Setting up a simple test suite
-------------------------------
-
-We want to register the doctests contained in the local ``cave``
-package. This can be simply archieved by doing::
-
-   >>> from z3c.testsetup import FunctionalDocTestSetup
-   >>> setup = FunctionalDocTestSetup('z3c.testsetup.tests.cave')
-   >>> setup
-   <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>
-
-Apparently the package to handle was passed as a string in 'dotted
-name' notation. We could also pass the package itself, if it was
-loaded before::
-
-   >>> from z3c.testsetup.tests import cave
-   >>> setup = FunctionalDocTestSetup(cave)
-   >>> setup
-   <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>   
-
-This setup is ready for use::
-
-   >>> suite = setup.getTestSuite()
-   >>> suite
-   <unittest.TestSuite tests=[...]>
-
-To sum it up, writing a test setup for a project now can be that
-short::
-
-   import z3c.testsetup
-   def test_suite():
-       setup = z3c.testsetup.FunctionalDocTestSetup('z3c.testsetup.tests.cave')
-       return setup.getTestSuite()
-
-This will find all .rst and .txt files in the package that provide a
-certain signature (see below), register the contained tests as
-functional tests and run them as part of a `unittest.TestSuite`.
-
-Note: in many test setups you will find a code fragment like the
-      following at the end of file::
-
-        if __name__ == '__main__':
-            unittest.main(default='test_suite')
-
-      This is not neccessary for usual testrunner setups. A testrunner
-      will look for appropriate filenames (modules) and if those
-      modules provide a callable ``test_suite`` (usually a function)
-      this callable will be called to deliver a test suite.
-
-FunctionalDocTestSetup default values
--------------------------------------
-
-Understanding the defaults is important, because the default values
-are driving the whole process of finding and registering the test.
-
-
-Which files are found by default?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Basically, all files are accepted that
-
-1) reside inside the package passed to the constructor. This includes
-   subdirectories.
-
-2) have a filename extension `.txt` or `.rst` (uppercase, lowercase
-   etc. does not matter).
-
-3) are *not* located inside a 'hidden' directory (i.e. a directory
-   starting with a dot ('.'). Also subdirectories of 'hidden'
-   directories are skipped.
-
-4) contain a ReStructured Text meta-marker somewhere, that defines the
-   file as a functional doctest explicitly::
-
-       :Test-Layer: functional
-
-   This means: there *must* be a line like the above one in the
-   doctest file. The term might be preceeded or followed by whitspace
-   characters (spaces, tabs).
-
-Only files, that meet all four conditions are searched for functional
-doctests. You can modify this behaviour of course, which will be
-explained below in detail.
-
-
-What options are set by default?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Many options can be set, when registering functional doctests. When
-using the default set of options, the following values are set::
-
-* The setup-instance's ``setUp``-method is set as the ``setUp``
-  function.
-
-* The setup-instance's ``tearDown``-method is set as the ``tearDown``
-  function.
-  
-     >>> setup.setUp
-     <bound method FunctionalDocTestSetup.setUp of
-      <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>>
-
-* The setup-instance's `globs` attribute is passed as the `globs`
-  parameter. By default `globs` is a dictionary of functions, that
-  should be'globally' available during testruns and it contains::
-
-     >>> setup.globs
-     {'http': <zope.app.testing.functional.HTTPCaller object at 0x...>,
-      'sync': <function sync at 0x...>,
-      'getRootFolder': <function getRootFolder at 0x...>}
-
-  The functions `sync` and `getRootFolder` are provided by
-  `zope.app.testing.functional`.
-
-* The setup-instance's `optionsflags` attribute is passed. It
-  includes by default the following doctest constants:
-
-     >>> from zope.testing import doctest
-     >>> setup.optionflags == (doctest.ELLIPSIS+
-     ...                       doctest.NORMALIZE_WHITESPACE |
-     ...                       doctest.REPORT_NDIFF)
-     True
-
-* The setup-instances `encoding` attribute is passed. Setting it in
-  the constructor will expect doctest files to provide the appropriate
-  encoding. By default it is set to 'utf-8':
-
-     >>> setup.encoding
-     'utf-8'
-
-  You can set it to a another value for differently encoded doctests.
-  If no encoding is set (`encoding` is None), 7-bit ASCII will be
-  assumed.
-
-* The `checker` attribute helps to renormalize expected
-  output. A typical output checker can be created like this::
-
-     >>> import re
-     >>> from zope.testing import renormalizing
-     >>> mychecker = renormalizing.RENormalizing([
-     ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
-     ...     '<SOME NUMBER OF> seconds'),
-     ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>'),
-     ... ])
-
-  By default a `FunctionalDocTest` instance has no checker::
-
-     >>> setup.checker is None
-     True
-
-Because functional tests require a ZCML layer, that defines a ZCML
-setup for the tests, we provide a layer, that is driven by the file
-`ftesting.zcml`, which comes with `z3c.testsetup`. The layer is
-accessible as the setup instance attribute `layer`::
-
-   >>> setup.layer
-   <zope.app.testing.functional.ZCMLLayer instance at 0x...>
-
-   >>> setup.layer.config_file
-   '...ftesting.zcml'
-
-You can define a custom layer. This is described below.
-
-
-No other options/parameters are set by default.
-
-
-Customizing functional test setup:
-----------------------------------
-
-You can modify the behaviour of z3c.testsetup.FunctionalTestSetup such,
-that a different set of files is registered and/or the found tests are
-registered with a different set of parameters/options. We will first
-discuss modifying the set of files to be searched.
-
-
-Customizing the doctest file search:
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The searching of appropriate doctest files is basically done by the
-base class `BasicTestSetup`. Its purpose is to determine the set of
-files in a package, that contain functional tests. See the testfile
-`basicsetup.txt` to learn more about the procedure.
-
-The functional test setup, however, provides a special
-`isDocTestFile()` method, which does additional checking. Namely it
-checks for the existance of the above mentioned ReStructured Text
-meta-marker::
-
-    `:Test-Layer: functional`
-
-This is determined by a list of regular expressions, which is also
-available as an object attribute::
-
-    >>> setup.regexp_list
-    ['^\\s*:(T|t)est-(L|l)ayer:\\s*(functional)\\s*']
-
-This is the default value of functional doctest setups.
-
-There are two files in the `cave` subpackage, which include that
-marker. We can get the list of test files using
-`getDocTestFiles()``::
-
-    >>> testfile_list = setup.getDocTestFiles()
-    >>> testfile_list.sort()
-    >>> testfile_list
-    ['...file1.txt', '...subdirfile.txt']
-
-    >>> len(testfile_list)
-    2
-
-The ``isTestFile()`` method of our setup object did the filtering
-here::
-
-    >>> setup.isTestFile(testfile_list[0])
-    True
-
-The file file1.rst does not contain a functional test marker::
-
-    >>> import os.path
-    >>> path = os.path.join(os.path.dirname(cave.__file__),
-    ...                     'test1.rst')
-    >>> setup.isTestFile(path)
-    False
-
-The `regexp_list` attribute of a ``FunctionalTestSetup`` contains a
-list of regular expressions, of which each one must at least match one
-line of a searched file to be accepted. If you want to include files
-with different marker-strings, just change this attribute. The value
-will influence behaviour of the `isTestFile()``, ``getDocTestFiles()``
-and ``getTestSuite()`` methods.
-
-If you need more complex checks here, you can derive your customized
-test setup class and overwrite ``isTestFile()``.
-
-See `basicsetup.py` for further methods how to modify test file
-search, for example by choosing another set of accepted filename
-extensions.
-
-
-Customizing the functional doctest setup
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To customize the setup of your tests, you have three options:
-
-- Pass appropriate parameters to the constructor.
-
-- Set attributes of an existing `FunctionalDocTestSetup` instance.
-
-- Create your own class derived from `FunctionalDocTestSetup`.
-
-The first two ways should suit most testing environments. All the
-attributes mentioned above are settable at creation time, namely:
-
-- `setup`::
-
-       >>> def myfunc(test):
-       ...     """A useless function."""
-       ...     print "Hello!"
-       >>> mysetup = FunctionalDocTestSetup(cave, setup=myfunc)
-       >>> mysetup.setUp(None)
-       Hello!
-
-- `teardown`::
-
-       >>> mysetup = FunctionalDocTestSetup(cave, teardown=myfunc)
-       >>> mysetup.tearDown(None)
-       Hello!
-
-- `globs`:
-
-   `globs` is a dictionary of things (objects, functions, vars) that
-   are available for every test immediately (without import or
-   similar)::
-
-       >>> mysetup = FunctionalDocTestSetup(
-       ...                cave, globs={'myfunc': myfunc})
-       >>> mysetup.globs
-       {'myfunc': <function myfunc at 0x...>}
-
-- `optionflags`
-
-    See the `zope.testing.doctest` module for all optionflags::
-
-       >>> from zope.testing import doctest
-       >>> mysetup = FunctionalDocTestSetup(
-       ...     cave, optionflags=(doctest.ELLIPSIS +
-       ...                        doctest.REPORT_UDIFF))
-       >>> mysetup.optionflags & doctest.REPORT_NDIFF == 0
-       True
-
-       >>> mysetup.optionflags & doctest.REPORT_UDIFF == doctest.REPORT_UDIFF
-       True
-
-- `checker`
-
-    An output checker for functional doctests. `None` by default. A
-    typical output checker can be created like this::
-
-       >>> import re
-       >>> from zope.testing import renormalizing
-       >>> mychecker = renormalizing.RENormalizing([
-       ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
-       ...     '<SOME NUMBER OF> seconds'),
-       ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>') ])
-
-    Then, a setup with this checker can be created::
-
-       >>> mysetup = FunctionalDocTestSetup(cave, checker = mychecker) 
-       >>> mysetup.checker
-       <zope.testing.renormalizing.RENormalizing instance at 0x...>
-
-    Let's see, whether we got the wanted checker, by passing an
-    example string, which should match the first of the terms defined
-    in the checker::
-
-       >>> mysetup.checker.check_output(
-       ... '''\
-       ...    Test took 0.012 seconds
-       ... ''', '''\
-       ...    Test took <SOME NUMBER OF> seconds
-       ... ''', 0)
-       True
-
-     See the `zope.testing.renormalizing` module for more things, you
-     can do with checkers.
-
-- `encoding`
-
-    If your doctests contain non-ASCII characters, this might lead to
-    problems. You can circumvent this by setting an appropriate
-    encoding string in the header of your doctest files. Another
-    possibility is to pass the encoding keyword. By default
-    z3c.testsetup uses 'utf-8' as default encoding::
-
-       >>> setup.encoding
-       'utf-8'
-
-    But you can set it as you like::
-
-       >>> mysetup = FunctionalDocTestSetup(cave, encoding = 'ascii')
-       >>> mysetup.encoding
-       'ascii'
-
-To setup layers, there are the following constructor options
-available:
-
-- `zcml_config`
-
-- `layer_name`
-
-- `layer`
-
-Their usage is explained in the next section.
-
-
-Cutomizing the ZCML layer
-+++++++++++++++++++++++++
-
-The ZCML layer registered by default by ``z3c.testsetup`` is very
-poor. In fact it only exists, to satisfy dependencies. In most cases,
-you would like to write your own ZCML configuration to register
-principals etc. during functional doctests.
-
-For this purpose, ``FunctionalDocTestSetup`` supports the constructor
-parameters `zcml_config` and `layer_name`. If the first is set, then
-the ZCML file denoted by the path in this variable will be used
-instead of the dummy ZCML contained in ``z3c.testsetup``.
-
-   >>> setup_w_custom_layer = FunctionalDocTestSetup(
-   ...     cave,
-   ...     zcml_config = 'sampleftesting.zcml')
-   >>> pnorm(setup_w_custom_layer.layer.config_file)
-   '.../tests/cave/sampleftesting.zcml'
-
-You can also pass a keyword parameter `layer`, which should provide a
-value with a ready-to-use ZCML layer. If this happens, the
-`zcml_config` and `layer_name` parameter will have no effect. 
-
-To show this, we first create a custom layer::
-
-   >>> from zope.app.testing.functional import ZCMLLayer
-   >>> mylayer = ZCMLLayer(
-   ...     os.path.join(os.path.dirname(__file__), 'ftesting.zcml'),
-   ...     __name__,
-   ...     'MyFunctionalLayer')
-
-and create a functional doctest setup with it::
-
-   >>> setup_w_custom_layer = FunctionalDocTestSetup(
-   ...     cave,
-   ...     zcml_config = 'sampleftesting.zcml',
-   ...     layer = mylayer)
-   >>> pnorm(setup_w_custom_layer.layer.config_file)
-   '.../testsetup/ftesting.zcml'
-
-As we can see, the `mylayer` config file is registered and the
-`zcml_config` parameter was skipped.
-
-
-"""

Copied: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt (from rev 83965, z3c.testsetup/trunk/src/z3c/testsetup/functionaldoctestsetup.txt)
===================================================================
--- z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt	                        (rev 0)
+++ z3c.testsetup/tags/0.2.0/src/z3c/testsetup/functionaldoctestsetup.txt	2008-02-17 01:36:53 UTC (rev 83969)
@@ -0,0 +1,485 @@
+##############################################################################
+#
+# Copyright (c) 2008 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.
+#
+##############################################################################
+"""
+=========================
+Functional Doc Test Setup
+=========================
+
+``FunctionalDocTestSetup`` helps to find and setup functional doctests
+contained in a package. The most important method therefore might be
+``getTestSuite()``, which searches a given package for doctest files
+and returns all tests found as a suite of functional doctests.
+
+Functional doctest setups find and register only doctests. Those tests
+can also be Python modules but if you defined real `unttest.TestCase`
+classes in your tests, then you most likely have 'normal' Python unit
+tests. Please see 'pythontestsetup.txt' in this case. For simple unit
+doctests, that do not require a more or less complex framework setup
+to be done for each test, the setups described in
+'unitdoctestsetup.txt' might suit your needs better.
+
+There are also real 'oneliners' possible, that wrap around the classes
+described here. See 'README.txt' to learn more about that.
+
+The work is done mainly in two stages:
+
+1) The package is searched for appropriate docfiles, based on the
+   settings of instance attributes.
+
+2) The tests contained in the found docfiles are setup as functional
+   tests and added to a ``unittest.TestSuite`` instance.
+
+There are plenty of default values active, if you use instances of
+this class without further modifications. Therefore we will first
+discuss the default behaviour and afterwards show, how you can modify
+this behaviour to suit your special expectations on the tests.
+
+
+Setting up a simple test suite
+------------------------------
+
+We want to register the doctests contained in the local ``cave``
+package. This can be simply archieved by doing::
+
+   >>> from z3c.testsetup import FunctionalDocTestSetup
+   >>> setup = FunctionalDocTestSetup('z3c.testsetup.tests.cave')
+   >>> setup
+   <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>
+
+Apparently the package to handle was passed as a string in 'dotted
+name' notation. We could also pass the package itself, if it was
+loaded before::
+
+   >>> from z3c.testsetup.tests import cave
+   >>> setup = FunctionalDocTestSetup(cave)
+   >>> setup
+   <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>   
+
+This setup is ready for use::
+
+   >>> suite = setup.getTestSuite()
+   >>> suite
+   <unittest.TestSuite tests=[...]>
+
+To sum it up, writing a test setup for a project now can be that
+short::
+
+   import z3c.testsetup
+   def test_suite():
+       setup = z3c.testsetup.FunctionalDocTestSetup('z3c.testsetup.tests.cave')
+       return setup.getTestSuite()
+
+This will find all .rst and .txt files in the package that provide a
+certain signature (see below), register the contained tests as
+functional tests and run them as part of a `unittest.TestSuite`.
+
+Note: in many test setups you will find a code fragment like the
+      following at the end of file::
+
+        if __name__ == '__main__':
+            unittest.main(default='test_suite')
+
+      This is not neccessary for usual testrunner setups. A testrunner
+      will look for appropriate filenames (modules) and if those
+      modules provide a callable ``test_suite`` (usually a function)
+      this callable will be called to deliver a test suite.
+
+FunctionalDocTestSetup default values
+-------------------------------------
+
+Understanding the defaults is important, because the default values
+are driving the whole process of finding and registering the test.
+
+
+Which files are found by default?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Basically, all files are accepted that
+
+1) reside inside the package passed to the constructor. This includes
+   subdirectories.
+
+2) have a filename extension `.txt` or `.rst` (uppercase, lowercase
+   etc. does not matter).
+
+3) are *not* located inside a 'hidden' directory (i.e. a directory
+   starting with a dot ('.'). Also subdirectories of 'hidden'
+   directories are skipped.
+
+4) contain a ReStructured Text meta-marker somewhere, that defines the
+   file as a functional doctest explicitly::
+
+       :Test-Layer: functional
+
+   This means: there *must* be a line like the above one in the
+   doctest file. The term might be preceeded or followed by whitspace
+   characters (spaces, tabs).
+
+Only files, that meet all four conditions are searched for functional
+doctests. You can modify this behaviour of course, which will be
+explained below in detail.
+
+
+What options are set by default?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many options can be set, when registering functional doctests. When
+using the default set of options, the following values are set::
+
+* The setup-instance's ``setUp``-method is set as the ``setUp``
+  function.
+
+* The setup-instance's ``tearDown``-method is set as the ``tearDown``
+  function.
+  
+     >>> setup.setUp
+     <bound method FunctionalDocTestSetup.setUp of
+      <z3c.testsetup.doctesting.FunctionalDocTestSetup object at 0x...>>
+
+* The setup-instance's `globs` attribute is passed as the `globs`
+  parameter. By default `globs` is a dictionary of functions, that
+  should be'globally' available during testruns and it contains::
+
+     >>> setup.globs
+     {'http': <zope.app.testing.functional.HTTPCaller object at 0x...>,
+      'sync': <function sync at 0x...>,
+      'getRootFolder': <function getRootFolder at 0x...>}
+
+  The functions `sync` and `getRootFolder` are provided by
+  `zope.app.testing.functional`.
+
+* The setup-instance's `optionsflags` attribute is passed. It
+  includes by default the following doctest constants:
+
+     >>> from zope.testing import doctest
+     >>> setup.optionflags == (doctest.ELLIPSIS+
+     ...                       doctest.NORMALIZE_WHITESPACE |
+     ...                       doctest.REPORT_NDIFF)
+     True
+
+* The setup-instances `encoding` attribute is passed. Setting it in
+  the constructor will expect doctest files to provide the appropriate
+  encoding. By default it is set to 'utf-8':
+
+     >>> setup.encoding
+     'utf-8'
+
+  You can set it to a another value for differently encoded doctests.
+  If no encoding is set (`encoding` is None), 7-bit ASCII will be
+  assumed.
+
+* The `checker` attribute helps to renormalize expected
+  output. A typical output checker can be created like this::
+
+     >>> import re
+     >>> from zope.testing import renormalizing
+     >>> mychecker = renormalizing.RENormalizing([
+     ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
+     ...     '<SOME NUMBER OF> seconds'),
+     ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>'),
+     ... ])
+
+  By default a `FunctionalDocTest` instance has no checker::
+
+     >>> setup.checker is None
+     True
+
+Because functional tests require a ZCML layer, that defines a ZCML
+setup for the tests, we provide a layer, that is driven by the file
+`ftesting.zcml`, which comes with `z3c.testsetup`. The layer is
+accessible as the setup instance attribute `layer`::
+
+   >>> setup.layer
+   <zope.app.testing.functional.ZCMLLayer instance at 0x...>
+
+   >>> setup.layer.config_file
+   '...ftesting.zcml'
+
+You can define a custom layer. This is described below.
+
+
+No other options/parameters are set by default.
+
+
+Customizing functional test setup:
+----------------------------------
+
+You can modify the behaviour of z3c.testsetup.FunctionalTestSetup such,
+that a different set of files is registered and/or the found tests are
+registered with a different set of parameters/options. We will first
+discuss modifying the set of files to be searched.
+
+
+Customizing the doctest file search:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The searching of appropriate doctest files is basically done by the
+base class `BasicTestSetup`. Its purpose is to determine the set of
+files in a package, that contain functional tests. See the testfile
+`basicsetup.txt` to learn more about the procedure.
+
+The functional test setup, however, provides a special
+`isDocTestFile()` method, which does additional checking. Namely it
+checks for the existance of the above mentioned ReStructured Text
+meta-marker::
+
+    `:Test-Layer: functional`
+
+This is determined by a list of regular expressions, which is also
+available as an object attribute::
+
+    >>> setup.regexp_list
+    ['^\\s*:(T|t)est-(L|l)ayer:\\s*(functional)\\s*']
+
+This is the default value of functional doctest setups.
+
+There are two files in the `cave` subpackage, which include that
+marker. We can get the list of test files using
+`getDocTestFiles()``::
+
+    >>> testfile_list = setup.getDocTestFiles()
+    >>> testfile_list.sort()
+    >>> testfile_list
+    ['...file1.txt', '...subdirfile.txt']
+
+    >>> len(testfile_list)
+    2
+
+The ``isTestFile()`` method of our setup object did the filtering
+here::
+
+    >>> setup.isTestFile(testfile_list[0])
+    True
+
+The file file1.rst does not contain a functional test marker::
+
+    >>> import os.path
+    >>> path = os.path.join(os.path.dirname(cave.__file__),
+    ...                     'test1.rst')
+    >>> setup.isTestFile(path)
+    False
+
+The `regexp_list` attribute of a ``FunctionalTestSetup`` contains a
+list of regular expressions, of which each one must at least match one
+line of a searched file to be accepted. If you want to include files
+with different marker-strings, just change this attribute. The value
+will influence behaviour of the `isTestFile()``, ``getDocTestFiles()``
+and ``getTestSuite()`` methods.
+
+If you need more complex checks here, you can derive your customized
+test setup class and overwrite ``isTestFile()``.
+
+See `basicsetup.py` for further methods how to modify test file
+search, for example by choosing another set of accepted filename
+extensions.
+
+
+Customizing the functional doctest setup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To customize the setup of your tests, you have three options:
+
+- Pass appropriate parameters to the constructor.
+
+- Set attributes of an existing `FunctionalDocTestSetup` instance.
+
+- Create your own class derived from `FunctionalDocTestSetup`.
+
+The first two ways should suit most testing environments. All the
+attributes mentioned above are settable at creation time, namely:
+
+- `setup`::
+
+       >>> def myfunc(test):
+       ...     """A useless function."""
+       ...     print "Hello!"
+       >>> mysetup = FunctionalDocTestSetup(cave, setup=myfunc)
+       >>> mysetup.setUp(None)
+       Hello!
+
+- `teardown`::
+
+       >>> mysetup = FunctionalDocTestSetup(cave, teardown=myfunc)
+       >>> mysetup.tearDown(None)
+       Hello!
+
+- `globs`:
+
+   `globs` is a dictionary of things (objects, functions, vars) that
+   are available for every test immediately (without import or
+   similar)::
+
+       >>> mysetup = FunctionalDocTestSetup(
+       ...                cave, globs={'myfunc': myfunc})
+       >>> mysetup.globs
+       {'myfunc': <function myfunc at 0x...>}
+
+- `optionflags`
+
+    See the `zope.testing.doctest` module for all optionflags::
+
+       >>> from zope.testing import doctest
+       >>> mysetup = FunctionalDocTestSetup(
+       ...     cave, optionflags=(doctest.ELLIPSIS +
+       ...                        doctest.REPORT_UDIFF))
+       >>> mysetup.optionflags & doctest.REPORT_NDIFF == 0
+       True
+
+       >>> mysetup.optionflags & doctest.REPORT_UDIFF == doctest.REPORT_UDIFF
+       True
+
+- `checker`
+
+    An output checker for functional doctests. `None` by default. A
+    typical output checker can be created like this::
+
+       >>> import re
+       >>> from zope.testing import renormalizing
+       >>> mychecker = renormalizing.RENormalizing([
+       ...    (re.compile('[0-9]*[.][0-9]* seconds'), 
+       ...     '<SOME NUMBER OF> seconds'),
+       ...    (re.compile('at 0x[0-9a-f]+'), 'at <SOME ADDRESS>') ])
+
+    Then, a setup with this checker can be created::
+
+       >>> mysetup = FunctionalDocTestSetup(cave, checker = mychecker) 
+       >>> mysetup.checker
+       <zope.testing.renormalizing.RENormalizing instance at 0x...>
+
+    Let's see, whether we got the wanted checker, by passing an
+    example string, which should match the first of the terms defined
+    in the checker::
+
+       >>> mysetup.checker.check_output(
+       ... '''\
+       ...    Test took 0.012 seconds
+       ... ''', '''\
+       ...    Test took <SOME NUMBER OF> seconds
+       ... ''', 0)
+       True
+
+     See the `zope.testing.renormalizing` module for more things, you
+     can do with checkers.
+
+- `encoding`
+
+    If your doctests contain non-ASCII characters, this might lead to
+    problems. You can circumvent this by setting an appropriate
+    encoding string in the header of your doctest files. Another
+    possibility is to pass the encoding keyword. By default
+    z3c.testsetup uses 'utf-8' as default encoding::
+
+       >>> setup.encoding
+       'utf-8'
+
+    But you can set it as you like::
+
+       >>> mysetup = FunctionalDocTestSetup(cave, encoding = 'ascii')
+       >>> mysetup.encoding
+       'ascii'
+
+To setup layers, there are the following constructor options
+available:
+
+- `zcml_config`
+
+    The path to a ZCML file, often named `ftesting.zcml`. If a
+    package, provides a file `ftesting.zcml` in its root, then this is
+    taken as default. The ``cave_to_let`` package in the tests/
+    directory provides such an `ftesting.zcml`::
+
+       >>> from z3c.testsetup.tests import cave_to_let
+       >>> setup = FunctionalDocTestSetup(cave_to_let)
+       >>> pnorm(setup.layer.config_file)
+       '.../tests/cave_to_let/ftesting.zcml'
+
+    The fallback-solution is to take the layer from the
+    `z3c.testsetup` package::
+
+       >>> setup = FunctionalDocTestSetup(cave)
+       >>> pnorm(setup.layer.config_file)
+       '...z3c/testsetup/ftesting.zcml'
+
+    Now the fallback `ftesting.zcml` was taken, because the cave got
+    no own ftesting.zcml.
+
+- `layer_name`
+
+    A string. The default is ``FunctionalLayer``.
+
+- `layer`
+
+    A ``zope.app.testing.functional.ZCMLLayer`` object. Setting a
+    layer overrides `zcml_config` and `layer_name`.
+
+Their usage is explained in the next section.
+
+
+Cutomizing the ZCML layer
++++++++++++++++++++++++++
+
+The ZCML layer of a FunctionalDocTestSetup is searched in four steps:
+
+1) If a setup is called with `layer` parameter, take this.
+
+2) If a setup is called with `zcml_config` paramter, take this.
+
+3) If an `ftesting.zcml` can be found in the root of the package to
+   search, take this (default).
+
+4) Take the (very poor) ftesting.zcml of the z3c.testsetup package
+   (fallback).
+
+The ZCML layer registered as fallback by ``z3c.testsetup`` is very
+poor. In fact it only exists, to satisfy dependencies. In most cases,
+you would like to write your own ZCML configuration to register
+principals etc. during functional doctests.
+
+For this purpose, ``FunctionalDocTestSetup`` supports the constructor
+parameters `zcml_config` and `layer_name`. If the first is set, then
+the ZCML file denoted by the path in this variable will be used
+instead of the dummy ZCML contained in ``z3c.testsetup``.
+
+   >>> setup_w_custom_layer = FunctionalDocTestSetup(
+   ...     cave,
+   ...     zcml_config = 'sampleftesting.zcml')
+   >>> pnorm(setup_w_custom_layer.layer.config_file)
+   '.../tests/cave/sampleftesting.zcml'
+
+You can also pass a keyword parameter `layer`, which should provide a
+value with a ready-to-use ZCML layer. If this happens, the
+`zcml_config` and `layer_name` parameter will have no effect. 
+
+To show this, we first create a custom layer::
+
+   >>> from zope.app.testing.functional import ZCMLLayer
+   >>> mylayer = ZCMLLayer(
+   ...     os.path.join(os.path.dirname(__file__), 'ftesting.zcml'),
+   ...     __name__,
+   ...     'MyFunctionalLayer')
+
+and create a functional doctest setup with it::
+
+   >>> setup_w_custom_layer = FunctionalDocTestSetup(
+   ...     cave,
+   ...     zcml_config = 'sampleftesting.zcml',
+   ...     layer = mylayer)
+   >>> pnorm(setup_w_custom_layer.layer.config_file)
+   '.../testsetup/ftesting.zcml'
+
+As we can see, the `mylayer` config file is registered and the
+`zcml_config` parameter was skipped.
+
+
+"""

Copied: z3c.testsetup/tags/0.2.0/src/z3c/testsetup/tests/cave_to_let (from rev 83965, z3c.testsetup/trunk/src/z3c/testsetup/tests/cave_to_let)



More information about the Checkins mailing list