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:
commit
eac4514227
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue