[Checkins] SVN: z3c.testsetup/trunk/ - Test files that we attempt to read but that do not exist raise an error
Reinout van Rees
reinout at vanrees.org
Thu Nov 19 06:36:24 EST 2009
Log message for revision 105870:
- Test files that we attempt to read but that do not exist raise an error
instead of passing silently.
- Also fixed the tests as several non-existing files were tested (with false
results). That try/except IOError was horrible.
- Internal refactoring: regex caching.
Changed:
U z3c.testsetup/trunk/CHANGES.txt
U z3c.testsetup/trunk/src/z3c/testsetup/base.py
U z3c.testsetup/trunk/src/z3c/testsetup/basicsetup.txt
U z3c.testsetup/trunk/src/z3c/testsetup/functional/functionaldoctestsetup.txt
U z3c.testsetup/trunk/src/z3c/testsetup/pythontestsetup.txt
U z3c.testsetup/trunk/src/z3c/testsetup/testing.py
U z3c.testsetup/trunk/src/z3c/testsetup/unitdoctestsetup.txt
U z3c.testsetup/trunk/src/z3c/testsetup/util.py
-=-
Modified: z3c.testsetup/trunk/CHANGES.txt
===================================================================
--- z3c.testsetup/trunk/CHANGES.txt 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/CHANGES.txt 2009-11-19 11:36:24 UTC (rev 105870)
@@ -4,9 +4,12 @@
0.7 (unreleased)
================
-- Nothing changed yet.
+- Test files that we attempt to read but that do not exist raise an error
+ instead of passing silently.
+- Internal refactoring: regex caching.
+
0.6 (2009-11-19)
================
Modified: z3c.testsetup/trunk/src/z3c/testsetup/base.py
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/base.py 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/base.py 2009-11-19 11:36:24 UTC (rev 105870)
@@ -29,9 +29,7 @@
"""
extensions = ['.rst', '.txt']
-
regexp_list = []
-
additional_options = {}
param_list = ['filter_func', 'extensions']
@@ -41,7 +39,8 @@
self.package = get_package(package)
self.filter_func = filter_func or self.isTestFile
self.extensions = extensions or self.extensions
- self.regexp_list = regexp_list or self.regexp_list
+ if regexp_list is not None:
+ self.regexp_list = regexp_list
self.additional_options = kw
self._init(package, filter_func, extensions, **kw)
return
@@ -52,30 +51,40 @@
"""
pass
+ @property
+ def regexs(self):
+ """Return compiled regexs (cached version, if possible)"""
+ cached = getattr(self, '_regexs', None)
+ if cached is not None:
+ return cached
+ self._regexs = [re.compile(regex) for regex in self.regexp_list]
+ return self._regexs
+
def setUp(self, test):
pass
def tearDown(self, test):
pass
- def fileContains(self, filename, regexp_list):
+ def fileContains(self, filename):
"""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)
+ content = open(filename).read()
+ return self.textContains(content)
+ def textContains(self, text):
+ lines = text.split('\n')
+ for regexp in self.regexs:
+ found = [True for line in lines if regexp.match(line)]
+ if len(found):
+ # Yeah, found a match, continue to the next regex.
+ continue
+ else:
+ return False
+ return True
+
def isTestFile(self, filepath):
"""Return ``True`` if a file matches our expectations for a
doctest file.
@@ -85,7 +94,7 @@
if os.path.basename(filepath).startswith('.'):
# Ignore *nix hidden files
return False
- if not self.fileContains(filepath, self.regexp_list):
+ if not self.fileContains(filepath):
return False
return True
Modified: z3c.testsetup/trunk/src/z3c/testsetup/basicsetup.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/basicsetup.txt 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/basicsetup.txt 2009-11-19 11:36:24 UTC (rev 105870)
@@ -124,15 +124,6 @@
>>> 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
@@ -215,11 +206,14 @@
complex implementation that also accesses other instance attributes
like the package or similar.
-File paths, that cannot be found, are silently ignored::
+File paths, that cannot be found, are treated as real errors as they signal an
+error in the way we set everything up:
>>> basic_setup4 = BasicTestSetup(cave, extensions=['.foo'])
- >>> basic_setup4.fileContains('blah', ['FOO'])
- False
+ >>> basic_setup4.fileContains('blah')
+ Traceback (most recent call last):
+ ...
+ IOError: [Errno 2] No such file or directory: 'blah'
We pick up an existing file path::
@@ -234,40 +228,54 @@
This file contains a string 'ME GROK SMASH ZCML!!', which we can
search for::
- >>> basic_setup4.fileContains(filepath, ['ME GROK'])
+ >>> basic_setup4.regexp_list = ['ME GROK']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
True
- >>> basic_setup4.fileContains(filepath, ['ME GROK IS DUMB'])
+ >>> basic_setup4.regexp_list = ['ME GROK IS DUMB']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
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.*'])
+ >>> basic_setup4.regexp_list = ['^ME (G|g)ROK.*']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
True
-We can also search for several matches::
+We can also search for several matches (which ALL have to be present):
- >>> basic_setup4.fileContains(filepath, ['.*SMASH.*', '.*GROK.*'])
+ >>> basic_setup4.regexp_list = ['.*SMASH.*', '.*GROK.*']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
True
If one of the searched terms is not found, the whole thing fails::
- >>> basic_setup4.fileContains(filepath, ['.*DUMB.*', '.*GROK.*'])
+ >>> basic_setup4.regexp_list = ['.*DUMB.*', '.*GROK.*']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
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'])
+ >>> basic_setup4.regexp_list = ['ME GROK', 'This is not']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
True
Note: The evaluation of regular expressions is done without any
modifiers. Namely the matching is case sensitive::
- >>> basic_setup4.fileContains(filepath, ['me grok'])
+ >>> basic_setup4.regexp_list = ['me grok']
+ >>> basic_setup4._regexs = None # Zap regex cache
+ >>> basic_setup4.fileContains(filepath)
False
Furthermore, matches are only done against one line at a time.
Modified: z3c.testsetup/trunk/src/z3c/testsetup/functional/functionaldoctestsetup.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/functional/functionaldoctestsetup.txt 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/functional/functionaldoctestsetup.txt 2009-11-19 11:36:24 UTC (rev 105870)
@@ -262,14 +262,6 @@
>>> 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
@@ -277,6 +269,12 @@
will influence behaviour of the `isTestFile()``, ``getDocTestFiles()``
and ``getTestSuite()`` methods.
+Note that the code uses self.regexs, which returns a cached compiled version
+of the regexs.
+
+ >>> setup.regexs
+ [<_sre.SRE_Pattern object at ...>]
+
If you need more complex checks here, you can derive your customized
test setup class and overwrite ``isTestFile()``.
@@ -464,6 +462,7 @@
To show this, we first create a custom layer::
>>> from zope.app.testing.functional import ZCMLLayer
+ >>> import os.path
>>> mylayer = ZCMLLayer(
... os.path.join(os.path.dirname(__file__), 'ftesting.zcml'),
... __name__,
Modified: z3c.testsetup/trunk/src/z3c/testsetup/pythontestsetup.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/pythontestsetup.txt 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/pythontestsetup.txt 2009-11-19 11:36:24 UTC (rev 105870)
@@ -218,6 +218,7 @@
and we want its tests to be registered::
>>> setup.regexp_list = ['^\\s*:(T|t)est-(L|l)ayer:\\s*(F|false)\\s*']
+ >>> setup._regexs = None # Zap internal regex cache
Now we fetch the module list again::
Modified: z3c.testsetup/trunk/src/z3c/testsetup/testing.py
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/testing.py 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/testing.py 2009-11-19 11:36:24 UTC (rev 105870)
@@ -45,7 +45,7 @@
self.pfilter_func = pfilter_func or self.isTestModule
self.filter_func = self.pfilter_func
- def docstrContains(self, docstr, regexp_list):
+ def docstrContains(self, docstr):
"""Does a docstring contain lines matching every of the regular
expressions?
"""
@@ -54,14 +54,7 @@
return False
if get_marker_from_string('unittest', docstr) is not None:
return True
- for line in docstr.split('\n'):
- 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
- return len(regexp_list) == len(found_list)
+ return self.textContains(docstr)
def isTestModule(self, module_info):
"""Return ``True`` if a module matches our expectations for a
@@ -71,8 +64,7 @@
each of our regular expressions.
"""
# Do not even try to load modules, that have no marker string.
- if not self.fileContains(
- module_info.path, self.regexp_list):
+ if not self.fileContains(module_info.path):
# No ":test-layer: python" marker, so check for :unittest:.
if get_marker_from_file('unittest', module_info.path) is None:
# Neither the old nor the new marker: this is no test module.
@@ -85,7 +77,7 @@
# warn about this!
print "Import error in", module_info.path
docstr = getattr(module, '__doc__', '')
- if not self.docstrContains(docstr, self.regexp_list):
+ if not self.docstrContains(docstr):
return False
return True
Modified: z3c.testsetup/trunk/src/z3c/testsetup/unitdoctestsetup.txt
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/unitdoctestsetup.txt 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/unitdoctestsetup.txt 2009-11-19 11:36:24 UTC (rev 105870)
@@ -216,14 +216,6 @@
>>> 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 ``UnitDocTestSetup`` 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
@@ -231,6 +223,8 @@
will influence behaviour of the `isTestFile()``, ``getDocTestFiles()``
and ``getTestSuite()`` methods.
+Note: in practice in the current code, it is always only one regex...
+
If you need more complex checks here, you can derive your customized
test setup class and overwrite ``isTestFile()``.
Modified: z3c.testsetup/trunk/src/z3c/testsetup/util.py
===================================================================
--- z3c.testsetup/trunk/src/z3c/testsetup/util.py 2009-11-19 10:02:48 UTC (rev 105869)
+++ z3c.testsetup/trunk/src/z3c/testsetup/util.py 2009-11-19 11:36:24 UTC (rev 105870)
@@ -15,9 +15,11 @@
"""
import sys
import re
+
from inspect import getmro, ismethod, getargspec
from martian.scan import resolve
+
def get_package(pkg_or_dotted_name):
"""Get a package denoted by the given argument.
@@ -32,6 +34,7 @@
pkg = resolve(pkg)
return pkg
+
def get_keyword_params(cls, method_name):
"""Get a list of args of a method of a class.
@@ -54,6 +57,9 @@
break
return list(result)
+marker_regexs = {}
+
+
def get_marker_from_string(marker, text):
"""Looks for a markerstring in a string.
@@ -64,19 +70,22 @@
or
.. :<Tag>: <Value>
-
+
"""
marker = ":%s:" % marker.lower()
- rexp = re.compile('^(\.\.\s+)?%s(.*)$' % (marker,), re.IGNORECASE)
+ if marker not in marker_regexs:
+ marker_regexs[marker] = re.compile('^(\.\.\s+)?%s(.*)$' % (marker,),
+ re.IGNORECASE)
for line in text.split('\n'):
line = line.strip()
- result = rexp.match(line)
+ result = marker_regexs[marker].match(line)
if result is None:
continue
result = result.groups()[1].strip()
return unicode(result)
return None
+
def get_marker_from_file(marker, filepath):
"""Looks for a markerstring in a file.
@@ -87,15 +96,17 @@
"""
return get_marker_from_string(marker, open(filepath, 'rb').read())
+
def warn(text):
print "Warning: ", text
+
def import_name(name):
__import__(name)
return sys.modules[name]
+
def get_attribute(name):
name, attr = name.rsplit('.', 1)
obj = import_name(name)
return getattr(obj, attr)
-
More information about the checkins
mailing list