2010-10-13 18:26:14 +08:00
|
|
|
""" generic mechanism for marking and selecting python functions. """
|
2017-03-17 09:21:30 +08:00
|
|
|
from __future__ import absolute_import, division, print_function
|
2018-01-17 04:35:57 +08:00
|
|
|
from _pytest.config import UsageError
|
2018-02-22 21:43:01 +08:00
|
|
|
from .structures import (
|
|
|
|
ParameterSet, EMPTY_PARAMETERSET_OPTION, MARK_GEN,
|
2018-02-22 22:13:01 +08:00
|
|
|
Mark, MarkInfo, MarkDecorator, MarkGenerator,
|
|
|
|
transfer_markers, get_empty_parameterset_mark
|
2018-02-22 21:43:01 +08:00
|
|
|
)
|
2018-02-22 22:11:55 +08:00
|
|
|
from .legacy import matchkeyword, matchmark
|
|
|
|
|
2018-02-22 22:13:01 +08:00
|
|
|
__all__ = [
|
|
|
|
'Mark', 'MarkInfo', 'MarkDecorator', 'MarkGenerator',
|
|
|
|
'transfer_markers', 'get_empty_parameterset_mark'
|
|
|
|
]
|
2017-12-17 18:26:51 +08:00
|
|
|
|
|
|
|
|
2015-03-24 03:01:58 +08:00
|
|
|
class MarkerError(Exception):
|
2015-03-24 04:28:29 +08:00
|
|
|
|
|
|
|
"""Error in use of a pytest marker/attribute."""
|
2015-03-24 03:01:58 +08:00
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
|
2017-03-21 00:58:34 +08:00
|
|
|
def param(*values, **kw):
|
2018-03-17 05:15:28 +08:00
|
|
|
"""Specify a parameter in a `pytest.mark.parametrize`_ call.
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("test_input,expected", [
|
|
|
|
("3+5", 8),
|
|
|
|
pytest.param("6*9", 42, marks=pytest.mark.xfail),
|
|
|
|
])
|
|
|
|
def test_eval(test_input, expected):
|
|
|
|
assert eval(test_input) == expected
|
|
|
|
|
|
|
|
:param values: variable args of the values of the parameter set, in order.
|
|
|
|
:keyword marks: a single mark or a list of marks to be applied to this parameter set.
|
|
|
|
:keyword str id: the id to attribute to this parameter set.
|
|
|
|
"""
|
2017-03-21 00:58:34 +08:00
|
|
|
return ParameterSet.param(*values, **kw)
|
2009-06-28 19:19:43 +08:00
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
|
2010-10-12 19:05:29 +08:00
|
|
|
def pytest_addoption(parser):
|
|
|
|
group = parser.getgroup("general")
|
2013-05-20 20:37:58 +08:00
|
|
|
group._addoption(
|
|
|
|
'-k',
|
2013-04-16 15:04:05 +08:00
|
|
|
action="store", dest="keyword", default='', metavar="EXPRESSION",
|
|
|
|
help="only run tests which match the given substring expression. "
|
2012-11-20 21:20:39 +08:00
|
|
|
"An expression is a python evaluatable expression "
|
2013-05-22 13:41:46 +08:00
|
|
|
"where all names are substring-matched against test names "
|
2016-09-05 16:48:04 +08:00
|
|
|
"and their parent classes. Example: -k 'test_method or test_"
|
2013-05-20 20:37:58 +08:00
|
|
|
"other' matches all test functions and classes whose name "
|
2017-10-01 06:36:09 +08:00
|
|
|
"contains 'test_method' or 'test_other', while -k 'not test_method' "
|
|
|
|
"matches those that don't contain 'test_method' in their names. "
|
2013-05-20 20:37:58 +08:00
|
|
|
"Additionally keywords are matched to classes and functions "
|
2013-05-28 00:14:35 +08:00
|
|
|
"containing extra names in their 'extra_keyword_matches' set, "
|
2013-05-20 20:37:58 +08:00
|
|
|
"as well as functions which have names assigned directly to them."
|
|
|
|
)
|
2010-10-12 19:05:29 +08:00
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
group._addoption(
|
|
|
|
"-m",
|
2011-11-12 07:02:06 +08:00
|
|
|
action="store", dest="markexpr", default="", metavar="MARKEXPR",
|
2011-11-19 02:32:11 +08:00
|
|
|
help="only run tests matching given mark expression. "
|
|
|
|
"example: -m 'mark1 and not mark2'."
|
2013-05-20 20:37:58 +08:00
|
|
|
)
|
2011-11-12 07:02:06 +08:00
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
group.addoption(
|
|
|
|
"--markers", action="store_true",
|
|
|
|
help="show markers (builtin, plugin and per-project ones)."
|
|
|
|
)
|
2011-11-12 06:56:11 +08:00
|
|
|
|
|
|
|
parser.addini("markers", "markers for test functions", 'linelist')
|
2017-12-17 19:49:12 +08:00
|
|
|
parser.addini(
|
2018-01-26 19:12:26 +08:00
|
|
|
EMPTY_PARAMETERSET_OPTION,
|
2017-12-17 19:49:12 +08:00
|
|
|
"default marker for empty parametersets")
|
2011-11-12 06:56:11 +08:00
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
|
2011-11-12 06:56:11 +08:00
|
|
|
def pytest_cmdline_main(config):
|
2015-07-19 03:39:55 +08:00
|
|
|
import _pytest.config
|
2011-11-12 06:56:11 +08:00
|
|
|
if config.option.markers:
|
2015-04-22 22:33:20 +08:00
|
|
|
config._do_configure()
|
2015-07-19 03:39:55 +08:00
|
|
|
tw = _pytest.config.create_terminal_writer(config)
|
2011-11-12 06:56:11 +08:00
|
|
|
for line in config.getini("markers"):
|
2017-11-22 20:47:15 +08:00
|
|
|
parts = line.split(":", 1)
|
|
|
|
name = parts[0]
|
|
|
|
rest = parts[1] if len(parts) == 2 else ''
|
2013-05-20 20:37:58 +08:00
|
|
|
tw.write("@pytest.mark.%s:" % name, bold=True)
|
2011-11-12 06:56:11 +08:00
|
|
|
tw.line(rest)
|
|
|
|
tw.line()
|
2015-04-22 22:33:20 +08:00
|
|
|
config._ensure_unconfigure()
|
2011-11-12 06:56:11 +08:00
|
|
|
return 0
|
2016-11-21 04:59:15 +08:00
|
|
|
|
|
|
|
|
2011-11-12 06:56:11 +08:00
|
|
|
pytest_cmdline_main.tryfirst = True
|
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
|
2018-02-22 22:11:55 +08:00
|
|
|
def deselect_by_keyword(items, config):
|
2016-04-01 13:20:22 +08:00
|
|
|
keywordexpr = config.option.keyword.lstrip()
|
2014-10-06 18:11:48 +08:00
|
|
|
if keywordexpr.startswith("-"):
|
|
|
|
keywordexpr = "not " + keywordexpr[1:]
|
2010-10-12 19:05:29 +08:00
|
|
|
selectuntil = False
|
2011-11-12 07:02:06 +08:00
|
|
|
if keywordexpr[-1:] == ":":
|
2010-10-12 19:05:29 +08:00
|
|
|
selectuntil = True
|
|
|
|
keywordexpr = keywordexpr[:-1]
|
|
|
|
|
|
|
|
remaining = []
|
|
|
|
deselected = []
|
|
|
|
for colitem in items:
|
2012-11-09 19:29:33 +08:00
|
|
|
if keywordexpr and not matchkeyword(colitem, keywordexpr):
|
2010-10-12 19:05:29 +08:00
|
|
|
deselected.append(colitem)
|
|
|
|
else:
|
|
|
|
if selectuntil:
|
|
|
|
keywordexpr = None
|
2011-11-12 07:02:06 +08:00
|
|
|
remaining.append(colitem)
|
2010-10-12 19:05:29 +08:00
|
|
|
|
|
|
|
if deselected:
|
|
|
|
config.hook.pytest_deselected(items=deselected)
|
|
|
|
items[:] = remaining
|
|
|
|
|
2013-05-20 20:37:58 +08:00
|
|
|
|
2018-02-22 22:11:55 +08:00
|
|
|
def deselect_by_mark(items, config):
|
|
|
|
matchexpr = config.option.markexpr
|
|
|
|
if not matchexpr:
|
|
|
|
return
|
|
|
|
|
|
|
|
remaining = []
|
|
|
|
deselected = []
|
|
|
|
for item in items:
|
|
|
|
if matchmark(item, matchexpr):
|
|
|
|
remaining.append(item)
|
|
|
|
else:
|
|
|
|
deselected.append(item)
|
|
|
|
|
|
|
|
if deselected:
|
|
|
|
config.hook.pytest_deselected(items=deselected)
|
|
|
|
items[:] = remaining
|
|
|
|
|
|
|
|
|
|
|
|
def pytest_collection_modifyitems(items, config):
|
|
|
|
deselect_by_keyword(items, config)
|
|
|
|
deselect_by_mark(items, config)
|
|
|
|
|
|
|
|
|
2011-11-12 06:56:11 +08:00
|
|
|
def pytest_configure(config):
|
2017-02-28 23:58:29 +08:00
|
|
|
config._old_mark_config = MARK_GEN._config
|
2011-11-12 06:56:11 +08:00
|
|
|
if config.option.strict:
|
2017-02-28 23:58:29 +08:00
|
|
|
MARK_GEN._config = config
|
|
|
|
|
2018-01-26 19:12:26 +08:00
|
|
|
empty_parameterset = config.getini(EMPTY_PARAMETERSET_OPTION)
|
2017-12-17 19:49:12 +08:00
|
|
|
|
|
|
|
if empty_parameterset not in ('skip', 'xfail', None, ''):
|
|
|
|
raise UsageError(
|
2018-01-26 19:12:26 +08:00
|
|
|
"{!s} must be one of skip and xfail,"
|
|
|
|
" but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset))
|
2017-12-17 19:49:12 +08:00
|
|
|
|
2017-02-28 23:58:29 +08:00
|
|
|
|
|
|
|
def pytest_unconfigure(config):
|
2017-03-01 00:30:52 +08:00
|
|
|
MARK_GEN._config = getattr(config, '_old_mark_config', None)
|