snapshot of 0.2.0

This commit is contained in:
Kurt Grandis 2015-06-24 01:02:38 -04:00
parent b07163b57e
commit 20c07d9522
10 changed files with 254 additions and 24 deletions

View File

@ -4,4 +4,7 @@ Kurt Grandis
Contributors
------------
* Ryan Hsu
* Piotr Husiatyński
* Joe Friedl
* Radu Voicilas

View File

@ -51,6 +51,26 @@ where ``exclude_dirs.txt`` might look like: ::
# Comments
test_dirs/test_not_me
Excluding Specific Test Methods and Classes
-------------------------------------------
Tests can now be excluded by specifying their fully qualified test paths.
Tests can be excluded using either ``--exclude-test`` or ``--exclude-test-file``.
To exclude test methods:
``--exclude-test=module1.module2.TestClass.test_method``
To exclude test classes:
``--exclude-test=module1.module2.TestClass``
To exclude test functions:
``--exclude-test-module1.module2.test_function``
Using Environment Variables
---------------------------

View File

@ -4,15 +4,19 @@ from nose.plugins import Plugin
log = logging.getLogger('nose.plugins.nose_exclude')
class NoseExclude(Plugin):
def options(self, parser, env=os.environ):
"""Define the command line options for the plugin."""
super(NoseExclude, self).options(parser, env)
env_dirs = []
env_tests = []
if 'NOSE_EXCLUDE_DIRS' in env:
exclude_dirs = env.get('NOSE_EXCLUDE_DIRS','')
exclude_dirs = env.get('NOSE_EXCLUDE_DIRS', '')
env_dirs.extend(exclude_dirs.split(';'))
parser.add_option(
"--exclude-dir", action="append",
dest="exclude_dirs",
@ -31,22 +35,35 @@ class NoseExclude(Plugin):
working directory or an absolute path. \
[NOSE_EXCLUDE_DIRS_FILE]")
def _force_to_abspath(self, pathname):
parser.add_option(
"--exclude-test", action="append",
dest="exclude_tests",
default=env_tests,
help="Fully qualified name of test method or class to exclude \
from test discovery.")
parser.add_option(
"--exclude-test-file", type="string",
dest="exclude_test_file",
default=False,
help="A file containing a list of fully qualified names of \
test methods or classes to exclude from test discovery.")
def _force_to_abspath(self, pathname, root):
if os.path.isabs(pathname):
abspath = pathname
else:
abspath = os.path.abspath(pathname)
abspath = os.path.abspath(os.path.join(root, pathname))
if os.path.exists(abspath):
return abspath
else:
log.warn('The following path was not found: %s' % pathname)
log.warning('The following path was not found: %s' % pathname)
def _load_from_file(self, filename):
infile = open(filename)
new_list = [l.strip() for l in infile.readlines() if l.strip()
and not l.startswith('#')]
with open(filename, 'r') as infile:
new_list = [l.strip() for l in infile.readlines() if l.strip()
and not l.startswith('#')]
return new_list
def configure(self, options, conf):
@ -54,6 +71,7 @@ class NoseExclude(Plugin):
super(NoseExclude, self).configure(options, conf)
self.exclude_dirs = {}
self.exclude_tests = options.exclude_tests[:]
# preload directories from file
if options.exclude_dir_file:
@ -63,12 +81,21 @@ class NoseExclude(Plugin):
new_dirs = self._load_from_file(options.exclude_dir_file)
options.exclude_dirs.extend(new_dirs)
if not options.exclude_dirs:
if options.exclude_test_file:
exc_tests = self._load_from_file(options.exclude_test_file)
self.exclude_tests.extend(exc_tests)
if not options.exclude_dirs and not self.exclude_tests:
self.enabled = False
return
self.enabled = True
root = os.getcwd()
if conf and conf.workingDir:
# Use nose's working directory
root = conf.workingDir
else:
root = os.getcwd()
log.debug('cwd: %s' % root)
# Normalize excluded directory names for lookup
@ -77,7 +104,7 @@ class NoseExclude(Plugin):
# separated by some character (new line is good enough)
for d in exclude_param.split('\n'):
d = d.strip()
abs_d = self._force_to_abspath(d)
abs_d = self._force_to_abspath(d, root)
if abs_d:
self.exclude_dirs[abs_d] = True
@ -92,4 +119,38 @@ class NoseExclude(Plugin):
else:
return None
def wantModule(self, module):
"""Filter out tests based on: <module path>.<module name>"""
if module.__name__ in self.exclude_tests:
return False
else:
return None
def wantFunction(self, fun):
"""Filter out tests based on: <module path>.<func name>"""
fqn = '%s.%s' % (fun.__module__, fun.__name__)
if fqn in self.exclude_tests:
return False
else:
return None
def wantMethod(self, meth):
"""Filter out tests based on <module path>.<class>.<method name>"""
try:
cls = meth.im_class # Don't test static methods
except AttributeError:
return False
fqn = '%s.%s.%s' % (cls.__module__, cls.__name__, meth.__name__)
if fqn in self.exclude_tests:
return False
else:
return None
def wantClass(self, cls):
"""Filter out the class based on <module path>.<class name>"""
fqn = '%s.%s' % (cls.__module__, cls.__name__)
if fqn in self.exclude_tests:
return False
else:
return None

View File

@ -9,7 +9,7 @@ from setuptools import setup
def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read().strip()
VERSION = '0.1.10'
VERSION = '0.2.0'
setup(
name = "nose-exclude",
@ -23,15 +23,15 @@ setup(
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
("License :: OSI Approved :: GNU Library or Lesser General "
"Public License (LGPL)"),
("License :: OSI Approved :: GNU Library or Lesser General "
"Public License (LGPL)"),
"Topic :: Software Development :: Testing",
"Programming Language :: Python",
],
py_modules = ['nose_exclude'],
zip_safe = False,
entry_points = {
'nose.plugins': ['nose_exclude = nose_exclude:NoseExclude']
},

0
test_dirs/__init__.py Normal file
View File

View File

@ -0,0 +1,2 @@
test_dirs.unittest.tests.UnitTests.test_a
test_dirs.unittest.tests.UnitTests.test_b

View File

View File

@ -0,0 +1,15 @@
import unittest
class UnitTests(unittest.TestCase):
def test_a(self):
assert True
def test_b(self):
assert True
@staticmethod
def test_e(self):
assert True
def test_c():
assert True

137
tests.py
View File

@ -3,6 +3,7 @@ import unittest
from nose.plugins import PluginTester
from nose_exclude import NoseExclude
class TestNoseExcludeDirs_Relative_Args(PluginTester, unittest.TestCase):
"""Test nose-exclude directories using relative paths passed
on the commandline via --exclude-dir
@ -16,6 +17,7 @@ class TestNoseExcludeDirs_Relative_Args(PluginTester, unittest.TestCase):
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirs_Absolute_Args(PluginTester, unittest.TestCase):
"""Test nose-exclude directories using absolute paths passed
on the commandline via --exclude-dir
@ -26,7 +28,7 @@ class TestNoseExcludeDirs_Absolute_Args(PluginTester, unittest.TestCase):
def __init__(self, *args, **kwargs):
self.activate = "--exclude-dir=%s" % \
os.path.join(self.suitepath, 'build')
os.path.join(self.suitepath, 'build')
arg_path = os.path.join(self.suitepath, 'test_not_me')
self.args = ['--exclude-dir=%s' % arg_path]
super(TestNoseExcludeDirs_Absolute_Args, self).__init__(*args, **kwargs)
@ -34,6 +36,7 @@ class TestNoseExcludeDirs_Absolute_Args(PluginTester, unittest.TestCase):
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirs_Relative_Args_File(PluginTester, unittest.TestCase):
"""Test nose-exclude directories using relative paths passed
by file using --exclude-dir-file
@ -46,6 +49,7 @@ class TestNoseExcludeDirs_Relative_Args_File(PluginTester, unittest.TestCase):
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirs_Relative_Args_Mixed(PluginTester, unittest.TestCase):
"""Test nose-exclude directories using paths passed
by file and commandline
@ -59,19 +63,21 @@ class TestNoseExcludeDirs_Relative_Args_Mixed(PluginTester, unittest.TestCase):
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeEnvVariables(PluginTester, unittest.TestCase):
"""Test nose-exclude's use of environment variables"""
#args = ['--exclude-dir=test_dirs/test_not_me']
activate = "-v"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs')
env = {'NOSE_EXCLUDE_DIRS':'test_dirs/build;test_dirs/test_not_me'}
env = {'NOSE_EXCLUDE_DIRS': 'test_dirs/build;test_dirs/test_not_me'}
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirsEnvFile(PluginTester, unittest.TestCase):
"""Test nose-exclude directories using relative paths passed
by file specified by environment variable
@ -79,12 +85,13 @@ class TestNoseExcludeDirsEnvFile(PluginTester, unittest.TestCase):
activate = "-v"
plugins = [NoseExclude()]
env = {'NOSE_EXCLUDE_DIRS_FILE':'test_dirs/exclude_dirs.txt'}
env = {'NOSE_EXCLUDE_DIRS_FILE': 'test_dirs/exclude_dirs.txt'}
suitepath = os.path.join(os.getcwd(), 'test_dirs')
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirs_Arg_Does_Not_Exist(PluginTester, unittest.TestCase):
"""Test nose-exclude directories for a directory that doesn't exist.
"""
@ -97,5 +104,125 @@ class TestNoseExcludeDirs_Arg_Does_Not_Exist(PluginTester, unittest.TestCase):
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeDirsNoseWorkingDir(PluginTester, unittest.TestCase):
"""Test nose-exclude directories with Nose's working directory."""
activate = "--exclude-dir=test_not_me"
args = ["--where=test_dirs"]
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs')
def tearDown(self):
# Nose changes cwd to config.workingDir, need to reset it
import os
os.chdir(os.path.join(os.getcwd(), os.path.pardir))
def test_proper_dirs_omitted(self):
assert "FAILED" not in self.output
class TestNoseExcludeTest(PluginTester, unittest.TestCase):
"""Test nose-exclude a single test"""
activate = "--exclude-test=test_dirs.unittest.tests.UnitTests.test_a"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_test_excluded(self):
assert 'Ran 2 tests' in self.output
class TestNoseExcludeTestNegative(PluginTester, unittest.TestCase):
"""Test nose-exclude a test that does not exist"""
activate = "--exclude-test=test_dirs.unittest.tests.UnitTests.does_not_exist"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_test_excluded_negative(self):
assert 'Ran 3 tests' in self.output
class TestNoseExcludeMultipleTest(PluginTester, unittest.TestCase):
"""Test nose-exclude multiple tests"""
activate = "--exclude-test=test_dirs.unittest.tests.UnitTests.test_a"
args = [
"--exclude-test=test_dirs.unittest.tests.UnitTests.test_b",
"--exclude-test=test_dirs.unittest.tests.test_c"
]
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_tests_excluded(self):
assert 'Ran 0 tests' in self.output
class TestNoseExcludeTestViaFile(PluginTester, unittest.TestCase):
"""Test nose-exclude tests with a file"""
activate = "--exclude-test-file=test_dirs/exclude_tests.txt"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_tests_excluded(self):
assert 'Ran 1 test' in self.output
class TestNoseExcludeDirAndTests(PluginTester, unittest.TestCase):
"""Test nose-exclude tests by specifying dirs and tests"""
activate = "--exclude-test=test_dirs.unittest.tests.UnitTests.test_a"
args = [
"--exclude-dir=test_dirs/build",
"--exclude-dir=test_dirs/build2",
"--exclude-dir=test_dirs/fish",
"--exclude-dir=test_dirs/test_not_me",
"--exclude-dir=test_dirs/test_yes",
"--exclude-dir=test_dirs/test_yes2",
]
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs')
def test_tests_excluded(self):
assert 'Ran 2 tests' in self.output
class TestNoseExcludeTestClass(PluginTester, unittest.TestCase):
"""Test nose-exclude tests by class"""
activate = "--exclude-test=test_dirs.unittest.tests.UnitTests"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_tests_excluded(self):
assert 'Ran 1 test' in self.output
class TestNoseExcludeTestFunction(PluginTester, unittest.TestCase):
"""Test nose-exclude tests by function"""
activate = "--exclude-test=test_dirs.unittest.tests.test_c"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_tests_excluded(self):
assert 'Ran 2 tests' in self.output
class TestNoseExcludeTestModule(PluginTester, unittest.TestCase):
"""Test nose-exclude tests by module"""
activate = "--exclude-test=test_dirs.unittest.test"
plugins = [NoseExclude()]
suitepath = os.path.join(os.getcwd(), 'test_dirs/unittest')
def test_tests_excluded(self):
assert 'Ran 3 tests' in self.output
if __name__ == '__main__':
unittest.main()

10
tox.ini
View File

@ -1,7 +1,9 @@
[tox]
envlist = py25,py26,py27
envlist = py25, py26, py27, py33
[testenv]
deps=nose
commands=
python setup.py test
deps = nose
commands = python setup.py test
[testenv:py25]
setenv = PIP_INSECURE=1