introduce new discovery mechanism

XXX experiment with using it before introducing it or wait
for feature request
This commit is contained in:
holger krekel 2010-11-24 22:01:04 +01:00
parent 03ee8b7fe0
commit 4cb2c74159
6 changed files with 124 additions and 8 deletions

View File

@ -258,6 +258,7 @@ class Config(object):
self.trace = self.pluginmanager.trace.root.get("config")
self._conftest = Conftest(onimport=self._onimportconftest)
self.hook = self.pluginmanager.hook
self._inicache = {}
def _onimportconftest(self, conftestmodule):
self.trace("loaded conftestmodule %r" %(conftestmodule,))
@ -332,6 +333,13 @@ class Config(object):
""" return configuration value from an ini file. If the
specified name hasn't been registered through a prior ``parse.addini``
call (usually from a plugin), a ValueError is raised. """
try:
return self._inicache[name]
except KeyError:
self._inicache[name] = val = self._getini(name)
return val
def _getini(self, name):
try:
description, type, default = self._parser._inidict[name]
except KeyError:

View File

@ -13,6 +13,13 @@ def pytest_addoption(parser):
group.addoption('--funcargs',
action="store_true", dest="showfuncargs", default=False,
help="show available function arguments, sorted by plugin")
parser.addini("python_files", type="args",
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")
parser.addini("python_functions", type="args", default=("test",),
help="prefixes for Python test function and method discovery")
def pytest_cmdline_main(config):
if config.option.showfuncargs:
@ -46,8 +53,13 @@ def pytest_pyfunc_call(__multicall__, pyfuncitem):
def pytest_collect_file(path, parent):
ext = path.ext
pb = path.purebasename
if ext == ".py" and (pb.startswith("test_") or pb.endswith("_test") or
parent.session.isinitpath(path)):
if ext == ".py":
if not parent.session.isinitpath(path):
for pat in parent.config.getini('python_files'):
if path.fnmatch(pat):
break
else:
return
return parent.ihook.pytest_pycollect_makemodule(
path=path, parent=parent)
@ -145,9 +157,14 @@ class PyobjMixin(object):
class PyCollectorMixin(PyobjMixin, pytest.Collector):
def funcnamefilter(self, name):
return name.startswith('test')
for prefix in self.config.getini("python_functions"):
if name.startswith(prefix):
return True
def classnamefilter(self, name):
return name.startswith('Test')
for prefix in self.config.getini("python_classes"):
if name.startswith(prefix):
return True
def collect(self):
# NB. we avoid random getattrs and peek in the __dict__ instead

View File

@ -86,3 +86,18 @@ builtin configuration file options
This would tell py.test to not recurse into typical subversion or
sphinx-build directories or into any ``tmp`` prefixed directory.
.. confval:: python_discovery
Determines names and patterns for finding Python tests, specified
through indendent ``name = value`` settings with these possible names::
[pytest]
python_discovery =
file = <glob-pattern> <glob-pattern>
func = <function-or-method-name-prefix>
class = <class-name-prefix>
See :ref:`change naming conventions` for examples. the ``class``
to be empty in which case all non-underscore empty classes
will be considered.

View File

@ -12,19 +12,63 @@ You can set the :confval:`norecursedirs` option in an ini-file, for example your
This would tell py.test to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
always try to interpret arguments as Python packages
.. _`change naming conventions`:
change naming conventions
-----------------------------------------------------
You can configure different naming conventions by setting
the :confval:`pytest_pycollect` configuration option. Example::
# content of setup.cfg
# can also be defined in in tox.ini or pytest.ini file
[pytest]
python_files=check_*.py
python_classes=Check
python_functions=check
This would make py.test look for ``check_`` prefixes in
Python filenames, ``Check`` prefixes in classes and ``check`` prefixes
in functions and classes. For example, if we have::
# content of check_myapp.py
class CheckMyApp:
def check_simple(self):
pass
def check_complex(self):
pass
then the test collection looks like this::
$ py.test --collectonly
<Module 'check_myapp.py'>
<Class 'CheckMyApp'>
<Instance '()'>
<Function 'check_simple'>
<Function 'check_complex'>
interpret cmdline arguments as Python packages
-----------------------------------------------------
You can use the ``--pyargs`` option to make py.test try
interpreting arguments as python package names, deriving
their file system path and then running the test. Through
an ini-file and the :confval:`addopts` option you can make
this change more permanently::
their file system path and then running the test. For
example if you have unittest2 installed you can type::
py.test --pyargs unittest2.test.test_skipping -q
which will run the respective test module. Like with
other options, through an ini-file and the :confval:`addopts` option you
can make this change more permanently::
# content of pytest.ini
[pytest]
addopts = --pyargs
Now a simple invocation of ``py.test NAME`` will check
if NAME exists as an importable package/module and otherwise
treat it as a filesystem path.
finding out what is collected
-----------------------------------------------

View File

@ -1208,3 +1208,32 @@ class TestRaises:
def test_customized_python_discovery(testdir):
testdir.makeini("""
[pytest]
python_files=check_*.py
python_classes=Check
python_functions=check
""")
p = testdir.makepyfile("""
def check_simple():
pass
class CheckMyApp:
def check_meth(self):
pass
""")
p2 = p.new(basename=p.basename.replace("test", "check"))
p.move(p2)
result = testdir.runpytest("--collectonly", "-s")
result.stdout.fnmatch_lines([
"*check_customized*",
"*check_simple*",
"*CheckMyApp*",
"*check_meth*",
])
result = testdir.runpytest()
assert result.ret == 0
result.stdout.fnmatch_lines([
"*2 passed*",
])

View File

@ -73,3 +73,6 @@ minversion=2.0
plugins=pytester
addopts= -rxf --pyargs --doctest-modules
rsyncdirs=tox.ini pytest.py _pytest testing
python_files=test_*.py *_test.py
python_classes=Test Acceptance
python_functions=test