__init__.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. # -*- coding: utf-8 -*-
  2. """ generic mechanism for marking and selecting python functions. """
  3. from __future__ import absolute_import
  4. from __future__ import division
  5. from __future__ import print_function
  6. from .legacy import matchkeyword
  7. from .legacy import matchmark
  8. from .structures import EMPTY_PARAMETERSET_OPTION
  9. from .structures import get_empty_parameterset_mark
  10. from .structures import Mark
  11. from .structures import MARK_GEN
  12. from .structures import MarkDecorator
  13. from .structures import MarkGenerator
  14. from .structures import ParameterSet
  15. from _pytest.config import UsageError
  16. __all__ = ["Mark", "MarkDecorator", "MarkGenerator", "get_empty_parameterset_mark"]
  17. def param(*values, **kw):
  18. """Specify a parameter in `pytest.mark.parametrize`_ calls or
  19. :ref:`parametrized fixtures <fixture-parametrize-marks>`.
  20. .. code-block:: python
  21. @pytest.mark.parametrize("test_input,expected", [
  22. ("3+5", 8),
  23. pytest.param("6*9", 42, marks=pytest.mark.xfail),
  24. ])
  25. def test_eval(test_input, expected):
  26. assert eval(test_input) == expected
  27. :param values: variable args of the values of the parameter set, in order.
  28. :keyword marks: a single mark or a list of marks to be applied to this parameter set.
  29. :keyword str id: the id to attribute to this parameter set.
  30. """
  31. return ParameterSet.param(*values, **kw)
  32. def pytest_addoption(parser):
  33. group = parser.getgroup("general")
  34. group._addoption(
  35. "-k",
  36. action="store",
  37. dest="keyword",
  38. default="",
  39. metavar="EXPRESSION",
  40. help="only run tests which match the given substring expression. "
  41. "An expression is a python evaluatable expression "
  42. "where all names are substring-matched against test names "
  43. "and their parent classes. Example: -k 'test_method or test_"
  44. "other' matches all test functions and classes whose name "
  45. "contains 'test_method' or 'test_other', while -k 'not test_method' "
  46. "matches those that don't contain 'test_method' in their names. "
  47. "-k 'not test_method and not test_other' will eliminate the matches. "
  48. "Additionally keywords are matched to classes and functions "
  49. "containing extra names in their 'extra_keyword_matches' set, "
  50. "as well as functions which have names assigned directly to them.",
  51. )
  52. group._addoption(
  53. "-m",
  54. action="store",
  55. dest="markexpr",
  56. default="",
  57. metavar="MARKEXPR",
  58. help="only run tests matching given mark expression. "
  59. "example: -m 'mark1 and not mark2'.",
  60. )
  61. group.addoption(
  62. "--markers",
  63. action="store_true",
  64. help="show markers (builtin, plugin and per-project ones).",
  65. )
  66. parser.addini("markers", "markers for test functions", "linelist")
  67. parser.addini(EMPTY_PARAMETERSET_OPTION, "default marker for empty parametersets")
  68. def pytest_cmdline_main(config):
  69. import _pytest.config
  70. if config.option.markers:
  71. config._do_configure()
  72. tw = _pytest.config.create_terminal_writer(config)
  73. for line in config.getini("markers"):
  74. parts = line.split(":", 1)
  75. name = parts[0]
  76. rest = parts[1] if len(parts) == 2 else ""
  77. tw.write("@pytest.mark.%s:" % name, bold=True)
  78. tw.line(rest)
  79. tw.line()
  80. config._ensure_unconfigure()
  81. return 0
  82. pytest_cmdline_main.tryfirst = True
  83. def deselect_by_keyword(items, config):
  84. keywordexpr = config.option.keyword.lstrip()
  85. if not keywordexpr:
  86. return
  87. if keywordexpr.startswith("-"):
  88. keywordexpr = "not " + keywordexpr[1:]
  89. selectuntil = False
  90. if keywordexpr[-1:] == ":":
  91. selectuntil = True
  92. keywordexpr = keywordexpr[:-1]
  93. remaining = []
  94. deselected = []
  95. for colitem in items:
  96. if keywordexpr and not matchkeyword(colitem, keywordexpr):
  97. deselected.append(colitem)
  98. else:
  99. if selectuntil:
  100. keywordexpr = None
  101. remaining.append(colitem)
  102. if deselected:
  103. config.hook.pytest_deselected(items=deselected)
  104. items[:] = remaining
  105. def deselect_by_mark(items, config):
  106. matchexpr = config.option.markexpr
  107. if not matchexpr:
  108. return
  109. remaining = []
  110. deselected = []
  111. for item in items:
  112. if matchmark(item, matchexpr):
  113. remaining.append(item)
  114. else:
  115. deselected.append(item)
  116. if deselected:
  117. config.hook.pytest_deselected(items=deselected)
  118. items[:] = remaining
  119. def pytest_collection_modifyitems(items, config):
  120. deselect_by_keyword(items, config)
  121. deselect_by_mark(items, config)
  122. def pytest_configure(config):
  123. config._old_mark_config = MARK_GEN._config
  124. MARK_GEN._config = config
  125. empty_parameterset = config.getini(EMPTY_PARAMETERSET_OPTION)
  126. if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""):
  127. raise UsageError(
  128. "{!s} must be one of skip, xfail or fail_at_collect"
  129. " but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset)
  130. )
  131. def pytest_unconfigure(config):
  132. MARK_GEN._config = getattr(config, "_old_mark_config", None)