[Checkins] SVN: grok/trunk/ Merge ulif-testsetup-pre0.13 branch
into trunk.
Uli Fouquet
uli at gnufix.de
Fri Apr 25 15:10:30 EDT 2008
Log message for revision 85730:
Merge ulif-testsetup-pre0.13 branch into trunk.
Changed:
U grok/trunk/CHANGES.txt
U grok/trunk/setup.py
U grok/trunk/src/grok/testing.py
D grok/trunk/src/grok/tests/testsetup/basicsetup.py
A grok/trunk/src/grok/tests/testsetup/cave/file1.py
A grok/trunk/src/grok/tests/testsetup/cave/ftesting.zcml
U grok/trunk/src/grok/tests/testsetup/cave/notatest1.foo
A grok/trunk/src/grok/tests/testsetup/cave/sample.zcml
A grok/trunk/src/grok/tests/testsetup/cave/samplesetup1.py
A grok/trunk/src/grok/tests/testsetup/cave/samplesetup2.py
A grok/trunk/src/grok/tests/testsetup/cave/samplesetup3.py
A grok/trunk/src/grok/tests/testsetup/cave/samplesetup4.py
A grok/trunk/src/grok/tests/testsetup/cave_to_let/
D grok/trunk/src/grok/tests/testsetup/functionalsetup.py
A grok/trunk/src/grok/tests/testsetup/testsetup.py
D grok/trunk/src/grok/tests/testsetup/unittestsetup.py
U grok/trunk/versions.cfg
-=-
Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/CHANGES.txt 2008-04-25 19:10:27 UTC (rev 85730)
@@ -4,9 +4,22 @@
0.13 (unreleased)
=================
-Bugs fixed
-----------
+Feature changes
+---------------
+* Added support for easier testsetup based on z3c.testsetup. This is a
+ more stable and more powerful implementation of
+ grok.testing.register_all_tests(). See
+
+ http://grok.zope.org/documentation/how-to/tests-with-grok-testing
+
+ for details.
+
+Bug fixes
+---------
+
+* Removed first testsetup hack from grok.testing.
+
* Version 2.1 of z3c.autoinclude contained code that caused Grok to
fail to start on some platforms if the system-supplied Python was
used (at least on some versions of Ubuntu and Debian). Now include
@@ -14,11 +27,6 @@
fix was also made on Grok 0.12 in its online versions list after
release.
-Feature changes
----------------
-
-* ...
-
0.12 (2008-04-22)
=================
Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/setup.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -81,5 +81,6 @@
'zc.catalog',
'z3c.flashmessage',
'z3c.autoinclude',
+ 'z3c.testsetup',
],
)
Modified: grok/trunk/src/grok/testing.py
===================================================================
--- grok/trunk/src/grok/testing.py 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/src/grok/testing.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -16,210 +16,27 @@
from zope.configuration.config import ConfigurationMachine
from martian import scan
from grok import zcml
-
-import unittest
-from os import listdir
+import z3c.testsetup
import os.path
-import re
-from zope.testing import doctest, cleanup
-from zope.app.testing.functional import (
- HTTPCaller, getRootFolder, FunctionalTestSetup,
- sync, ZCMLLayer, FunctionalDocFileSuite)
-class BasicTestSetup(object):
- """A basic test setup for a package.
+class GrokTestCollector(z3c.testsetup.TestCollector):
- A basic test setup is a aggregation of methods and attributes to
- search for appropriate doctest files in a package. Its purpose is
- to collect all basic functionality, that is needed by derived
- classes, that do real test registration.
- """
+ def initialize(self):
+ # inject the grok ftesting ZCML as fallback...
+ if 'zcml_config' in self.settings.keys():
+ return
+ pkg_path = os.path.dirname(self.package.__file__)
+ if os.path.isfile(os.path.join(pkg_path, 'ftesting.zcml')):
+ return
+ self.settings['zcml_config'] = os.path.join(
+ os.path.dirname(__file__), 'ftesting.zcml')
+ if 'layer_name' in self.settings.keys():
+ return
+ self.settings['layer_name'] = 'GrokFunctionalLayer'
- extensions = ['.rst', '.txt']
+def register_all_tests(pkg, *args, **kw):
+ return GrokTestCollector(pkg, *args, **kw)
- regexp_list = []
-
- additional_options = {}
-
- def __init__(self, package, filter_func=None, extensions=None, **kw):
- self.package = package
- self.filter_func = filter_func or self.isTestFile
- self.extensions = extensions or self.extensions
- self.additional_options = kw
- return
-
- def setUp(self, test):
- pass
-
- def tearDown(self, test):
- pass
-
- def fileContains(self, filename, regexp_list):
- """Does a file contain lines matching every of the regular
- expressions?
- """
- found_list = []
- try:
- for line in open(filename):
- for regexp in regexp_list:
- if re.compile(regexp).match(line) and (
- regexp not in found_list):
- found_list.append(regexp)
- if len(regexp_list) == len(found_list):
- break
- except IOError:
- # be gentle
- pass
- return len(regexp_list) == len(found_list)
-
- def isTestFile(self, filepath):
- """Return ``True`` if a file matches our expectations for a
- doctest file.
- """
- if os.path.splitext(filepath)[1].lower() not in self.extensions:
- return False
- if not self.fileContains(filepath, self.regexp_list):
- return False
- return True
-
- def isTestDirectory(self, dirpath):
- """Check whether a given directory should be searched for tests.
- """
- if os.path.basename(dirpath).startswith('.'):
- # We don't search hidden directories like '.svn'
- return False
- return True
-
- def getDocTestFiles(self, dirpath=None, **kw):
- """Find all doctest files filtered by filter_func.
- """
- if dirpath is None:
- dirpath = os.path.dirname(self.package.__file__)
- dirlist = []
- for filename in listdir(dirpath):
- abs_path = os.path.join(dirpath, filename)
- if not os.path.isdir(abs_path):
- if self.filter_func(abs_path):
- dirlist.append(abs_path)
- continue
- # Search subdirectories...
- if not self.isTestDirectory(abs_path):
- continue
- subdir_files = self.getDocTestFiles(dirpath=abs_path, **kw)
- dirlist.extend(subdir_files)
- return dirlist
-
-
-class UnitTestSetup(BasicTestSetup):
- """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*',
- ]
-
-
- 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,
- optionflags=self.optionflags,
- **self.additional_options
- ))
- return suite
-
-
-class FunctionalTestSetup(BasicTestSetup):
- """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*',
- ]
-
- 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,
- **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
-
-
def grok(module_name):
config = ConfigurationMachine()
zcml.do_grok('grok.meta', config)
Deleted: grok/trunk/src/grok/tests/testsetup/basicsetup.py
===================================================================
--- grok/trunk/src/grok/tests/testsetup/basicsetup.py 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/src/grok/tests/testsetup/basicsetup.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -1,258 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-================
-Basic Test Setup
-================
-
-``BasicTestSetup`` is a class to support easier setup of tests in grok
-projects. It acts merely as a container for shared functions, methods
-and attributes needed by 'real' test setups which are derived from
-it. Itself provides *no* ``getTestSuite()`` method, which is needed to
-setup real tests.
-
-A ``BasicTestSetup`` tries to find all doctest files defined in a given
-package. See `functionalsetup.py` for setting up real functional tests
-and `unittestsetup.py` for 'real' setup of unittests.
-
-For a general introduction into testing with grok see the appropriate
-howto on the grok homepage.
-
-The TestSetup classes all search and handle doctest files.
-
-All we need to setup a testsuite, is the package to search::
-
- >>> from grok.tests.testsetup import cave
- >>> from grok.testing import BasicTestSetup
- >>> basic_setup = BasicTestSetup(cave)
- >>> basic_setup
- <grok.testing.BasicTestSetup object at 0x...>
-
-The package is stored as an instance-attribute::
-
- >>> basic_setup.package
- <module 'grok.tests.testsetup.cave' from ...>
-
-The ``BasicTestSetup`` serves merely as a container for attributes and
-methods needed by derived classes, that provide proper test setup.
-
-One of it's resposibilities is, to find doctest files, which is done
-by the ``getDocTestFiles()`` method. If we run this method, we
-get a list of filenames::
-
- >>> file_list = basic_setup.getDocTestFiles()
- >>> len(file_list)
- 4
-
-The filenames are all absolute::
-
- >>> import os.path
- >>> [x for x in file_list if not os.path.isabs(file_list[0])]
- []
-
-
-Which files are found?
-----------------------
-
-By default, all .txt and .rst files are taken
-into account::
-
- >>> exts = ['.rst', '.txt']
- >>> [x for x in file_list if not os.path.splitext(x)[1].lower() in exts]
- []
-
-All forms of an extension are found, regardless of whether they are
-uppercase, lowercase or mixed-case::
-
- >>> file_list
- [...'...file2.TXT'...]
-
-Also subdirectories are searched::
-
- >>> file_list
- [...'...subdirfile.txt'...]
-
-Hidden directories, however, are skipped. To check this, we look for a
-'hidden' testfile put into a hidden directory in the `cave`
-directory. We first make sure, that the hidden file really exists::
-
- >>> cavepath = os.path.dirname(cave.__file__)
- >>> hiddenpath = os.path.join(cavepath, '.hiddendir', 'hiddenfile.txt')
- >>> os.path.exists(hiddenpath)
- True
-
-And now check that it was *not* included in the file list::
-
- >>> hiddenpath in file_list
- False
-
-To provide a more finegrained filtering, ``BasicTestSetup`` provides a
-method ``isTestFile(filepath)``, which returns ``True`` for accepted
-files and ``False`` otherwise. This method is called for every file
-found by ``getDoctesFiles``. By default it only filters files by their
-filename extension and compares it with the instance-attribute
-``extensions``, which by default is the list ``['.rst', '.txt']``::
-
- >>> basic_setup.extensions
- ['.rst', '.txt']
-
- >>> basic_setup.isTestFile('')
- False
-
- >>> basic_setup.isTestFile('cave.txt')
- True
-
- >>> basic_setup.isTestFile('cave.rst')
- True
-
- >>> basic_setup.isTestFile('cave.RsT')
- True
-
- >>> basic_setup.isTestFile('cave.foo')
- False
-
-
-How to find a customized set of files:
---------------------------------------
-
-There are several possibilities to modify the search results of
-``getDocTestFiles()``. If it is only a matter of filename extension,
-the instance's attribute ``extensions`` can be modified::
-
- >>> basic_setup.extensions = ['.foo']
- >>> basic_setup.getDocTestFiles()
- ['...notatest1.foo']
-
-If things need a more complex filtering, you can also redefine the
-filter function, which by default is the ``isTestFile()`` function as
-mentioned above.
-
-You can pass an alternative filterfunction as keyword parameter
-``filter_func`` to the ``BasicTestSetup`` constructor::
-
- >>> def myFilter(filename):
- ... return filename.endswith('.txt')
- >>> basic_setup2 = BasicTestSetup(cave, filter_func=myFilter)
- >>> len(basic_setup2.getDocTestFiles())
- 2
-
-Note, that the filter function must accept a single parameter, which
-should contain a filepath as string and it should return a boolean
-value to indicate, whether the file given by the filepath should be
-included in the test suite or not.
-
-A different set of accepted filename extensions can also be passed to
-the constructor, using the ``extensions`` keyword::
-
- >>> basic_setup3 = BasicTestSetup(cave, extensions=['.txt'])
-
-Note, that the extensions should alway be written with a leading dot
-and in lower case. Such we can find only .txt files::
-
- >>> len(basic_setup3.getDocTestFiles())
- 3
-
-Now also the .TXT file was found, which was omitted in the test
-before.
-
-The set of directories, which are accepted as doctest containers, is
-defined by the ``isTestDirectory`` method, which by default only skips
-'hidden' directories, i.e. directories, that start with a dot ('.').
-
- >>> basic_setup3.isTestDirectory('foo/bar/somdir')
- True
-
- >>> basic_setup3.isTestDirectory('foo/bar/.hiddendir')
- False
-
-You can change this behaviour by deriving your own setup class and
-overwriting the method. This works also with derived classes like
-``FunctionalTestSetup``.
-
-
-Find terms in docfiles:
------------------------
-
-For convenience ``BasicTestSetup`` provides a method ``fileContains``,
-which parses the contents of a file to match a list of regular
-expressions. If every of the regular expressions in the list matched
-at least one line of the file, ``True`` is returned, ``False``
-otherwise.
-
-``fileContains`` is a helper function to search files for certain
-terms and expressions. It is implemented as a method (instead a
-standalone function), to enable developers to replace it with a more
-complex implementation that also accesses other instance attributes
-like the package or similar.
-
-File paths, that cannot be found, are silently ignored::
-
- >>> basic_setup4 = BasicTestSetup(cave, extensions=['.foo'])
- >>> basic_setup4.fileContains('blah', ['FOO'])
- False
-
-We pick up an existing file path::
-
- >>> file_list = basic_setup4.getDocTestFiles()
- >>> len(file_list)
- 1
-
- >>> filepath = file_list[0]
- >>> filepath.endswith('notatest1.foo')
- True
-
-This file contains a string 'ME GROK SMASH ZCML!!', which we can
-search for::
-
- >>> basic_setup4.fileContains(filepath, ['ME GROK'])
- True
-
- >>> basic_setup4.fileContains(filepath, ['ME GROK IS DUMB'])
- False
-
-The terms to search are handled as real regular expressions as
-provided by the ``re`` package::
-
- >>> basic_setup4.fileContains(filepath, ['^ME (G|g)ROK.*'])
- True
-
-We can also search for several matches::
-
- >>> basic_setup4.fileContains(filepath, ['.*SMASH.*', '.*GROK.*'])
- True
-
-If one of the searched terms is not found, the whole thing fails::
-
- >>> basic_setup4.fileContains(filepath, ['.*DUMB.*', '.*GROK.*'])
- False
-
-It does not matter, whether matches occur in the same line or in
-different ones. In the example file there is also a heading stating
-'This is not a test'. Let's check this::
-
- >>> basic_setup4.fileContains(filepath, ['ME GROK', 'This is not'])
- True
-
-
-Note: The evaluation of regular expressions is done without any
-modifiers. Namely the matching is case sensitive::
-
- >>> basic_setup4.fileContains(filepath, ['me grok'])
- False
-
-Furthermore, matches are only done against one line at a time.
-
-
-
-"""
Copied: grok/trunk/src/grok/tests/testsetup/cave/file1.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/file1.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/file1.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/file1.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,17 @@
+"""
+Tests with real TestCase objects.
+
+:Test-Layer: python
+
+"""
+
+import unittest
+
+class TestTest(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def testFoo(self):
+ self.assertEqual(2, 1+1)
+
Copied: grok/trunk/src/grok/tests/testsetup/cave/ftesting.zcml (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/ftesting.zcml)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/ftesting.zcml (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/ftesting.zcml 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,8 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="cave"
+ >
+
+ <!-- Just a dummy ZCML for testing -->
+
+</configure>
Modified: grok/trunk/src/grok/tests/testsetup/cave/notatest1.foo
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/notatest1.foo 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/src/grok/tests/testsetup/cave/notatest1.foo 2008-04-25 19:10:27 UTC (rev 85730)
@@ -2,4 +2,7 @@
This is not a test
==================
+:Test-Layer: functional
+:Test-Layer: unit
+
ME GROK SMASH ZCML!!
Copied: grok/trunk/src/grok/tests/testsetup/cave/sample.zcml (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/sample.zcml)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/sample.zcml (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/sample.zcml 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,8 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="cave"
+ >
+
+ <!-- Just a dummy ZCML for testing -->
+
+</configure>
Copied: grok/trunk/src/grok/tests/testsetup/cave/samplesetup1.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/samplesetup1.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/samplesetup1.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/samplesetup1.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,10 @@
+import os.path
+from zope.app.testing.functional import ZCMLLayer
+from grok.testing import register_all_tests
+samplelayer = ZCMLLayer(
+ os.path.join(os.path.dirname(__file__), 'sample.zcml'),
+ __name__, 'CustomSampleLayer')
+test_suite = register_all_tests(
+ 'grok.tests.testsetup.cave',
+ layer = samplelayer
+ )
Copied: grok/trunk/src/grok/tests/testsetup/cave/samplesetup2.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/samplesetup2.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/samplesetup2.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/samplesetup2.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,8 @@
+import os.path
+from grok.testing import register_all_tests
+test_suite = register_all_tests(
+ 'grok.tests.testsetup.cave',
+ zcml_config = os.path.join(os.path.dirname(__file__),
+ 'sample.zcml'),
+ layer_name = 'CustomLayerFromPath')
+
Copied: grok/trunk/src/grok/tests/testsetup/cave/samplesetup3.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/samplesetup3.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/samplesetup3.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/samplesetup3.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,5 @@
+from grok.testing import register_all_tests
+test_suite = register_all_tests('grok.tests.testsetup.cave')
+
+
+
Copied: grok/trunk/src/grok/tests/testsetup/cave/samplesetup4.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave/samplesetup4.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/cave/samplesetup4.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/cave/samplesetup4.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,5 @@
+from grok.testing import register_all_tests
+test_suite = register_all_tests('grok.tests.testsetup.cave_to_let')
+
+
+
Copied: grok/trunk/src/grok/tests/testsetup/cave_to_let (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/cave_to_let)
Deleted: grok/trunk/src/grok/tests/testsetup/functionalsetup.py
===================================================================
--- grok/trunk/src/grok/tests/testsetup/functionalsetup.py 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/src/grok/tests/testsetup/functionalsetup.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -1,280 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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 Test Setup
-=====================
-
-``FunctionalTestSetup`` 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 tests.
-
-The work is done mainly in two stages:
-
-1) The package is searched for appropriate docfiles, based on the
- settings of instcance 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 tests contained in the local ``cave``
-package. This has to be imported first, because we need the package as
-a parameter for the testseupt constructor::
-
- >>> from grok.tests.testsetup import cave
-
-Using the ``FunctionalTestSetup`` then is easy::
-
- >>> from grok.testing import FunctionalTestSetup
- >>> setup = FunctionalTestSetup(cave)
- >>> setup
- <grok.testing.FunctionalTestSetup 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 grok project now can be that
-short::
-
- import unittest
- import grok
- import cave
- def test_suite():
- setup = grok.testing.FunctionalTestSetup(cave)
- return setup.getTestSuite()
- if __name__ == '__main__':
- unittest.main(default='test_suite')
-
-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`.
-
-
-FunctionalTestSetup 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 test 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 FunctionalTestSetup.setUp of
- <grok.testing.FunctionalTestSetup 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
-
-* Furthermore, additional keyword parameters are passed, which were
- set when calling the constructor. These keywords are stored in the
- setup object as `additional_options`. Those are empty by default::
-
- >>> setup.additional_options
- {}
-
-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 grok. 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'
-
-
-
-No other options/parameters are set by default.
-
-
-Customizing functional test setup:
-----------------------------------
-
-You can modify the behaviour of grok.testing.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.py` 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 test 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 test setup
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To customize the setup of your tests, just modify the appropriate
-attributes as explained before.
-
-To setup a different setUp or tearDown function, you can define a
-derived class, that overwrites these methods.
-
-A convenient way to pass keyword parameters to the test setup, which
-do not appear in the attributes, is passing these keywords (and the
-values) to the constructor::
-
- >>> encoded_setup = FunctionalTestSetup(cave,
- ... encoding='utf-8')
-
-This will read all doctests 'utf-8' encoded, which allow umlauts and
-similar chars in tests. Note, however, that you can archieve this very
-special behaviour also by writing an appropriate encoding string in
-the head of the doctest file.
-
-All keywords passed to the constructor (except 'filter_func' and
-'extensions') are also given to each individual test setup 'as-is'.
-
-Alternatively you can also modify the `additional_options` dictionary
-of a ``FunctionalTestSetup`` object.
-
- >>> encoded_setup.additional_options
- {'encoding': 'utf-8'}
-
- >>> encoded_setup.additional_options['encoding'] = 'latin1'
-
-
-
-"""
Copied: grok/trunk/src/grok/tests/testsetup/testsetup.py (from rev 85728, grok/branches/ulif-testsetup-pre0.13/src/grok/tests/testsetup/testsetup.py)
===================================================================
--- grok/trunk/src/grok/tests/testsetup/testsetup.py (rev 0)
+++ grok/trunk/src/grok/tests/testsetup/testsetup.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -0,0 +1,602 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""
+Tests for testsetups in grok.testing
+************************************
+
+The grok testing support provides a z3c.testsetup which should suit
+most grokprojects. Main parts of this support are
+
+- a grok.testing.register_all_tests() function that registers all
+ marked tests found in a package and
+
+- a TestGetter, that is reusable in own projects.
+
+We will discuss both in the following sections.
+
+grok.testing.register_all_tests(<pkg>)
+======================================
+
+A function that requires a package and delivers a callable which, if
+called without arguments, returns a test suite with all tests of all
+doctestfiles (functional *and* unit doctests) and Python tests found
+in the given package.
+
+With this function you can setup tests like this::
+
+ import grok
+ test_suite = grok.testing.register_all_tests('cave')
+
+In standard grokprojects, this should find all files and modules, that
+have a .txt or .rst filename extension (doctests) or are regular
+Python modules (Python tests). Only those tests are found, that
+provide a certain marker string (see below).
+
+To modify the default values (described below), you can pass
+(optional) keyword parameters. The complete syntax is::
+
+ grok.testing.register_all_tests(
+ <pkg_or_dotted_name>,
+ filter_func = <function>,
+ ffilter_func = <function>,
+ ufilter_func = <function>,
+ pfilter_func = <function>,
+ extensions = <list_of_filename_extenstions>,
+ fextensions = <list_of_filename_extenstions>,
+ uextensions = <list_of_filename_extenstions>
+ regexp_list = <list_of_regular_expression_terms>,
+ uregexp_list = <list_of_regular_expression_terms>,
+ fregexp_list = <list_of_regular_expression_terms>,
+ pregexp_list = <list_of_regular_expression_terms>,
+ encoding = <string_with_encoding_specifier>,
+ checker = <output_checker>,
+ globs = <dict_of_globals>,
+ fglobs = <dict_of_globals>,
+ uglobs = <dict_of_globals>,
+ setup = <function>,
+ fsetup = <function>,
+ usetup = <function>,
+ teardown = <function>,
+ fteardown = <function>,
+ uteardown = <function>,
+ optionflags = <optionflags>,
+ foptionflags = <optionflags>,
+ uoptionflags = <optionflags>,
+ zcml_config = <path_to_zcml_config_file>,
+ layer_name = <string>,
+ layer = <complete_zcml_layer>)
+
+where all parameters (except the first one) are optional. Those
+options that are preceeded by 'u', 'f', or 'p' affect only unit
+doctests, functional doctests or Python tests respectively.
+
+The work of the function is done in two steps:
+
+1) Doctestfiles and Python modules with tests are collected and
+
+2) the tests contained in them are registered with the given values or
+ default values.
+
+We will discuss the default values and how to modify the behaviour of
+both steps.
+
+
+A simple test setup with register_all_tests()
+---------------------------------------------
+
+The `register_all_tests()` function must be called with a package as
+first argument. This package can be given in 'dotted name' notation::
+
+ >>> import grok
+ >>> setup = grok.testing.register_all_tests(
+ ... 'grok.tests.testsetup.cave')
+ >>> setup
+ <grok.testing.GrokTestCollector object at 0x...>
+
+Alternatively, we can pass the 'real' package, which requires to
+import it before::
+
+ >>> from grok.tests.testsetup import cave
+ >>> setup = grok.testing.register_all_tests(cave)
+ >>> setup
+ <grok.testing.GrokTestCollector object at 0x...>
+
+In both cases we get a `GrokTestCollector` which is a callable, that
+returns a ``unittest.TestSuite`` upon being called::
+
+ >>> suite = setup()
+ >>> suite
+ <unittest.TestSuite tests=[...]>
+
+We import a function of the z3c.testsetup to list the set of included
+testfiles/modules::
+
+ >>> from z3c.testsetup.tests.test_testsetup import get_basenames_from_suite
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'file1.rst', 'file1.txt', 'subdirfile.txt']
+
+These are files/modules located in the ``cave`` package. If you look
+into these files, you will see, that `file1.py` is a normal Pyhton
+testmodule, `file1.rst` contains unitdoctests and both .txt-files
+are functional doctest files.
+
+There are some more files in the `cave` package, which also contain
+tests. Why haven't they been found? A doctestfile or module must meet
+certain requirements to be accepted.
+
+
+Which files/modules are found by default?
+-----------------------------------------
+
+Basically, all files/modules are found that
+
+1) reside inside the package passed to the function. This includes
+ subdirectories/subpackages.
+
+2) have a filename extension `.txt` or `.rst` (uppercase, lowercase
+ etc. does not matter) if they should be registered as unit or
+ functional doctests. Python tests are always looked up in regular
+ Python modules.
+
+3) are *not* located inside a 'hidden' directory (i.e. a directory
+ starting with a dot ('.'). Also subdirectories of 'hidden'
+ directories are skipped. Python tests are only found, if the
+ subpackage they are in is a real subpackage (the directory itself
+ and all parent directories inside the root package must have an
+ `__init__.py`).
+
+4) contain a ReStructured Text meta-marker somewhere, that defines the
+ file as a functional or unit doctest or Python test explicitly.
+
+ For functional doctests, the file must contain::
+
+ :Test-Layer: functional
+
+ For unit doctests the file must contain::
+
+ :Test-Layer: functional
+
+ Python test modules must provide a module docstring that contains::
+
+ :Test-Layer: python
+
+ This means: there *must* be a line like the above one in the
+ doctest file or python modules. The terms might be preceeded or
+ followed by whitspace characters (spaces, tabs).
+
+All this is the default behaviour.
+
+
+Customize the set of files/modules found
+----------------------------------------
+
+If we want to grab a different set of doctest files and/or modules, we
+can use three options:
+
+1) Pass an `extensions` parameter (doctests only):
+
+ This by default is the list ``['.txt', '.rst']. If we want to
+ search .foo files too, then we can do it like this::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, extensions=['.foo'])
+
+ Note, that the behaviour is not cummulative. We have to give the
+ complete list. This will result in a different set of files
+ found::
+
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'notatest1.foo', 'notatest1.foo']
+
+ This result may look surprisingly, but is correct. The `file1.py`
+ module was included, because Python tests are not affected by the
+ `extensions` option and `file1.py` is a Python test. The
+ `notatest1.foo` file appears twice, because it was once
+ registered as a unit test and once as a functional test (yes,
+ this is possible although it might not make too much sense in
+ reality).
+
+ To modify only the selection of functional doctests, you can pass
+ the `fextensions` option::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, fextensions=['.foo'])
+
+ Now .txt and .rst files will be searched for unit doctests and
+ .foo files for functional doctests::
+
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'file1.rst', 'notatest1.foo']
+
+ If we provide an `<x>extensions` parameter and an `extensions`
+ parameter, the more specific one will override the more general
+ one. If for example we use::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, extensions=['.foo'], fextensions=['.txt'])
+
+ then all unitdoctests with filename extension .foo will be found
+ and all functional doctests in .txt files::
+
+ >>> suite=setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'file1.txt', 'notatest1.foo', 'subdirfile.txt']
+
+ Python tests are not affected by the `extensions` parameter. But
+ to be clear: you can search for doctests (and find them!) in
+ Python files. See `Doctests in Python modules`_ below.
+
+2) Pass an `regexp_list` parameter:
+
+ The `regexp_list` parameter determins, which terms we want to
+ search for in potential doctest files and modules. By default the
+ 'Test-Layer' terms mentioned above are used.
+
+ To set a required term for one specific test type (unitdoctest,
+ functional doctests or Python tests), you can use the
+ `uregexp_list`, `fregexp_list` and `pregexp_list` keywords
+ respectively.
+
+ If you use the `regexp_list` parameter only, all kinds of tests
+ require the same term. That is normally not what you want, but
+ works::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, regexp_list = [':Test-Layer:'])
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'file1.rst', 'file1.rst', 'file1.txt',
+ 'file1.txt', 'subdirfile.txt', 'subdirfile.txt']
+
+ Here the .txt and .rst files were registered twice, once as a
+ unit doctest and once as a functional doctest.
+
+ Normally you want to set a special marker for one type of
+ tests. We require the unit doctest marker for functional doctests
+ now::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, fregexp_list = [':Test-Layer: unit'])
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'file1.rst', 'file1.rst']
+
+ The file `file1.rst` was now registered as a functional doctest
+ as well.
+
+ As you see, regexp_lists are lists. They match (accept) a file
+ iff each of the expressions of the list could be found in a line
+ of a considered file.
+
+ For example the string ':Test-Layer:' can be found in many test
+ files. But the additional string 'TestCase' appears only in the
+ file1.py file in the cave package::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, regexp_list = ['.*:Test-Layer:.*',
+ ... '.*TestCase.*'])
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py']
+
+3) Pass a `filter_func` parameter:
+
+ This keyword expects an callable, which can be called with a file
+ path as argument. It should return `True` or `False`. We define
+ an example function::
+
+ >>> import os.path
+ >>> def myfilter(path):
+ ... if os.path.basename(path).startswith('subdir'):
+ ... return True
+ ... return False
+
+ This function accepts all filenames that start with 'subdir',
+ which matches exactly one file in our example cave. Let's see the
+ results::
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, filter_func = myfilter)
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.py', 'subdirfile.txt', 'subdirfile.txt']
+
+ Again we see the one Python module. The module search is not
+ affected by `filter_func`. Use `pfilter_func` instead::
+
+ >>> def mypfilter(module):
+ ... basename = os.path.basename(module.__file__)
+ ... if basename.startswith('subdirfile'):
+ ... return True
+ ... return False
+
+ >>> setup = grok.testing.register_all_tests(
+ ... cave, pfilter_func = mypfilter)
+ >>> suite = setup()
+ >>> get_basenames_from_suite(suite)
+ ['file1.rst', 'file1.txt', 'subdirfile.txt']
+
+ Unit and functional dotests can be selected specifically by using
+ `ufilter_func` or `ffilter_func` respectively.
+
+ Note, that using a custom `filter_func` will disable filename
+ extension filtering. You have to implement it yourself in this
+ case. Therefore also the `regexp_list` parameter will have no
+ effect when you define your own filter functions.
+
+
+Customizing the setup of single tests
+-------------------------------------
+
+The other keyword parameters of `register_all_tests()` influence not
+the set of files handled, but the manner in which each individual test
+is set up.
+
+The descriptions here will be somewhat short, because testing of such
+stuff requires a more complex test setup. But the behaviour is (with
+one exception described below) like the behaviour of the original
+z3c.testsetup.register_all_tests() function. See
+
+ http://svn.zope.org/z3c.testsetup/trunk/z3c/testsetup/testrunner.txt
+
+and
+
+ http://svn.zope.org/z3c.testsetup/trunk/z3c/testsetup/README.txt
+
+for some examples in action.
+
+The difference from original behaviour is the default value of the
+layer for functional doctests. We will therefore start with it.
+
+* `zcml_config`, `layer_name` and `layer`:
+
+ `zcml_config`: a string with a filesystem path to a ZCML layer,
+ that should be used during functional doctests.
+
+ `layer_name`: a string with an arbitrary name for the file
+ identified by the `zcml_config` file. The layer name is only used,
+ if a `zcml_config` is set. Default is: `FunctionalLayer`.
+
+ `layer`: a ready to use zope.testing.functional.ZCMLLayer object.
+
+ Functional doctests need a layer to set up some framework stuff
+ like registering of principals etc. The grok.register_all_tests()
+ function will lookup a few places for such a file or, if the
+ `zcml_config` keyword is passed, take this. The order is like
+ this:
+
+ 1) if `layer` is set, take that. This overrides any
+ `zcml_config` given.
+
+ 2) if `zcml_config` is set, lookup the file, setup a layer with
+ that file and take that.
+
+ 3) if a file `ftesting.zcml` exists in the root of the package
+ scanned for tests, register and take that.
+
+ 4) as fallback take the `ftesting.zcml` from the `grok`
+ package. This is the only difference from the original
+ z3c.testsetup behaviour, which takes another file as fallback
+ solution.
+
+ We will now simulate each of this four cases. For this purpose we
+ will call testrunners that collect and run tests in the `cave` and
+ the `cave_to_let` package.
+
+ In `samplesetup1.py` in the cave package is a testsetup, that
+ defines an own test layer and passes it as `layer` parameter. We
+ dump the file contents here::
+
+ >>> cavepath = os.path.join(os.path.dirname(__file__), 'cave')
+ >>> setupfile = os.path.join(cavepath, 'samplesetup1.py')
+ >>> print open(setupfile).read()
+ import os.path
+ from zope.app.testing.functional import ZCMLLayer
+ from grok.testing import register_all_tests
+ samplelayer = ZCMLLayer(
+ os.path.join(os.path.dirname(__file__), 'sample.zcml'),
+ __name__, 'CustomSampleLayer')
+ test_suite = register_all_tests(
+ 'grok.tests.testsetup.cave',
+ layer = samplelayer
+ )
+
+ Note, that here a custom ZCML layer is defined, based on the file
+ `sample.zcml`. Now we setup a testrunner, that will read exactly
+ this file. We configure it such, that it runs only functional
+ tests::
+
+ >>> import sys
+ >>> old_sysargv = sys.argv # store
+ >>> defaults = [
+ ... '--path', cavepath,
+ ... '--tests-pattern', '^samplesetup1$',
+ ... ]
+ >>> sys.argv = 'test -f '.split()
+ >>> from zope.testing import testrunner
+
+ The testrunner is ready. Let's start it::
+
+ >>> testrunner.run(defaults)
+ Running samplesetup1.CustomSampleLayer tests:
+ Set up samplesetup1.CustomSampleLayer in ... seconds.
+ Ran 2 tests with 0 failures and 0 errors in ... seconds.
+ Tearing down left over layers:
+ Tear down samplesetup1.CustomSampleLayer ... not supported
+ False
+
+ We see, that the custom layer was used. The `False` at the end
+ indicates, that the testrun was finished without any failures.
+
+ Now let's do the same, but give a path to the ZCML file instead of
+ a fully configured layer. For this we use `samplesetup2` from the
+ cave package::
+
+ >>> setupfile = os.path.join(cavepath, 'samplesetup2.py')
+ >>> print open(setupfile).read()
+ import os.path
+ from grok.testing import register_all_tests
+ test_suite = register_all_tests(
+ 'grok.tests.testsetup.cave',
+ zcml_config = os.path.join(os.path.dirname(__file__),
+ 'sample.zcml'),
+ layer_name = 'CustomLayerFromPath')
+
+ If we feed this setup to a testrunner, we get the following::
+
+ >>> defaults = [
+ ... '--path', cavepath,
+ ... '--tests-pattern', '^samplesetup2$',
+ ... ]
+ >>> sys.argv = 'test -f '.split()
+ >>> testrunner.run(defaults)
+ Running grok.tests.testsetup.cave.CustomLayerFromPath tests:
+ Set up grok.tests.testsetup.cave.CustomLayerFromPath in ... seconds.
+ Ran 2 tests with 0 failures and 0 errors in ... seconds.
+ Tearing down left over layers:
+ Tear down grok.tests.testsetup.cave.CustomLayerFromPath ...
+ not supported
+ False
+
+ Apparently the CustomLayerFromPath was found and registered.
+
+ Now we will use the default value. The `cave` package provides an
+ (empty) `ftesting.zcml` which should be found and registered, when
+ no other option was given.
+
+ The file `samplesetup3.py` will do so::
+
+ >>> setupfile = os.path.join(cavepath, 'samplesetup3.py')
+ >>> print open(setupfile).read()
+ from grok.testing import register_all_tests
+ test_suite = register_all_tests('grok.tests.testsetup.cave')
+
+ This test setup has only two lines, but is perfectly valid. Will
+ it register the right thing?
+
+ >>> defaults = [
+ ... '--path', cavepath,
+ ... '--tests-pattern', '^samplesetup3$',
+ ... ]
+ >>> sys.argv = 'test -f '.split()
+ >>> testrunner.run(defaults)
+ Running grok.tests.testsetup.cave.FunctionalLayer tests:
+ Set up grok.tests.testsetup.cave.FunctionalLayer in ... seconds.
+ Ran 2 tests with 0 failures and 0 errors in ... seconds.
+ Tearing down left over layers:
+ Tear down grok.tests.testsetup.cave.FunctionalLayer ...
+ not supported
+ False
+
+ The ftesting.zcml layer from the cave package was used
+ automatically. The name `FunctionalLayer` is the default for such
+ cases. It can be overriden by passing the `layer_name` keyword.
+
+ Now, the last layer test.
+
+ In `samplesetup4.py` in the cave package, there is another
+ testsetup, which is as short as the last one, but registers tests
+ for the `cave_to_let` package, which contrary to the `cave`
+ package does not provide an `ftesting.zcml`. It looks like this::
+
+ >>> setupfile = os.path.join(cavepath, 'samplesetup4.py')
+ >>> print open(setupfile).read()
+ from grok.testing import register_all_tests
+ test_suite = register_all_tests('grok.tests.testsetup.cave_to_let')
+
+ Obviously, the only difference is the 'cave_to_let' package
+ registered. Let's run it::
+
+ >>> defaults = [
+ ... '--path', cavepath,
+ ... '--tests-pattern', '^samplesetup4$',
+ ... ]
+ >>> sys.argv = 'test -f '.split()
+ >>> testrunner.run(defaults)
+ Running grok.tests.testsetup.cave_to_let.GrokFunctionalLayer tests:
+ Set up grok.tests.testsetup.cave_to_let.GrokFunctionalLayer in ... seconds.
+ Ran 1 tests with 0 failures and 0 errors in ... seconds.
+ Tearing down left over layers:
+ Tear down grok.tests.testsetup.cave_to_let.GrokFunctionalLayer ... not supported
+ False
+
+ So, the `GrokFunctionalLayer` was used as fallback, because the
+ `cave_to_let` package has no own ftesting.zcml. Note also, that
+ here the testsetup was put into a location out of the package
+ tested. A testsetup does not have to be part of the package it
+ tests.
+
+ >>> sys.argv = old_sysargv # restore old values
+
+Doctests in Python modules
+==========================
+
+or: what the heck are those 'Python tests' after all?
+
+That a file with tests is a Python module, does not mean
+automatically, that it is a Python test in the sense of
+z3c.testsetup. Instead many packages contain Python files, that
+contain **doctests** and not real Python tests. The file you are
+reading is an example for such a module with doctests.
+
+A real python test modules defines tests as follows::
+
+ '''
+ Tests with real TestCase objects.
+
+ :Test-Layer: python
+
+ '''
+
+ import unittest
+
+ class TestTest(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def testFoo(self):
+ self.assertEqual(2, 1+1)
+
+while a doctestfile with .py filename extension might look like this::
+
+ '''
+ Doctests in a Python module.
+
+ :Test-Layer: functional
+
+ This file contains a lot of examples::
+
+ >>> 1+1
+ 2
+
+ Another example::
+
+ >>> 1+2
+ 3
+
+ '''
+ # Setup stuff...
+ class MyTestClass:
+ pass
+
+You can also define doctests in functions and classes of a regular
+Python module. The single tests will be collected as well and setup as
+doctests, as long as .py files are accepted and the file contains the
+required marker string somewhere in the file.
+
+
+"""
Deleted: grok/trunk/src/grok/tests/testsetup/unittestsetup.py
===================================================================
--- grok/trunk/src/grok/tests/testsetup/unittestsetup.py 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/src/grok/tests/testsetup/unittestsetup.py 2008-04-25 19:10:27 UTC (rev 85730)
@@ -1,252 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2007 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.
-#
-##############################################################################
-"""
-===============
-Unit Test Setup
-===============
-
-``UnitTestSetup`` helps to find and setup unit 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 unit tests.
-
-The work is done mainly in two stages:
-
-1) The package is searched for appropriate docfiles, based on the
- settings of instcance attributes.
-
-2) The tests contained in the found docfiles are setup as unit 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 tests contained in the local ``cave``
-package. This has to be imported first, because we need the package as
-a parameter for the testseupt constructor::
-
- >>> from grok.tests.testsetup import cave
-
-Using the ``UnitTestSetup`` then is easy::
-
- >>> from grok.testing import UnitTestSetup
- >>> setup = UnitTestSetup(cave)
- >>> setup
- <grok.testing.UnitTestSetup 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 grok project now can be that
-short::
-
- import unittest
- import grok
- import cave
- def test_suite():
- setup = grok.testing.UnitTestSetup(cave)
- return setup.getTestSuite()
- if __name__ == '__main__':
- unittest.main(default='test_suite')
-
-This will find all .rst and .txt files in the package that provide a
-certain signature (see below), register the contained tests as unit
-tests and run them as part of a `unittest.TestSuite`.
-
-
-UnitTestSetup 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 unit test (and not: functional test) explicitly::
-
- :Test-Layer: unit
-
- 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 unit
-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 unit 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 UnitTestSetup.setUp of
- <grok.testing.UnitTestSetup object at 0x...>>
-
-* 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
-
-* Furthermore, additional keyword parameters are passed, which were
- set when calling the constructor. These keywords are stored in the
- setup object as `additional_options`. Those are empty by default::
-
- >>> setup.additional_options
- {}
-
-No other options/parameters are set by default.
-
-
-Customizing unit test setup:
-----------------------------
-
-You can modify the behaviour of grok.testing.UnitTestSetup 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 unit tests. See the testfile
-`basicsetup.py` to learn more about the procedure.
-
-The unit test setup, however, requires that files contain the above
-mentioned ReStructured Text meta-marker::
-
- `:Test-Layer: unit`
-
-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*(unit)\\\\s*']
-
-This is the default value of unit test setups.
-
-There is one file in the `cave` subpackage, which includes that
-marker. We can get the list of test files using
-`getDocTestFiles()``::
-
- >>> testfile_list = setup.getDocTestFiles()
- >>> testfile_list
- ['...file1.rst']
-
- >>> len(testfile_list)
- 1
-
-The ``isTestFile()`` method of our setup object did the filtering
-here::
-
- >>> setup.isTestFile(testfile_list[0])
- True
-
-The file file1.txt does not contain a unit test marker::
-
- >>> import os.path
- >>> path = os.path.join(os.path.dirname(cave.__file__),
- ... 'test1.txt')
- >>> setup.isTestFile(path)
- False
-
-The `regexp_list` attribute of a ``UnitTestSetup`` 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 unit test setup
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To customize the setup of your tests, just modify the appropriate
-attributes as explained before.
-
-To setup a different setUp or tearDown function, you can define a
-derived class, that overwrites these methods.
-
-A convenient way to pass keyword parameters to the test setup, which
-do not appear in the attributes, is passing these keywords (and the
-values) to the constructor::
-
- >>> encoded_setup = UnitTestSetup(cave,
- ... encoding='utf-8')
-
-This will read all doctests 'utf-8' encoded, which allow umlauts and
-similar chars in tests. Note, however, that you can archieve this very
-special behaviour also by writing an appropriate encoding string in
-the head of the doctest file.
-
-All keywords passed to the constructor (except 'filter_func' and
-'extensions') are also given to each individual test setup 'as-is'.
-
-Alternatively you can also modify the `additional_options` dictionary
-of a ``UnitTestSetup`` object.
-
- >>> encoded_setup.additional_options
- {'encoding': 'utf-8'}
-
- >>> encoded_setup.additional_options['encoding'] = 'latin1'
-
-
-
-"""
Modified: grok/trunk/versions.cfg
===================================================================
--- grok/trunk/versions.cfg 2008-04-25 19:06:16 UTC (rev 85729)
+++ grok/trunk/versions.cfg 2008-04-25 19:10:27 UTC (rev 85730)
@@ -9,6 +9,7 @@
simplejson = 1.7.1
z3c.autoinclude = 0.2.2
z3c.flashmessage = 1.0b2
+z3c.testsetup = 0.2.1
zc.catalog = 1.2b
ZConfig = 2.5
zdaemon = 2.0.0
More information about the Checkins
mailing list