Merged in nicoddemus/pytest/python-classes-glob (pull request #225)

added support for glob-style patterns to python_classes and python_functions config options
This commit is contained in:
holger krekel 2014-10-22 07:14:10 +02:00
commit eac4514227
5 changed files with 81 additions and 24 deletions

View File

@ -16,6 +16,9 @@
parameter is a callable, you also need to pass in a reason to disambiguate
it from the "decorator" case. Thanks Tom Viner.
- "python_classes" and "python_functions" options now support glob-patterns
for test discovery, as discussed in issue600. Thanks Ldiary Translations.
2.6.4.dev
----------
@ -86,7 +89,7 @@
Thanks sontek.
- Implement issue549: user-provided assertion messages now no longer
replace the py.test instrospection message but are shown in addition
replace the py.test introspection message but are shown in addition
to them.
2.6.1

View File

@ -1,4 +1,5 @@
""" Python test discovery, setup and run of test functions. """
import fnmatch
import py
import inspect
import sys
@ -127,9 +128,10 @@ def pytest_addoption(parser):
default=['test_*.py', '*_test.py'],
help="glob-style file patterns for Python test module discovery")
parser.addini("python_classes", type="args", default=["Test",],
help="prefixes for Python test class discovery")
help="prefixes or glob names for Python test class discovery")
parser.addini("python_functions", type="args", default=["test",],
help="prefixes for Python test function and method discovery")
help="prefixes or glob names for Python test function and "
"method discovery")
def pytest_cmdline_main(config):
if config.option.showfixtures:
@ -307,14 +309,26 @@ class PyobjMixin(PyobjContext):
class PyCollector(PyobjMixin, pytest.Collector):
def funcnamefilter(self, name):
for prefix in self.config.getini("python_functions"):
if name.startswith(prefix):
return True
return self._matches_prefix_or_glob_option('python_functions', name)
def classnamefilter(self, name):
for prefix in self.config.getini("python_classes"):
if name.startswith(prefix):
return self._matches_prefix_or_glob_option('python_classes', name)
def _matches_prefix_or_glob_option(self, option_name, name):
"""
checks if the given name matches the prefix or glob-pattern defined
in ini configuration.
"""
for option in self.config.getini(option_name):
if name.startswith(option):
return True
# check that name looks like a glob-string before calling fnmatch
# because this is called for every name in each collected module,
# and fnmatch is somewhat expensive to call
elif ('*' in option or '?' in option or '[' in option) and \
fnmatch.fnmatch(name, option):
return True
return False
def collect(self):
if not getattr(self.obj, "__test__", True):

View File

@ -115,17 +115,33 @@ Builtin configuration file options
.. confval:: python_classes
One or more name prefixes determining which test classes
are considered as test modules.
One or more name prefixes or glob-style patterns determining which classes
are considered for test collection. Here is an example of how to collect
tests from classes that end in ``Suite``::
# content of pytest.ini
[pytest]
python_classes = *Suite
Note that ``unittest.TestCase`` derived classes are always collected
regardless of this option, as ``unittest``'s own collection framework is used
to collect those tests.
.. confval:: python_functions
One or more name prefixes determining which test functions
and methods are considered as test modules. Note that this
has no effect on methods that live on a ``unittest.TestCase``
derived class.
One or more name prefixes or glob-patterns determining which test functions
and methods are considered tests. Here is an example of how
to collect test functions and methods that end in ``_test``::
See :ref:`change naming conventions` for examples.
# content of pytest.ini
[pytest]
python_functions = *_test
Note that this has no effect on methods that live on a ``unittest
.TestCase`` derived class, as ``unittest``'s own collection framework is used
to collect those tests.
See :ref:`change naming conventions` for more detailed examples.
.. confval:: doctest_optionflags

View File

@ -26,17 +26,17 @@ the :confval:`python_files`, :confval:`python_classes` and
[pytest]
python_files=check_*.py
python_classes=Check
python_functions=check
python_functions=*_check
This would make ``pytest`` look for ``check_`` prefixes in
Python filenames, ``Check`` prefixes in classes and ``check`` prefixes
in functions and classes. For example, if we have::
This would make ``pytest`` look for tests in files that match the ``check_*
.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
that match ``*_check``. For example, if we have::
# content of check_myapp.py
class CheckMyApp:
def check_simple(self):
def simple_check(self):
pass
def check_complex(self):
def complex_check(self):
pass
then the test collection looks like this::
@ -48,14 +48,14 @@ then the test collection looks like this::
<Module 'check_myapp.py'>
<Class 'CheckMyApp'>
<Instance '()'>
<Function 'check_simple'>
<Function 'check_complex'>
<Function 'simple_check'>
<Function 'complex_check'>
============================= in 0.01 seconds =============================
.. note::
the ``python_functions`` and ``python_classes`` has no effect
the ``python_functions`` and ``python_classes`` options has no effect
for ``unittest.TestCase`` test discovery because pytest delegates
detection of test case methods to unittest code.

View File

@ -528,6 +528,30 @@ class Test_genitems:
assert s.endswith("test_example_items1.testone")
print(s)
def test_class_and_functions_discovery_using_glob(self, testdir):
"""
tests that python_classes and python_functions config options work
as prefixes and glob-like patterns (issue #600).
"""
testdir.makeini("""
[pytest]
python_classes = *Suite Test
python_functions = *_test test
""")
p = testdir.makepyfile('''
class MyTestSuite:
def x_test(self):
pass
class TestCase:
def test_y(self):
pass
''')
items, reprec = testdir.inline_genitems(p)
ids = [x.getmodpath() for x in items]
assert ids == ['MyTestSuite.x_test', 'TestCase.test_y']
def test_matchnodes_two_collections_same_file(testdir):
testdir.makeconftest("""
import pytest