From 8774ea73a6273dab1ae02e862f220dd0e88a50ae Mon Sep 17 00:00:00 2001 From: Pooja Shah Date: Thu, 22 Jun 2017 19:32:43 +0530 Subject: [PATCH 1/4] added support for method match only --- nose/config.py | 17 +++++++++++-- nose/selector.py | 65 +++++++++++++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/nose/config.py b/nose/config.py index 5997aaf7..eb30e131 100644 --- a/nose/config.py +++ b/nose/config.py @@ -147,7 +147,7 @@ class Config(object): self.env = env = kw.pop('env', {}) self.args = () - self.testMatch = re.compile(env.get('NOSE_TESTMATCH', r'(?:\b|_)[Tt]est')) + self.testMatch = re.compile(r'(?:^|[\\b_\\.%s-])[Tt]est' % os.sep) self.addPaths = not env.get('NOSE_NOPATH', False) self.configSection = 'nosetests' self.debug = env.get('NOSE_DEBUG') @@ -180,8 +180,10 @@ class Config(object): def __init__(self, **kw): self.env = env = kw.pop('env', {}) self.args = () - self.testMatchPat = env.get('NOSE_TESTMATCH', r'(?:\b|_)[Tt]est') + self.testMatchPat = env.get('NOSE_TESTMATCH', + r'(?:^|[\b_\.%s-])[Tt]est' % os.sep) self.testMatch = re.compile(self.testMatchPat) + self.testMethodMatch = re.compile(self.testMatchPat) self.addPaths = not env.get('NOSE_NOPATH', False) self.configSection = 'nosetests' self.debug = env.get('NOSE_DEBUG') @@ -326,6 +328,9 @@ def configure(self, argv=None, doc=None): if options.testMatch: self.testMatch = re.compile(options.testMatch) + if options.testMethodMatch: + self.testMethodMatch = re.compile(options.testMethodMatch) + if options.ignoreFiles: self.ignoreFiles = map(re.compile, tolist(options.ignoreFiles)) log.info("Ignoring files matching %s", options.ignoreFiles) @@ -501,6 +506,14 @@ def getParser(self, doc=None): "that match this regular expression are considered tests. " "Default: %s [NOSE_TESTMATCH]" % self.testMatchPat, default=self.testMatchPat) + + parser.add_option( + "--matchMethod", action="store", + dest="testMethodMatch", metavar="REGEX", + help="method/function names that match this regular expression are considered tests. " + "Default: %s [NOSE_TESTMATCH]" % self.testMatchPat, + default=self.testMatchPat) + parser.add_option( "--tests", action="store", dest="testNames", default=None, metavar='NAMES', diff --git a/nose/selector.py b/nose/selector.py index b63f7af0..4347df73 100644 --- a/nose/selector.py +++ b/nose/selector.py @@ -11,7 +11,7 @@ import unittest from nose.config import Config from nose.util import split_test_name, src, getfilename, getpackage, ispackage, is_executable - +import re log = logging.getLogger(__name__) __all__ = ['Selector', 'defaultSelector', 'TestAddress'] @@ -43,22 +43,41 @@ def configure(self, config): self.include = config.include self.plugins = config.plugins self.match = config.testMatch - + self.matchMethod = config.testMethodMatch + self.matchDefault = re.compile(config.testMatchPat) + + + def matchRegex(self, regex, name): + return ((regex.search(name) + or (self.include and + filter(None, + [inc.search(name) for inc in self.include]))) + and ((not self.exclude) + or not filter(None, + [exc.search(name) for exc in self.exclude]) + )) + def matches(self, name): """Does the name match my requirements? To match, a name must match config.testMatch OR config.include and it must not match config.exclude """ - return ((self.match.search(name) - or (self.include and - filter(None, - [inc.search(name) for inc in self.include]))) - and ((not self.exclude) - or not filter(None, - [exc.search(name) for exc in self.exclude]) - )) - + return self.matchRegex(self.match, name) + + def matchesMethod(self, name): + """Does the name match my requirements? + + To match, a name must match config.testMatch OR config.include + and it must not match config.exclude + """ + if self.match != self.matchDefault: #if user gave match option as well along with match-method + match = self.match + if self.matchMethod != self.matchDefault: + match = self.matchMethod + + return self.matchRegex(match, name) + def wantClass(self, cls): """Is the class a wanted test class? @@ -72,8 +91,8 @@ def wantClass(self, cls): wanted = (not cls.__name__.startswith('_') and (issubclass(cls, unittest.TestCase) or self.matches(cls.__name__))) - - plug_wants = self.plugins.wantClass(cls) + + plug_wants = self.plugins.wantClass(cls) if plug_wants is not None: log.debug("Plugin setting selection of %s to %s", cls, plug_wants) wanted = plug_wants @@ -83,7 +102,7 @@ def wantClass(self, cls): def wantDirectory(self, dirname): """Is the directory a wanted test directory? - All package directories match, so long as they do not match exclude. + All package directories match, so long as they do not match exclude. All other directories must match test requirements. """ tail = op_basename(dirname) @@ -103,7 +122,7 @@ def wantDirectory(self, dirname): wanted = plug_wants log.debug("wantDirectory %s? %s", dirname, wanted) return wanted - + def wantFile(self, file): """Is the file a wanted test file? @@ -118,7 +137,7 @@ def wantFile(self, file): if ignore_this.search(base) ] if ignore_matches: log.debug('%s matches ignoreFiles pattern; skipped', - base) + base) return False if not self.config.includeExe and is_executable(file): log.info('%s is executable; skipped', file) @@ -126,7 +145,7 @@ def wantFile(self, file): dummy, ext = op_splitext(base) pysrc = ext == '.py' - wanted = pysrc and self.matches(base) + wanted = pysrc and self.matches(base) plug_wants = self.plugins.wantFile(file) if plug_wants is not None: log.debug("plugin setting want %s to %s", file, plug_wants) @@ -149,7 +168,7 @@ def wantFunction(self, function): if declared is not None: wanted = declared else: - wanted = not funcname.startswith('_') and self.matches(funcname) + wanted = not funcname.startswith('_') and self.matchesMethod(funcname) plug_wants = self.plugins.wantFunction(function) if plug_wants is not None: wanted = plug_wants @@ -171,13 +190,13 @@ def wantMethod(self, method): if declared is not None: wanted = declared else: - wanted = self.matches(method_name) + wanted = self.matchesMethod(method_name) plug_wants = self.plugins.wantMethod(method) if plug_wants is not None: wanted = plug_wants log.debug("wantMethod %s? %s", method, wanted) return wanted - + def wantModule(self, module): """Is the module a test module? @@ -195,8 +214,8 @@ def wantModule(self, module): wanted = plug_wants log.debug("wantModule %s? %s", module, wanted) return wanted - -defaultSelector = Selector + +defaultSelector = Selector class TestAddress(object): @@ -242,7 +261,7 @@ def __init__(self, name, workingDir=None): def totuple(self): return (self.filename, self.module, self.call) - + def __str__(self): return self.name From 2c04998ec1d04203f01e24450dec5cd87fdccdb6 Mon Sep 17 00:00:00 2001 From: Pooja Shah Date: Thu, 22 Jun 2017 19:33:50 +0530 Subject: [PATCH 2/4] removed additional space line --- nose/selector.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nose/selector.py b/nose/selector.py index 4347df73..069e4881 100644 --- a/nose/selector.py +++ b/nose/selector.py @@ -46,7 +46,6 @@ def configure(self, config): self.matchMethod = config.testMethodMatch self.matchDefault = re.compile(config.testMatchPat) - def matchRegex(self, regex, name): return ((regex.search(name) or (self.include and From 80b7c3a60695d07f2187aa54299fe4ec6fbcd543 Mon Sep 17 00:00:00 2001 From: Pooja Shah Date: Fri, 23 Jun 2017 12:54:47 +0530 Subject: [PATCH 3/4] added doc str --- nose/selector.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nose/selector.py b/nose/selector.py index 069e4881..3857e5cd 100644 --- a/nose/selector.py +++ b/nose/selector.py @@ -47,6 +47,7 @@ def configure(self, config): self.matchDefault = re.compile(config.testMatchPat) def matchRegex(self, regex, name): + """ Does given name matches the given match expression """ return ((regex.search(name) or (self.include and filter(None, @@ -65,12 +66,12 @@ def matches(self, name): return self.matchRegex(self.match, name) def matchesMethod(self, name): - """Does the name match my requirements? + """Does the method name match my requirements? To match, a name must match config.testMatch OR config.include and it must not match config.exclude """ - if self.match != self.matchDefault: #if user gave match option as well along with match-method + if self.match != self.matchDefault: #if user gave match option as well along with matchMethod match = self.match if self.matchMethod != self.matchDefault: match = self.matchMethod From 0d5ac2e88c7aa3f1085d305220c7d80fcdb3f033 Mon Sep 17 00:00:00 2001 From: Pooja Shah Date: Tue, 27 Jun 2017 19:26:04 +0530 Subject: [PATCH 4/4] default value for match --- nose/selector.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nose/selector.py b/nose/selector.py index 3857e5cd..232b878c 100644 --- a/nose/selector.py +++ b/nose/selector.py @@ -71,6 +71,7 @@ def matchesMethod(self, name): To match, a name must match config.testMatch OR config.include and it must not match config.exclude """ + match = self.matchDefault if self.match != self.matchDefault: #if user gave match option as well along with matchMethod match = self.match if self.matchMethod != self.matchDefault: