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
|
parameter is a callable, you also need to pass in a reason to disambiguate
|
||||||
it from the "decorator" case. Thanks Tom Viner.
|
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
|
2.6.4.dev
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -86,7 +89,7 @@
|
||||||
Thanks sontek.
|
Thanks sontek.
|
||||||
|
|
||||||
- Implement issue549: user-provided assertion messages now no longer
|
- 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.
|
to them.
|
||||||
|
|
||||||
2.6.1
|
2.6.1
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
""" Python test discovery, setup and run of test functions. """
|
""" Python test discovery, setup and run of test functions. """
|
||||||
|
import fnmatch
|
||||||
import py
|
import py
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
|
@ -127,9 +128,10 @@ def pytest_addoption(parser):
|
||||||
default=['test_*.py', '*_test.py'],
|
default=['test_*.py', '*_test.py'],
|
||||||
help="glob-style file patterns for Python test module discovery")
|
help="glob-style file patterns for Python test module discovery")
|
||||||
parser.addini("python_classes", type="args", default=["Test",],
|
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",],
|
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):
|
def pytest_cmdline_main(config):
|
||||||
if config.option.showfixtures:
|
if config.option.showfixtures:
|
||||||
|
@ -307,14 +309,26 @@ class PyobjMixin(PyobjContext):
|
||||||
class PyCollector(PyobjMixin, pytest.Collector):
|
class PyCollector(PyobjMixin, pytest.Collector):
|
||||||
|
|
||||||
def funcnamefilter(self, name):
|
def funcnamefilter(self, name):
|
||||||
for prefix in self.config.getini("python_functions"):
|
return self._matches_prefix_or_glob_option('python_functions', name)
|
||||||
if name.startswith(prefix):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def classnamefilter(self, name):
|
def classnamefilter(self, name):
|
||||||
for prefix in self.config.getini("python_classes"):
|
return self._matches_prefix_or_glob_option('python_classes', name)
|
||||||
if name.startswith(prefix):
|
|
||||||
|
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
|
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):
|
def collect(self):
|
||||||
if not getattr(self.obj, "__test__", True):
|
if not getattr(self.obj, "__test__", True):
|
||||||
|
|
|
@ -115,17 +115,33 @@ Builtin configuration file options
|
||||||
|
|
||||||
.. confval:: python_classes
|
.. confval:: python_classes
|
||||||
|
|
||||||
One or more name prefixes determining which test classes
|
One or more name prefixes or glob-style patterns determining which classes
|
||||||
are considered as test modules.
|
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
|
.. confval:: python_functions
|
||||||
|
|
||||||
One or more name prefixes determining which test functions
|
One or more name prefixes or glob-patterns determining which test functions
|
||||||
and methods are considered as test modules. Note that this
|
and methods are considered tests. Here is an example of how
|
||||||
has no effect on methods that live on a ``unittest.TestCase``
|
to collect test functions and methods that end in ``_test``::
|
||||||
derived class.
|
|
||||||
|
|
||||||
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
|
.. confval:: doctest_optionflags
|
||||||
|
|
||||||
|
|
|
@ -26,17 +26,17 @@ the :confval:`python_files`, :confval:`python_classes` and
|
||||||
[pytest]
|
[pytest]
|
||||||
python_files=check_*.py
|
python_files=check_*.py
|
||||||
python_classes=Check
|
python_classes=Check
|
||||||
python_functions=check
|
python_functions=*_check
|
||||||
|
|
||||||
This would make ``pytest`` look for ``check_`` prefixes in
|
This would make ``pytest`` look for tests in files that match the ``check_*
|
||||||
Python filenames, ``Check`` prefixes in classes and ``check`` prefixes
|
.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
|
||||||
in functions and classes. For example, if we have::
|
that match ``*_check``. For example, if we have::
|
||||||
|
|
||||||
# content of check_myapp.py
|
# content of check_myapp.py
|
||||||
class CheckMyApp:
|
class CheckMyApp:
|
||||||
def check_simple(self):
|
def simple_check(self):
|
||||||
pass
|
pass
|
||||||
def check_complex(self):
|
def complex_check(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
then the test collection looks like this::
|
then the test collection looks like this::
|
||||||
|
@ -48,14 +48,14 @@ then the test collection looks like this::
|
||||||
<Module 'check_myapp.py'>
|
<Module 'check_myapp.py'>
|
||||||
<Class 'CheckMyApp'>
|
<Class 'CheckMyApp'>
|
||||||
<Instance '()'>
|
<Instance '()'>
|
||||||
<Function 'check_simple'>
|
<Function 'simple_check'>
|
||||||
<Function 'check_complex'>
|
<Function 'complex_check'>
|
||||||
|
|
||||||
============================= in 0.01 seconds =============================
|
============================= in 0.01 seconds =============================
|
||||||
|
|
||||||
.. note::
|
.. 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
|
for ``unittest.TestCase`` test discovery because pytest delegates
|
||||||
detection of test case methods to unittest code.
|
detection of test case methods to unittest code.
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,30 @@ class Test_genitems:
|
||||||
assert s.endswith("test_example_items1.testone")
|
assert s.endswith("test_example_items1.testone")
|
||||||
print(s)
|
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):
|
def test_matchnodes_two_collections_same_file(testdir):
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
Loading…
Reference in New Issue