How to use show_fixtures_per_test method in Pytest

Best Python code snippet using pytest

python.py

Source:python.py Github

copy

Full Screen

...82 if config.option.showfixtures:83 showfixtures(config)84 return 085 if config.option.show_fixtures_per_test:86 show_fixtures_per_test(config)87 return 088def pytest_generate_tests(metafunc):89 # those alternative spellings are common - raise a specific error to alert90 # the user91 alt_spellings = ['parameterize', 'parametrise', 'parameterise']92 for attr in alt_spellings:93 if hasattr(metafunc.function, attr):94 msg = "{0} has '{1}', spelling should be 'parametrize'"95 raise MarkerError(msg.format(metafunc.function.__name__, attr))96 try:97 markers = metafunc.function.parametrize98 except AttributeError:99 return100 for marker in markers:101 metafunc.parametrize(*marker.args, **marker.kwargs)102def pytest_configure(config):103 config.addinivalue_line("markers",104 "parametrize(argnames, argvalues): call a test function multiple "105 "times passing in different arguments in turn. argvalues generally "106 "needs to be a list of values if argnames specifies only one name "107 "or a list of tuples of values if argnames specifies multiple names. "108 "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "109 "decorated test function, one with arg1=1 and another with arg1=2."110 "see http://pytest.org/latest/parametrize.html for more info and "111 "examples."112 )113 config.addinivalue_line("markers",114 "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "115 "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "116 )117@hookimpl(trylast=True)118def pytest_pyfunc_call(pyfuncitem):119 testfunction = pyfuncitem.obj120 if pyfuncitem._isyieldedfunction():121 testfunction(*pyfuncitem._args)122 else:123 funcargs = pyfuncitem.funcargs124 testargs = {}125 for arg in pyfuncitem._fixtureinfo.argnames:126 testargs[arg] = funcargs[arg]127 testfunction(**testargs)128 return True129def pytest_collect_file(path, parent):130 ext = path.ext131 if ext == ".py":132 if not parent.session.isinitpath(path):133 for pat in parent.config.getini('python_files'):134 if path.fnmatch(pat):135 break136 else:137 return138 ihook = parent.session.gethookproxy(path)139 return ihook.pytest_pycollect_makemodule(path=path, parent=parent)140def pytest_pycollect_makemodule(path, parent):141 return Module(path, parent)142@hookimpl(hookwrapper=True)143def pytest_pycollect_makeitem(collector, name, obj):144 outcome = yield145 res = outcome.get_result()146 if res is not None:147 return148 # nothing was collected elsewhere, let's do it here149 if isclass(obj):150 if collector.istestclass(obj, name):151 Class = collector._getcustomclass("Class")152 outcome.force_result(Class(name, parent=collector))153 elif collector.istestfunction(obj, name):154 # mock seems to store unbound methods (issue473), normalize it155 obj = getattr(obj, "__func__", obj)156 # We need to try and unwrap the function if it's a functools.partial157 # or a funtools.wrapped.158 # We musn't if it's been wrapped with mock.patch (python 2 only)159 if not (isfunction(obj) or isfunction(get_real_func(obj))):160 collector.warn(code="C2", message="cannot collect %r because it is not a function."161 % name, )162 elif getattr(obj, "__test__", True):163 if is_generator(obj):164 res = Generator(name, parent=collector)165 else:166 res = list(collector._genfunctions(name, obj))167 outcome.force_result(res)168def pytest_make_parametrize_id(config, val, argname=None):169 return None170class PyobjContext(object):171 module = pyobj_property("Module")172 cls = pyobj_property("Class")173 instance = pyobj_property("Instance")174class PyobjMixin(PyobjContext):175 def obj():176 def fget(self):177 obj = getattr(self, '_obj', None)178 if obj is None:179 self._obj = obj = self._getobj()180 return obj181 def fset(self, value):182 self._obj = value183 return property(fget, fset, None, "underlying python object")184 obj = obj()185 def _getobj(self):186 return getattr(self.parent.obj, self.name)187 def getmodpath(self, stopatmodule=True, includemodule=False):188 """ return python path relative to the containing module. """189 chain = self.listchain()190 chain.reverse()191 parts = []192 for node in chain:193 if isinstance(node, Instance):194 continue195 name = node.name196 if isinstance(node, Module):197 name = os.path.splitext(name)[0]198 if stopatmodule:199 if includemodule:200 parts.append(name)201 break202 parts.append(name)203 parts.reverse()204 s = ".".join(parts)205 return s.replace(".[", "[")206 def _getfslineno(self):207 return getfslineno(self.obj)208 def reportinfo(self):209 # XXX caching?210 obj = self.obj211 compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)212 if isinstance(compat_co_firstlineno, int):213 # nose compatibility214 fspath = sys.modules[obj.__module__].__file__215 if fspath.endswith(".pyc"):216 fspath = fspath[:-1]217 lineno = compat_co_firstlineno218 else:219 fspath, lineno = getfslineno(obj)220 modpath = self.getmodpath()221 assert isinstance(lineno, int)222 return fspath, lineno, modpath223class PyCollector(PyobjMixin, main.Collector):224 def funcnamefilter(self, name):225 return self._matches_prefix_or_glob_option('python_functions', name)226 def isnosetest(self, obj):227 """ Look for the __test__ attribute, which is applied by the228 @nose.tools.istest decorator229 """230 # We explicitly check for "is True" here to not mistakenly treat231 # classes with a custom __getattr__ returning something truthy (like a232 # function) as test classes.233 return safe_getattr(obj, '__test__', False) is True234 def classnamefilter(self, name):235 return self._matches_prefix_or_glob_option('python_classes', name)236 def istestfunction(self, obj, name):237 if self.funcnamefilter(name) or self.isnosetest(obj):238 if isinstance(obj, staticmethod):239 # static methods need to be unwrapped240 obj = safe_getattr(obj, '__func__', False)241 if obj is False:242 # Python 2.6 wraps in a different way that we won't try to handle243 msg = "cannot collect static method %r because " \244 "it is not a function (always the case in Python 2.6)"245 self.warn(246 code="C2", message=msg % name)247 return False248 return (249 safe_getattr(obj, "__call__", False) and fixtures.getfixturemarker(obj) is None250 )251 else:252 return False253 def istestclass(self, obj, name):254 return self.classnamefilter(name) or self.isnosetest(obj)255 def _matches_prefix_or_glob_option(self, option_name, name):256 """257 checks if the given name matches the prefix or glob-pattern defined258 in ini configuration.259 """260 for option in self.config.getini(option_name):261 if name.startswith(option):262 return True263 # check that name looks like a glob-string before calling fnmatch264 # because this is called for every name in each collected module,265 # and fnmatch is somewhat expensive to call266 elif ('*' in option or '?' in option or '[' in option) and \267 fnmatch.fnmatch(name, option):268 return True269 return False270 def collect(self):271 if not getattr(self.obj, "__test__", True):272 return []273 # NB. we avoid random getattrs and peek in the __dict__ instead274 # (XXX originally introduced from a PyPy need, still true?)275 dicts = [getattr(self.obj, '__dict__', {})]276 for basecls in inspect.getmro(self.obj.__class__):277 dicts.append(basecls.__dict__)278 seen = {}279 values = []280 for dic in dicts:281 for name, obj in list(dic.items()):282 if name in seen:283 continue284 seen[name] = True285 res = self._makeitem(name, obj)286 if res is None:287 continue288 if not isinstance(res, list):289 res = [res]290 values.extend(res)291 values.sort(key=lambda item: item.reportinfo()[:2])292 return values293 def makeitem(self, name, obj):294 warnings.warn(deprecated.COLLECTOR_MAKEITEM, stacklevel=2)295 self._makeitem(name, obj)296 def _makeitem(self, name, obj):297 # assert self.ihook.fspath == self.fspath, self298 return self.ihook.pytest_pycollect_makeitem(299 collector=self, name=name, obj=obj)300 def _genfunctions(self, name, funcobj):301 module = self.getparent(Module).obj302 clscol = self.getparent(Class)303 cls = clscol and clscol.obj or None304 transfer_markers(funcobj, cls, module)305 fm = self.session._fixturemanager306 fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)307 metafunc = Metafunc(funcobj, fixtureinfo, self.config,308 cls=cls, module=module)309 methods = []310 if hasattr(module, "pytest_generate_tests"):311 methods.append(module.pytest_generate_tests)312 if hasattr(cls, "pytest_generate_tests"):313 methods.append(cls().pytest_generate_tests)314 if methods:315 self.ihook.pytest_generate_tests.call_extra(methods,316 dict(metafunc=metafunc))317 else:318 self.ihook.pytest_generate_tests(metafunc=metafunc)319 Function = self._getcustomclass("Function")320 if not metafunc._calls:321 yield Function(name, parent=self, fixtureinfo=fixtureinfo)322 else:323 # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs324 fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm)325 for callspec in metafunc._calls:326 subname = "%s[%s]" % (name, callspec.id)327 yield Function(name=subname, parent=self,328 callspec=callspec, callobj=funcobj,329 fixtureinfo=fixtureinfo,330 keywords={callspec.id: True},331 originalname=name,332 )333class Module(main.File, PyCollector):334 """ Collector for test classes and functions. """335 def _getobj(self):336 return self._importtestmodule()337 def collect(self):338 self.session._fixturemanager.parsefactories(self)339 return super(Module, self).collect()340 def _importtestmodule(self):341 # we assume we are only called once per module342 importmode = self.config.getoption("--import-mode")343 try:344 mod = self.fspath.pyimport(ensuresyspath=importmode)345 except SyntaxError:346 raise self.CollectError(347 _pytest._code.ExceptionInfo().getrepr(style="short"))348 except self.fspath.ImportMismatchError:349 e = sys.exc_info()[1]350 raise self.CollectError(351 "import file mismatch:\n"352 "imported module %r has this __file__ attribute:\n"353 " %s\n"354 "which is not the same as the test file we want to collect:\n"355 " %s\n"356 "HINT: remove __pycache__ / .pyc files and/or use a "357 "unique basename for your test file modules"358 % e.args359 )360 except ImportError:361 from _pytest._code.code import ExceptionInfo362 exc_info = ExceptionInfo()363 if self.config.getoption('verbose') < 2:364 exc_info.traceback = exc_info.traceback.filter(filter_traceback)365 exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly()366 formatted_tb = safe_str(exc_repr)367 raise self.CollectError(368 "ImportError while importing test module '{fspath}'.\n"369 "Hint: make sure your test modules/packages have valid Python names.\n"370 "Traceback:\n"371 "{traceback}".format(fspath=self.fspath, traceback=formatted_tb)372 )373 except _pytest.runner.Skipped as e:374 if e.allow_module_level:375 raise376 raise self.CollectError(377 "Using pytest.skip outside of a test is not allowed. "378 "To decorate a test function, use the @pytest.mark.skip "379 "or @pytest.mark.skipif decorators instead, and to skip a "380 "module use `pytestmark = pytest.mark.{skip,skipif}."381 )382 self.config.pluginmanager.consider_module(mod)383 return mod384 def setup(self):385 setup_module = _get_xunit_setup_teardown(self.obj, "setUpModule")386 if setup_module is None:387 setup_module = _get_xunit_setup_teardown(self.obj, "setup_module")388 if setup_module is not None:389 setup_module()390 teardown_module = _get_xunit_setup_teardown(self.obj, 'tearDownModule')391 if teardown_module is None:392 teardown_module = _get_xunit_setup_teardown(self.obj, 'teardown_module')393 if teardown_module is not None:394 self.addfinalizer(teardown_module)395def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):396 """397 Return a callable to perform xunit-style setup or teardown if398 the function exists in the ``holder`` object.399 The ``param_obj`` parameter is the parameter which will be passed to the function400 when the callable is called without arguments, defaults to the ``holder`` object.401 Return ``None`` if a suitable callable is not found.402 """403 param_obj = param_obj if param_obj is not None else holder404 result = _get_xunit_func(holder, attr_name)405 if result is not None:406 arg_count = result.__code__.co_argcount407 if inspect.ismethod(result):408 arg_count -= 1409 if arg_count:410 return lambda: result(param_obj)411 else:412 return result413def _get_xunit_func(obj, name):414 """Return the attribute from the given object to be used as a setup/teardown415 xunit-style function, but only if not marked as a fixture to416 avoid calling it twice.417 """418 meth = getattr(obj, name, None)419 if fixtures.getfixturemarker(meth) is None:420 return meth421class Class(PyCollector):422 """ Collector for test methods. """423 def collect(self):424 if not safe_getattr(self.obj, "__test__", True):425 return []426 if hasinit(self.obj):427 self.warn("C1", "cannot collect test class %r because it has a "428 "__init__ constructor" % self.obj.__name__)429 return []430 elif hasnew(self.obj):431 self.warn("C1", "cannot collect test class %r because it has a "432 "__new__ constructor" % self.obj.__name__)433 return []434 return [self._getcustomclass("Instance")(name="()", parent=self)]435 def setup(self):436 setup_class = _get_xunit_func(self.obj, 'setup_class')437 if setup_class is not None:438 setup_class = getattr(setup_class, 'im_func', setup_class)439 setup_class = getattr(setup_class, '__func__', setup_class)440 setup_class(self.obj)441 fin_class = getattr(self.obj, 'teardown_class', None)442 if fin_class is not None:443 fin_class = getattr(fin_class, 'im_func', fin_class)444 fin_class = getattr(fin_class, '__func__', fin_class)445 self.addfinalizer(lambda: fin_class(self.obj))446class Instance(PyCollector):447 def _getobj(self):448 return self.parent.obj()449 def collect(self):450 self.session._fixturemanager.parsefactories(self)451 return super(Instance, self).collect()452 def newinstance(self):453 self.obj = self._getobj()454 return self.obj455class FunctionMixin(PyobjMixin):456 """ mixin for the code common to Function and Generator.457 """458 def setup(self):459 """ perform setup for this test function. """460 if hasattr(self, '_preservedparent'):461 obj = self._preservedparent462 elif isinstance(self.parent, Instance):463 obj = self.parent.newinstance()464 self.obj = self._getobj()465 else:466 obj = self.parent.obj467 if inspect.ismethod(self.obj):468 setup_name = 'setup_method'469 teardown_name = 'teardown_method'470 else:471 setup_name = 'setup_function'472 teardown_name = 'teardown_function'473 setup_func_or_method = _get_xunit_setup_teardown(obj, setup_name, param_obj=self.obj)474 if setup_func_or_method is not None:475 setup_func_or_method()476 teardown_func_or_method = _get_xunit_setup_teardown(obj, teardown_name, param_obj=self.obj)477 if teardown_func_or_method is not None:478 self.addfinalizer(teardown_func_or_method)479 def _prunetraceback(self, excinfo):480 if hasattr(self, '_obj') and not self.config.option.fulltrace:481 code = _pytest._code.Code(get_real_func(self.obj))482 path, firstlineno = code.path, code.firstlineno483 traceback = excinfo.traceback484 ntraceback = traceback.cut(path=path, firstlineno=firstlineno)485 if ntraceback == traceback:486 ntraceback = ntraceback.cut(path=path)487 if ntraceback == traceback:488 # ntraceback = ntraceback.cut(excludepath=cutdir2)489 ntraceback = ntraceback.filter(filter_traceback)490 if not ntraceback:491 ntraceback = traceback492 excinfo.traceback = ntraceback.filter()493 # issue364: mark all but first and last frames to494 # only show a single-line message for each frame495 if self.config.option.tbstyle == "auto":496 if len(excinfo.traceback) > 2:497 for entry in excinfo.traceback[1:-1]:498 entry.set_repr_style('short')499 def _repr_failure_py(self, excinfo, style="long"):500 if excinfo.errisinstance(fail.Exception):501 if not excinfo.value.pytrace:502 return py._builtin._totext(excinfo.value)503 return super(FunctionMixin, self)._repr_failure_py(excinfo,504 style=style)505 def repr_failure(self, excinfo, outerr=None):506 assert outerr is None, "XXX outerr usage is deprecated"507 style = self.config.option.tbstyle508 if style == "auto":509 style = "long"510 return self._repr_failure_py(excinfo, style=style)511class Generator(FunctionMixin, PyCollector):512 def collect(self):513 # test generators are seen as collectors but they also514 # invoke setup/teardown on popular request515 # (induced by the common "test_*" naming shared with normal tests)516 from _pytest import deprecated517 self.session._setupstate.prepare(self)518 # see FunctionMixin.setup and test_setupstate_is_preserved_134519 self._preservedparent = self.parent.obj520 values = []521 seen = {}522 for i, x in enumerate(self.obj()):523 name, call, args = self.getcallargs(x)524 if not callable(call):525 raise TypeError("%r yielded non callable test %r" % (self.obj, call,))526 if name is None:527 name = "[%d]" % i528 else:529 name = "['%s']" % name530 if name in seen:531 raise ValueError("%r generated tests with non-unique name %r" % (self, name))532 seen[name] = True533 values.append(self.Function(name, self, args=args, callobj=call))534 self.warn('C1', deprecated.YIELD_TESTS)535 return values536 def getcallargs(self, obj):537 if not isinstance(obj, (tuple, list)):538 obj = (obj,)539 # explicit naming540 if isinstance(obj[0], six.string_types):541 name = obj[0]542 obj = obj[1:]543 else:544 name = None545 call, args = obj[0], obj[1:]546 return name, call, args547def hasinit(obj):548 init = getattr(obj, '__init__', None)549 if init:550 return init != object.__init__551def hasnew(obj):552 new = getattr(obj, '__new__', None)553 if new:554 return new != object.__new__555class CallSpec2(object):556 def __init__(self, metafunc):557 self.metafunc = metafunc558 self.funcargs = {}559 self._idlist = []560 self.params = {}561 self._globalid = NOTSET562 self._globalid_args = set()563 self._globalparam = NOTSET564 self._arg2scopenum = {} # used for sorting parametrized resources565 self.marks = []566 self.indices = {}567 def copy(self, metafunc):568 cs = CallSpec2(self.metafunc)569 cs.funcargs.update(self.funcargs)570 cs.params.update(self.params)571 cs.marks.extend(self.marks)572 cs.indices.update(self.indices)573 cs._arg2scopenum.update(self._arg2scopenum)574 cs._idlist = list(self._idlist)575 cs._globalid = self._globalid576 cs._globalid_args = self._globalid_args577 cs._globalparam = self._globalparam578 return cs579 def _checkargnotcontained(self, arg):580 if arg in self.params or arg in self.funcargs:581 raise ValueError("duplicate %r" % (arg,))582 def getparam(self, name):583 try:584 return self.params[name]585 except KeyError:586 if self._globalparam is NOTSET:587 raise ValueError(name)588 return self._globalparam589 @property590 def id(self):591 return "-".join(map(str, filter(None, self._idlist)))592 def setmulti2(self, valtypes, argnames, valset, id, marks, scopenum,593 param_index):594 for arg, val in zip(argnames, valset):595 self._checkargnotcontained(arg)596 valtype_for_arg = valtypes[arg]597 getattr(self, valtype_for_arg)[arg] = val598 self.indices[arg] = param_index599 self._arg2scopenum[arg] = scopenum600 self._idlist.append(id)601 self.marks.extend(marks)602 def setall(self, funcargs, id, param):603 for x in funcargs:604 self._checkargnotcontained(x)605 self.funcargs.update(funcargs)606 if id is not NOTSET:607 self._idlist.append(id)608 if param is not NOTSET:609 assert self._globalparam is NOTSET610 self._globalparam = param611 for arg in funcargs:612 self._arg2scopenum[arg] = fixtures.scopenum_function613class Metafunc(fixtures.FuncargnamesCompatAttr):614 """615 Metafunc objects are passed to the ``pytest_generate_tests`` hook.616 They help to inspect a test function and to generate tests according to617 test configuration or values specified in the class or module where a618 test function is defined.619 """620 def __init__(self, function, fixtureinfo, config, cls=None, module=None):621 #: access to the :class:`_pytest.config.Config` object for the test session622 self.config = config623 #: the module object where the test function is defined in.624 self.module = module625 #: underlying python test function626 self.function = function627 #: set of fixture names required by the test function628 self.fixturenames = fixtureinfo.names_closure629 #: class object where the test function is defined in or ``None``.630 self.cls = cls631 self._calls = []632 self._ids = set()633 self._arg2fixturedefs = fixtureinfo.name2fixturedefs634 def parametrize(self, argnames, argvalues, indirect=False, ids=None,635 scope=None):636 """ Add new invocations to the underlying test function using the list637 of argvalues for the given argnames. Parametrization is performed638 during the collection phase. If you need to setup expensive resources639 see about setting indirect to do it rather at test setup time.640 :arg argnames: a comma-separated string denoting one or more argument641 names, or a list/tuple of argument strings.642 :arg argvalues: The list of argvalues determines how often a643 test is invoked with different argument values. If only one644 argname was specified argvalues is a list of values. If N645 argnames were specified, argvalues must be a list of N-tuples,646 where each tuple-element specifies a value for its respective647 argname.648 :arg indirect: The list of argnames or boolean. A list of arguments'649 names (subset of argnames). If True the list contains all names from650 the argnames. Each argvalue corresponding to an argname in this list will651 be passed as request.param to its respective argname fixture652 function so that it can perform more expensive setups during the653 setup phase of a test rather than at collection time.654 :arg ids: list of string ids, or a callable.655 If strings, each is corresponding to the argvalues so that they are656 part of the test id. If None is given as id of specific test, the657 automatically generated id for that argument will be used.658 If callable, it should take one argument (a single argvalue) and return659 a string or return None. If None, the automatically generated id for that660 argument will be used.661 If no ids are provided they will be generated automatically from662 the argvalues.663 :arg scope: if specified it denotes the scope of the parameters.664 The scope is used for grouping tests by parameter instances.665 It will also override any fixture-function defined scope, allowing666 to set a dynamic scope using test context or configuration.667 """668 from _pytest.fixtures import scope2index669 from _pytest.mark import ParameterSet670 from py.io import saferepr671 argnames, parameters = ParameterSet._for_parameterize(672 argnames, argvalues, self.function)673 del argvalues674 if scope is None:675 scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)676 scopenum = scope2index(scope, descr='call to {0}'.format(self.parametrize))677 valtypes = {}678 for arg in argnames:679 if arg not in self.fixturenames:680 if isinstance(indirect, (tuple, list)):681 name = 'fixture' if arg in indirect else 'argument'682 else:683 name = 'fixture' if indirect else 'argument'684 raise ValueError(685 "%r uses no %s %r" % (686 self.function, name, arg))687 if indirect is True:688 valtypes = dict.fromkeys(argnames, "params")689 elif indirect is False:690 valtypes = dict.fromkeys(argnames, "funcargs")691 elif isinstance(indirect, (tuple, list)):692 valtypes = dict.fromkeys(argnames, "funcargs")693 for arg in indirect:694 if arg not in argnames:695 raise ValueError("indirect given to %r: fixture %r doesn't exist" % (696 self.function, arg))697 valtypes[arg] = "params"698 idfn = None699 if callable(ids):700 idfn = ids701 ids = None702 if ids:703 if len(ids) != len(parameters):704 raise ValueError('%d tests specified with %d ids' % (705 len(parameters), len(ids)))706 for id_value in ids:707 if id_value is not None and not isinstance(id_value, six.string_types):708 msg = 'ids must be list of strings, found: %s (type: %s)'709 raise ValueError(msg % (saferepr(id_value), type(id_value).__name__))710 ids = idmaker(argnames, parameters, idfn, ids, self.config)711 newcalls = []712 for callspec in self._calls or [CallSpec2(self)]:713 elements = zip(ids, parameters, count())714 for a_id, param, param_index in elements:715 if len(param.values) != len(argnames):716 raise ValueError(717 'In "parametrize" the number of values ({0}) must be '718 'equal to the number of names ({1})'.format(719 param.values, argnames))720 newcallspec = callspec.copy(self)721 newcallspec.setmulti2(valtypes, argnames, param.values, a_id,722 param.marks, scopenum, param_index)723 newcalls.append(newcallspec)724 self._calls = newcalls725 def addcall(self, funcargs=None, id=NOTSET, param=NOTSET):726 """ Add a new call to the underlying test function during the collection phase of a test run.727 .. deprecated:: 3.3728 Use :meth:`parametrize` instead.729 Note that request.addcall() is called during the test collection phase prior and730 independently to actual test execution. You should only use addcall()731 if you need to specify multiple arguments of a test function.732 :arg funcargs: argument keyword dictionary used when invoking733 the test function.734 :arg id: used for reporting and identification purposes. If you735 don't supply an `id` an automatic unique id will be generated.736 :arg param: a parameter which will be exposed to a later fixture function737 invocation through the ``request.param`` attribute.738 """739 if self.config:740 self.config.warn('C1', message=deprecated.METAFUNC_ADD_CALL, fslocation=None)741 assert funcargs is None or isinstance(funcargs, dict)742 if funcargs is not None:743 for name in funcargs:744 if name not in self.fixturenames:745 fail("funcarg %r not used in this function." % name)746 else:747 funcargs = {}748 if id is None:749 raise ValueError("id=None not allowed")750 if id is NOTSET:751 id = len(self._calls)752 id = str(id)753 if id in self._ids:754 raise ValueError("duplicate id %r" % id)755 self._ids.add(id)756 cs = CallSpec2(self)757 cs.setall(funcargs, id, param)758 self._calls.append(cs)759def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):760 """Find the most appropriate scope for a parametrized call based on its arguments.761 When there's at least one direct argument, always use "function" scope.762 When a test function is parametrized and all its arguments are indirect763 (e.g. fixtures), return the most narrow scope based on the fixtures used.764 Related to issue #1832, based on code posted by @Kingdread.765 """766 from _pytest.fixtures import scopes767 indirect_as_list = isinstance(indirect, (list, tuple))768 all_arguments_are_fixtures = indirect is True or \769 indirect_as_list and len(indirect) == argnames770 if all_arguments_are_fixtures:771 fixturedefs = arg2fixturedefs or {}772 used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]773 if used_scopes:774 # Takes the most narrow scope from used fixtures775 for scope in reversed(scopes):776 if scope in used_scopes:777 return scope778 return 'function'779def _idval(val, argname, idx, idfn, config=None):780 if idfn:781 s = None782 try:783 s = idfn(val)784 except Exception:785 # See issue https://github.com/pytest-dev/pytest/issues/2169786 import warnings787 msg = "Raised while trying to determine id of parameter %s at position %d." % (argname, idx)788 msg += '\nUpdate your code as this will raise an error in pytest-4.0.'789 warnings.warn(msg, DeprecationWarning)790 if s:791 return ascii_escaped(s)792 if config:793 hook_id = config.hook.pytest_make_parametrize_id(794 config=config, val=val, argname=argname)795 if hook_id:796 return hook_id797 if isinstance(val, STRING_TYPES):798 return ascii_escaped(val)799 elif isinstance(val, (float, int, bool, NoneType)):800 return str(val)801 elif isinstance(val, REGEX_TYPE):802 return ascii_escaped(val.pattern)803 elif enum is not None and isinstance(val, enum.Enum):804 return str(val)805 elif isclass(val) and hasattr(val, '__name__'):806 return val.__name__807 return str(argname) + str(idx)808def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):809 if parameterset.id is not None:810 return parameterset.id811 if ids is None or (idx >= len(ids) or ids[idx] is None):812 this_id = [_idval(val, argname, idx, idfn, config)813 for val, argname in zip(parameterset.values, argnames)]814 return "-".join(this_id)815 else:816 return ascii_escaped(ids[idx])817def idmaker(argnames, parametersets, idfn=None, ids=None, config=None):818 ids = [_idvalset(valindex, parameterset, argnames, idfn, ids, config)819 for valindex, parameterset in enumerate(parametersets)]820 if len(set(ids)) != len(ids):821 # The ids are not unique822 duplicates = [testid for testid in ids if ids.count(testid) > 1]823 counters = collections.defaultdict(lambda: 0)824 for index, testid in enumerate(ids):825 if testid in duplicates:826 ids[index] = testid + str(counters[testid])827 counters[testid] += 1828 return ids829def show_fixtures_per_test(config):830 from _pytest.main import wrap_session831 return wrap_session(config, _show_fixtures_per_test)832def _show_fixtures_per_test(config, session):833 import _pytest.config834 session.perform_collect()835 curdir = py.path.local()836 tw = _pytest.config.create_terminal_writer(config)837 verbose = config.getvalue("verbose")838 def get_best_relpath(func):839 loc = getlocation(func, curdir)840 return curdir.bestrelpath(loc)841 def write_fixture(fixture_def):842 argname = fixture_def.argname843 if verbose <= 0 and argname.startswith("_"):844 return845 if verbose > 0:846 bestrel = get_best_relpath(fixture_def.func)...

Full Screen

Full Screen

test_pytester.py

Source:test_pytester.py Github

copy

Full Screen

1import os2import subprocess3import sys4import time5from typing import List6import py.path7import _pytest.pytester as pytester8import pytest9from _pytest.config import ExitCode10from _pytest.config import PytestPluginManager11from _pytest.pytester import CwdSnapshot12from _pytest.pytester import HookRecorder13from _pytest.pytester import LineMatcher14from _pytest.pytester import SysModulesSnapshot15from _pytest.pytester import SysPathsSnapshot16from _pytest.pytester import Testdir17def test_make_hook_recorder(testdir) -> None:18 item = testdir.getitem("def test_func(): pass")19 recorder = testdir.make_hook_recorder(item.config.pluginmanager)20 assert not recorder.getfailures()21 pytest.xfail("internal reportrecorder tests need refactoring")22 class rep:23 excinfo = None24 passed = False25 failed = True26 skipped = False27 when = "call"28 recorder.hook.pytest_runtest_logreport(report=rep)29 failures = recorder.getfailures()30 assert failures == [rep]31 failures = recorder.getfailures()32 assert failures == [rep]33 class rep2:34 excinfo = None35 passed = False36 failed = False37 skipped = True38 when = "call"39 rep2.passed = False40 rep2.skipped = True41 recorder.hook.pytest_runtest_logreport(report=rep2)42 modcol = testdir.getmodulecol("")43 rep3 = modcol.config.hook.pytest_make_collect_report(collector=modcol)44 rep3.passed = False45 rep3.failed = True46 rep3.skipped = False47 recorder.hook.pytest_collectreport(report=rep3)48 passed, skipped, failed = recorder.listoutcomes()49 assert not passed and skipped and failed50 numpassed, numskipped, numfailed = recorder.countoutcomes()51 assert numpassed == 052 assert numskipped == 153 assert numfailed == 154 assert len(recorder.getfailedcollections()) == 155 recorder.unregister()56 recorder.clear()57 recorder.hook.pytest_runtest_logreport(report=rep3)58 pytest.raises(ValueError, recorder.getfailures)59def test_parseconfig(testdir) -> None:60 config1 = testdir.parseconfig()61 config2 = testdir.parseconfig()62 assert config2 is not config163def test_testdir_runs_with_plugin(testdir) -> None:64 testdir.makepyfile(65 """66 pytest_plugins = "pytester"67 def test_hello(testdir):68 assert 169 """70 )71 result = testdir.runpytest()72 result.assert_outcomes(passed=1)73def test_runresult_assertion_on_xfail(testdir) -> None:74 testdir.makepyfile(75 """76 import pytest77 pytest_plugins = "pytester"78 @pytest.mark.xfail79 def test_potato():80 assert False81 """82 )83 result = testdir.runpytest()84 result.assert_outcomes(xfailed=1)85 assert result.ret == 086def test_runresult_assertion_on_xpassed(testdir) -> None:87 testdir.makepyfile(88 """89 import pytest90 pytest_plugins = "pytester"91 @pytest.mark.xfail92 def test_potato():93 assert True94 """95 )96 result = testdir.runpytest()97 result.assert_outcomes(xpassed=1)98 assert result.ret == 099def test_xpassed_with_strict_is_considered_a_failure(testdir) -> None:100 testdir.makepyfile(101 """102 import pytest103 pytest_plugins = "pytester"104 @pytest.mark.xfail(strict=True)105 def test_potato():106 assert True107 """108 )109 result = testdir.runpytest()110 result.assert_outcomes(failed=1)111 assert result.ret != 0112def make_holder():113 class apiclass:114 def pytest_xyz(self, arg):115 "x"116 def pytest_xyz_noarg(self):117 "x"118 apimod = type(os)("api")119 def pytest_xyz(arg):120 "x"121 def pytest_xyz_noarg():122 "x"123 apimod.pytest_xyz = pytest_xyz # type: ignore124 apimod.pytest_xyz_noarg = pytest_xyz_noarg # type: ignore125 return apiclass, apimod126@pytest.mark.parametrize("holder", make_holder())127def test_hookrecorder_basic(holder) -> None:128 pm = PytestPluginManager()129 pm.add_hookspecs(holder)130 rec = HookRecorder(pm)131 pm.hook.pytest_xyz(arg=123)132 call = rec.popcall("pytest_xyz")133 assert call.arg == 123134 assert call._name == "pytest_xyz"135 pytest.raises(pytest.fail.Exception, rec.popcall, "abc")136 pm.hook.pytest_xyz_noarg()137 call = rec.popcall("pytest_xyz_noarg")138 assert call._name == "pytest_xyz_noarg"139def test_makepyfile_unicode(testdir) -> None:140 testdir.makepyfile(chr(0xFFFD))141def test_makepyfile_utf8(testdir) -> None:142 """Ensure makepyfile accepts utf-8 bytes as input (#2738)"""143 utf8_contents = """144 def setup_function(function):145 mixed_encoding = 'São Paulo'146 """.encode()147 p = testdir.makepyfile(utf8_contents)148 assert "mixed_encoding = 'São Paulo'".encode() in p.read("rb")149class TestInlineRunModulesCleanup:150 def test_inline_run_test_module_not_cleaned_up(self, testdir) -> None:151 test_mod = testdir.makepyfile("def test_foo(): assert True")152 result = testdir.inline_run(str(test_mod))153 assert result.ret == ExitCode.OK154 # rewrite module, now test should fail if module was re-imported155 test_mod.write("def test_foo(): assert False")156 result2 = testdir.inline_run(str(test_mod))157 assert result2.ret == ExitCode.TESTS_FAILED158 def spy_factory(self):159 class SysModulesSnapshotSpy:160 instances = [] # type: List[SysModulesSnapshotSpy]161 def __init__(self, preserve=None) -> None:162 SysModulesSnapshotSpy.instances.append(self)163 self._spy_restore_count = 0164 self._spy_preserve = preserve165 self.__snapshot = SysModulesSnapshot(preserve=preserve)166 def restore(self):167 self._spy_restore_count += 1168 return self.__snapshot.restore()169 return SysModulesSnapshotSpy170 def test_inline_run_taking_and_restoring_a_sys_modules_snapshot(171 self, testdir, monkeypatch172 ) -> None:173 spy_factory = self.spy_factory()174 monkeypatch.setattr(pytester, "SysModulesSnapshot", spy_factory)175 testdir.syspathinsert()176 original = dict(sys.modules)177 testdir.makepyfile(import1="# you son of a silly person")178 testdir.makepyfile(import2="# my hovercraft is full of eels")179 test_mod = testdir.makepyfile(180 """181 import import1182 def test_foo(): import import2"""183 )184 testdir.inline_run(str(test_mod))185 assert len(spy_factory.instances) == 1186 spy = spy_factory.instances[0]187 assert spy._spy_restore_count == 1188 assert sys.modules == original189 assert all(sys.modules[x] is original[x] for x in sys.modules)190 def test_inline_run_sys_modules_snapshot_restore_preserving_modules(191 self, testdir, monkeypatch192 ) -> None:193 spy_factory = self.spy_factory()194 monkeypatch.setattr(pytester, "SysModulesSnapshot", spy_factory)195 test_mod = testdir.makepyfile("def test_foo(): pass")196 testdir.inline_run(str(test_mod))197 spy = spy_factory.instances[0]198 assert not spy._spy_preserve("black_knight")199 assert spy._spy_preserve("zope")200 assert spy._spy_preserve("zope.interface")201 assert spy._spy_preserve("zopelicious")202 def test_external_test_module_imports_not_cleaned_up(self, testdir) -> None:203 testdir.syspathinsert()204 testdir.makepyfile(imported="data = 'you son of a silly person'")205 import imported206 test_mod = testdir.makepyfile(207 """208 def test_foo():209 import imported210 imported.data = 42"""211 )212 testdir.inline_run(str(test_mod))213 assert imported.data == 42214def test_assert_outcomes_after_pytest_error(testdir) -> None:215 testdir.makepyfile("def test_foo(): assert True")216 result = testdir.runpytest("--unexpected-argument")217 with pytest.raises(ValueError, match="Pytest terminal summary report not found"):218 result.assert_outcomes(passed=0)219def test_cwd_snapshot(testdir: Testdir) -> None:220 tmpdir = testdir.tmpdir221 foo = tmpdir.ensure("foo", dir=1)222 bar = tmpdir.ensure("bar", dir=1)223 foo.chdir()224 snapshot = CwdSnapshot()225 bar.chdir()226 assert py.path.local() == bar227 snapshot.restore()228 assert py.path.local() == foo229class TestSysModulesSnapshot:230 key = "my-test-module"231 def test_remove_added(self) -> None:232 original = dict(sys.modules)233 assert self.key not in sys.modules234 snapshot = SysModulesSnapshot()235 sys.modules[self.key] = "something" # type: ignore236 assert self.key in sys.modules237 snapshot.restore()238 assert sys.modules == original239 def test_add_removed(self, monkeypatch) -> None:240 assert self.key not in sys.modules241 monkeypatch.setitem(sys.modules, self.key, "something")242 assert self.key in sys.modules243 original = dict(sys.modules)244 snapshot = SysModulesSnapshot()245 del sys.modules[self.key]246 assert self.key not in sys.modules247 snapshot.restore()248 assert sys.modules == original249 def test_restore_reloaded(self, monkeypatch) -> None:250 assert self.key not in sys.modules251 monkeypatch.setitem(sys.modules, self.key, "something")252 assert self.key in sys.modules253 original = dict(sys.modules)254 snapshot = SysModulesSnapshot()255 sys.modules[self.key] = "something else" # type: ignore256 snapshot.restore()257 assert sys.modules == original258 def test_preserve_modules(self, monkeypatch) -> None:259 key = [self.key + str(i) for i in range(3)]260 assert not any(k in sys.modules for k in key)261 for i, k in enumerate(key):262 monkeypatch.setitem(sys.modules, k, "something" + str(i))263 original = dict(sys.modules)264 def preserve(name):265 return name in (key[0], key[1], "some-other-key")266 snapshot = SysModulesSnapshot(preserve=preserve)267 sys.modules[key[0]] = original[key[0]] = "something else0" # type: ignore268 sys.modules[key[1]] = original[key[1]] = "something else1" # type: ignore269 sys.modules[key[2]] = "something else2" # type: ignore270 snapshot.restore()271 assert sys.modules == original272 def test_preserve_container(self, monkeypatch) -> None:273 original = dict(sys.modules)274 assert self.key not in original275 replacement = dict(sys.modules)276 replacement[self.key] = "life of brian" # type: ignore277 snapshot = SysModulesSnapshot()278 monkeypatch.setattr(sys, "modules", replacement)279 snapshot.restore()280 assert sys.modules is replacement281 assert sys.modules == original282@pytest.mark.parametrize("path_type", ("path", "meta_path"))283class TestSysPathsSnapshot:284 other_path = {"path": "meta_path", "meta_path": "path"}285 @staticmethod286 def path(n: int) -> str:287 return "my-dirty-little-secret-" + str(n)288 def test_restore(self, monkeypatch, path_type) -> None:289 other_path_type = self.other_path[path_type]290 for i in range(10):291 assert self.path(i) not in getattr(sys, path_type)292 sys_path = [self.path(i) for i in range(6)]293 monkeypatch.setattr(sys, path_type, sys_path)294 original = list(sys_path)295 original_other = list(getattr(sys, other_path_type))296 snapshot = SysPathsSnapshot()297 transformation = {"source": (0, 1, 2, 3, 4, 5), "target": (6, 2, 9, 7, 5, 8)}298 assert sys_path == [self.path(x) for x in transformation["source"]]299 sys_path[1] = self.path(6)300 sys_path[3] = self.path(7)301 sys_path.append(self.path(8))302 del sys_path[4]303 sys_path[3:3] = [self.path(9)]304 del sys_path[0]305 assert sys_path == [self.path(x) for x in transformation["target"]]306 snapshot.restore()307 assert getattr(sys, path_type) is sys_path308 assert getattr(sys, path_type) == original309 assert getattr(sys, other_path_type) == original_other310 def test_preserve_container(self, monkeypatch, path_type) -> None:311 other_path_type = self.other_path[path_type]312 original_data = list(getattr(sys, path_type))313 original_other = getattr(sys, other_path_type)314 original_other_data = list(original_other)315 new = [] # type: List[object]316 snapshot = SysPathsSnapshot()317 monkeypatch.setattr(sys, path_type, new)318 snapshot.restore()319 assert getattr(sys, path_type) is new320 assert getattr(sys, path_type) == original_data321 assert getattr(sys, other_path_type) is original_other322 assert getattr(sys, other_path_type) == original_other_data323def test_testdir_subprocess(testdir) -> None:324 testfile = testdir.makepyfile("def test_one(): pass")325 assert testdir.runpytest_subprocess(testfile).ret == 0326def test_testdir_subprocess_via_runpytest_arg(testdir) -> None:327 testfile = testdir.makepyfile(328 """329 def test_testdir_subprocess(testdir):330 import os331 testfile = testdir.makepyfile(332 \"""333 import os334 def test_one():335 assert {} != os.getpid()336 \""".format(os.getpid())337 )338 assert testdir.runpytest(testfile).ret == 0339 """340 )341 result = testdir.runpytest_subprocess(342 "-p", "pytester", "--runpytest", "subprocess", testfile343 )344 assert result.ret == 0345def test_unicode_args(testdir) -> None:346 result = testdir.runpytest("-k", "💩")347 assert result.ret == ExitCode.NO_TESTS_COLLECTED348def test_testdir_run_no_timeout(testdir) -> None:349 testfile = testdir.makepyfile("def test_no_timeout(): pass")350 assert testdir.runpytest_subprocess(testfile).ret == ExitCode.OK351def test_testdir_run_with_timeout(testdir) -> None:352 testfile = testdir.makepyfile("def test_no_timeout(): pass")353 timeout = 120354 start = time.time()355 result = testdir.runpytest_subprocess(testfile, timeout=timeout)356 end = time.time()357 duration = end - start358 assert result.ret == ExitCode.OK359 assert duration < timeout360def test_testdir_run_timeout_expires(testdir) -> None:361 testfile = testdir.makepyfile(362 """363 import time364 def test_timeout():365 time.sleep(10)"""366 )367 with pytest.raises(testdir.TimeoutExpired):368 testdir.runpytest_subprocess(testfile, timeout=1)369def test_linematcher_with_nonlist() -> None:370 """Test LineMatcher with regard to passing in a set (accidentally)."""371 from _pytest._code.source import Source372 lm = LineMatcher([])373 with pytest.raises(TypeError, match="invalid type for lines2: set"):374 lm.fnmatch_lines(set()) # type: ignore[arg-type] # noqa: F821375 with pytest.raises(TypeError, match="invalid type for lines2: dict"):376 lm.fnmatch_lines({}) # type: ignore[arg-type] # noqa: F821377 with pytest.raises(TypeError, match="invalid type for lines2: set"):378 lm.re_match_lines(set()) # type: ignore[arg-type] # noqa: F821379 with pytest.raises(TypeError, match="invalid type for lines2: dict"):380 lm.re_match_lines({}) # type: ignore[arg-type] # noqa: F821381 with pytest.raises(TypeError, match="invalid type for lines2: Source"):382 lm.fnmatch_lines(Source()) # type: ignore[arg-type] # noqa: F821383 lm.fnmatch_lines([])384 lm.fnmatch_lines(())385 lm.fnmatch_lines("")386 assert lm._getlines({}) == {} # type: ignore[arg-type,comparison-overlap] # noqa: F821387 assert lm._getlines(set()) == set() # type: ignore[arg-type,comparison-overlap] # noqa: F821388 assert lm._getlines(Source()) == []389 assert lm._getlines(Source("pass\npass")) == ["pass", "pass"]390def test_linematcher_match_failure() -> None:391 lm = LineMatcher(["foo", "foo", "bar"])392 with pytest.raises(pytest.fail.Exception) as e:393 lm.fnmatch_lines(["foo", "f*", "baz"])394 assert e.value.msg is not None395 assert e.value.msg.splitlines() == [396 "exact match: 'foo'",397 "fnmatch: 'f*'",398 " with: 'foo'",399 "nomatch: 'baz'",400 " and: 'bar'",401 "remains unmatched: 'baz'",402 ]403 lm = LineMatcher(["foo", "foo", "bar"])404 with pytest.raises(pytest.fail.Exception) as e:405 lm.re_match_lines(["foo", "^f.*", "baz"])406 assert e.value.msg is not None407 assert e.value.msg.splitlines() == [408 "exact match: 'foo'",409 "re.match: '^f.*'",410 " with: 'foo'",411 " nomatch: 'baz'",412 " and: 'bar'",413 "remains unmatched: 'baz'",414 ]415def test_linematcher_consecutive():416 lm = LineMatcher(["1", "", "2"])417 with pytest.raises(pytest.fail.Exception) as excinfo:418 lm.fnmatch_lines(["1", "2"], consecutive=True)419 assert str(excinfo.value).splitlines() == [420 "exact match: '1'",421 "no consecutive match: '2'",422 " with: ''",423 ]424 lm.re_match_lines(["1", r"\d?", "2"], consecutive=True)425 with pytest.raises(pytest.fail.Exception) as excinfo:426 lm.re_match_lines(["1", r"\d", "2"], consecutive=True)427 assert str(excinfo.value).splitlines() == [428 "exact match: '1'",429 r"no consecutive match: '\\d'",430 " with: ''",431 ]432@pytest.mark.parametrize("function", ["no_fnmatch_line", "no_re_match_line"])433def test_linematcher_no_matching(function) -> None:434 if function == "no_fnmatch_line":435 good_pattern = "*.py OK*"436 bad_pattern = "*X.py OK*"437 else:438 assert function == "no_re_match_line"439 good_pattern = r".*py OK"440 bad_pattern = r".*Xpy OK"441 lm = LineMatcher(442 [443 "cachedir: .pytest_cache",444 "collecting ... collected 1 item",445 "",446 "show_fixtures_per_test.py OK",447 "=== elapsed 1s ===",448 ]449 )450 # check the function twice to ensure we don't accumulate the internal buffer451 for i in range(2):452 with pytest.raises(pytest.fail.Exception) as e:453 func = getattr(lm, function)454 func(good_pattern)455 obtained = str(e.value).splitlines()456 if function == "no_fnmatch_line":457 assert obtained == [458 "nomatch: '{}'".format(good_pattern),459 " and: 'cachedir: .pytest_cache'",460 " and: 'collecting ... collected 1 item'",461 " and: ''",462 "fnmatch: '{}'".format(good_pattern),463 " with: 'show_fixtures_per_test.py OK'",464 ]465 else:466 assert obtained == [467 " nomatch: '{}'".format(good_pattern),468 " and: 'cachedir: .pytest_cache'",469 " and: 'collecting ... collected 1 item'",470 " and: ''",471 "re.match: '{}'".format(good_pattern),472 " with: 'show_fixtures_per_test.py OK'",473 ]474 func = getattr(lm, function)475 func(bad_pattern) # bad pattern does not match any line: passes476def test_linematcher_no_matching_after_match() -> None:477 lm = LineMatcher(["1", "2", "3"])478 lm.fnmatch_lines(["1", "3"])479 with pytest.raises(pytest.fail.Exception) as e:480 lm.no_fnmatch_line("*")481 assert str(e.value).splitlines() == ["fnmatch: '*'", " with: '1'"]482def test_pytester_addopts_before_testdir(request, monkeypatch) -> None:483 orig = os.environ.get("PYTEST_ADDOPTS", None)484 monkeypatch.setenv("PYTEST_ADDOPTS", "--orig-unused")485 testdir = request.getfixturevalue("testdir")486 assert "PYTEST_ADDOPTS" not in os.environ487 testdir.finalize()488 assert os.environ.get("PYTEST_ADDOPTS") == "--orig-unused"489 monkeypatch.undo()490 assert os.environ.get("PYTEST_ADDOPTS") == orig491def test_run_stdin(testdir) -> None:492 with pytest.raises(testdir.TimeoutExpired):493 testdir.run(494 sys.executable,495 "-c",496 "import sys, time; time.sleep(1); print(sys.stdin.read())",497 stdin=subprocess.PIPE,498 timeout=0.1,499 )500 with pytest.raises(testdir.TimeoutExpired):501 result = testdir.run(502 sys.executable,503 "-c",504 "import sys, time; time.sleep(1); print(sys.stdin.read())",505 stdin=b"input\n2ndline",506 timeout=0.1,507 )508 result = testdir.run(509 sys.executable,510 "-c",511 "import sys; print(sys.stdin.read())",512 stdin=b"input\n2ndline",513 )514 assert result.stdout.lines == ["input", "2ndline"]515 assert result.stderr.str() == ""516 assert result.ret == 0517def test_popen_stdin_pipe(testdir) -> None:518 proc = testdir.popen(519 [sys.executable, "-c", "import sys; print(sys.stdin.read())"],520 stdout=subprocess.PIPE,521 stderr=subprocess.PIPE,522 stdin=subprocess.PIPE,523 )524 stdin = b"input\n2ndline"525 stdout, stderr = proc.communicate(input=stdin)526 assert stdout.decode("utf8").splitlines() == ["input", "2ndline"]527 assert stderr == b""528 assert proc.returncode == 0529def test_popen_stdin_bytes(testdir) -> None:530 proc = testdir.popen(531 [sys.executable, "-c", "import sys; print(sys.stdin.read())"],532 stdout=subprocess.PIPE,533 stderr=subprocess.PIPE,534 stdin=b"input\n2ndline",535 )536 stdout, stderr = proc.communicate()537 assert stdout.decode("utf8").splitlines() == ["input", "2ndline"]538 assert stderr == b""539 assert proc.returncode == 0540def test_popen_default_stdin_stderr_and_stdin_None(testdir) -> None:541 # stdout, stderr default to pipes,542 # stdin can be None to not close the pipe, avoiding543 # "ValueError: flush of closed file" with `communicate()`.544 p1 = testdir.makepyfile(545 """546 import sys547 print(sys.stdin.read()) # empty548 print('stdout')549 sys.stderr.write('stderr')550 """551 )552 proc = testdir.popen([sys.executable, str(p1)], stdin=None)553 stdout, stderr = proc.communicate(b"ignored")554 assert stdout.splitlines() == [b"", b"stdout"]555 assert stderr.splitlines() == [b"stderr"]556 assert proc.returncode == 0557def test_spawn_uses_tmphome(testdir) -> None:558 tmphome = str(testdir.tmpdir)559 assert os.environ.get("HOME") == tmphome560 testdir.monkeypatch.setenv("CUSTOMENV", "42")561 p1 = testdir.makepyfile(562 """563 import os564 def test():565 assert os.environ["HOME"] == {tmphome!r}566 assert os.environ["CUSTOMENV"] == "42"567 """.format(568 tmphome=tmphome569 )570 )571 child = testdir.spawn_pytest(str(p1))572 out = child.read()573 assert child.wait() == 0, out.decode("utf8")574def test_run_result_repr() -> None:575 outlines = ["some", "normal", "output"]576 errlines = ["some", "nasty", "errors", "happened"]577 # known exit code578 r = pytester.RunResult(1, outlines, errlines, duration=0.5)579 assert (580 repr(r) == "<RunResult ret=ExitCode.TESTS_FAILED len(stdout.lines)=3"581 " len(stderr.lines)=4 duration=0.50s>"582 )583 # unknown exit code: just the number584 r = pytester.RunResult(99, outlines, errlines, duration=0.5)585 assert (586 repr(r) == "<RunResult ret=99 len(stdout.lines)=3"587 " len(stderr.lines)=4 duration=0.50s>"588 )589def test_testdir_outcomes_with_multiple_errors(testdir):590 p1 = testdir.makepyfile(591 """592 import pytest593 @pytest.fixture594 def bad_fixture():595 raise Exception("bad")596 def test_error1(bad_fixture):597 pass598 def test_error2(bad_fixture):599 pass600 """601 )602 result = testdir.runpytest(str(p1))603 result.assert_outcomes(error=2)604 assert result.parseoutcomes() == {"error": 2}605def test_makefile_joins_absolute_path(testdir: Testdir) -> None:606 absfile = testdir.tmpdir / "absfile"607 if sys.platform == "win32":608 with pytest.raises(OSError):609 testdir.makepyfile(**{str(absfile): ""})610 else:611 p1 = testdir.makepyfile(**{str(absfile): ""})...

Full Screen

Full Screen

Pytest Tutorial

Looking for an in-depth tutorial around pytest? LambdaTest covers the detailed pytest tutorial that has everything related to the pytest, from setting up the pytest framework to automation testing. Delve deeper into pytest testing by exploring advanced use cases like parallel testing, pytest fixtures, parameterization, executing multiple test cases from a single file, and more.

Chapters

  1. What is pytest
  2. Pytest installation: Want to start pytest from scratch? See how to install and configure pytest for Python automation testing.
  3. Run first test with pytest framework: Follow this step-by-step tutorial to write and run your first pytest script.
  4. Parallel testing with pytest: A hands-on guide to parallel testing with pytest to improve the scalability of your test automation.
  5. Generate pytest reports: Reports make it easier to understand the results of pytest-based test runs. Learn how to generate pytest reports.
  6. Pytest Parameterized tests: Create and run your pytest scripts while avoiding code duplication and increasing test coverage with parameterization.
  7. Pytest Fixtures: Check out how to implement pytest fixtures for your end-to-end testing needs.
  8. Execute Multiple Test Cases: Explore different scenarios for running multiple test cases in pytest from a single file.
  9. Stop Test Suite after N Test Failures: See how to stop your test suite after n test failures in pytest using the @pytest.mark.incremental decorator and maxfail command-line option.

YouTube

Skim our below pytest tutorial playlist to get started with automation testing using the pytest framework.

https://www.youtube.com/playlist?list=PLZMWkkQEwOPlcGgDmHl8KkXKeLF83XlrP

Run Pytest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful