Best Python code snippet using pytest
python.py
Source:python.py
...76 help="prepend/append to sys.path when importing test modules, "77 "default is to prepend.")78def pytest_cmdline_main(config):79 if config.option.showfixtures:80 showfixtures(config)81 return 082 if config.option.show_fixtures_per_test:83 show_fixtures_per_test(config)84 return 085def pytest_generate_tests(metafunc):86 # those alternative spellings are common - raise a specific error to alert87 # the user88 alt_spellings = ['parameterize', 'parametrise', 'parameterise']89 for attr in alt_spellings:90 if hasattr(metafunc.function, attr):91 msg = "{0} has '{1}', spelling should be 'parametrize'"92 raise MarkerError(msg.format(metafunc.function.__name__, attr))93 try:94 markers = metafunc.function.parametrize95 except AttributeError:96 return97 for marker in markers:98 metafunc.parametrize(*marker.args, **marker.kwargs)99def pytest_configure(config):100 config.addinivalue_line("markers",101 "parametrize(argnames, argvalues): call a test function multiple "102 "times passing in different arguments in turn. argvalues generally "103 "needs to be a list of values if argnames specifies only one name "104 "or a list of tuples of values if argnames specifies multiple names. "105 "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "106 "decorated test function, one with arg1=1 and another with arg1=2."107 "see http://pytest.org/latest/parametrize.html for more info and "108 "examples."109 )110 config.addinivalue_line("markers",111 "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "112 "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "113 )114@hookimpl(trylast=True)115def pytest_pyfunc_call(pyfuncitem):116 testfunction = pyfuncitem.obj117 if pyfuncitem._isyieldedfunction():118 testfunction(*pyfuncitem._args)119 else:120 funcargs = pyfuncitem.funcargs121 testargs = {}122 for arg in pyfuncitem._fixtureinfo.argnames:123 testargs[arg] = funcargs[arg]124 testfunction(**testargs)125 return True126def pytest_collect_file(path, parent):127 ext = path.ext128 if ext == ".py":129 if not parent.session.isinitpath(path):130 for pat in parent.config.getini('python_files'):131 if path.fnmatch(pat):132 break133 else:134 return135 ihook = parent.session.gethookproxy(path)136 return ihook.pytest_pycollect_makemodule(path=path, parent=parent)137def pytest_pycollect_makemodule(path, parent):138 return Module(path, parent)139@hookimpl(hookwrapper=True)140def pytest_pycollect_makeitem(collector, name, obj):141 outcome = yield142 res = outcome.get_result()143 if res is not None:144 return145 # nothing was collected elsewhere, let's do it here146 if isclass(obj):147 if collector.istestclass(obj, name):148 Class = collector._getcustomclass("Class")149 outcome.force_result(Class(name, parent=collector))150 elif collector.istestfunction(obj, name):151 # mock seems to store unbound methods (issue473), normalize it152 obj = getattr(obj, "__func__", obj)153 # We need to try and unwrap the function if it's a functools.partial154 # or a funtools.wrapped.155 # We musn't if it's been wrapped with mock.patch (python 2 only)156 if not (isfunction(obj) or isfunction(get_real_func(obj))):157 collector.warn(code="C2", message="cannot collect %r because it is not a function."158 % name, )159 elif getattr(obj, "__test__", True):160 if is_generator(obj):161 res = Generator(name, parent=collector)162 else:163 res = list(collector._genfunctions(name, obj))164 outcome.force_result(res)165def pytest_make_parametrize_id(config, val, argname=None):166 return None167class PyobjContext(object):168 module = pyobj_property("Module")169 cls = pyobj_property("Class")170 instance = pyobj_property("Instance")171class PyobjMixin(PyobjContext):172 def obj():173 def fget(self):174 obj = getattr(self, '_obj', None)175 if obj is None:176 self._obj = obj = self._getobj()177 return obj178 def fset(self, value):179 self._obj = value180 return property(fget, fset, None, "underlying python object")181 obj = obj()182 def _getobj(self):183 return getattr(self.parent.obj, self.name)184 def getmodpath(self, stopatmodule=True, includemodule=False):185 """ return python path relative to the containing module. """186 chain = self.listchain()187 chain.reverse()188 parts = []189 for node in chain:190 if isinstance(node, Instance):191 continue192 name = node.name193 if isinstance(node, Module):194 name = os.path.splitext(name)[0]195 if stopatmodule:196 if includemodule:197 parts.append(name)198 break199 parts.append(name)200 parts.reverse()201 s = ".".join(parts)202 return s.replace(".[", "[")203 def _getfslineno(self):204 return getfslineno(self.obj)205 def reportinfo(self):206 # XXX caching?207 obj = self.obj208 compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)209 if isinstance(compat_co_firstlineno, int):210 # nose compatibility211 fspath = sys.modules[obj.__module__].__file__212 if fspath.endswith(".pyc"):213 fspath = fspath[:-1]214 lineno = compat_co_firstlineno215 else:216 fspath, lineno = getfslineno(obj)217 modpath = self.getmodpath()218 assert isinstance(lineno, int)219 return fspath, lineno, modpath220class PyCollector(PyobjMixin, main.Collector):221 def funcnamefilter(self, name):222 return self._matches_prefix_or_glob_option('python_functions', name)223 def isnosetest(self, obj):224 """ Look for the __test__ attribute, which is applied by the225 @nose.tools.istest decorator226 """227 # We explicitly check for "is True" here to not mistakenly treat228 # classes with a custom __getattr__ returning something truthy (like a229 # function) as test classes.230 return safe_getattr(obj, '__test__', False) is True231 def classnamefilter(self, name):232 return self._matches_prefix_or_glob_option('python_classes', name)233 def istestfunction(self, obj, name):234 if self.funcnamefilter(name) or self.isnosetest(obj):235 if isinstance(obj, staticmethod):236 # static methods need to be unwrapped237 obj = safe_getattr(obj, '__func__', False)238 if obj is False:239 # Python 2.6 wraps in a different way that we won't try to handle240 msg = "cannot collect static method %r because " \241 "it is not a function (always the case in Python 2.6)"242 self.warn(243 code="C2", message=msg % name)244 return False245 return (246 safe_getattr(obj, "__call__", False) and fixtures.getfixturemarker(obj) is None247 )248 else:249 return False250 def istestclass(self, obj, name):251 return self.classnamefilter(name) or self.isnosetest(obj)252 def _matches_prefix_or_glob_option(self, option_name, name):253 """254 checks if the given name matches the prefix or glob-pattern defined255 in ini configuration.256 """257 for option in self.config.getini(option_name):258 if name.startswith(option):259 return True260 # check that name looks like a glob-string before calling fnmatch261 # because this is called for every name in each collected module,262 # and fnmatch is somewhat expensive to call263 elif ('*' in option or '?' in option or '[' in option) and \264 fnmatch.fnmatch(name, option):265 return True266 return False267 def collect(self):268 if not getattr(self.obj, "__test__", True):269 return []270 # NB. we avoid random getattrs and peek in the __dict__ instead271 # (XXX originally introduced from a PyPy need, still true?)272 dicts = [getattr(self.obj, '__dict__', {})]273 for basecls in inspect.getmro(self.obj.__class__):274 dicts.append(basecls.__dict__)275 seen = {}276 values = []277 for dic in dicts:278 for name, obj in list(dic.items()):279 if name in seen:280 continue281 seen[name] = True282 res = self.makeitem(name, obj)283 if res is None:284 continue285 if not isinstance(res, list):286 res = [res]287 values.extend(res)288 values.sort(key=lambda item: item.reportinfo()[:2])289 return values290 def makeitem(self, name, obj):291 # assert self.ihook.fspath == self.fspath, self292 return self.ihook.pytest_pycollect_makeitem(293 collector=self, name=name, obj=obj)294 def _genfunctions(self, name, funcobj):295 module = self.getparent(Module).obj296 clscol = self.getparent(Class)297 cls = clscol and clscol.obj or None298 transfer_markers(funcobj, cls, module)299 fm = self.session._fixturemanager300 fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)301 metafunc = Metafunc(funcobj, fixtureinfo, self.config,302 cls=cls, module=module)303 methods = []304 if hasattr(module, "pytest_generate_tests"):305 methods.append(module.pytest_generate_tests)306 if hasattr(cls, "pytest_generate_tests"):307 methods.append(cls().pytest_generate_tests)308 if methods:309 self.ihook.pytest_generate_tests.call_extra(methods,310 dict(metafunc=metafunc))311 else:312 self.ihook.pytest_generate_tests(metafunc=metafunc)313 Function = self._getcustomclass("Function")314 if not metafunc._calls:315 yield Function(name, parent=self, fixtureinfo=fixtureinfo)316 else:317 # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs318 fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm)319 for callspec in metafunc._calls:320 subname = "%s[%s]" % (name, callspec.id)321 yield Function(name=subname, parent=self,322 callspec=callspec, callobj=funcobj,323 fixtureinfo=fixtureinfo,324 keywords={callspec.id: True},325 originalname=name,326 )327class Module(main.File, PyCollector):328 """ Collector for test classes and functions. """329 def _getobj(self):330 return self._importtestmodule()331 def collect(self):332 self.session._fixturemanager.parsefactories(self)333 return super(Module, self).collect()334 def _importtestmodule(self):335 # we assume we are only called once per module336 importmode = self.config.getoption("--import-mode")337 try:338 mod = self.fspath.pyimport(ensuresyspath=importmode)339 except SyntaxError:340 raise self.CollectError(341 _pytest._code.ExceptionInfo().getrepr(style="short"))342 except self.fspath.ImportMismatchError:343 e = sys.exc_info()[1]344 raise self.CollectError(345 "import file mismatch:\n"346 "imported module %r has this __file__ attribute:\n"347 " %s\n"348 "which is not the same as the test file we want to collect:\n"349 " %s\n"350 "HINT: remove __pycache__ / .pyc files and/or use a "351 "unique basename for your test file modules"352 % e.args353 )354 except ImportError:355 from _pytest._code.code import ExceptionInfo356 exc_info = ExceptionInfo()357 if self.config.getoption('verbose') < 2:358 exc_info.traceback = exc_info.traceback.filter(filter_traceback)359 exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly()360 formatted_tb = safe_str(exc_repr)361 raise self.CollectError(362 "ImportError while importing test module '{fspath}'.\n"363 "Hint: make sure your test modules/packages have valid Python names.\n"364 "Traceback:\n"365 "{traceback}".format(fspath=self.fspath, traceback=formatted_tb)366 )367 except _pytest.runner.Skipped as e:368 if e.allow_module_level:369 raise370 raise self.CollectError(371 "Using pytest.skip outside of a test is not allowed. "372 "To decorate a test function, use the @pytest.mark.skip "373 "or @pytest.mark.skipif decorators instead, and to skip a "374 "module use `pytestmark = pytest.mark.{skip,skipif}."375 )376 self.config.pluginmanager.consider_module(mod)377 return mod378 def setup(self):379 setup_module = _get_xunit_setup_teardown(self.obj, "setUpModule")380 if setup_module is None:381 setup_module = _get_xunit_setup_teardown(self.obj, "setup_module")382 if setup_module is not None:383 setup_module()384 teardown_module = _get_xunit_setup_teardown(self.obj, 'tearDownModule')385 if teardown_module is None:386 teardown_module = _get_xunit_setup_teardown(self.obj, 'teardown_module')387 if teardown_module is not None:388 self.addfinalizer(teardown_module)389def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):390 """391 Return a callable to perform xunit-style setup or teardown if392 the function exists in the ``holder`` object.393 The ``param_obj`` parameter is the parameter which will be passed to the function394 when the callable is called without arguments, defaults to the ``holder`` object.395 Return ``None`` if a suitable callable is not found.396 """397 param_obj = param_obj if param_obj is not None else holder398 result = _get_xunit_func(holder, attr_name)399 if result is not None:400 arg_count = result.__code__.co_argcount401 if inspect.ismethod(result):402 arg_count -= 1403 if arg_count:404 return lambda: result(param_obj)405 else:406 return result407def _get_xunit_func(obj, name):408 """Return the attribute from the given object to be used as a setup/teardown409 xunit-style function, but only if not marked as a fixture to410 avoid calling it twice.411 """412 meth = getattr(obj, name, None)413 if fixtures.getfixturemarker(meth) is None:414 return meth415class Class(PyCollector):416 """ Collector for test methods. """417 def collect(self):418 if not safe_getattr(self.obj, "__test__", True):419 return []420 if hasinit(self.obj):421 self.warn("C1", "cannot collect test class %r because it has a "422 "__init__ constructor" % self.obj.__name__)423 return []424 elif hasnew(self.obj):425 self.warn("C1", "cannot collect test class %r because it has a "426 "__new__ constructor" % self.obj.__name__)427 return []428 return [self._getcustomclass("Instance")(name="()", parent=self)]429 def setup(self):430 setup_class = _get_xunit_func(self.obj, 'setup_class')431 if setup_class is not None:432 setup_class = getattr(setup_class, 'im_func', setup_class)433 setup_class = getattr(setup_class, '__func__', setup_class)434 setup_class(self.obj)435 fin_class = getattr(self.obj, 'teardown_class', None)436 if fin_class is not None:437 fin_class = getattr(fin_class, 'im_func', fin_class)438 fin_class = getattr(fin_class, '__func__', fin_class)439 self.addfinalizer(lambda: fin_class(self.obj))440class Instance(PyCollector):441 def _getobj(self):442 return self.parent.obj()443 def collect(self):444 self.session._fixturemanager.parsefactories(self)445 return super(Instance, self).collect()446 def newinstance(self):447 self.obj = self._getobj()448 return self.obj449class FunctionMixin(PyobjMixin):450 """ mixin for the code common to Function and Generator.451 """452 def setup(self):453 """ perform setup for this test function. """454 if hasattr(self, '_preservedparent'):455 obj = self._preservedparent456 elif isinstance(self.parent, Instance):457 obj = self.parent.newinstance()458 self.obj = self._getobj()459 else:460 obj = self.parent.obj461 if inspect.ismethod(self.obj):462 setup_name = 'setup_method'463 teardown_name = 'teardown_method'464 else:465 setup_name = 'setup_function'466 teardown_name = 'teardown_function'467 setup_func_or_method = _get_xunit_setup_teardown(obj, setup_name, param_obj=self.obj)468 if setup_func_or_method is not None:469 setup_func_or_method()470 teardown_func_or_method = _get_xunit_setup_teardown(obj, teardown_name, param_obj=self.obj)471 if teardown_func_or_method is not None:472 self.addfinalizer(teardown_func_or_method)473 def _prunetraceback(self, excinfo):474 if hasattr(self, '_obj') and not self.config.option.fulltrace:475 code = _pytest._code.Code(get_real_func(self.obj))476 path, firstlineno = code.path, code.firstlineno477 traceback = excinfo.traceback478 ntraceback = traceback.cut(path=path, firstlineno=firstlineno)479 if ntraceback == traceback:480 ntraceback = ntraceback.cut(path=path)481 if ntraceback == traceback:482 # ntraceback = ntraceback.cut(excludepath=cutdir2)483 ntraceback = ntraceback.filter(filter_traceback)484 if not ntraceback:485 ntraceback = traceback486 excinfo.traceback = ntraceback.filter()487 # issue364: mark all but first and last frames to488 # only show a single-line message for each frame489 if self.config.option.tbstyle == "auto":490 if len(excinfo.traceback) > 2:491 for entry in excinfo.traceback[1:-1]:492 entry.set_repr_style('short')493 def _repr_failure_py(self, excinfo, style="long"):494 if excinfo.errisinstance(fail.Exception):495 if not excinfo.value.pytrace:496 return py._builtin._totext(excinfo.value)497 return super(FunctionMixin, self)._repr_failure_py(excinfo,498 style=style)499 def repr_failure(self, excinfo, outerr=None):500 assert outerr is None, "XXX outerr usage is deprecated"501 style = self.config.option.tbstyle502 if style == "auto":503 style = "long"504 return self._repr_failure_py(excinfo, style=style)505class Generator(FunctionMixin, PyCollector):506 def collect(self):507 # test generators are seen as collectors but they also508 # invoke setup/teardown on popular request509 # (induced by the common "test_*" naming shared with normal tests)510 from _pytest import deprecated511 self.session._setupstate.prepare(self)512 # see FunctionMixin.setup and test_setupstate_is_preserved_134513 self._preservedparent = self.parent.obj514 values = []515 seen = {}516 for i, x in enumerate(self.obj()):517 name, call, args = self.getcallargs(x)518 if not callable(call):519 raise TypeError("%r yielded non callable test %r" % (self.obj, call,))520 if name is None:521 name = "[%d]" % i522 else:523 name = "['%s']" % name524 if name in seen:525 raise ValueError("%r generated tests with non-unique name %r" % (self, name))526 seen[name] = True527 values.append(self.Function(name, self, args=args, callobj=call))528 self.warn('C1', deprecated.YIELD_TESTS)529 return values530 def getcallargs(self, obj):531 if not isinstance(obj, (tuple, list)):532 obj = (obj,)533 # explicit naming534 if isinstance(obj[0], py.builtin._basestring):535 name = obj[0]536 obj = obj[1:]537 else:538 name = None539 call, args = obj[0], obj[1:]540 return name, call, args541def hasinit(obj):542 init = getattr(obj, '__init__', None)543 if init:544 return init != object.__init__545def hasnew(obj):546 new = getattr(obj, '__new__', None)547 if new:548 return new != object.__new__549class CallSpec2(object):550 def __init__(self, metafunc):551 self.metafunc = metafunc552 self.funcargs = {}553 self._idlist = []554 self.params = {}555 self._globalid = NOTSET556 self._globalid_args = set()557 self._globalparam = NOTSET558 self._arg2scopenum = {} # used for sorting parametrized resources559 self.keywords = {}560 self.indices = {}561 def copy(self, metafunc):562 cs = CallSpec2(self.metafunc)563 cs.funcargs.update(self.funcargs)564 cs.params.update(self.params)565 cs.keywords.update(self.keywords)566 cs.indices.update(self.indices)567 cs._arg2scopenum.update(self._arg2scopenum)568 cs._idlist = list(self._idlist)569 cs._globalid = self._globalid570 cs._globalid_args = self._globalid_args571 cs._globalparam = self._globalparam572 return cs573 def _checkargnotcontained(self, arg):574 if arg in self.params or arg in self.funcargs:575 raise ValueError("duplicate %r" % (arg,))576 def getparam(self, name):577 try:578 return self.params[name]579 except KeyError:580 if self._globalparam is NOTSET:581 raise ValueError(name)582 return self._globalparam583 @property584 def id(self):585 return "-".join(map(str, filter(None, self._idlist)))586 def setmulti(self, valtypes, argnames, valset, id, keywords, scopenum,587 param_index):588 for arg, val in zip(argnames, valset):589 self._checkargnotcontained(arg)590 valtype_for_arg = valtypes[arg]591 getattr(self, valtype_for_arg)[arg] = val592 self.indices[arg] = param_index593 self._arg2scopenum[arg] = scopenum594 self._idlist.append(id)595 self.keywords.update(keywords)596 def setall(self, funcargs, id, param):597 for x in funcargs:598 self._checkargnotcontained(x)599 self.funcargs.update(funcargs)600 if id is not NOTSET:601 self._idlist.append(id)602 if param is not NOTSET:603 assert self._globalparam is NOTSET604 self._globalparam = param605 for arg in funcargs:606 self._arg2scopenum[arg] = fixtures.scopenum_function607class Metafunc(fixtures.FuncargnamesCompatAttr):608 """609 Metafunc objects are passed to the ``pytest_generate_tests`` hook.610 They help to inspect a test function and to generate tests according to611 test configuration or values specified in the class or module where a612 test function is defined.613 """614 def __init__(self, function, fixtureinfo, config, cls=None, module=None):615 #: access to the :class:`_pytest.config.Config` object for the test session616 self.config = config617 #: the module object where the test function is defined in.618 self.module = module619 #: underlying python test function620 self.function = function621 #: set of fixture names required by the test function622 self.fixturenames = fixtureinfo.names_closure623 #: class object where the test function is defined in or ``None``.624 self.cls = cls625 self._calls = []626 self._ids = py.builtin.set()627 self._arg2fixturedefs = fixtureinfo.name2fixturedefs628 def parametrize(self, argnames, argvalues, indirect=False, ids=None,629 scope=None):630 """ Add new invocations to the underlying test function using the list631 of argvalues for the given argnames. Parametrization is performed632 during the collection phase. If you need to setup expensive resources633 see about setting indirect to do it rather at test setup time.634 :arg argnames: a comma-separated string denoting one or more argument635 names, or a list/tuple of argument strings.636 :arg argvalues: The list of argvalues determines how often a637 test is invoked with different argument values. If only one638 argname was specified argvalues is a list of values. If N639 argnames were specified, argvalues must be a list of N-tuples,640 where each tuple-element specifies a value for its respective641 argname.642 :arg indirect: The list of argnames or boolean. A list of arguments'643 names (subset of argnames). If True the list contains all names from644 the argnames. Each argvalue corresponding to an argname in this list will645 be passed as request.param to its respective argname fixture646 function so that it can perform more expensive setups during the647 setup phase of a test rather than at collection time.648 :arg ids: list of string ids, or a callable.649 If strings, each is corresponding to the argvalues so that they are650 part of the test id. If None is given as id of specific test, the651 automatically generated id for that argument will be used.652 If callable, it should take one argument (a single argvalue) and return653 a string or return None. If None, the automatically generated id for that654 argument will be used.655 If no ids are provided they will be generated automatically from656 the argvalues.657 :arg scope: if specified it denotes the scope of the parameters.658 The scope is used for grouping tests by parameter instances.659 It will also override any fixture-function defined scope, allowing660 to set a dynamic scope using test context or configuration.661 """662 from _pytest.fixtures import scope2index663 from _pytest.mark import MARK_GEN, ParameterSet664 from py.io import saferepr665 if not isinstance(argnames, (tuple, list)):666 argnames = [x.strip() for x in argnames.split(",") if x.strip()]667 force_tuple = len(argnames) == 1668 else:669 force_tuple = False670 parameters = [671 ParameterSet.extract_from(x, legacy_force_tuple=force_tuple)672 for x in argvalues]673 del argvalues674 if not parameters:675 fs, lineno = getfslineno(self.function)676 reason = "got empty parameter set %r, function %s at %s:%d" % (677 argnames, self.function.__name__, fs, lineno)678 mark = MARK_GEN.skip(reason=reason)679 parameters.append(ParameterSet(680 values=(NOTSET,) * len(argnames),681 marks=[mark],682 id=None,683 ))684 if scope is None:685 scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)686 scopenum = scope2index(scope, descr='call to {0}'.format(self.parametrize))687 valtypes = {}688 for arg in argnames:689 if arg not in self.fixturenames:690 if isinstance(indirect, (tuple, list)):691 name = 'fixture' if arg in indirect else 'argument'692 else:693 name = 'fixture' if indirect else 'argument'694 raise ValueError(695 "%r uses no %s %r" % (696 self.function, name, arg))697 if indirect is True:698 valtypes = dict.fromkeys(argnames, "params")699 elif indirect is False:700 valtypes = dict.fromkeys(argnames, "funcargs")701 elif isinstance(indirect, (tuple, list)):702 valtypes = dict.fromkeys(argnames, "funcargs")703 for arg in indirect:704 if arg not in argnames:705 raise ValueError("indirect given to %r: fixture %r doesn't exist" % (706 self.function, arg))707 valtypes[arg] = "params"708 idfn = None709 if callable(ids):710 idfn = ids711 ids = None712 if ids:713 if len(ids) != len(parameters):714 raise ValueError('%d tests specified with %d ids' % (715 len(parameters), len(ids)))716 for id_value in ids:717 if id_value is not None and not isinstance(id_value, py.builtin._basestring):718 msg = 'ids must be list of strings, found: %s (type: %s)'719 raise ValueError(msg % (saferepr(id_value), type(id_value).__name__))720 ids = idmaker(argnames, parameters, idfn, ids, self.config)721 newcalls = []722 for callspec in self._calls or [CallSpec2(self)]:723 elements = zip(ids, parameters, count())724 for a_id, param, param_index in elements:725 if len(param.values) != len(argnames):726 raise ValueError(727 'In "parametrize" the number of values ({0}) must be '728 'equal to the number of names ({1})'.format(729 param.values, argnames))730 newcallspec = callspec.copy(self)731 newcallspec.setmulti(valtypes, argnames, param.values, a_id,732 param.deprecated_arg_dict, scopenum, param_index)733 newcalls.append(newcallspec)734 self._calls = newcalls735 def addcall(self, funcargs=None, id=NOTSET, param=NOTSET):736 """ (deprecated, use parametrize) Add a new call to the underlying737 test function during the collection phase of a test run. Note that738 request.addcall() is called during the test collection phase prior and739 independently to actual test execution. You should only use addcall()740 if you need to specify multiple arguments of a test function.741 :arg funcargs: argument keyword dictionary used when invoking742 the test function.743 :arg id: used for reporting and identification purposes. If you744 don't supply an `id` an automatic unique id will be generated.745 :arg param: a parameter which will be exposed to a later fixture function746 invocation through the ``request.param`` attribute.747 """748 assert funcargs is None or isinstance(funcargs, dict)749 if funcargs is not None:750 for name in funcargs:751 if name not in self.fixturenames:752 fail("funcarg %r not used in this function." % name)753 else:754 funcargs = {}755 if id is None:756 raise ValueError("id=None not allowed")757 if id is NOTSET:758 id = len(self._calls)759 id = str(id)760 if id in self._ids:761 raise ValueError("duplicate id %r" % id)762 self._ids.add(id)763 cs = CallSpec2(self)764 cs.setall(funcargs, id, param)765 self._calls.append(cs)766def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):767 """Find the most appropriate scope for a parametrized call based on its arguments.768 When there's at least one direct argument, always use "function" scope.769 When a test function is parametrized and all its arguments are indirect770 (e.g. fixtures), return the most narrow scope based on the fixtures used.771 Related to issue #1832, based on code posted by @Kingdread.772 """773 from _pytest.fixtures import scopes774 indirect_as_list = isinstance(indirect, (list, tuple))775 all_arguments_are_fixtures = indirect is True or \776 indirect_as_list and len(indirect) == argnames777 if all_arguments_are_fixtures:778 fixturedefs = arg2fixturedefs or {}779 used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]780 if used_scopes:781 # Takes the most narrow scope from used fixtures782 for scope in reversed(scopes):783 if scope in used_scopes:784 return scope785 return 'function'786def _idval(val, argname, idx, idfn, config=None):787 if idfn:788 s = None789 try:790 s = idfn(val)791 except Exception:792 # See issue https://github.com/pytest-dev/pytest/issues/2169793 import warnings794 msg = "Raised while trying to determine id of parameter %s at position %d." % (argname, idx)795 msg += '\nUpdate your code as this will raise an error in pytest-4.0.'796 warnings.warn(msg, DeprecationWarning)797 if s:798 return _ascii_escaped(s)799 if config:800 hook_id = config.hook.pytest_make_parametrize_id(801 config=config, val=val, argname=argname)802 if hook_id:803 return hook_id804 if isinstance(val, STRING_TYPES):805 return _ascii_escaped(val)806 elif isinstance(val, (float, int, bool, NoneType)):807 return str(val)808 elif isinstance(val, REGEX_TYPE):809 return _ascii_escaped(val.pattern)810 elif enum is not None and isinstance(val, enum.Enum):811 return str(val)812 elif isclass(val) and hasattr(val, '__name__'):813 return val.__name__814 return str(argname) + str(idx)815def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):816 if parameterset.id is not None:817 return parameterset.id818 if ids is None or (idx >= len(ids) or ids[idx] is None):819 this_id = [_idval(val, argname, idx, idfn, config)820 for val, argname in zip(parameterset.values, argnames)]821 return "-".join(this_id)822 else:823 return _ascii_escaped(ids[idx])824def idmaker(argnames, parametersets, idfn=None, ids=None, config=None):825 ids = [_idvalset(valindex, parameterset, argnames, idfn, ids, config)826 for valindex, parameterset in enumerate(parametersets)]827 if len(set(ids)) != len(ids):828 # The ids are not unique829 duplicates = [testid for testid in ids if ids.count(testid) > 1]830 counters = collections.defaultdict(lambda: 0)831 for index, testid in enumerate(ids):832 if testid in duplicates:833 ids[index] = testid + str(counters[testid])834 counters[testid] += 1835 return ids836def show_fixtures_per_test(config):837 from _pytest.main import wrap_session838 return wrap_session(config, _show_fixtures_per_test)839def _show_fixtures_per_test(config, session):840 import _pytest.config841 session.perform_collect()842 curdir = py.path.local()843 tw = _pytest.config.create_terminal_writer(config)844 verbose = config.getvalue("verbose")845 def get_best_relpath(func):846 loc = getlocation(func, curdir)847 return curdir.bestrelpath(loc)848 def write_fixture(fixture_def):849 argname = fixture_def.argname850 if verbose <= 0 and argname.startswith("_"):851 return852 if verbose > 0:853 bestrel = get_best_relpath(fixture_def.func)854 funcargspec = "{0} -- {1}".format(argname, bestrel)855 else:856 funcargspec = argname857 tw.line(funcargspec, green=True)858 fixture_doc = fixture_def.func.__doc__859 if fixture_doc:860 write_docstring(tw, fixture_doc)861 else:862 tw.line(' no docstring available', red=True)863 def write_item(item):864 try:865 info = item._fixtureinfo866 except AttributeError:867 # doctests items have no _fixtureinfo attribute868 return869 if not info.name2fixturedefs:870 # this test item does not use any fixtures871 return872 tw.line()873 tw.sep('-', 'fixtures used by {0}'.format(item.name))874 tw.sep('-', '({0})'.format(get_best_relpath(item.function)))875 # dict key not used in loop but needed for sorting876 for _, fixturedefs in sorted(info.name2fixturedefs.items()):877 assert fixturedefs is not None878 if not fixturedefs:879 continue880 # last item is expected to be the one used by the test item881 write_fixture(fixturedefs[-1])882 for session_item in session.items:883 write_item(session_item)884def showfixtures(config):885 from _pytest.main import wrap_session886 return wrap_session(config, _showfixtures_main)887def _showfixtures_main(config, session):888 import _pytest.config889 session.perform_collect()890 curdir = py.path.local()891 tw = _pytest.config.create_terminal_writer(config)892 verbose = config.getvalue("verbose")893 fm = session._fixturemanager894 available = []895 seen = set()896 for argname, fixturedefs in fm._arg2fixturedefs.items():897 assert fixturedefs is not None898 if not fixturedefs:...
fixtures.py
Source:fixtures.py
1'''2 This program is free software: you can redistribute it and/or modify3 it under the terms of the GNU General Public License as published by4 the Free Software Foundation, either version 3 of the License, or5 (at your option) any later version.6 This program is distributed in the hope that it will be useful,7 but WITHOUT ANY WARRANTY; without even the implied warranty of8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9 GNU General Public License for more details.10 You should have received a copy of the GNU General Public License11 along with this program. If not, see <http://www.gnu.org/licenses/>.12'''13''' This script is part of the BBC Football Scores service by elParaguayo14 It allows users to select which leagues they wish to receive updates15 for.16 It is called via the script configuration screen or by passing17 parameters to trigger specific functions.18 The script accepts the following parameters:19 toggle: Turns score notifications on and off20 reset: Resets watched league data21 NB only one parameter should be passed at a time.22'''23import sys24if sys.version_info >= (2, 7):25 import json as json26 from collections import OrderedDict27else:28 import simplejson as json29 from resources.lib.ordereddict import OrderedDict30import xbmc31import xbmcgui32import xbmcaddon33from resources.lib.footballscores import Fixtures34from resources.lib.utils import closeAddonSettings35# Import PyXBMCt module.36from pyxbmct.addonwindow import *37_A_ = xbmcaddon.Addon("service.bbclivefootballscores")38_S_ = _A_.getSetting39def localise(id):40 '''Gets localised string.41 Shamelessly copied from service.xbmc.versioncheck42 '''43 string = _A_.getLocalizedString(id).encode( 'utf-8', 'ignore' )44 return string45class XBMCFixtures(object):46 def __init__(self):47 # It may take a bit of time to display menus/fixtures so let's48 # make sure the user knows what's going on49 self.prog = xbmcgui.DialogProgressBG()50 self.prog.create(localise(32114), localise(32107))51 # variables for league fixtures display52 self.redraw = False53 self.offset = 054 self.menu = True55 self.leagueid = 056 # variables for root menu57 self.showall = True58 self.active = True59 # Get our favourite leagues60 self.watchedleagues = json.loads(str(_S_("watchedleagues")))61 # Create a Fixtures instance62 self.fixtures = Fixtures()63 self.prog.update(25, localise(32108))64 allcomps = self.fixtures.getCompetitions()65 allcomps = [x for x in allcomps if x["id"][:11] == "competition"]66 # Get all of the available leagues, store it in an Ordered Dict67 # key=League name68 # value=League ID69 self.allleagues = OrderedDict((x["name"],70 x["id"][-9:])71 for x in allcomps)72 self.prog.update(75, localise(32109))73 # Create a similar Ordered Dict for just those leagues that we're74 # currently followin75 lgid = x["id"][-9:]76 self.watchedleagues = OrderedDict((x["name"], x["id"][-9:])77 for x in allcomps78 if (unicode(lgid).isnumeric() and79 int(lgid) in self.watchedleagues))80 self.prog.close()81 def showMenu(self, all_leagues=False):82 # Setting this to False means that the menu won't display if83 # we hit escape84 self.active = False85 # Set the title and menu size86 window = AddonDialogWindow(localise(32100))87 window.setGeometry(450,300,5,4)88 # Create a List object89 self.leaguelist = List()90 # Get the appropriate list of leagues depending on what mode we're in91 displaylist = self.allleagues if self.showall else self.watchedleagues92 #self.prog.update(92)93 # Add the List to the menu94 window.placeControl(self.leaguelist, 0, 0, rowspan=4, columnspan=4)95 self.leaguelist.addItems(displaylist.keys())96 # Bind the list action97 p = self.leaguelist.getSelectedPosition98 window.connect(self.leaguelist,99 lambda w = window:100 self.setID(self.leaguelist.getListItem(p()).getLabel(),101 w))102 # Don't think these are needed, but what the hell...103 window.connect(ACTION_PREVIOUS_MENU, lambda w=window: self.finish(w))104 window.connect(ACTION_NAV_BACK, lambda w=window: self.finish(w))105 #self.prog.update(94)106 # Create the button to toggle mode107 leaguetext = localise(32101) if self.showall else localise(32102)108 self.leaguebutton = Button(leaguetext)109 window.placeControl(self.leaguebutton, 4, 0, columnspan=2)110 # Bind the button111 window.connect(self.leaguebutton, lambda w=window: self.toggleMode(w))112 #self.prog.update(96)113 # Add the close button114 self.closebutton = Button(localise(32103))115 window.placeControl(self.closebutton, 4, 2, columnspan=2)116 window.setFocus(self.leaguelist)117 # Connect the button to a function.118 window.connect(self.closebutton, lambda w=window:self.finish(w))119 #self.prog.update(98)120 # Handle navigation to make user experience better121 self.leaguelist.controlLeft(self.leaguebutton)122 self.leaguelist.controlRight(self.closebutton)123 self.closebutton.controlUp(self.leaguelist)124 self.closebutton.controlLeft(self.leaguebutton)125 self.leaguebutton.controlRight(self.closebutton)126 self.leaguebutton.controlUp(self.leaguelist)127 # Ready to go...128 window.doModal()129 # Clean up130 window = None131 def showFixtures(self):132 # Basic variables133 self.redraw = False134 # If there are multiple fixture dates for a competition135 # Let's just get the required one136 fixtures = self.rawdata[self.offset]137 #self.prog.update(92)138 # How many fixtures are there on this date?139 # We'll need this to set the size of the display140 n = len(fixtures["fixtures"])141 # Create a window instance and size it142 window = AddonDialogWindow(fixtures["date"])143 window.setGeometry(450, (n + 4) * 30, n + 3, 11)144 #self.prog.update(94)145 # Add the teams146 for i,f in enumerate(fixtures["fixtures"]):147 home = Label(u"{hometeam}".format(**f), alignment=1)148 vlab = Label("v", alignment=2)149 away = Label(u"{awayteam}".format(**f))150 window.placeControl(home, i+1, 0, columnspan=5)151 window.placeControl(vlab, i+1, 5)152 window.placeControl(away, i+1, 6, columnspan=5)153 #self.prog.update(94)154 # Add the close button155 closebutton = Button(localise(32103))156 window.placeControl(closebutton, n+2, 4, columnspan=3)157 window.setFocus(closebutton)158 # Connect the button to a function.159 window.connect(closebutton, lambda w=window: self.finish(w))160 # Not sure we need these...161 window.connect(ACTION_PREVIOUS_MENU, lambda w=window: self.finish(w))162 window.connect(ACTION_NAV_BACK, lambda w=window: self.finish(w))163 #self.prog.update(96)164 # We may need some extra buttons165 nextbutton = Button(localise(32104))166 prevbutton = Button(localise(32105))167 # There are more fixtures after the ones we're showing168 if self.offset < (len(self.rawdata) - 1):169 window.placeControl(nextbutton, n+2, 7, columnspan=4)170 window.connect(nextbutton, lambda w=window: self.next(w))171 nextbutton.controlLeft(closebutton)172 closebutton.controlRight(nextbutton)173 # There are more fixtures before the ones we're showing174 if self.offset > 0:175 window.placeControl(prevbutton, n+2, 0, columnspan=4)176 window.connect(prevbutton, lambda w=window: self.previous(w))177 prevbutton.controlRight(closebutton)178 closebutton.controlLeft(prevbutton)179 #self.prog.close()180 # Ready to go...181 window.doModal()182 # Clean up183 window = None184 def getFixturesData(self, ID):185 self.prog.create(localise(32114), localise(32115))186 try:187 raw = self.fixtures.getFixtures("competition-%s"188 % (self.leagueid))189 except:190 print "ERROR"191 raw = None192 self.prog.close()193 return raw194 def setID(self, ID, w):195 # Gets the ID of the selected league196 ID = self.allleagues[ID]197 self.setleague(ID,w)198 def next(self,w):199 # Display the next fixture day in the competion200 self.offset += 1201 self.redraw = True202 w.close()203 def previous(self,w):204 # Display the previous fixture day the competition205 self.offset -= 1206 self.redraw = True207 w.close()208 def finish(self,w):209 # We're done. Gracefully close down menu.210 self.redraw = False211 self.menu = False212 self.active = False213 w.close()214 def setleague(self,lg, w):215 # Set up the variables to display the league fixtures216 self.leagueid = lg217 self.offset = 0218 self.redraw = True219 w.close()220 self.rawdata = self.getFixturesData(self.leagueid)221 self.prog.update(90)222 def toggleMode(self,w):223 # Toggle between showing all competitions and just our favourites224 self.showall = not self.showall225 self.active = True226 w.close()227 def start(self):228 # Let's begin229 while self.active:230 # Show the main menu231 self.showMenu()232 while self.redraw:233 # Show fixtures234 self.showFixtures()235if __name__ == "__main__":236 # Close addon setting window (if open)237 closeAddonSettings()238 # Create an instance of the XBMC Fixtures239 xf = XBMCFixtures()240 # and display it!...
test_showfixtures_command.py
Source:test_showfixtures_command.py
...103 ]104 # no missing permissions105 mock_get_permissions.side_effect = [[], [], []]106 assert command.missing_permissions() == []107def test_showfixtures(capsys, mocker):108 mocker.patch(109 'django_north.management.commands.showfixtures.Command'110 '.unknown_contenttypes',111 return_value=['DELETE 1', 'DELETE 2', 'DELETE 3'])112 mocker.patch(113 'django_north.management.commands.showfixtures.Command'114 '.missing_contenttypes',115 return_value=['INSERT 1', 'INSERT 2', 'INSERT 3'])116 mocker.patch(117 'django_north.management.commands.showfixtures.Command'118 '.missing_permissions',119 return_value=['INSERT 4', 'INSERT 5', 'INSERT 6'])120 call_command('showfixtures')121 captured = capsys.readouterr()...
test_pytest.py
Source:test_pytest.py
1from copy import copy2from _pytest.python import _showfixtures_main3def test_pytest_fixtures(request):4 """Running `py.test --fixtures` should not fail5 """6 #7 # Use a copy of the session, so as not to interfere with collection stats.8 #9 # If the actual session are is used, pytest will exit with code 5:10 # no tests collected. This causes the Travis build to be marked as failed.11 #12 session = copy(request.session)13 try:14 _showfixtures_main(request.config, session)15 except Exception as e:...
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.
Skim our below pytest tutorial playlist to get started with automation testing using the pytest framework.
https://www.youtube.com/playlist?list=PLZMWkkQEwOPlcGgDmHl8KkXKeLF83XlrP
Get 100 minutes of automation test minutes FREE!!