Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for method match only #1051

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions nose/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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',
Expand Down
66 changes: 43 additions & 23 deletions nose/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -43,22 +43,42 @@ 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):
""" Does given name matches the given match expression """
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 method name match my requirements?

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:
match = self.matchMethod

return self.matchRegex(match, name)

def wantClass(self, cls):
"""Is the class a wanted test class?

Expand All @@ -72,8 +92,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
Expand All @@ -83,7 +103,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)
Expand All @@ -103,7 +123,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?

Expand All @@ -118,15 +138,15 @@ 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)
return False
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)
Expand All @@ -149,7 +169,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
Expand All @@ -171,13 +191,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?

Expand All @@ -195,8 +215,8 @@ def wantModule(self, module):
wanted = plug_wants
log.debug("wantModule %s? %s", module, wanted)
return wanted
defaultSelector = Selector

defaultSelector = Selector


class TestAddress(object):
Expand Down Expand Up @@ -242,7 +262,7 @@ def __init__(self, name, workingDir=None):

def totuple(self):
return (self.filename, self.module, self.call)

def __str__(self):
return self.name

Expand Down