4 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/4fb4cb5ae00f/ Changeset: 4fb4cb5ae00f Branch: python-classes-glob User: nicoddemus Date: 2014-10-16 22:27:10+00:00 Summary: added support for glob-style patterns to python_classes and python_functions config options
fixes #600 Affected #: 4 files diff -r 4696fc59a5a15f9c79902d34489865bf7f840b6c -r 4fb4cb5ae00f6ca77992b2a566eefb073f299d27 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -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 @@ 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,22 @@ 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 + elif fnmatch.fnmatch(name, option): + return True + return False def collect(self): if not getattr(self.obj, "__test__", True): diff -r 4696fc59a5a15f9c79902d34489865bf7f840b6c -r 4fb4cb5ae00f6ca77992b2a566eefb073f299d27 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -115,17 +115,33 @@ .. 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 diff -r 4696fc59a5a15f9c79902d34489865bf7f840b6c -r 4fb4cb5ae00f6ca77992b2a566eefb073f299d27 doc/en/example/pythoncollection.txt --- a/doc/en/example/pythoncollection.txt +++ b/doc/en/example/pythoncollection.txt @@ -26,17 +26,17 @@ [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 @@ <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. diff -r 4696fc59a5a15f9c79902d34489865bf7f840b6c -r 4fb4cb5ae00f6ca77992b2a566eefb073f299d27 testing/test_collection.py --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -528,6 +528,30 @@ 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 https://bitbucket.org/hpk42/pytest/commits/f975c55d571f/ Changeset: f975c55d571f Branch: python-classes-glob User: nicoddemus Date: 2014-10-20 20:36:31+00:00 Summary: checking that option contains glob characters before calling fnmatch requested during code review Affected #: 1 file diff -r 4fb4cb5ae00f6ca77992b2a566eefb073f299d27 -r f975c55d571f3d08a1e3a02d6b2c13a9f4257d48 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -322,7 +322,11 @@ for option in self.config.getini(option_name): if name.startswith(option): return True - elif fnmatch.fnmatch(name, option): + # 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 https://bitbucket.org/hpk42/pytest/commits/447020d27a8e/ Changeset: 447020d27a8e Branch: python-classes-glob User: nicoddemus Date: 2014-10-21 21:22:53+00:00 Summary: added changelog entry about glob-patterns in python_classes and python_functions - also fixed small typo Affected #: 1 file diff -r f975c55d571f3d08a1e3a02d6b2c13a9f4257d48 -r 447020d27a8ef51b4a03b76fab923a0b8c4b2000 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -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 https://bitbucket.org/hpk42/pytest/commits/e9bfc62abed3/ Changeset: e9bfc62abed3 User: hpk42 Date: 2014-10-22 05:14:10+00:00 Summary: Merged in nicoddemus/pytest/python-classes-glob (pull request #225) added support for glob-style patterns to python_classes and python_functions config options Affected #: 5 files diff -r 78def8dd5c941ec312994f87fd31f8a422943879 -r e9bfc62abed3c6151cd6978167377f4bb1566802 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff -r 78def8dd5c941ec312994f87fd31f8a422943879 -r e9bfc62abed3c6151cd6978167377f4bb1566802 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -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 @@ 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 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): diff -r 78def8dd5c941ec312994f87fd31f8a422943879 -r e9bfc62abed3c6151cd6978167377f4bb1566802 doc/en/customize.txt --- a/doc/en/customize.txt +++ b/doc/en/customize.txt @@ -115,17 +115,33 @@ .. 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 diff -r 78def8dd5c941ec312994f87fd31f8a422943879 -r e9bfc62abed3c6151cd6978167377f4bb1566802 doc/en/example/pythoncollection.txt --- a/doc/en/example/pythoncollection.txt +++ b/doc/en/example/pythoncollection.txt @@ -26,17 +26,17 @@ [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 @@ <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. diff -r 78def8dd5c941ec312994f87fd31f8a422943879 -r e9bfc62abed3c6151cd6978167377f4bb1566802 testing/test_collection.py --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -528,6 +528,30 @@ 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 Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. _______________________________________________ pytest-commit mailing list pytest-commit@python.org https://mail.python.org/mailman/listinfo/pytest-commit