python.py 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507
  1. # -*- coding: utf-8 -*-
  2. """ Python test discovery, setup and run of test functions. """
  3. from __future__ import absolute_import
  4. from __future__ import division
  5. from __future__ import print_function
  6. import collections
  7. import fnmatch
  8. import inspect
  9. import os
  10. import sys
  11. import warnings
  12. from functools import partial
  13. from textwrap import dedent
  14. import py
  15. import six
  16. import _pytest
  17. from _pytest import deprecated
  18. from _pytest import fixtures
  19. from _pytest import nodes
  20. from _pytest._code import filter_traceback
  21. from _pytest.compat import ascii_escaped
  22. from _pytest.compat import enum
  23. from _pytest.compat import get_default_arg_names
  24. from _pytest.compat import get_real_func
  25. from _pytest.compat import getfslineno
  26. from _pytest.compat import getimfunc
  27. from _pytest.compat import getlocation
  28. from _pytest.compat import is_generator
  29. from _pytest.compat import isclass
  30. from _pytest.compat import isfunction
  31. from _pytest.compat import NOTSET
  32. from _pytest.compat import REGEX_TYPE
  33. from _pytest.compat import safe_getattr
  34. from _pytest.compat import safe_isclass
  35. from _pytest.compat import safe_str
  36. from _pytest.compat import STRING_TYPES
  37. from _pytest.config import hookimpl
  38. from _pytest.main import FSHookProxy
  39. from _pytest.mark import MARK_GEN
  40. from _pytest.mark.structures import get_unpacked_marks
  41. from _pytest.mark.structures import normalize_mark_list
  42. from _pytest.outcomes import fail
  43. from _pytest.outcomes import skip
  44. from _pytest.pathlib import parts
  45. from _pytest.warning_types import PytestCollectionWarning
  46. from _pytest.warning_types import PytestUnhandledCoroutineWarning
  47. def pyobj_property(name):
  48. def get(self):
  49. node = self.getparent(getattr(__import__("pytest"), name))
  50. if node is not None:
  51. return node.obj
  52. doc = "python %s object this node was collected from (can be None)." % (
  53. name.lower(),
  54. )
  55. return property(get, None, None, doc)
  56. def pytest_addoption(parser):
  57. group = parser.getgroup("general")
  58. group.addoption(
  59. "--fixtures",
  60. "--funcargs",
  61. action="store_true",
  62. dest="showfixtures",
  63. default=False,
  64. help="show available fixtures, sorted by plugin appearance "
  65. "(fixtures with leading '_' are only shown with '-v')",
  66. )
  67. group.addoption(
  68. "--fixtures-per-test",
  69. action="store_true",
  70. dest="show_fixtures_per_test",
  71. default=False,
  72. help="show fixtures per test",
  73. )
  74. parser.addini(
  75. "python_files",
  76. type="args",
  77. # NOTE: default is also used in AssertionRewritingHook.
  78. default=["test_*.py", "*_test.py"],
  79. help="glob-style file patterns for Python test module discovery",
  80. )
  81. parser.addini(
  82. "python_classes",
  83. type="args",
  84. default=["Test"],
  85. help="prefixes or glob names for Python test class discovery",
  86. )
  87. parser.addini(
  88. "python_functions",
  89. type="args",
  90. default=["test"],
  91. help="prefixes or glob names for Python test function and method discovery",
  92. )
  93. parser.addini(
  94. "disable_test_id_escaping_and_forfeit_all_rights_to_community_support",
  95. type="bool",
  96. default=False,
  97. help="disable string escape non-ascii characters, might cause unwanted "
  98. "side effects(use at your own risk)",
  99. )
  100. group.addoption(
  101. "--import-mode",
  102. default="prepend",
  103. choices=["prepend", "append"],
  104. dest="importmode",
  105. help="prepend/append to sys.path when importing test modules, "
  106. "default is to prepend.",
  107. )
  108. def pytest_cmdline_main(config):
  109. if config.option.showfixtures:
  110. showfixtures(config)
  111. return 0
  112. if config.option.show_fixtures_per_test:
  113. show_fixtures_per_test(config)
  114. return 0
  115. def pytest_generate_tests(metafunc):
  116. # those alternative spellings are common - raise a specific error to alert
  117. # the user
  118. alt_spellings = ["parameterize", "parametrise", "parameterise"]
  119. for mark_name in alt_spellings:
  120. if metafunc.definition.get_closest_marker(mark_name):
  121. msg = "{0} has '{1}' mark, spelling should be 'parametrize'"
  122. fail(msg.format(metafunc.function.__name__, mark_name), pytrace=False)
  123. for marker in metafunc.definition.iter_markers(name="parametrize"):
  124. metafunc.parametrize(*marker.args, **marker.kwargs)
  125. def pytest_configure(config):
  126. config.addinivalue_line(
  127. "markers",
  128. "parametrize(argnames, argvalues): call a test function multiple "
  129. "times passing in different arguments in turn. argvalues generally "
  130. "needs to be a list of values if argnames specifies only one name "
  131. "or a list of tuples of values if argnames specifies multiple names. "
  132. "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "
  133. "decorated test function, one with arg1=1 and another with arg1=2."
  134. "see https://docs.pytest.org/en/latest/parametrize.html for more info "
  135. "and examples.",
  136. )
  137. config.addinivalue_line(
  138. "markers",
  139. "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
  140. "all of the specified fixtures. see "
  141. "https://docs.pytest.org/en/latest/fixture.html#usefixtures ",
  142. )
  143. @hookimpl(trylast=True)
  144. def pytest_pyfunc_call(pyfuncitem):
  145. testfunction = pyfuncitem.obj
  146. iscoroutinefunction = getattr(inspect, "iscoroutinefunction", None)
  147. if iscoroutinefunction is not None and iscoroutinefunction(testfunction):
  148. msg = "Coroutine functions are not natively supported and have been skipped.\n"
  149. msg += "You need to install a suitable plugin for your async framework, for example:\n"
  150. msg += " - pytest-asyncio\n"
  151. msg += " - pytest-trio\n"
  152. msg += " - pytest-tornasync"
  153. warnings.warn(PytestUnhandledCoroutineWarning(msg.format(pyfuncitem.nodeid)))
  154. skip(msg="coroutine function and no async plugin installed (see warnings)")
  155. funcargs = pyfuncitem.funcargs
  156. testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames}
  157. testfunction(**testargs)
  158. return True
  159. def pytest_collect_file(path, parent):
  160. ext = path.ext
  161. if ext == ".py":
  162. if not parent.session.isinitpath(path):
  163. if not path_matches_patterns(
  164. path, parent.config.getini("python_files") + ["__init__.py"]
  165. ):
  166. return
  167. ihook = parent.session.gethookproxy(path)
  168. return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
  169. def path_matches_patterns(path, patterns):
  170. """Returns True if the given py.path.local matches one of the patterns in the list of globs given"""
  171. return any(path.fnmatch(pattern) for pattern in patterns)
  172. def pytest_pycollect_makemodule(path, parent):
  173. if path.basename == "__init__.py":
  174. return Package(path, parent)
  175. return Module(path, parent)
  176. @hookimpl(hookwrapper=True)
  177. def pytest_pycollect_makeitem(collector, name, obj):
  178. outcome = yield
  179. res = outcome.get_result()
  180. if res is not None:
  181. return
  182. # nothing was collected elsewhere, let's do it here
  183. if safe_isclass(obj):
  184. if collector.istestclass(obj, name):
  185. outcome.force_result(Class(name, parent=collector))
  186. elif collector.istestfunction(obj, name):
  187. # mock seems to store unbound methods (issue473), normalize it
  188. obj = getattr(obj, "__func__", obj)
  189. # We need to try and unwrap the function if it's a functools.partial
  190. # or a funtools.wrapped.
  191. # We musn't if it's been wrapped with mock.patch (python 2 only)
  192. if not (isfunction(obj) or isfunction(get_real_func(obj))):
  193. filename, lineno = getfslineno(obj)
  194. warnings.warn_explicit(
  195. message=PytestCollectionWarning(
  196. "cannot collect %r because it is not a function." % name
  197. ),
  198. category=None,
  199. filename=str(filename),
  200. lineno=lineno + 1,
  201. )
  202. elif getattr(obj, "__test__", True):
  203. if is_generator(obj):
  204. res = Function(name, parent=collector)
  205. reason = deprecated.YIELD_TESTS.format(name=name)
  206. res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
  207. res.warn(PytestCollectionWarning(reason))
  208. else:
  209. res = list(collector._genfunctions(name, obj))
  210. outcome.force_result(res)
  211. def pytest_make_parametrize_id(config, val, argname=None):
  212. return None
  213. class PyobjContext(object):
  214. module = pyobj_property("Module")
  215. cls = pyobj_property("Class")
  216. instance = pyobj_property("Instance")
  217. class PyobjMixin(PyobjContext):
  218. _ALLOW_MARKERS = True
  219. def __init__(self, *k, **kw):
  220. super(PyobjMixin, self).__init__(*k, **kw)
  221. @property
  222. def obj(self):
  223. """Underlying Python object."""
  224. obj = getattr(self, "_obj", None)
  225. if obj is None:
  226. self._obj = obj = self._getobj()
  227. # XXX evil hack
  228. # used to avoid Instance collector marker duplication
  229. if self._ALLOW_MARKERS:
  230. self.own_markers.extend(get_unpacked_marks(self.obj))
  231. return obj
  232. @obj.setter
  233. def obj(self, value):
  234. self._obj = value
  235. def _getobj(self):
  236. """Gets the underlying Python object. May be overwritten by subclasses."""
  237. return getattr(self.parent.obj, self.name)
  238. def getmodpath(self, stopatmodule=True, includemodule=False):
  239. """ return python path relative to the containing module. """
  240. chain = self.listchain()
  241. chain.reverse()
  242. parts = []
  243. for node in chain:
  244. if isinstance(node, Instance):
  245. continue
  246. name = node.name
  247. if isinstance(node, Module):
  248. name = os.path.splitext(name)[0]
  249. if stopatmodule:
  250. if includemodule:
  251. parts.append(name)
  252. break
  253. parts.append(name)
  254. parts.reverse()
  255. s = ".".join(parts)
  256. return s.replace(".[", "[")
  257. def reportinfo(self):
  258. # XXX caching?
  259. obj = self.obj
  260. compat_co_firstlineno = getattr(obj, "compat_co_firstlineno", None)
  261. if isinstance(compat_co_firstlineno, int):
  262. # nose compatibility
  263. fspath = sys.modules[obj.__module__].__file__
  264. if fspath.endswith(".pyc"):
  265. fspath = fspath[:-1]
  266. lineno = compat_co_firstlineno
  267. else:
  268. fspath, lineno = getfslineno(obj)
  269. modpath = self.getmodpath()
  270. assert isinstance(lineno, int)
  271. return fspath, lineno, modpath
  272. class PyCollector(PyobjMixin, nodes.Collector):
  273. def funcnamefilter(self, name):
  274. return self._matches_prefix_or_glob_option("python_functions", name)
  275. def isnosetest(self, obj):
  276. """ Look for the __test__ attribute, which is applied by the
  277. @nose.tools.istest decorator
  278. """
  279. # We explicitly check for "is True" here to not mistakenly treat
  280. # classes with a custom __getattr__ returning something truthy (like a
  281. # function) as test classes.
  282. return safe_getattr(obj, "__test__", False) is True
  283. def classnamefilter(self, name):
  284. return self._matches_prefix_or_glob_option("python_classes", name)
  285. def istestfunction(self, obj, name):
  286. if self.funcnamefilter(name) or self.isnosetest(obj):
  287. if isinstance(obj, staticmethod):
  288. # static methods need to be unwrapped
  289. obj = safe_getattr(obj, "__func__", False)
  290. return (
  291. safe_getattr(obj, "__call__", False)
  292. and fixtures.getfixturemarker(obj) is None
  293. )
  294. else:
  295. return False
  296. def istestclass(self, obj, name):
  297. return self.classnamefilter(name) or self.isnosetest(obj)
  298. def _matches_prefix_or_glob_option(self, option_name, name):
  299. """
  300. checks if the given name matches the prefix or glob-pattern defined
  301. in ini configuration.
  302. """
  303. for option in self.config.getini(option_name):
  304. if name.startswith(option):
  305. return True
  306. # check that name looks like a glob-string before calling fnmatch
  307. # because this is called for every name in each collected module,
  308. # and fnmatch is somewhat expensive to call
  309. elif ("*" in option or "?" in option or "[" in option) and fnmatch.fnmatch(
  310. name, option
  311. ):
  312. return True
  313. return False
  314. def collect(self):
  315. if not getattr(self.obj, "__test__", True):
  316. return []
  317. # NB. we avoid random getattrs and peek in the __dict__ instead
  318. # (XXX originally introduced from a PyPy need, still true?)
  319. dicts = [getattr(self.obj, "__dict__", {})]
  320. for basecls in inspect.getmro(self.obj.__class__):
  321. dicts.append(basecls.__dict__)
  322. seen = {}
  323. values = []
  324. for dic in dicts:
  325. for name, obj in list(dic.items()):
  326. if name in seen:
  327. continue
  328. seen[name] = True
  329. res = self._makeitem(name, obj)
  330. if res is None:
  331. continue
  332. if not isinstance(res, list):
  333. res = [res]
  334. values.extend(res)
  335. values.sort(key=lambda item: item.reportinfo()[:2])
  336. return values
  337. def _makeitem(self, name, obj):
  338. # assert self.ihook.fspath == self.fspath, self
  339. return self.ihook.pytest_pycollect_makeitem(collector=self, name=name, obj=obj)
  340. def _genfunctions(self, name, funcobj):
  341. module = self.getparent(Module).obj
  342. clscol = self.getparent(Class)
  343. cls = clscol and clscol.obj or None
  344. fm = self.session._fixturemanager
  345. definition = FunctionDefinition(name=name, parent=self, callobj=funcobj)
  346. fixtureinfo = fm.getfixtureinfo(definition, funcobj, cls)
  347. metafunc = Metafunc(
  348. definition, fixtureinfo, self.config, cls=cls, module=module
  349. )
  350. methods = []
  351. if hasattr(module, "pytest_generate_tests"):
  352. methods.append(module.pytest_generate_tests)
  353. if hasattr(cls, "pytest_generate_tests"):
  354. methods.append(cls().pytest_generate_tests)
  355. if methods:
  356. self.ihook.pytest_generate_tests.call_extra(
  357. methods, dict(metafunc=metafunc)
  358. )
  359. else:
  360. self.ihook.pytest_generate_tests(metafunc=metafunc)
  361. if not metafunc._calls:
  362. yield Function(name, parent=self, fixtureinfo=fixtureinfo)
  363. else:
  364. # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs
  365. fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm)
  366. # add_funcarg_pseudo_fixture_def may have shadowed some fixtures
  367. # with direct parametrization, so make sure we update what the
  368. # function really needs.
  369. fixtureinfo.prune_dependency_tree()
  370. for callspec in metafunc._calls:
  371. subname = "%s[%s]" % (name, callspec.id)
  372. yield Function(
  373. name=subname,
  374. parent=self,
  375. callspec=callspec,
  376. callobj=funcobj,
  377. fixtureinfo=fixtureinfo,
  378. keywords={callspec.id: True},
  379. originalname=name,
  380. )
  381. class Module(nodes.File, PyCollector):
  382. """ Collector for test classes and functions. """
  383. def _getobj(self):
  384. return self._importtestmodule()
  385. def collect(self):
  386. self._inject_setup_module_fixture()
  387. self._inject_setup_function_fixture()
  388. self.session._fixturemanager.parsefactories(self)
  389. return super(Module, self).collect()
  390. def _inject_setup_module_fixture(self):
  391. """Injects a hidden autouse, module scoped fixture into the collected module object
  392. that invokes setUpModule/tearDownModule if either or both are available.
  393. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
  394. other fixtures (#517).
  395. """
  396. setup_module = _get_non_fixture_func(self.obj, "setUpModule")
  397. if setup_module is None:
  398. setup_module = _get_non_fixture_func(self.obj, "setup_module")
  399. teardown_module = _get_non_fixture_func(self.obj, "tearDownModule")
  400. if teardown_module is None:
  401. teardown_module = _get_non_fixture_func(self.obj, "teardown_module")
  402. if setup_module is None and teardown_module is None:
  403. return
  404. @fixtures.fixture(autouse=True, scope="module")
  405. def xunit_setup_module_fixture(request):
  406. if setup_module is not None:
  407. _call_with_optional_argument(setup_module, request.module)
  408. yield
  409. if teardown_module is not None:
  410. _call_with_optional_argument(teardown_module, request.module)
  411. self.obj.__pytest_setup_module = xunit_setup_module_fixture
  412. def _inject_setup_function_fixture(self):
  413. """Injects a hidden autouse, function scoped fixture into the collected module object
  414. that invokes setup_function/teardown_function if either or both are available.
  415. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
  416. other fixtures (#517).
  417. """
  418. setup_function = _get_non_fixture_func(self.obj, "setup_function")
  419. teardown_function = _get_non_fixture_func(self.obj, "teardown_function")
  420. if setup_function is None and teardown_function is None:
  421. return
  422. @fixtures.fixture(autouse=True, scope="function")
  423. def xunit_setup_function_fixture(request):
  424. if request.instance is not None:
  425. # in this case we are bound to an instance, so we need to let
  426. # setup_method handle this
  427. yield
  428. return
  429. if setup_function is not None:
  430. _call_with_optional_argument(setup_function, request.function)
  431. yield
  432. if teardown_function is not None:
  433. _call_with_optional_argument(teardown_function, request.function)
  434. self.obj.__pytest_setup_function = xunit_setup_function_fixture
  435. def _importtestmodule(self):
  436. # we assume we are only called once per module
  437. importmode = self.config.getoption("--import-mode")
  438. try:
  439. mod = self.fspath.pyimport(ensuresyspath=importmode)
  440. except SyntaxError:
  441. raise self.CollectError(
  442. _pytest._code.ExceptionInfo.from_current().getrepr(style="short")
  443. )
  444. except self.fspath.ImportMismatchError:
  445. e = sys.exc_info()[1]
  446. raise self.CollectError(
  447. "import file mismatch:\n"
  448. "imported module %r has this __file__ attribute:\n"
  449. " %s\n"
  450. "which is not the same as the test file we want to collect:\n"
  451. " %s\n"
  452. "HINT: remove __pycache__ / .pyc files and/or use a "
  453. "unique basename for your test file modules" % e.args
  454. )
  455. except ImportError:
  456. from _pytest._code.code import ExceptionInfo
  457. exc_info = ExceptionInfo.from_current()
  458. if self.config.getoption("verbose") < 2:
  459. exc_info.traceback = exc_info.traceback.filter(filter_traceback)
  460. exc_repr = (
  461. exc_info.getrepr(style="short")
  462. if exc_info.traceback
  463. else exc_info.exconly()
  464. )
  465. formatted_tb = safe_str(exc_repr)
  466. raise self.CollectError(
  467. "ImportError while importing test module '{fspath}'.\n"
  468. "Hint: make sure your test modules/packages have valid Python names.\n"
  469. "Traceback:\n"
  470. "{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
  471. )
  472. except _pytest.runner.Skipped as e:
  473. if e.allow_module_level:
  474. raise
  475. raise self.CollectError(
  476. "Using pytest.skip outside of a test is not allowed. "
  477. "To decorate a test function, use the @pytest.mark.skip "
  478. "or @pytest.mark.skipif decorators instead, and to skip a "
  479. "module use `pytestmark = pytest.mark.{skip,skipif}."
  480. )
  481. self.config.pluginmanager.consider_module(mod)
  482. return mod
  483. class Package(Module):
  484. def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
  485. session = parent.session
  486. nodes.FSCollector.__init__(
  487. self, fspath, parent=parent, config=config, session=session, nodeid=nodeid
  488. )
  489. self.name = fspath.dirname
  490. self.trace = session.trace
  491. self._norecursepatterns = session._norecursepatterns
  492. self.fspath = fspath
  493. def setup(self):
  494. # not using fixtures to call setup_module here because autouse fixtures
  495. # from packages are not called automatically (#4085)
  496. setup_module = _get_non_fixture_func(self.obj, "setUpModule")
  497. if setup_module is None:
  498. setup_module = _get_non_fixture_func(self.obj, "setup_module")
  499. if setup_module is not None:
  500. _call_with_optional_argument(setup_module, self.obj)
  501. teardown_module = _get_non_fixture_func(self.obj, "tearDownModule")
  502. if teardown_module is None:
  503. teardown_module = _get_non_fixture_func(self.obj, "teardown_module")
  504. if teardown_module is not None:
  505. func = partial(_call_with_optional_argument, teardown_module, self.obj)
  506. self.addfinalizer(func)
  507. def _recurse(self, dirpath):
  508. if dirpath.basename == "__pycache__":
  509. return False
  510. ihook = self.gethookproxy(dirpath.dirpath())
  511. if ihook.pytest_ignore_collect(path=dirpath, config=self.config):
  512. return
  513. for pat in self._norecursepatterns:
  514. if dirpath.check(fnmatch=pat):
  515. return False
  516. ihook = self.gethookproxy(dirpath)
  517. ihook.pytest_collect_directory(path=dirpath, parent=self)
  518. return True
  519. def gethookproxy(self, fspath):
  520. # check if we have the common case of running
  521. # hooks with all conftest.py filesall conftest.py
  522. pm = self.config.pluginmanager
  523. my_conftestmodules = pm._getconftestmodules(fspath)
  524. remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
  525. if remove_mods:
  526. # one or more conftests are not in use at this fspath
  527. proxy = FSHookProxy(fspath, pm, remove_mods)
  528. else:
  529. # all plugis are active for this fspath
  530. proxy = self.config.hook
  531. return proxy
  532. def _collectfile(self, path, handle_dupes=True):
  533. assert path.isfile(), "%r is not a file (isdir=%r, exists=%r, islink=%r)" % (
  534. path,
  535. path.isdir(),
  536. path.exists(),
  537. path.islink(),
  538. )
  539. ihook = self.gethookproxy(path)
  540. if not self.isinitpath(path):
  541. if ihook.pytest_ignore_collect(path=path, config=self.config):
  542. return ()
  543. if handle_dupes:
  544. keepduplicates = self.config.getoption("keepduplicates")
  545. if not keepduplicates:
  546. duplicate_paths = self.config.pluginmanager._duplicatepaths
  547. if path in duplicate_paths:
  548. return ()
  549. else:
  550. duplicate_paths.add(path)
  551. if self.fspath == path: # __init__.py
  552. return [self]
  553. return ihook.pytest_collect_file(path=path, parent=self)
  554. def isinitpath(self, path):
  555. return path in self.session._initialpaths
  556. def collect(self):
  557. this_path = self.fspath.dirpath()
  558. init_module = this_path.join("__init__.py")
  559. if init_module.check(file=1) and path_matches_patterns(
  560. init_module, self.config.getini("python_files")
  561. ):
  562. yield Module(init_module, self)
  563. pkg_prefixes = set()
  564. for path in this_path.visit(rec=self._recurse, bf=True, sort=True):
  565. # We will visit our own __init__.py file, in which case we skip it.
  566. is_file = path.isfile()
  567. if is_file:
  568. if path.basename == "__init__.py" and path.dirpath() == this_path:
  569. continue
  570. parts_ = parts(path.strpath)
  571. if any(
  572. pkg_prefix in parts_ and pkg_prefix.join("__init__.py") != path
  573. for pkg_prefix in pkg_prefixes
  574. ):
  575. continue
  576. if is_file:
  577. for x in self._collectfile(path):
  578. yield x
  579. elif not path.isdir():
  580. # Broken symlink or invalid/missing file.
  581. continue
  582. elif path.join("__init__.py").check(file=1):
  583. pkg_prefixes.add(path)
  584. def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):
  585. """
  586. Return a callable to perform xunit-style setup or teardown if
  587. the function exists in the ``holder`` object.
  588. The ``param_obj`` parameter is the parameter which will be passed to the function
  589. when the callable is called without arguments, defaults to the ``holder`` object.
  590. Return ``None`` if a suitable callable is not found.
  591. """
  592. # TODO: only needed because of Package!
  593. param_obj = param_obj if param_obj is not None else holder
  594. result = _get_non_fixture_func(holder, attr_name)
  595. if result is not None:
  596. arg_count = result.__code__.co_argcount
  597. if inspect.ismethod(result):
  598. arg_count -= 1
  599. if arg_count:
  600. return lambda: result(param_obj)
  601. else:
  602. return result
  603. def _call_with_optional_argument(func, arg):
  604. """Call the given function with the given argument if func accepts one argument, otherwise
  605. calls func without arguments"""
  606. arg_count = func.__code__.co_argcount
  607. if inspect.ismethod(func):
  608. arg_count -= 1
  609. if arg_count:
  610. func(arg)
  611. else:
  612. func()
  613. def _get_non_fixture_func(obj, name):
  614. """Return the attribute from the given object to be used as a setup/teardown
  615. xunit-style function, but only if not marked as a fixture to
  616. avoid calling it twice.
  617. """
  618. meth = getattr(obj, name, None)
  619. if fixtures.getfixturemarker(meth) is None:
  620. return meth
  621. class Class(PyCollector):
  622. """ Collector for test methods. """
  623. def collect(self):
  624. if not safe_getattr(self.obj, "__test__", True):
  625. return []
  626. if hasinit(self.obj):
  627. self.warn(
  628. PytestCollectionWarning(
  629. "cannot collect test class %r because it has a "
  630. "__init__ constructor (from: %s)"
  631. % (self.obj.__name__, self.parent.nodeid)
  632. )
  633. )
  634. return []
  635. elif hasnew(self.obj):
  636. self.warn(
  637. PytestCollectionWarning(
  638. "cannot collect test class %r because it has a "
  639. "__new__ constructor (from: %s)"
  640. % (self.obj.__name__, self.parent.nodeid)
  641. )
  642. )
  643. return []
  644. self._inject_setup_class_fixture()
  645. self._inject_setup_method_fixture()
  646. return [Instance(name="()", parent=self)]
  647. def _inject_setup_class_fixture(self):
  648. """Injects a hidden autouse, class scoped fixture into the collected class object
  649. that invokes setup_class/teardown_class if either or both are available.
  650. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
  651. other fixtures (#517).
  652. """
  653. setup_class = _get_non_fixture_func(self.obj, "setup_class")
  654. teardown_class = getattr(self.obj, "teardown_class", None)
  655. if setup_class is None and teardown_class is None:
  656. return
  657. @fixtures.fixture(autouse=True, scope="class")
  658. def xunit_setup_class_fixture(cls):
  659. if setup_class is not None:
  660. func = getimfunc(setup_class)
  661. _call_with_optional_argument(func, self.obj)
  662. yield
  663. if teardown_class is not None:
  664. func = getimfunc(teardown_class)
  665. _call_with_optional_argument(func, self.obj)
  666. self.obj.__pytest_setup_class = xunit_setup_class_fixture
  667. def _inject_setup_method_fixture(self):
  668. """Injects a hidden autouse, function scoped fixture into the collected class object
  669. that invokes setup_method/teardown_method if either or both are available.
  670. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
  671. other fixtures (#517).
  672. """
  673. setup_method = _get_non_fixture_func(self.obj, "setup_method")
  674. teardown_method = getattr(self.obj, "teardown_method", None)
  675. if setup_method is None and teardown_method is None:
  676. return
  677. @fixtures.fixture(autouse=True, scope="function")
  678. def xunit_setup_method_fixture(self, request):
  679. method = request.function
  680. if setup_method is not None:
  681. func = getattr(self, "setup_method")
  682. _call_with_optional_argument(func, method)
  683. yield
  684. if teardown_method is not None:
  685. func = getattr(self, "teardown_method")
  686. _call_with_optional_argument(func, method)
  687. self.obj.__pytest_setup_method = xunit_setup_method_fixture
  688. class Instance(PyCollector):
  689. _ALLOW_MARKERS = False # hack, destroy later
  690. # instances share the object with their parents in a way
  691. # that duplicates markers instances if not taken out
  692. # can be removed at node structure reorganization time
  693. def _getobj(self):
  694. return self.parent.obj()
  695. def collect(self):
  696. self.session._fixturemanager.parsefactories(self)
  697. return super(Instance, self).collect()
  698. def newinstance(self):
  699. self.obj = self._getobj()
  700. return self.obj
  701. class FunctionMixin(PyobjMixin):
  702. """ mixin for the code common to Function and Generator.
  703. """
  704. def setup(self):
  705. """ perform setup for this test function. """
  706. if isinstance(self.parent, Instance):
  707. self.parent.newinstance()
  708. self.obj = self._getobj()
  709. def _prunetraceback(self, excinfo):
  710. if hasattr(self, "_obj") and not self.config.getoption("fulltrace", False):
  711. code = _pytest._code.Code(get_real_func(self.obj))
  712. path, firstlineno = code.path, code.firstlineno
  713. traceback = excinfo.traceback
  714. ntraceback = traceback.cut(path=path, firstlineno=firstlineno)
  715. if ntraceback == traceback:
  716. ntraceback = ntraceback.cut(path=path)
  717. if ntraceback == traceback:
  718. ntraceback = ntraceback.filter(filter_traceback)
  719. if not ntraceback:
  720. ntraceback = traceback
  721. excinfo.traceback = ntraceback.filter()
  722. # issue364: mark all but first and last frames to
  723. # only show a single-line message for each frame
  724. if self.config.getoption("tbstyle", "auto") == "auto":
  725. if len(excinfo.traceback) > 2:
  726. for entry in excinfo.traceback[1:-1]:
  727. entry.set_repr_style("short")
  728. def repr_failure(self, excinfo, outerr=None):
  729. assert outerr is None, "XXX outerr usage is deprecated"
  730. style = self.config.getoption("tbstyle", "auto")
  731. if style == "auto":
  732. style = "long"
  733. return self._repr_failure_py(excinfo, style=style)
  734. def hasinit(obj):
  735. init = getattr(obj, "__init__", None)
  736. if init:
  737. return init != object.__init__
  738. def hasnew(obj):
  739. new = getattr(obj, "__new__", None)
  740. if new:
  741. return new != object.__new__
  742. class CallSpec2(object):
  743. def __init__(self, metafunc):
  744. self.metafunc = metafunc
  745. self.funcargs = {}
  746. self._idlist = []
  747. self.params = {}
  748. self._globalid = NOTSET
  749. self._globalparam = NOTSET
  750. self._arg2scopenum = {} # used for sorting parametrized resources
  751. self.marks = []
  752. self.indices = {}
  753. def copy(self):
  754. cs = CallSpec2(self.metafunc)
  755. cs.funcargs.update(self.funcargs)
  756. cs.params.update(self.params)
  757. cs.marks.extend(self.marks)
  758. cs.indices.update(self.indices)
  759. cs._arg2scopenum.update(self._arg2scopenum)
  760. cs._idlist = list(self._idlist)
  761. cs._globalid = self._globalid
  762. cs._globalparam = self._globalparam
  763. return cs
  764. def _checkargnotcontained(self, arg):
  765. if arg in self.params or arg in self.funcargs:
  766. raise ValueError("duplicate %r" % (arg,))
  767. def getparam(self, name):
  768. try:
  769. return self.params[name]
  770. except KeyError:
  771. if self._globalparam is NOTSET:
  772. raise ValueError(name)
  773. return self._globalparam
  774. @property
  775. def id(self):
  776. return "-".join(map(safe_str, self._idlist))
  777. def setmulti2(self, valtypes, argnames, valset, id, marks, scopenum, param_index):
  778. for arg, val in zip(argnames, valset):
  779. self._checkargnotcontained(arg)
  780. valtype_for_arg = valtypes[arg]
  781. getattr(self, valtype_for_arg)[arg] = val
  782. self.indices[arg] = param_index
  783. self._arg2scopenum[arg] = scopenum
  784. self._idlist.append(id)
  785. self.marks.extend(normalize_mark_list(marks))
  786. def setall(self, funcargs, id, param):
  787. for x in funcargs:
  788. self._checkargnotcontained(x)
  789. self.funcargs.update(funcargs)
  790. if id is not NOTSET:
  791. self._idlist.append(id)
  792. if param is not NOTSET:
  793. assert self._globalparam is NOTSET
  794. self._globalparam = param
  795. for arg in funcargs:
  796. self._arg2scopenum[arg] = fixtures.scopenum_function
  797. class Metafunc(fixtures.FuncargnamesCompatAttr):
  798. """
  799. Metafunc objects are passed to the :func:`pytest_generate_tests <_pytest.hookspec.pytest_generate_tests>` hook.
  800. They help to inspect a test function and to generate tests according to
  801. test configuration or values specified in the class or module where a
  802. test function is defined.
  803. """
  804. def __init__(self, definition, fixtureinfo, config, cls=None, module=None):
  805. assert (
  806. isinstance(definition, FunctionDefinition)
  807. or type(definition).__name__ == "DefinitionMock"
  808. )
  809. self.definition = definition
  810. #: access to the :class:`_pytest.config.Config` object for the test session
  811. self.config = config
  812. #: the module object where the test function is defined in.
  813. self.module = module
  814. #: underlying python test function
  815. self.function = definition.obj
  816. #: set of fixture names required by the test function
  817. self.fixturenames = fixtureinfo.names_closure
  818. #: class object where the test function is defined in or ``None``.
  819. self.cls = cls
  820. self._calls = []
  821. self._ids = set()
  822. self._arg2fixturedefs = fixtureinfo.name2fixturedefs
  823. def parametrize(self, argnames, argvalues, indirect=False, ids=None, scope=None):
  824. """ Add new invocations to the underlying test function using the list
  825. of argvalues for the given argnames. Parametrization is performed
  826. during the collection phase. If you need to setup expensive resources
  827. see about setting indirect to do it rather at test setup time.
  828. :arg argnames: a comma-separated string denoting one or more argument
  829. names, or a list/tuple of argument strings.
  830. :arg argvalues: The list of argvalues determines how often a
  831. test is invoked with different argument values. If only one
  832. argname was specified argvalues is a list of values. If N
  833. argnames were specified, argvalues must be a list of N-tuples,
  834. where each tuple-element specifies a value for its respective
  835. argname.
  836. :arg indirect: The list of argnames or boolean. A list of arguments'
  837. names (subset of argnames). If True the list contains all names from
  838. the argnames. Each argvalue corresponding to an argname in this list will
  839. be passed as request.param to its respective argname fixture
  840. function so that it can perform more expensive setups during the
  841. setup phase of a test rather than at collection time.
  842. :arg ids: list of string ids, or a callable.
  843. If strings, each is corresponding to the argvalues so that they are
  844. part of the test id. If None is given as id of specific test, the
  845. automatically generated id for that argument will be used.
  846. If callable, it should take one argument (a single argvalue) and return
  847. a string or return None. If None, the automatically generated id for that
  848. argument will be used.
  849. If no ids are provided they will be generated automatically from
  850. the argvalues.
  851. :arg scope: if specified it denotes the scope of the parameters.
  852. The scope is used for grouping tests by parameter instances.
  853. It will also override any fixture-function defined scope, allowing
  854. to set a dynamic scope using test context or configuration.
  855. """
  856. from _pytest.fixtures import scope2index
  857. from _pytest.mark import ParameterSet
  858. argnames, parameters = ParameterSet._for_parametrize(
  859. argnames,
  860. argvalues,
  861. self.function,
  862. self.config,
  863. function_definition=self.definition,
  864. )
  865. del argvalues
  866. if scope is None:
  867. scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
  868. self._validate_if_using_arg_names(argnames, indirect)
  869. arg_values_types = self._resolve_arg_value_types(argnames, indirect)
  870. ids = self._resolve_arg_ids(argnames, ids, parameters, item=self.definition)
  871. scopenum = scope2index(
  872. scope, descr="parametrize() call in {}".format(self.function.__name__)
  873. )
  874. # create the new calls: if we are parametrize() multiple times (by applying the decorator
  875. # more than once) then we accumulate those calls generating the cartesian product
  876. # of all calls
  877. newcalls = []
  878. for callspec in self._calls or [CallSpec2(self)]:
  879. for param_index, (param_id, param_set) in enumerate(zip(ids, parameters)):
  880. newcallspec = callspec.copy()
  881. newcallspec.setmulti2(
  882. arg_values_types,
  883. argnames,
  884. param_set.values,
  885. param_id,
  886. param_set.marks,
  887. scopenum,
  888. param_index,
  889. )
  890. newcalls.append(newcallspec)
  891. self._calls = newcalls
  892. def _resolve_arg_ids(self, argnames, ids, parameters, item):
  893. """Resolves the actual ids for the given argnames, based on the ``ids`` parameter given
  894. to ``parametrize``.
  895. :param List[str] argnames: list of argument names passed to ``parametrize()``.
  896. :param ids: the ids parameter of the parametrized call (see docs).
  897. :param List[ParameterSet] parameters: the list of parameter values, same size as ``argnames``.
  898. :param Item item: the item that generated this parametrized call.
  899. :rtype: List[str]
  900. :return: the list of ids for each argname given
  901. """
  902. from _pytest._io.saferepr import saferepr
  903. idfn = None
  904. if callable(ids):
  905. idfn = ids
  906. ids = None
  907. if ids:
  908. func_name = self.function.__name__
  909. if len(ids) != len(parameters):
  910. msg = "In {}: {} parameter sets specified, with different number of ids: {}"
  911. fail(msg.format(func_name, len(parameters), len(ids)), pytrace=False)
  912. for id_value in ids:
  913. if id_value is not None and not isinstance(id_value, six.string_types):
  914. msg = "In {}: ids must be list of strings, found: {} (type: {!r})"
  915. fail(
  916. msg.format(func_name, saferepr(id_value), type(id_value)),
  917. pytrace=False,
  918. )
  919. ids = idmaker(argnames, parameters, idfn, ids, self.config, item=item)
  920. return ids
  921. def _resolve_arg_value_types(self, argnames, indirect):
  922. """Resolves if each parametrized argument must be considered a parameter to a fixture or a "funcarg"
  923. to the function, based on the ``indirect`` parameter of the parametrized() call.
  924. :param List[str] argnames: list of argument names passed to ``parametrize()``.
  925. :param indirect: same ``indirect`` parameter of ``parametrize()``.
  926. :rtype: Dict[str, str]
  927. A dict mapping each arg name to either:
  928. * "params" if the argname should be the parameter of a fixture of the same name.
  929. * "funcargs" if the argname should be a parameter to the parametrized test function.
  930. """
  931. valtypes = {}
  932. if indirect is True:
  933. valtypes = dict.fromkeys(argnames, "params")
  934. elif indirect is False:
  935. valtypes = dict.fromkeys(argnames, "funcargs")
  936. elif isinstance(indirect, (tuple, list)):
  937. valtypes = dict.fromkeys(argnames, "funcargs")
  938. for arg in indirect:
  939. if arg not in argnames:
  940. fail(
  941. "In {}: indirect fixture '{}' doesn't exist".format(
  942. self.function.__name__, arg
  943. ),
  944. pytrace=False,
  945. )
  946. valtypes[arg] = "params"
  947. return valtypes
  948. def _validate_if_using_arg_names(self, argnames, indirect):
  949. """
  950. Check if all argnames are being used, by default values, or directly/indirectly.
  951. :param List[str] argnames: list of argument names passed to ``parametrize()``.
  952. :param indirect: same ``indirect`` parameter of ``parametrize()``.
  953. :raise ValueError: if validation fails.
  954. """
  955. default_arg_names = set(get_default_arg_names(self.function))
  956. func_name = self.function.__name__
  957. for arg in argnames:
  958. if arg not in self.fixturenames:
  959. if arg in default_arg_names:
  960. fail(
  961. "In {}: function already takes an argument '{}' with a default value".format(
  962. func_name, arg
  963. ),
  964. pytrace=False,
  965. )
  966. else:
  967. if isinstance(indirect, (tuple, list)):
  968. name = "fixture" if arg in indirect else "argument"
  969. else:
  970. name = "fixture" if indirect else "argument"
  971. fail(
  972. "In {}: function uses no {} '{}'".format(func_name, name, arg),
  973. pytrace=False,
  974. )
  975. def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
  976. """Find the most appropriate scope for a parametrized call based on its arguments.
  977. When there's at least one direct argument, always use "function" scope.
  978. When a test function is parametrized and all its arguments are indirect
  979. (e.g. fixtures), return the most narrow scope based on the fixtures used.
  980. Related to issue #1832, based on code posted by @Kingdread.
  981. """
  982. from _pytest.fixtures import scopes
  983. if isinstance(indirect, (list, tuple)):
  984. all_arguments_are_fixtures = len(indirect) == len(argnames)
  985. else:
  986. all_arguments_are_fixtures = bool(indirect)
  987. if all_arguments_are_fixtures:
  988. fixturedefs = arg2fixturedefs or {}
  989. used_scopes = [
  990. fixturedef[0].scope
  991. for name, fixturedef in fixturedefs.items()
  992. if name in argnames
  993. ]
  994. if used_scopes:
  995. # Takes the most narrow scope from used fixtures
  996. for scope in reversed(scopes):
  997. if scope in used_scopes:
  998. return scope
  999. return "function"
  1000. def _ascii_escaped_by_config(val, config):
  1001. if config is None:
  1002. escape_option = False
  1003. else:
  1004. escape_option = config.getini(
  1005. "disable_test_id_escaping_and_forfeit_all_rights_to_community_support"
  1006. )
  1007. return val if escape_option else ascii_escaped(val)
  1008. def _idval(val, argname, idx, idfn, item, config):
  1009. if idfn:
  1010. try:
  1011. generated_id = idfn(val)
  1012. if generated_id is not None:
  1013. val = generated_id
  1014. except Exception as e:
  1015. # See issue https://github.com/pytest-dev/pytest/issues/2169
  1016. msg = "{}: error raised while trying to determine id of parameter '{}' at position {}\n"
  1017. msg = msg.format(item.nodeid, argname, idx)
  1018. # we only append the exception type and message because on Python 2 reraise does nothing
  1019. msg += " {}: {}\n".format(type(e).__name__, e)
  1020. six.raise_from(ValueError(msg), e)
  1021. elif config:
  1022. hook_id = config.hook.pytest_make_parametrize_id(
  1023. config=config, val=val, argname=argname
  1024. )
  1025. if hook_id:
  1026. return hook_id
  1027. if isinstance(val, STRING_TYPES):
  1028. return _ascii_escaped_by_config(val, config)
  1029. elif val is None or isinstance(val, (float, int, bool)):
  1030. return str(val)
  1031. elif isinstance(val, REGEX_TYPE):
  1032. return ascii_escaped(val.pattern)
  1033. elif enum is not None and isinstance(val, enum.Enum):
  1034. return str(val)
  1035. elif (isclass(val) or isfunction(val)) and hasattr(val, "__name__"):
  1036. return val.__name__
  1037. return str(argname) + str(idx)
  1038. def limit_idval(limit):
  1039. import functools
  1040. names = {}
  1041. limit -= 6
  1042. assert limit > 0
  1043. def decorator(func):
  1044. @functools.wraps(func)
  1045. def wrapper(*args, **kw):
  1046. idval = func(*args, **kw)
  1047. if len(idval) > limit:
  1048. prefix = idval[:limit]
  1049. # There might be same prefix for the different test cases - take item into account
  1050. name = "{}-{}".format(kw.get('item', ''), safe_str(prefix))
  1051. idx = names.setdefault(name, -1) + 1
  1052. names[name] = idx
  1053. idval = "{}-{}".format(safe_str(prefix), idx)
  1054. return idval
  1055. return wrapper
  1056. return decorator
  1057. # XXX limit testnames in the name of sanity and readability
  1058. @limit_idval(limit=500)
  1059. def _idvalset(idx, parameterset, argnames, idfn, ids, item, config):
  1060. if parameterset.id is not None:
  1061. return parameterset.id
  1062. if ids is None or (idx >= len(ids) or ids[idx] is None):
  1063. this_id = [
  1064. _idval(val, argname, idx, idfn, item=item, config=config)
  1065. for val, argname in zip(parameterset.values, argnames)
  1066. ]
  1067. return "-".join(this_id)
  1068. else:
  1069. return _ascii_escaped_by_config(ids[idx], config)
  1070. def idmaker(argnames, parametersets, idfn=None, ids=None, config=None, item=None):
  1071. ids = [
  1072. _idvalset(valindex, parameterset, argnames, idfn, ids, config=config, item=item)
  1073. for valindex, parameterset in enumerate(parametersets)
  1074. ]
  1075. if len(set(ids)) != len(ids):
  1076. # The ids are not unique
  1077. duplicates = [testid for testid in ids if ids.count(testid) > 1]
  1078. counters = collections.defaultdict(lambda: 0)
  1079. for index, testid in enumerate(ids):
  1080. if testid in duplicates:
  1081. ids[index] = testid + str(counters[testid])
  1082. counters[testid] += 1
  1083. return ids
  1084. def show_fixtures_per_test(config):
  1085. from _pytest.main import wrap_session
  1086. return wrap_session(config, _show_fixtures_per_test)
  1087. def _show_fixtures_per_test(config, session):
  1088. import _pytest.config
  1089. session.perform_collect()
  1090. curdir = py.path.local()
  1091. tw = _pytest.config.create_terminal_writer(config)
  1092. verbose = config.getvalue("verbose")
  1093. def get_best_relpath(func):
  1094. loc = getlocation(func, curdir)
  1095. return curdir.bestrelpath(loc)
  1096. def write_fixture(fixture_def):
  1097. argname = fixture_def.argname
  1098. if verbose <= 0 and argname.startswith("_"):
  1099. return
  1100. if verbose > 0:
  1101. bestrel = get_best_relpath(fixture_def.func)
  1102. funcargspec = "{} -- {}".format(argname, bestrel)
  1103. else:
  1104. funcargspec = argname
  1105. tw.line(funcargspec, green=True)
  1106. fixture_doc = fixture_def.func.__doc__
  1107. if fixture_doc:
  1108. write_docstring(tw, fixture_doc)
  1109. else:
  1110. tw.line(" no docstring available", red=True)
  1111. def write_item(item):
  1112. try:
  1113. info = item._fixtureinfo
  1114. except AttributeError:
  1115. # doctests items have no _fixtureinfo attribute
  1116. return
  1117. if not info.name2fixturedefs:
  1118. # this test item does not use any fixtures
  1119. return
  1120. tw.line()
  1121. tw.sep("-", "fixtures used by {}".format(item.name))
  1122. tw.sep("-", "({})".format(get_best_relpath(item.function)))
  1123. # dict key not used in loop but needed for sorting
  1124. for _, fixturedefs in sorted(info.name2fixturedefs.items()):
  1125. assert fixturedefs is not None
  1126. if not fixturedefs:
  1127. continue
  1128. # last item is expected to be the one used by the test item
  1129. write_fixture(fixturedefs[-1])
  1130. for session_item in session.items:
  1131. write_item(session_item)
  1132. def showfixtures(config):
  1133. from _pytest.main import wrap_session
  1134. return wrap_session(config, _showfixtures_main)
  1135. def _showfixtures_main(config, session):
  1136. import _pytest.config
  1137. session.perform_collect()
  1138. curdir = py.path.local()
  1139. tw = _pytest.config.create_terminal_writer(config)
  1140. verbose = config.getvalue("verbose")
  1141. fm = session._fixturemanager
  1142. available = []
  1143. seen = set()
  1144. for argname, fixturedefs in fm._arg2fixturedefs.items():
  1145. assert fixturedefs is not None
  1146. if not fixturedefs:
  1147. continue
  1148. for fixturedef in fixturedefs:
  1149. loc = getlocation(fixturedef.func, curdir)
  1150. if (fixturedef.argname, loc) in seen:
  1151. continue
  1152. seen.add((fixturedef.argname, loc))
  1153. available.append(
  1154. (
  1155. len(fixturedef.baseid),
  1156. fixturedef.func.__module__,
  1157. curdir.bestrelpath(loc),
  1158. fixturedef.argname,
  1159. fixturedef,
  1160. )
  1161. )
  1162. available.sort()
  1163. currentmodule = None
  1164. for baseid, module, bestrel, argname, fixturedef in available:
  1165. if currentmodule != module:
  1166. if not module.startswith("_pytest."):
  1167. tw.line()
  1168. tw.sep("-", "fixtures defined from %s" % (module,))
  1169. currentmodule = module
  1170. if verbose <= 0 and argname[0] == "_":
  1171. continue
  1172. tw.write(argname, green=True)
  1173. if fixturedef.scope != "function":
  1174. tw.write(" [%s scope]" % fixturedef.scope, cyan=True)
  1175. if verbose > 0:
  1176. tw.write(" -- %s" % bestrel, yellow=True)
  1177. tw.write("\n")
  1178. loc = getlocation(fixturedef.func, curdir)
  1179. doc = fixturedef.func.__doc__ or ""
  1180. if doc:
  1181. write_docstring(tw, doc)
  1182. else:
  1183. tw.line(" %s: no docstring available" % (loc,), red=True)
  1184. tw.line()
  1185. def write_docstring(tw, doc, indent=" "):
  1186. doc = doc.rstrip()
  1187. if "\n" in doc:
  1188. firstline, rest = doc.split("\n", 1)
  1189. else:
  1190. firstline, rest = doc, ""
  1191. if firstline.strip():
  1192. tw.line(indent + firstline.strip())
  1193. if rest:
  1194. for line in dedent(rest).split("\n"):
  1195. tw.write(indent + line + "\n")
  1196. class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr):
  1197. """ a Function Item is responsible for setting up and executing a
  1198. Python test function.
  1199. """
  1200. # disable since functions handle it themselves
  1201. _ALLOW_MARKERS = False
  1202. def __init__(
  1203. self,
  1204. name,
  1205. parent,
  1206. args=None,
  1207. config=None,
  1208. callspec=None,
  1209. callobj=NOTSET,
  1210. keywords=None,
  1211. session=None,
  1212. fixtureinfo=None,
  1213. originalname=None,
  1214. ):
  1215. super(Function, self).__init__(name, parent, config=config, session=session)
  1216. self._args = args
  1217. if callobj is not NOTSET:
  1218. self.obj = callobj
  1219. self.keywords.update(self.obj.__dict__)
  1220. self.own_markers.extend(get_unpacked_marks(self.obj))
  1221. if callspec:
  1222. self.callspec = callspec
  1223. # this is total hostile and a mess
  1224. # keywords are broken by design by now
  1225. # this will be redeemed later
  1226. for mark in callspec.marks:
  1227. # feel free to cry, this was broken for years before
  1228. # and keywords cant fix it per design
  1229. self.keywords[mark.name] = mark
  1230. self.own_markers.extend(normalize_mark_list(callspec.marks))
  1231. if keywords:
  1232. self.keywords.update(keywords)
  1233. # todo: this is a hell of a hack
  1234. # https://github.com/pytest-dev/pytest/issues/4569
  1235. self.keywords.update(
  1236. dict.fromkeys(
  1237. [
  1238. mark.name
  1239. for mark in self.iter_markers()
  1240. if mark.name not in self.keywords
  1241. ],
  1242. True,
  1243. )
  1244. )
  1245. if fixtureinfo is None:
  1246. fixtureinfo = self.session._fixturemanager.getfixtureinfo(
  1247. self, self.obj, self.cls, funcargs=True
  1248. )
  1249. self._fixtureinfo = fixtureinfo
  1250. self.fixturenames = fixtureinfo.names_closure
  1251. self._initrequest()
  1252. #: original function name, without any decorations (for example
  1253. #: parametrization adds a ``"[...]"`` suffix to function names).
  1254. #:
  1255. #: .. versionadded:: 3.0
  1256. self.originalname = originalname
  1257. def _initrequest(self):
  1258. self.funcargs = {}
  1259. self._request = fixtures.FixtureRequest(self)
  1260. @property
  1261. def function(self):
  1262. "underlying python 'function' object"
  1263. return getimfunc(self.obj)
  1264. def _getobj(self):
  1265. name = self.name
  1266. i = name.find("[") # parametrization
  1267. if i != -1:
  1268. name = name[:i]
  1269. return getattr(self.parent.obj, name)
  1270. @property
  1271. def _pyfuncitem(self):
  1272. "(compatonly) for code expecting pytest-2.2 style request objects"
  1273. return self
  1274. def runtest(self):
  1275. """ execute the underlying test function. """
  1276. self.ihook.pytest_pyfunc_call(pyfuncitem=self)
  1277. def setup(self):
  1278. super(Function, self).setup()
  1279. fixtures.fillfixtures(self)
  1280. class FunctionDefinition(Function):
  1281. """
  1282. internal hack until we get actual definition nodes instead of the
  1283. crappy metafunc hack
  1284. """
  1285. def runtest(self):
  1286. raise RuntimeError("function definitions are not supposed to be used")
  1287. setup = runtest