Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" generic mechanism for marking and selecting python functions. """ 

2from .legacy import matchkeyword 

3from .legacy import matchmark 

4from .structures import EMPTY_PARAMETERSET_OPTION 

5from .structures import get_empty_parameterset_mark 

6from .structures import Mark 

7from .structures import MARK_GEN 

8from .structures import MarkDecorator 

9from .structures import MarkGenerator 

10from .structures import ParameterSet 

11from _pytest.config import hookimpl 

12from _pytest.config import UsageError 

13 

14__all__ = ["Mark", "MarkDecorator", "MarkGenerator", "get_empty_parameterset_mark"] 

15 

16 

17def param(*values, **kw): 

18 """Specify a parameter in `pytest.mark.parametrize`_ calls or 

19 :ref:`parametrized fixtures <fixture-parametrize-marks>`. 

20 

21 .. code-block:: python 

22 

23 @pytest.mark.parametrize("test_input,expected", [ 

24 ("3+5", 8), 

25 pytest.param("6*9", 42, marks=pytest.mark.xfail), 

26 ]) 

27 def test_eval(test_input, expected): 

28 assert eval(test_input) == expected 

29 

30 :param values: variable args of the values of the parameter set, in order. 

31 :keyword marks: a single mark or a list of marks to be applied to this parameter set. 

32 :keyword str id: the id to attribute to this parameter set. 

33 """ 

34 return ParameterSet.param(*values, **kw) 

35 

36 

37def pytest_addoption(parser): 

38 group = parser.getgroup("general") 

39 group._addoption( 

40 "-k", 

41 action="store", 

42 dest="keyword", 

43 default="", 

44 metavar="EXPRESSION", 

45 help="only run tests which match the given substring expression. " 

46 "An expression is a python evaluatable expression " 

47 "where all names are substring-matched against test names " 

48 "and their parent classes. Example: -k 'test_method or test_" 

49 "other' matches all test functions and classes whose name " 

50 "contains 'test_method' or 'test_other', while -k 'not test_method' " 

51 "matches those that don't contain 'test_method' in their names. " 

52 "-k 'not test_method and not test_other' will eliminate the matches. " 

53 "Additionally keywords are matched to classes and functions " 

54 "containing extra names in their 'extra_keyword_matches' set, " 

55 "as well as functions which have names assigned directly to them.", 

56 ) 

57 

58 group._addoption( 

59 "-m", 

60 action="store", 

61 dest="markexpr", 

62 default="", 

63 metavar="MARKEXPR", 

64 help="only run tests matching given mark expression. " 

65 "example: -m 'mark1 and not mark2'.", 

66 ) 

67 

68 group.addoption( 

69 "--markers", 

70 action="store_true", 

71 help="show markers (builtin, plugin and per-project ones).", 

72 ) 

73 

74 parser.addini("markers", "markers for test functions", "linelist") 

75 parser.addini(EMPTY_PARAMETERSET_OPTION, "default marker for empty parametersets") 

76 

77 

78@hookimpl(tryfirst=True) 

79def pytest_cmdline_main(config): 

80 import _pytest.config 

81 

82 if config.option.markers: 

83 config._do_configure() 

84 tw = _pytest.config.create_terminal_writer(config) 

85 for line in config.getini("markers"): 

86 parts = line.split(":", 1) 

87 name = parts[0] 

88 rest = parts[1] if len(parts) == 2 else "" 

89 tw.write("@pytest.mark.%s:" % name, bold=True) 

90 tw.line(rest) 

91 tw.line() 

92 config._ensure_unconfigure() 

93 return 0 

94 

95 

96def deselect_by_keyword(items, config): 

97 keywordexpr = config.option.keyword.lstrip() 

98 if not keywordexpr: 

99 return 

100 

101 if keywordexpr.startswith("-"): 

102 keywordexpr = "not " + keywordexpr[1:] 

103 selectuntil = False 

104 if keywordexpr[-1:] == ":": 

105 selectuntil = True 

106 keywordexpr = keywordexpr[:-1] 

107 

108 remaining = [] 

109 deselected = [] 

110 for colitem in items: 

111 if keywordexpr and not matchkeyword(colitem, keywordexpr): 

112 deselected.append(colitem) 

113 else: 

114 if selectuntil: 

115 keywordexpr = None 

116 remaining.append(colitem) 

117 

118 if deselected: 

119 config.hook.pytest_deselected(items=deselected) 

120 items[:] = remaining 

121 

122 

123def deselect_by_mark(items, config): 

124 matchexpr = config.option.markexpr 

125 if not matchexpr: 

126 return 

127 

128 remaining = [] 

129 deselected = [] 

130 for item in items: 

131 if matchmark(item, matchexpr): 

132 remaining.append(item) 

133 else: 

134 deselected.append(item) 

135 

136 if deselected: 

137 config.hook.pytest_deselected(items=deselected) 

138 items[:] = remaining 

139 

140 

141def pytest_collection_modifyitems(items, config): 

142 deselect_by_keyword(items, config) 

143 deselect_by_mark(items, config) 

144 

145 

146def pytest_configure(config): 

147 config._old_mark_config = MARK_GEN._config 

148 MARK_GEN._config = config 

149 

150 empty_parameterset = config.getini(EMPTY_PARAMETERSET_OPTION) 

151 

152 if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""): 

153 raise UsageError( 

154 "{!s} must be one of skip, xfail or fail_at_collect" 

155 " but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset) 

156 ) 

157 

158 

159def pytest_unconfigure(config): 

160 MARK_GEN._config = getattr(config, "_old_mark_config", None)