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