From bc2247219f5aae1f8e05ccc913bbb49fe4384d7c Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 5 Jun 2018 09:06:43 +0200 Subject: [PATCH 01/31] turn config into package this prepares the splitting --- setup.py | 8 +++++++- src/_pytest/{config.py => config/__init__.py} | 0 2 files changed, 7 insertions(+), 1 deletion(-) rename src/_pytest/{config.py => config/__init__.py} (100%) diff --git a/setup.py b/setup.py index 3f5ed39be..69692198f 100644 --- a/setup.py +++ b/setup.py @@ -109,7 +109,13 @@ def main(): python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", install_requires=install_requires, extras_require=extras_require, - packages=["_pytest", "_pytest.assertion", "_pytest._code", "_pytest.mark"], + packages=[ + "_pytest", + "_pytest.assertion", + "_pytest._code", + "_pytest.mark", + "_pytest.config", + ], py_modules=["pytest"], zip_safe=False, ) diff --git a/src/_pytest/config.py b/src/_pytest/config/__init__.py similarity index 100% rename from src/_pytest/config.py rename to src/_pytest/config/__init__.py From 026cd36237f75ee8b4c858dc6530ebfcdc117d24 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 5 Jun 2018 09:40:50 +0200 Subject: [PATCH 02/31] make builtin plugins a list --- src/_pytest/config/__init__.py | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 53e74cf1c..96a9cec4b 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -107,11 +107,33 @@ def directory_arg(path, optname): default_plugins = ( - "mark main terminal runner python fixtures debugging unittest capture skipping " - "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion " - "junitxml resultlog doctest cacheprovider freeze_support " - "setuponly setupplan warnings logging" -).split() + "mark", + "main", + "terminal", + "runner", + "python", + "fixtures", + "debugging", + "unittest", + "capture", + "skipping", + "tmpdir", + "monkeypatch", + "recwarn", + "pastebin", + "helpconfig", + "nose", + "assertion", + "junitxml", + "resultlog", + "doctest", + "cacheprovider", + "freeze_support", + "setuponly", + "setupplan", + "warnings", + "logging", +) builtin_plugins = set(default_plugins) From c9df77cbd6a365dcb73c39618e4842711817e871 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 5 Jun 2018 09:55:28 +0200 Subject: [PATCH 03/31] move argument parser to own file --- src/_pytest/config/__init__.py | 392 +----------------------------- src/_pytest/config/argparsing.py | 394 +++++++++++++++++++++++++++++++ 2 files changed, 396 insertions(+), 390 deletions(-) create mode 100644 src/_pytest/config/argparsing.py diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 96a9cec4b..3423a7091 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -518,395 +518,6 @@ def _get_plugin_specs_as_list(specs): return [] -class Parser(object): - """ Parser for command line arguments and ini-file values. - - :ivar extra_info: dict of generic param -> value to display in case - there's an error processing the command line arguments. - """ - - def __init__(self, usage=None, processopt=None): - self._anonymous = OptionGroup("custom options", parser=self) - self._groups = [] - self._processopt = processopt - self._usage = usage - self._inidict = {} - self._ininames = [] - self.extra_info = {} - - def processoption(self, option): - if self._processopt: - if option.dest: - self._processopt(option) - - def getgroup(self, name, description="", after=None): - """ get (or create) a named option Group. - - :name: name of the option group. - :description: long description for --help output. - :after: name of other group, used for ordering --help output. - - The returned group object has an ``addoption`` method with the same - signature as :py:func:`parser.addoption - <_pytest.config.Parser.addoption>` but will be shown in the - respective group in the output of ``pytest. --help``. - """ - for group in self._groups: - if group.name == name: - return group - group = OptionGroup(name, description, parser=self) - i = 0 - for i, grp in enumerate(self._groups): - if grp.name == after: - break - self._groups.insert(i + 1, group) - return group - - def addoption(self, *opts, **attrs): - """ register a command line option. - - :opts: option names, can be short or long options. - :attrs: same attributes which the ``add_option()`` function of the - `argparse library - `_ - accepts. - - After command line parsing options are available on the pytest config - object via ``config.option.NAME`` where ``NAME`` is usually set - by passing a ``dest`` attribute, for example - ``addoption("--long", dest="NAME", ...)``. - """ - self._anonymous.addoption(*opts, **attrs) - - def parse(self, args, namespace=None): - from _pytest._argcomplete import try_argcomplete - - self.optparser = self._getparser() - try_argcomplete(self.optparser) - return self.optparser.parse_args([str(x) for x in args], namespace=namespace) - - def _getparser(self): - from _pytest._argcomplete import filescompleter - - optparser = MyOptionParser(self, self.extra_info) - groups = self._groups + [self._anonymous] - for group in groups: - if group.options: - desc = group.description or group.name - arggroup = optparser.add_argument_group(desc) - for option in group.options: - n = option.names() - a = option.attrs() - arggroup.add_argument(*n, **a) - # bash like autocompletion for dirs (appending '/') - optparser.add_argument(FILE_OR_DIR, nargs="*").completer = filescompleter - return optparser - - def parse_setoption(self, args, option, namespace=None): - parsedoption = self.parse(args, namespace=namespace) - for name, value in parsedoption.__dict__.items(): - setattr(option, name, value) - return getattr(parsedoption, FILE_OR_DIR) - - def parse_known_args(self, args, namespace=None): - """parses and returns a namespace object with known arguments at this - point. - """ - return self.parse_known_and_unknown_args(args, namespace=namespace)[0] - - def parse_known_and_unknown_args(self, args, namespace=None): - """parses and returns a namespace object with known arguments, and - the remaining arguments unknown at this point. - """ - optparser = self._getparser() - args = [str(x) for x in args] - return optparser.parse_known_args(args, namespace=namespace) - - def addini(self, name, help, type=None, default=None): - """ register an ini-file option. - - :name: name of the ini-variable - :type: type of the variable, can be ``pathlist``, ``args``, ``linelist`` - or ``bool``. - :default: default value if no ini-file option exists but is queried. - - The value of ini-variables can be retrieved via a call to - :py:func:`config.getini(name) <_pytest.config.Config.getini>`. - """ - assert type in (None, "pathlist", "args", "linelist", "bool") - self._inidict[name] = (help, type, default) - self._ininames.append(name) - - -class ArgumentError(Exception): - """ - Raised if an Argument instance is created with invalid or - inconsistent arguments. - """ - - def __init__(self, msg, option): - self.msg = msg - self.option_id = str(option) - - def __str__(self): - if self.option_id: - return "option %s: %s" % (self.option_id, self.msg) - else: - return self.msg - - -class Argument(object): - """class that mimics the necessary behaviour of optparse.Option - - its currently a least effort implementation - and ignoring choices and integer prefixes - https://docs.python.org/3/library/optparse.html#optparse-standard-option-types - """ - _typ_map = {"int": int, "string": str, "float": float, "complex": complex} - - def __init__(self, *names, **attrs): - """store parms in private vars for use in add_argument""" - self._attrs = attrs - self._short_opts = [] - self._long_opts = [] - self.dest = attrs.get("dest") - if "%default" in (attrs.get("help") or ""): - warnings.warn( - 'pytest now uses argparse. "%default" should be' - ' changed to "%(default)s" ', - DeprecationWarning, - stacklevel=3, - ) - try: - typ = attrs["type"] - except KeyError: - pass - else: - # this might raise a keyerror as well, don't want to catch that - if isinstance(typ, six.string_types): - if typ == "choice": - warnings.warn( - "type argument to addoption() is a string %r." - " For parsearg this is optional and when supplied" - " should be a type." - " (options: %s)" % (typ, names), - DeprecationWarning, - stacklevel=3, - ) - # argparse expects a type here take it from - # the type of the first element - attrs["type"] = type(attrs["choices"][0]) - else: - warnings.warn( - "type argument to addoption() is a string %r." - " For parsearg this should be a type." - " (options: %s)" % (typ, names), - DeprecationWarning, - stacklevel=3, - ) - attrs["type"] = Argument._typ_map[typ] - # used in test_parseopt -> test_parse_defaultgetter - self.type = attrs["type"] - else: - self.type = typ - try: - # attribute existence is tested in Config._processopt - self.default = attrs["default"] - except KeyError: - pass - self._set_opt_strings(names) - if not self.dest: - if self._long_opts: - self.dest = self._long_opts[0][2:].replace("-", "_") - else: - try: - self.dest = self._short_opts[0][1:] - except IndexError: - raise ArgumentError("need a long or short option", self) - - def names(self): - return self._short_opts + self._long_opts - - def attrs(self): - # update any attributes set by processopt - attrs = "default dest help".split() - if self.dest: - attrs.append(self.dest) - for attr in attrs: - try: - self._attrs[attr] = getattr(self, attr) - except AttributeError: - pass - if self._attrs.get("help"): - a = self._attrs["help"] - a = a.replace("%default", "%(default)s") - # a = a.replace('%prog', '%(prog)s') - self._attrs["help"] = a - return self._attrs - - def _set_opt_strings(self, opts): - """directly from optparse - - might not be necessary as this is passed to argparse later on""" - for opt in opts: - if len(opt) < 2: - raise ArgumentError( - "invalid option string %r: " - "must be at least two characters long" % opt, - self, - ) - elif len(opt) == 2: - if not (opt[0] == "-" and opt[1] != "-"): - raise ArgumentError( - "invalid short option string %r: " - "must be of the form -x, (x any non-dash char)" % opt, - self, - ) - self._short_opts.append(opt) - else: - if not (opt[0:2] == "--" and opt[2] != "-"): - raise ArgumentError( - "invalid long option string %r: " - "must start with --, followed by non-dash" % opt, - self, - ) - self._long_opts.append(opt) - - def __repr__(self): - args = [] - if self._short_opts: - args += ["_short_opts: " + repr(self._short_opts)] - if self._long_opts: - args += ["_long_opts: " + repr(self._long_opts)] - args += ["dest: " + repr(self.dest)] - if hasattr(self, "type"): - args += ["type: " + repr(self.type)] - if hasattr(self, "default"): - args += ["default: " + repr(self.default)] - return "Argument({})".format(", ".join(args)) - - -class OptionGroup(object): - - def __init__(self, name, description="", parser=None): - self.name = name - self.description = description - self.options = [] - self.parser = parser - - def addoption(self, *optnames, **attrs): - """ add an option to this group. - - if a shortened version of a long option is specified it will - be suppressed in the help. addoption('--twowords', '--two-words') - results in help showing '--two-words' only, but --twowords gets - accepted **and** the automatic destination is in args.twowords - """ - conflict = set(optnames).intersection( - name for opt in self.options for name in opt.names() - ) - if conflict: - raise ValueError("option names %s already added" % conflict) - option = Argument(*optnames, **attrs) - self._addoption_instance(option, shortupper=False) - - def _addoption(self, *optnames, **attrs): - option = Argument(*optnames, **attrs) - self._addoption_instance(option, shortupper=True) - - def _addoption_instance(self, option, shortupper=False): - if not shortupper: - for opt in option._short_opts: - if opt[0] == "-" and opt[1].islower(): - raise ValueError("lowercase shortoptions reserved") - if self.parser: - self.parser.processoption(option) - self.options.append(option) - - -class MyOptionParser(argparse.ArgumentParser): - - def __init__(self, parser, extra_info=None): - if not extra_info: - extra_info = {} - self._parser = parser - argparse.ArgumentParser.__init__( - self, - usage=parser._usage, - add_help=False, - formatter_class=DropShorterLongHelpFormatter, - ) - # extra_info is a dict of (param -> value) to display if there's - # an usage error to provide more contextual information to the user - self.extra_info = extra_info - - def parse_args(self, args=None, namespace=None): - """allow splitting of positional arguments""" - args, argv = self.parse_known_args(args, namespace) - if argv: - for arg in argv: - if arg and arg[0] == "-": - lines = ["unrecognized arguments: %s" % (" ".join(argv))] - for k, v in sorted(self.extra_info.items()): - lines.append(" %s: %s" % (k, v)) - self.error("\n".join(lines)) - getattr(args, FILE_OR_DIR).extend(argv) - return args - - -class DropShorterLongHelpFormatter(argparse.HelpFormatter): - """shorten help for long options that differ only in extra hyphens - - - collapse **long** options that are the same except for extra hyphens - - special action attribute map_long_option allows surpressing additional - long options - - shortcut if there are only two options and one of them is a short one - - cache result on action object as this is called at least 2 times - """ - - def _format_action_invocation(self, action): - orgstr = argparse.HelpFormatter._format_action_invocation(self, action) - if orgstr and orgstr[0] != "-": # only optional arguments - return orgstr - res = getattr(action, "_formatted_action_invocation", None) - if res: - return res - options = orgstr.split(", ") - if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2): - # a shortcut for '-h, --help' or '--abc', '-a' - action._formatted_action_invocation = orgstr - return orgstr - return_list = [] - option_map = getattr(action, "map_long_option", {}) - if option_map is None: - option_map = {} - short_long = {} - for option in options: - if len(option) == 2 or option[2] == " ": - continue - if not option.startswith("--"): - raise ArgumentError( - 'long optional argument without "--": [%s]' % (option), self - ) - xxoption = option[2:] - if xxoption.split()[0] not in option_map: - shortened = xxoption.replace("-", "") - if ( - shortened not in short_long - or len(short_long[shortened]) < len(xxoption) - ): - short_long[shortened] = xxoption - # now short_long has been filled out to the longest with dashes - # **and** we keep the right option ordering from add_argument - for option in options: - if len(option) == 2 or option[2] == " ": - return_list.append(option) - if option[2:] == short_long.get(option.replace("-", "")): - return_list.append(option.replace(" ", "=", 1)) - action._formatted_action_invocation = ", ".join(return_list) - return action._formatted_action_invocation - - def _ensure_removed_sysmodule(modname): try: del sys.modules[modname] @@ -921,7 +532,6 @@ class Notset(object): notset = Notset() -FILE_OR_DIR = "file_or_dir" def _iter_rewritable_modules(package_files): @@ -943,6 +553,8 @@ class Config(object): #: access to command line option as attributes. #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead self.option = argparse.Namespace() + from .argparsing import Parser, FILE_OR_DIR + _a = FILE_OR_DIR self._parser = Parser( usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a), diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py new file mode 100644 index 000000000..781d8e8c4 --- /dev/null +++ b/src/_pytest/config/argparsing.py @@ -0,0 +1,394 @@ +import six +import warnings +import argparse + +FILE_OR_DIR = "file_or_dir" + + +class Parser(object): + """ Parser for command line arguments and ini-file values. + + :ivar extra_info: dict of generic param -> value to display in case + there's an error processing the command line arguments. + """ + + def __init__(self, usage=None, processopt=None): + self._anonymous = OptionGroup("custom options", parser=self) + self._groups = [] + self._processopt = processopt + self._usage = usage + self._inidict = {} + self._ininames = [] + self.extra_info = {} + + def processoption(self, option): + if self._processopt: + if option.dest: + self._processopt(option) + + def getgroup(self, name, description="", after=None): + """ get (or create) a named option Group. + + :name: name of the option group. + :description: long description for --help output. + :after: name of other group, used for ordering --help output. + + The returned group object has an ``addoption`` method with the same + signature as :py:func:`parser.addoption + <_pytest.config.Parser.addoption>` but will be shown in the + respective group in the output of ``pytest. --help``. + """ + for group in self._groups: + if group.name == name: + return group + group = OptionGroup(name, description, parser=self) + i = 0 + for i, grp in enumerate(self._groups): + if grp.name == after: + break + self._groups.insert(i + 1, group) + return group + + def addoption(self, *opts, **attrs): + """ register a command line option. + + :opts: option names, can be short or long options. + :attrs: same attributes which the ``add_option()`` function of the + `argparse library + `_ + accepts. + + After command line parsing options are available on the pytest config + object via ``config.option.NAME`` where ``NAME`` is usually set + by passing a ``dest`` attribute, for example + ``addoption("--long", dest="NAME", ...)``. + """ + self._anonymous.addoption(*opts, **attrs) + + def parse(self, args, namespace=None): + from _pytest._argcomplete import try_argcomplete + + self.optparser = self._getparser() + try_argcomplete(self.optparser) + return self.optparser.parse_args([str(x) for x in args], namespace=namespace) + + def _getparser(self): + from _pytest._argcomplete import filescompleter + + optparser = MyOptionParser(self, self.extra_info) + groups = self._groups + [self._anonymous] + for group in groups: + if group.options: + desc = group.description or group.name + arggroup = optparser.add_argument_group(desc) + for option in group.options: + n = option.names() + a = option.attrs() + arggroup.add_argument(*n, **a) + # bash like autocompletion for dirs (appending '/') + optparser.add_argument(FILE_OR_DIR, nargs="*").completer = filescompleter + return optparser + + def parse_setoption(self, args, option, namespace=None): + parsedoption = self.parse(args, namespace=namespace) + for name, value in parsedoption.__dict__.items(): + setattr(option, name, value) + return getattr(parsedoption, FILE_OR_DIR) + + def parse_known_args(self, args, namespace=None): + """parses and returns a namespace object with known arguments at this + point. + """ + return self.parse_known_and_unknown_args(args, namespace=namespace)[0] + + def parse_known_and_unknown_args(self, args, namespace=None): + """parses and returns a namespace object with known arguments, and + the remaining arguments unknown at this point. + """ + optparser = self._getparser() + args = [str(x) for x in args] + return optparser.parse_known_args(args, namespace=namespace) + + def addini(self, name, help, type=None, default=None): + """ register an ini-file option. + + :name: name of the ini-variable + :type: type of the variable, can be ``pathlist``, ``args``, ``linelist`` + or ``bool``. + :default: default value if no ini-file option exists but is queried. + + The value of ini-variables can be retrieved via a call to + :py:func:`config.getini(name) <_pytest.config.Config.getini>`. + """ + assert type in (None, "pathlist", "args", "linelist", "bool") + self._inidict[name] = (help, type, default) + self._ininames.append(name) + + +class ArgumentError(Exception): + """ + Raised if an Argument instance is created with invalid or + inconsistent arguments. + """ + + def __init__(self, msg, option): + self.msg = msg + self.option_id = str(option) + + def __str__(self): + if self.option_id: + return "option %s: %s" % (self.option_id, self.msg) + else: + return self.msg + + +class Argument(object): + """class that mimics the necessary behaviour of optparse.Option + + its currently a least effort implementation + and ignoring choices and integer prefixes + https://docs.python.org/3/library/optparse.html#optparse-standard-option-types + """ + _typ_map = {"int": int, "string": str, "float": float, "complex": complex} + + def __init__(self, *names, **attrs): + """store parms in private vars for use in add_argument""" + self._attrs = attrs + self._short_opts = [] + self._long_opts = [] + self.dest = attrs.get("dest") + if "%default" in (attrs.get("help") or ""): + warnings.warn( + 'pytest now uses argparse. "%default" should be' + ' changed to "%(default)s" ', + DeprecationWarning, + stacklevel=3, + ) + try: + typ = attrs["type"] + except KeyError: + pass + else: + # this might raise a keyerror as well, don't want to catch that + if isinstance(typ, six.string_types): + if typ == "choice": + warnings.warn( + "type argument to addoption() is a string %r." + " For parsearg this is optional and when supplied" + " should be a type." + " (options: %s)" % (typ, names), + DeprecationWarning, + stacklevel=3, + ) + # argparse expects a type here take it from + # the type of the first element + attrs["type"] = type(attrs["choices"][0]) + else: + warnings.warn( + "type argument to addoption() is a string %r." + " For parsearg this should be a type." + " (options: %s)" % (typ, names), + DeprecationWarning, + stacklevel=3, + ) + attrs["type"] = Argument._typ_map[typ] + # used in test_parseopt -> test_parse_defaultgetter + self.type = attrs["type"] + else: + self.type = typ + try: + # attribute existence is tested in Config._processopt + self.default = attrs["default"] + except KeyError: + pass + self._set_opt_strings(names) + if not self.dest: + if self._long_opts: + self.dest = self._long_opts[0][2:].replace("-", "_") + else: + try: + self.dest = self._short_opts[0][1:] + except IndexError: + raise ArgumentError("need a long or short option", self) + + def names(self): + return self._short_opts + self._long_opts + + def attrs(self): + # update any attributes set by processopt + attrs = "default dest help".split() + if self.dest: + attrs.append(self.dest) + for attr in attrs: + try: + self._attrs[attr] = getattr(self, attr) + except AttributeError: + pass + if self._attrs.get("help"): + a = self._attrs["help"] + a = a.replace("%default", "%(default)s") + # a = a.replace('%prog', '%(prog)s') + self._attrs["help"] = a + return self._attrs + + def _set_opt_strings(self, opts): + """directly from optparse + + might not be necessary as this is passed to argparse later on""" + for opt in opts: + if len(opt) < 2: + raise ArgumentError( + "invalid option string %r: " + "must be at least two characters long" % opt, + self, + ) + elif len(opt) == 2: + if not (opt[0] == "-" and opt[1] != "-"): + raise ArgumentError( + "invalid short option string %r: " + "must be of the form -x, (x any non-dash char)" % opt, + self, + ) + self._short_opts.append(opt) + else: + if not (opt[0:2] == "--" and opt[2] != "-"): + raise ArgumentError( + "invalid long option string %r: " + "must start with --, followed by non-dash" % opt, + self, + ) + self._long_opts.append(opt) + + def __repr__(self): + args = [] + if self._short_opts: + args += ["_short_opts: " + repr(self._short_opts)] + if self._long_opts: + args += ["_long_opts: " + repr(self._long_opts)] + args += ["dest: " + repr(self.dest)] + if hasattr(self, "type"): + args += ["type: " + repr(self.type)] + if hasattr(self, "default"): + args += ["default: " + repr(self.default)] + return "Argument({})".format(", ".join(args)) + + +class OptionGroup(object): + + def __init__(self, name, description="", parser=None): + self.name = name + self.description = description + self.options = [] + self.parser = parser + + def addoption(self, *optnames, **attrs): + """ add an option to this group. + + if a shortened version of a long option is specified it will + be suppressed in the help. addoption('--twowords', '--two-words') + results in help showing '--two-words' only, but --twowords gets + accepted **and** the automatic destination is in args.twowords + """ + conflict = set(optnames).intersection( + name for opt in self.options for name in opt.names() + ) + if conflict: + raise ValueError("option names %s already added" % conflict) + option = Argument(*optnames, **attrs) + self._addoption_instance(option, shortupper=False) + + def _addoption(self, *optnames, **attrs): + option = Argument(*optnames, **attrs) + self._addoption_instance(option, shortupper=True) + + def _addoption_instance(self, option, shortupper=False): + if not shortupper: + for opt in option._short_opts: + if opt[0] == "-" and opt[1].islower(): + raise ValueError("lowercase shortoptions reserved") + if self.parser: + self.parser.processoption(option) + self.options.append(option) + + +class MyOptionParser(argparse.ArgumentParser): + + def __init__(self, parser, extra_info=None): + if not extra_info: + extra_info = {} + self._parser = parser + argparse.ArgumentParser.__init__( + self, + usage=parser._usage, + add_help=False, + formatter_class=DropShorterLongHelpFormatter, + ) + # extra_info is a dict of (param -> value) to display if there's + # an usage error to provide more contextual information to the user + self.extra_info = extra_info + + def parse_args(self, args=None, namespace=None): + """allow splitting of positional arguments""" + args, argv = self.parse_known_args(args, namespace) + if argv: + for arg in argv: + if arg and arg[0] == "-": + lines = ["unrecognized arguments: %s" % (" ".join(argv))] + for k, v in sorted(self.extra_info.items()): + lines.append(" %s: %s" % (k, v)) + self.error("\n".join(lines)) + getattr(args, FILE_OR_DIR).extend(argv) + return args + + +class DropShorterLongHelpFormatter(argparse.HelpFormatter): + """shorten help for long options that differ only in extra hyphens + + - collapse **long** options that are the same except for extra hyphens + - special action attribute map_long_option allows surpressing additional + long options + - shortcut if there are only two options and one of them is a short one + - cache result on action object as this is called at least 2 times + """ + + def _format_action_invocation(self, action): + orgstr = argparse.HelpFormatter._format_action_invocation(self, action) + if orgstr and orgstr[0] != "-": # only optional arguments + return orgstr + res = getattr(action, "_formatted_action_invocation", None) + if res: + return res + options = orgstr.split(", ") + if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2): + # a shortcut for '-h, --help' or '--abc', '-a' + action._formatted_action_invocation = orgstr + return orgstr + return_list = [] + option_map = getattr(action, "map_long_option", {}) + if option_map is None: + option_map = {} + short_long = {} + for option in options: + if len(option) == 2 or option[2] == " ": + continue + if not option.startswith("--"): + raise ArgumentError( + 'long optional argument without "--": [%s]' % (option), self + ) + xxoption = option[2:] + if xxoption.split()[0] not in option_map: + shortened = xxoption.replace("-", "") + if ( + shortened not in short_long + or len(short_long[shortened]) < len(xxoption) + ): + short_long[shortened] = xxoption + # now short_long has been filled out to the longest with dashes + # **and** we keep the right option ordering from add_argument + for option in options: + if len(option) == 2 or option[2] == " ": + return_list.append(option) + if option[2:] == short_long.get(option.replace("-", "")): + return_list.append(option.replace(" ", "=", 1)) + action._formatted_action_invocation = ", ".join(return_list) + return action._formatted_action_invocation From 1459cbe01f9f6707405c66af8dcf6020641c163b Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 5 Jun 2018 10:07:02 +0200 Subject: [PATCH 04/31] put config path finding and exceptions into own modules --- src/_pytest/config/__init__.py | 149 +------------------------------ src/_pytest/config/exceptions.py | 8 ++ src/_pytest/config/findpaths.py | 140 +++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 147 deletions(-) create mode 100644 src/_pytest/config/exceptions.py create mode 100644 src/_pytest/config/findpaths.py diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 3423a7091..11348b80d 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -19,6 +19,8 @@ import _pytest.hookspec # the extension point definitions import _pytest.assertion from pluggy import PluginManager, HookimplMarker, HookspecMarker from _pytest.compat import safe_str +from .exceptions import UsageError, PrintHelp +from .findpaths import determine_setup, exists hookimpl = HookimplMarker("pytest") hookspec = HookspecMarker("pytest") @@ -74,16 +76,6 @@ class cmdline(object): # NOQA compatibility namespace main = staticmethod(main) -class UsageError(Exception): - """ error in pytest usage or invocation""" - - -class PrintHelp(Exception): - """Raised when pytest should print it's help to skip the rest of the - argument parsing and validation.""" - pass - - def filename_arg(path, optname): """ Argparse type validator for filename arguments. @@ -934,143 +926,6 @@ def _warn_about_missing_assertion(mode): ) -def exists(path, ignore=EnvironmentError): - try: - return path.check() - except ignore: - return False - - -def getcfg(args, warnfunc=None): - """ - Search the list of arguments for a valid ini-file for pytest, - and return a tuple of (rootdir, inifile, cfg-dict). - - note: warnfunc is an optional function used to warn - about ini-files that use deprecated features. - This parameter should be removed when pytest - adopts standard deprecation warnings (#1804). - """ - from _pytest.deprecated import CFG_PYTEST_SECTION - - inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"] - args = [x for x in args if not str(x).startswith("-")] - if not args: - args = [py.path.local()] - for arg in args: - arg = py.path.local(arg) - for base in arg.parts(reverse=True): - for inibasename in inibasenames: - p = base.join(inibasename) - if exists(p): - iniconfig = py.iniconfig.IniConfig(p) - if "pytest" in iniconfig.sections: - if inibasename == "setup.cfg" and warnfunc: - warnfunc( - "C1", CFG_PYTEST_SECTION.format(filename=inibasename) - ) - return base, p, iniconfig["pytest"] - if ( - inibasename == "setup.cfg" - and "tool:pytest" in iniconfig.sections - ): - return base, p, iniconfig["tool:pytest"] - elif inibasename == "pytest.ini": - # allowed to be empty - return base, p, {} - return None, None, None - - -def get_common_ancestor(paths): - common_ancestor = None - for path in paths: - if not path.exists(): - continue - if common_ancestor is None: - common_ancestor = path - else: - if path.relto(common_ancestor) or path == common_ancestor: - continue - elif common_ancestor.relto(path): - common_ancestor = path - else: - shared = path.common(common_ancestor) - if shared is not None: - common_ancestor = shared - if common_ancestor is None: - common_ancestor = py.path.local() - elif common_ancestor.isfile(): - common_ancestor = common_ancestor.dirpath() - return common_ancestor - - -def get_dirs_from_args(args): - - def is_option(x): - return str(x).startswith("-") - - def get_file_part_from_node_id(x): - return str(x).split("::")[0] - - def get_dir_from_path(path): - if path.isdir(): - return path - return py.path.local(path.dirname) - - # These look like paths but may not exist - possible_paths = ( - py.path.local(get_file_part_from_node_id(arg)) - for arg in args - if not is_option(arg) - ) - - return [get_dir_from_path(path) for path in possible_paths if path.exists()] - - -def determine_setup(inifile, args, warnfunc=None, rootdir_cmd_arg=None): - dirs = get_dirs_from_args(args) - if inifile: - iniconfig = py.iniconfig.IniConfig(inifile) - is_cfg_file = str(inifile).endswith(".cfg") - # TODO: [pytest] section in *.cfg files is depricated. Need refactoring. - sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"] - for section in sections: - try: - inicfg = iniconfig[section] - if is_cfg_file and section == "pytest" and warnfunc: - from _pytest.deprecated import CFG_PYTEST_SECTION - - warnfunc("C1", CFG_PYTEST_SECTION.format(filename=str(inifile))) - break - except KeyError: - inicfg = None - rootdir = get_common_ancestor(dirs) - else: - ancestor = get_common_ancestor(dirs) - rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc) - if rootdir is None: - for rootdir in ancestor.parts(reverse=True): - if rootdir.join("setup.py").exists(): - break - else: - rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc) - if rootdir is None: - rootdir = get_common_ancestor([py.path.local(), ancestor]) - is_fs_root = os.path.splitdrive(str(rootdir))[1] == "/" - if is_fs_root: - rootdir = ancestor - if rootdir_cmd_arg: - rootdir_abs_path = py.path.local(os.path.expandvars(rootdir_cmd_arg)) - if not os.path.isdir(str(rootdir_abs_path)): - raise UsageError( - "Directory '{}' not found. Check your '--rootdir' option.".format( - rootdir_abs_path - ) - ) - rootdir = rootdir_abs_path - return rootdir, inifile, inicfg or {} - - def setns(obj, dic): import pytest diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py new file mode 100644 index 000000000..64bae834d --- /dev/null +++ b/src/_pytest/config/exceptions.py @@ -0,0 +1,8 @@ +class UsageError(Exception): + """ error in pytest usage or invocation""" + + +class PrintHelp(Exception): + """Raised when pytest should print it's help to skip the rest of the + argument parsing and validation.""" + pass diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py new file mode 100644 index 000000000..fde7bddb9 --- /dev/null +++ b/src/_pytest/config/findpaths.py @@ -0,0 +1,140 @@ +import py +import os +from .exceptions import UsageError + + +def exists(path, ignore=EnvironmentError): + try: + return path.check() + except ignore: + return False + + +def getcfg(args, warnfunc=None): + """ + Search the list of arguments for a valid ini-file for pytest, + and return a tuple of (rootdir, inifile, cfg-dict). + + note: warnfunc is an optional function used to warn + about ini-files that use deprecated features. + This parameter should be removed when pytest + adopts standard deprecation warnings (#1804). + """ + from _pytest.deprecated import CFG_PYTEST_SECTION + + inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"] + args = [x for x in args if not str(x).startswith("-")] + if not args: + args = [py.path.local()] + for arg in args: + arg = py.path.local(arg) + for base in arg.parts(reverse=True): + for inibasename in inibasenames: + p = base.join(inibasename) + if exists(p): + iniconfig = py.iniconfig.IniConfig(p) + if "pytest" in iniconfig.sections: + if inibasename == "setup.cfg" and warnfunc: + warnfunc( + "C1", CFG_PYTEST_SECTION.format(filename=inibasename) + ) + return base, p, iniconfig["pytest"] + if ( + inibasename == "setup.cfg" + and "tool:pytest" in iniconfig.sections + ): + return base, p, iniconfig["tool:pytest"] + elif inibasename == "pytest.ini": + # allowed to be empty + return base, p, {} + return None, None, None + + +def get_common_ancestor(paths): + common_ancestor = None + for path in paths: + if not path.exists(): + continue + if common_ancestor is None: + common_ancestor = path + else: + if path.relto(common_ancestor) or path == common_ancestor: + continue + elif common_ancestor.relto(path): + common_ancestor = path + else: + shared = path.common(common_ancestor) + if shared is not None: + common_ancestor = shared + if common_ancestor is None: + common_ancestor = py.path.local() + elif common_ancestor.isfile(): + common_ancestor = common_ancestor.dirpath() + return common_ancestor + + +def get_dirs_from_args(args): + + def is_option(x): + return str(x).startswith("-") + + def get_file_part_from_node_id(x): + return str(x).split("::")[0] + + def get_dir_from_path(path): + if path.isdir(): + return path + return py.path.local(path.dirname) + + # These look like paths but may not exist + possible_paths = ( + py.path.local(get_file_part_from_node_id(arg)) + for arg in args + if not is_option(arg) + ) + + return [get_dir_from_path(path) for path in possible_paths if path.exists()] + + +def determine_setup(inifile, args, warnfunc=None, rootdir_cmd_arg=None): + dirs = get_dirs_from_args(args) + if inifile: + iniconfig = py.iniconfig.IniConfig(inifile) + is_cfg_file = str(inifile).endswith(".cfg") + # TODO: [pytest] section in *.cfg files is depricated. Need refactoring. + sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"] + for section in sections: + try: + inicfg = iniconfig[section] + if is_cfg_file and section == "pytest" and warnfunc: + from _pytest.deprecated import CFG_PYTEST_SECTION + + warnfunc("C1", CFG_PYTEST_SECTION.format(filename=str(inifile))) + break + except KeyError: + inicfg = None + rootdir = get_common_ancestor(dirs) + else: + ancestor = get_common_ancestor(dirs) + rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc) + if rootdir is None: + for rootdir in ancestor.parts(reverse=True): + if rootdir.join("setup.py").exists(): + break + else: + rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc) + if rootdir is None: + rootdir = get_common_ancestor([py.path.local(), ancestor]) + is_fs_root = os.path.splitdrive(str(rootdir))[1] == "/" + if is_fs_root: + rootdir = ancestor + if rootdir_cmd_arg: + rootdir_abs_path = py.path.local(os.path.expandvars(rootdir_cmd_arg)) + if not os.path.isdir(str(rootdir_abs_path)): + raise UsageError( + "Directory '{}' not found. Check your '--rootdir' option.".format( + rootdir_abs_path + ) + ) + rootdir = rootdir_abs_path + return rootdir, inifile, inicfg or {} From 464117b4725b853feb15c965732526448128a45a Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 5 Jun 2018 10:20:36 +0200 Subject: [PATCH 05/31] fix imports in tests --- testing/test_capture.py | 2 +- testing/test_config.py | 8 ++------ testing/test_parseopt.py | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/testing/test_capture.py b/testing/test_capture.py index 5cedc99bb..e14b3af78 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -51,7 +51,7 @@ class TestCaptureManager(object): def test_getmethod_default_no_fd(self, monkeypatch): from _pytest.capture import pytest_addoption - from _pytest.config import Parser + from _pytest.config.argparsing import Parser parser = Parser() pytest_addoption(parser) diff --git a/testing/test_config.py b/testing/test_config.py index 56a51514d..5fb048364 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -4,12 +4,8 @@ import textwrap import pytest import _pytest._code -from _pytest.config import ( - getcfg, - get_common_ancestor, - determine_setup, - _iter_rewritable_modules, -) +from _pytest.config.findpaths import getcfg, get_common_ancestor, determine_setup +from _pytest.config import _iter_rewritable_modules from _pytest.main import EXIT_NOTESTSCOLLECTED diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index a8fc6d724..79076cafd 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -4,7 +4,7 @@ import sys import os import py import pytest -from _pytest import config as parseopt +from _pytest.config import argparsing as parseopt @pytest.fixture From 1aba123ac50f8df2859d6b12d9c571aa3f93c3af Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 11 Jun 2018 16:20:24 +0200 Subject: [PATCH 06/31] fix doc build --- doc/en/reference.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/reference.rst b/doc/en/reference.rst index 28a375139..8d5dcdbb8 100644 --- a/doc/en/reference.rst +++ b/doc/en/reference.rst @@ -733,7 +733,7 @@ Node Parser ~~~~~~ -.. autoclass:: _pytest.config.Parser() +.. autoclass:: _pytest.config.argparsing.Parser() :members: PluginManager From 5221a147640ca2da975c32a238d27b295cc3e095 Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Thu, 14 Jun 2018 20:00:38 +0000 Subject: [PATCH 07/31] Failing test case for #3583 --- testing/test_doctest.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 8ef7cfd65..7f3aff3b0 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -655,6 +655,22 @@ class TestDoctests(object): result = testdir.runpytest(p, "--doctest-modules") result.stdout.fnmatch_lines(["* 1 passed *"]) + def test_print_unicode_value(self, testdir): + """ + Test case for issue 3583: Printing Unicode in doctest under Python 2.7 + doesn't work + """ + p = testdir.maketxtfile( + test_print_unicode_value=r""" + Here is a doctest:: + + >>> print(u'\xE5\xE9\xEE\xF8\xFC') + åéîøü + """ + ) + result = testdir.runpytest(p) + result.stdout.fnmatch_lines(["* 1 passed *"]) + def test_reportinfo(self, testdir): """ Test case to make sure that DoctestItem.reportinfo() returns lineno. From d382f3e77ffe6db49ebc6a93f81fcdeea8ea5458 Mon Sep 17 00:00:00 2001 From: "John T. Wodder II" Date: Thu, 14 Jun 2018 19:05:07 +0000 Subject: [PATCH 08/31] [#3583] Fix encoding error with `print` statements in doctests This fix was suggested by Stack Overflow user phd in . --- changelog/3583.bugfix.rst | 1 + src/_pytest/doctest.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/3583.bugfix.rst diff --git a/changelog/3583.bugfix.rst b/changelog/3583.bugfix.rst new file mode 100644 index 000000000..cfa662580 --- /dev/null +++ b/changelog/3583.bugfix.rst @@ -0,0 +1 @@ +Fix encoding error with `print` statements in doctests diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 3b58f955f..b0a3ad08d 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -505,7 +505,7 @@ def _fix_spoof_python2(runner, encoding): def getvalue(self): result = _SpoofOut.getvalue(self) - if encoding: + if encoding and isinstance(result, bytes): result = result.decode(encoding) return result From acb8f23311ea66b6dce46bbd85db9c08d38ef981 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sat, 16 Jun 2018 10:37:33 +0200 Subject: [PATCH 09/31] Fix 2 DeprecationWarnings about invalid escape seq --- src/_pytest/python_api.py | 2 +- src/_pytest/recwarn.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 955fb4165..9257d210c 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -497,7 +497,7 @@ def _is_numpy_array(obj): def raises(expected_exception, *args, **kwargs): - """ + r""" Assert that a code block/function call raises ``expected_exception`` and raise a failure exception otherwise. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 565af8a3f..7839f5700 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -85,7 +85,7 @@ class _DeprecatedCallContext(object): def warns(expected_warning, *args, **kwargs): - """Assert that code raises a particular class of warning. + r"""Assert that code raises a particular class of warning. Specifically, the parameter ``expected_warning`` can be a warning class or sequence of warning classes, and the inside the ``with`` block must issue a warning of that class or From 9408291c50c2576d62ebd517e51c2275ea18f63f Mon Sep 17 00:00:00 2001 From: Alex Barbato Date: Sat, 16 Jun 2018 12:40:25 -0400 Subject: [PATCH 10/31] Fixing parens typo in fixture.rst --- doc/en/fixture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index dfbf519db..d4d386792 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -165,7 +165,7 @@ Scope: sharing a fixture instance across tests in a class, module or session Fixtures requiring network access depend on connectivity and are usually time-expensive to create. Extending the previous example, we -can add a ``scope='module'`` parameter to the +can add a ``scope="module"`` parameter to the :py:func:`@pytest.fixture <_pytest.python.fixture>` invocation to cause the decorated ``smtp`` fixture function to only be invoked once per test *module* (the default is to invoke once per test *function*). From 561db95521a945fb2f80fb6767f70d6fb73279d6 Mon Sep 17 00:00:00 2001 From: Alex Barbato Date: Sat, 16 Jun 2018 12:44:19 -0400 Subject: [PATCH 11/31] Add changelog file. --- changelog/3525.trivial.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3525.trivial.rst diff --git a/changelog/3525.trivial.rst b/changelog/3525.trivial.rst new file mode 100644 index 000000000..4607c3bd5 --- /dev/null +++ b/changelog/3525.trivial.rst @@ -0,0 +1 @@ +Update old quotation style to parens in fixture.rst documentation. From 93e55ad2fae3a08ced8f324f9b01abe0fce6ed39 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 18 Jun 2018 21:45:46 -0300 Subject: [PATCH 12/31] Remove unused attribute and parameter in CallSpec2 --- changelog/3598.trivial.rst | 1 + src/_pytest/python.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 changelog/3598.trivial.rst diff --git a/changelog/3598.trivial.rst b/changelog/3598.trivial.rst new file mode 100644 index 000000000..fd80f58cd --- /dev/null +++ b/changelog/3598.trivial.rst @@ -0,0 +1 @@ +Internal refactoring: removed unused ``CallSpec2tox ._globalid_args`` attribute and ``metafunc`` parameter from ``CallSpec2.copy()``. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 48516199f..0dcecdd55 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -735,13 +735,12 @@ class CallSpec2(object): self._idlist = [] self.params = {} self._globalid = NOTSET - self._globalid_args = set() self._globalparam = NOTSET self._arg2scopenum = {} # used for sorting parametrized resources self.marks = [] self.indices = {} - def copy(self, metafunc): + def copy(self): cs = CallSpec2(self.metafunc) cs.funcargs.update(self.funcargs) cs.params.update(self.params) @@ -750,7 +749,6 @@ class CallSpec2(object): cs._arg2scopenum.update(self._arg2scopenum) cs._idlist = list(self._idlist) cs._globalid = self._globalid - cs._globalid_args = self._globalid_args cs._globalparam = self._globalparam return cs @@ -933,7 +931,7 @@ class Metafunc(fixtures.FuncargnamesCompatAttr): param.values, argnames ) ) - newcallspec = callspec.copy(self) + newcallspec = callspec.copy() newcallspec.setmulti2( valtypes, argnames, From 8e9f1d24172d3b9c64f00d4448a95c38e39ddeb3 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Mon, 18 Jun 2018 18:27:48 -0700 Subject: [PATCH 13/31] Use --show-diff-on-failure for pre-commit CI invocation --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c346b5682..cb3846d54 100644 --- a/tox.ini +++ b/tox.ini @@ -40,7 +40,7 @@ skipsdist = True usedevelop = True basepython = python3.6 deps = pre-commit -commands = pre-commit run --all-files +commands = pre-commit run --all-files --show-diff-on-failure [testenv:py27-xdist] deps = From af5d41fdfd70c99134165438dad44cf53d6076dd Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 19 Jun 2018 10:41:04 +0200 Subject: [PATCH 14/31] add build-system section to pyproject.toml this makes the file valid and prepares for https://github.com/pypa/pip/issues/5416 and https://github.com/pypa/pip/pull/5512 --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ffce583f6..65e6bf59b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,10 @@ +[build-system] +requires = [ + "setuptools", + "setuptools-scm", + "wheel", +] + [tool.towncrier] package = "pytest" package_dir = "src" From 617a5fcf98d56d19779eace036555f17a8d08422 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 20 Jun 2018 00:29:58 +0000 Subject: [PATCH 15/31] Preparing release version 3.6.2 --- CHANGELOG.rst | 46 ++++ changelog/3525.trivial.rst | 1 - changelog/3545.trivial.rst | 1 - changelog/3549.doc.rst | 1 - changelog/3552.trivial.rst | 1 - changelog/3555.bugfix.rst | 1 - changelog/3563.bugfix.rst | 1 - changelog/3567.trivial.rst | 1 - changelog/3569.bugfix.rst | 1 - changelog/3583.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-3.6.2.rst | 29 +++ doc/en/assert.rst | 20 +- doc/en/builtin.rst | 28 +-- doc/en/cache.rst | 58 ++--- doc/en/capture.rst | 8 +- doc/en/doctest.rst | 4 +- doc/en/example/markers.rst | 92 +++---- doc/en/example/nonpython.rst | 10 +- doc/en/example/parametrize.rst | 34 +-- doc/en/example/pythoncollection.rst | 6 +- doc/en/example/reportingdemo.rst | 370 ++++++++++++++-------------- doc/en/example/simple.rst | 102 ++++---- doc/en/fixture.rst | 80 +++--- doc/en/getting-started.rst | 20 +- doc/en/index.rst | 8 +- doc/en/parametrize.rst | 20 +- doc/en/skipping.rst | 6 +- doc/en/tmpdir.rst | 10 +- doc/en/unittest.rst | 16 +- doc/en/usage.rst | 2 +- doc/en/warnings.rst | 18 +- 32 files changed, 532 insertions(+), 465 deletions(-) delete mode 100644 changelog/3525.trivial.rst delete mode 100644 changelog/3545.trivial.rst delete mode 100644 changelog/3549.doc.rst delete mode 100644 changelog/3552.trivial.rst delete mode 100644 changelog/3555.bugfix.rst delete mode 100644 changelog/3563.bugfix.rst delete mode 100644 changelog/3567.trivial.rst delete mode 100644 changelog/3569.bugfix.rst delete mode 100644 changelog/3583.bugfix.rst create mode 100644 doc/en/announce/release-3.6.2.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f61319db7..21a090414 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,52 @@ .. towncrier release notes start +Pytest 3.6.2 (2018-06-20) +========================= + +Bug Fixes +--------- + +- Fix regression in ``Node.add_marker`` by extracting the mark object of a + ``MarkDecorator``. (`#3555 + `_) + +- Warnings without ``location`` were reported as ``None``. This is corrected to + now report ````. (`#3563 + `_) + +- Continue to call finalizers in the stack when a finalizer in a former scope + raises an exception. (`#3569 + `_) + +- Fix encoding error with `print` statements in doctests (`#3583 + `_) + + +Improved Documentation +---------------------- + +- Add documentation for the ``--strict`` flag. (`#3549 + `_) + + +Trivial/Internal Changes +------------------------ + +- Update old quotation style to parens in fixture.rst documentation. (`#3525 + `_) + +- Improve display of hint about ``--fulltrace`` with ``KeyboardInterrupt``. + (`#3545 `_) + +- pytest's testsuite is no longer runnable through ``python setup.py test`` -- + instead invoke ``pytest`` or ``tox`` directly. (`#3552 + `_) + +- Fix typo in documentation (`#3567 + `_) + + Pytest 3.6.1 (2018-06-05) ========================= diff --git a/changelog/3525.trivial.rst b/changelog/3525.trivial.rst deleted file mode 100644 index 4607c3bd5..000000000 --- a/changelog/3525.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Update old quotation style to parens in fixture.rst documentation. diff --git a/changelog/3545.trivial.rst b/changelog/3545.trivial.rst deleted file mode 100644 index 0b98f78b1..000000000 --- a/changelog/3545.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Improve display of hint about ``--fulltrace`` with ``KeyboardInterrupt``. diff --git a/changelog/3549.doc.rst b/changelog/3549.doc.rst deleted file mode 100644 index 62bc4f9a5..000000000 --- a/changelog/3549.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Add documentation for the ``--strict`` flag. diff --git a/changelog/3552.trivial.rst b/changelog/3552.trivial.rst deleted file mode 100644 index dc4fb8be5..000000000 --- a/changelog/3552.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -pytest's testsuite is no longer runnable through ``python setup.py test`` -- instead invoke ``pytest`` or ``tox`` directly. diff --git a/changelog/3555.bugfix.rst b/changelog/3555.bugfix.rst deleted file mode 100644 index b86012c6b..000000000 --- a/changelog/3555.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix regression in ``Node.add_marker`` by extracting the mark object of a ``MarkDecorator``. diff --git a/changelog/3563.bugfix.rst b/changelog/3563.bugfix.rst deleted file mode 100644 index 8ba24c5dd..000000000 --- a/changelog/3563.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Warnings without ``location`` were reported as ``None``. This is corrected to now report ````. diff --git a/changelog/3567.trivial.rst b/changelog/3567.trivial.rst deleted file mode 100644 index b0bd6fdd4..000000000 --- a/changelog/3567.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typo in documentation diff --git a/changelog/3569.bugfix.rst b/changelog/3569.bugfix.rst deleted file mode 100644 index 586ecaf95..000000000 --- a/changelog/3569.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Continue to call finalizers in the stack when a finalizer in a former scope raises an exception. diff --git a/changelog/3583.bugfix.rst b/changelog/3583.bugfix.rst deleted file mode 100644 index cfa662580..000000000 --- a/changelog/3583.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix encoding error with `print` statements in doctests diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 09840708d..107fcd2ad 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.6.2 release-3.6.1 release-3.6.0 release-3.5.1 diff --git a/doc/en/announce/release-3.6.2.rst b/doc/en/announce/release-3.6.2.rst new file mode 100644 index 000000000..a1215f576 --- /dev/null +++ b/doc/en/announce/release-3.6.2.rst @@ -0,0 +1,29 @@ +pytest-3.6.2 +======================================= + +pytest 3.6.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at http://doc.pytest.org/en/latest/changelog.html. + +Thanks to all who contributed to this release, among them: + +* Alan Velasco +* Alex Barbato +* Anthony Sottile +* Bartosz Cierocki +* Bruno Oliveira +* Daniel Hahler +* Guoqiang Zhang +* Hynek Schlawack +* John T. Wodder II +* Michael Käufl +* Ronny Pfannschmidt +* Samuel Dion-Girardeau + + +Happy testing, +The pytest Development Team diff --git a/doc/en/assert.rst b/doc/en/assert.rst index e0e9b9305..bcc0a28c9 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -29,17 +29,17 @@ you will see the return value of the function call:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_assert1.py F [100%] - + ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + def test_function(): > assert f() == 4 E assert 3 == 4 E + where 3 = f() - + test_assert1.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -172,12 +172,12 @@ if you run this module:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_assert2.py F [100%] - + ================================= FAILURES ================================= ___________________________ test_set_comparison ____________________________ - + def test_set_comparison(): set1 = set("1308") set2 = set("8035") @@ -188,7 +188,7 @@ if you run this module:: E Extra items in the right set: E '5' E Use -v to get the full diff - + test_assert2.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -241,14 +241,14 @@ the conftest file:: F [100%] ================================= FAILURES ================================= _______________________________ test_compare _______________________________ - + def test_compare(): f1 = Foo(1) f2 = Foo(2) > assert f1 == f2 E assert Comparing Foo instances: E vals: 1 != 2 - + test_foocompare.py:11: AssertionError 1 failed in 0.12 seconds diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index c2d23469b..f5e1fd155 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -17,13 +17,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a $ pytest -q --fixtures cache Return a cache object that can persist state between testing sessions. - + cache.get(key, default) cache.set(key, value) - + Keys must be a ``/`` separated value, where the first part is usually the name of your plugin or application to avoid clashes with other cache users. - + Values can be any object handled by the json stdlib module. capsys Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make @@ -49,9 +49,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. pytestconfig Session-scoped fixture that returns the :class:`_pytest.config.Config` object. - + Example:: - + def test_foo(pytestconfig): if pytestconfig.getoption("verbose"): ... @@ -61,9 +61,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a configured reporters, like JUnit XML. The fixture is callable with ``(name, value)``, with value being automatically xml-encoded. - + Example:: - + def test_function(record_property): record_property("example_key", 1) record_xml_property @@ -74,9 +74,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a automatically xml-encoded caplog Access and control log capturing. - + Captured logs are available through the following methods:: - + * caplog.text -> string containing formatted log output * caplog.records -> list of logging.LogRecord instances * caplog.record_tuples -> list of (logger_name, level, message) tuples @@ -84,7 +84,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch The returned ``monkeypatch`` fixture provides these helper methods to modify objects, dictionaries or os.environ:: - + monkeypatch.setattr(obj, name, value, raising=True) monkeypatch.delattr(obj, name, raising=True) monkeypatch.setitem(mapping, name, value) @@ -93,14 +93,14 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch.delenv(name, value, raising=True) monkeypatch.syspath_prepend(path) monkeypatch.chdir(path) - + All modifications will be undone after the requesting test function or fixture has finished. The ``raising`` parameter determines if a KeyError or AttributeError will be raised if the set/deletion operation has no target. recwarn Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. - + See http://docs.python.org/library/warnings.html for information on warning categories. tmpdir_factory @@ -111,9 +111,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a created as a sub directory of the base temporary directory. The returned object is a `py.path.local`_ path object. - + .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html - + no tests ran in 0.12 seconds You can also interactively ask for help, e.g. by typing on the Python interactive prompt something like:: diff --git a/doc/en/cache.rst b/doc/en/cache.rst index 37bcf7070..437109db0 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -49,26 +49,26 @@ If you run this for the first time you will see two failures:: .................F.......F........................ [100%] ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed 2 failed, 48 passed in 0.12 seconds @@ -80,31 +80,31 @@ If you then run it with ``--lf``:: rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items / 48 deselected run-last-failure: rerun previous 2 failures - + test_50.py FF [100%] - + ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed ================= 2 failed, 48 deselected in 0.12 seconds ================== @@ -121,31 +121,31 @@ of ``FF`` and dots):: rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items run-last-failure: rerun previous 2 failures first - + test_50.py FF................................................ [100%] - + ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed =================== 2 failed, 48 passed in 0.12 seconds ==================== @@ -198,13 +198,13 @@ of the sleep:: F [100%] ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + mydata = 42 - + def test_function(mydata): > assert mydata == 23 E assert 42 == 23 - + test_caching.py:14: AssertionError 1 failed in 0.12 seconds @@ -215,13 +215,13 @@ the cache and this will be quick:: F [100%] ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + mydata = 42 - + def test_function(mydata): > assert mydata == 23 E assert 42 == 23 - + test_caching.py:14: AssertionError 1 failed in 0.12 seconds @@ -246,7 +246,7 @@ You can always peek at the content of the cache using the ['test_caching.py::test_function'] example/value contains: 42 - + ======================= no tests ran in 0.12 seconds ======================= Clearing Cache content diff --git a/doc/en/capture.rst b/doc/en/capture.rst index ab86fb55f..549845cc9 100644 --- a/doc/en/capture.rst +++ b/doc/en/capture.rst @@ -68,16 +68,16 @@ of the failing function and hide the other one:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .F [100%] - + ================================= FAILURES ================================= ________________________________ test_func2 ________________________________ - + def test_func2(): > assert False E assert False - + test_module.py:9: AssertionError -------------------------- Captured stdout setup --------------------------- setting up diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 9488ee826..ac470d105 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -65,9 +65,9 @@ then you can just invoke ``pytest`` without command line options:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 1 item - + mymodule.py . [100%] - + ========================= 1 passed in 0.12 seconds ========================= It is possible to use fixtures using the ``getfixture`` helper:: diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index bf352bc81..176fdccdb 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -35,9 +35,9 @@ You can then restrict a test run to only run tests marked with ``webtest``:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected - + test_server.py::test_send_http PASSED [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== Or the inverse, running all tests except the webtest ones:: @@ -48,11 +48,11 @@ Or the inverse, running all tests except the webtest ones:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected - + test_server.py::test_something_quick PASSED [ 33%] test_server.py::test_another PASSED [ 66%] test_server.py::TestClass::test_method PASSED [100%] - + ================== 3 passed, 1 deselected in 0.12 seconds ================== Selecting tests based on their node ID @@ -68,9 +68,9 @@ tests based on their module, class, method, or function name:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item - + test_server.py::TestClass::test_method PASSED [100%] - + ========================= 1 passed in 0.12 seconds ========================= You can also select on the class:: @@ -81,9 +81,9 @@ You can also select on the class:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item - + test_server.py::TestClass::test_method PASSED [100%] - + ========================= 1 passed in 0.12 seconds ========================= Or select multiple nodes:: @@ -94,10 +94,10 @@ Or select multiple nodes:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items - + test_server.py::TestClass::test_method PASSED [ 50%] test_server.py::test_send_http PASSED [100%] - + ========================= 2 passed in 0.12 seconds ========================= .. _node-id: @@ -132,9 +132,9 @@ select tests based on their names:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected - + test_server.py::test_send_http PASSED [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== And you can also run all tests except the ones that match the keyword:: @@ -145,11 +145,11 @@ And you can also run all tests except the ones that match the keyword:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected - + test_server.py::test_something_quick PASSED [ 33%] test_server.py::test_another PASSED [ 66%] test_server.py::TestClass::test_method PASSED [100%] - + ================== 3 passed, 1 deselected in 0.12 seconds ================== Or to select "http" and "quick" tests:: @@ -160,10 +160,10 @@ Or to select "http" and "quick" tests:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 2 deselected - + test_server.py::test_send_http PASSED [ 50%] test_server.py::test_something_quick PASSED [100%] - + ================== 2 passed, 2 deselected in 0.12 seconds ================== .. note:: @@ -199,21 +199,21 @@ You can ask which markers exist for your test suite - the list includes our just $ pytest --markers @pytest.mark.webtest: mark a test as a webtest. - + @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test. - + @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html - + @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. - - @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures - + + @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures + @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible. - + @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible. - + For an example on how to add and work with markers from a plugin, see :ref:`adding a custom marker from a plugin`. @@ -352,9 +352,9 @@ the test needs:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_someenv.py s [100%] - + ======================== 1 skipped in 0.12 seconds ========================= and here is one that specifies exactly the environment needed:: @@ -364,30 +364,30 @@ and here is one that specifies exactly the environment needed:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_someenv.py . [100%] - + ========================= 1 passed in 0.12 seconds ========================= The ``--markers`` option always gives you a list of available markers:: $ pytest --markers @pytest.mark.env(name): mark test to run only on named environment - + @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test. - + @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html - + @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. - - @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures - + + @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures + @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible. - + @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible. - + .. _`passing callables to custom markers`: @@ -523,11 +523,11 @@ then you will see two tests skipped and two executed tests as expected:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_plat.py s.s. [100%] ========================= short test summary info ========================== SKIP [2] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux - + =================== 2 passed, 2 skipped in 0.12 seconds ==================== Note that if you specify a platform via the marker-command line option like this:: @@ -537,9 +537,9 @@ Note that if you specify a platform via the marker-command line option like this platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 3 deselected - + test_plat.py . [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests. @@ -588,9 +588,9 @@ We can now use the ``-m option`` to select one set:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 2 deselected - + test_module.py FF [100%] - + ================================= FAILURES ================================= __________________________ test_interface_simple ___________________________ test_module.py:3: in test_interface_simple @@ -609,9 +609,9 @@ or to select both "event" and "interface" tests:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 1 deselected - + test_module.py FFF [100%] - + ================================= FAILURES ================================= __________________________ test_interface_simple ___________________________ test_module.py:3: in test_interface_simple diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index 4f5adf63f..ca7b2c8df 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -30,9 +30,9 @@ now execute the test specification:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collected 2 items - + test_simple.yml F. [100%] - + ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ usecase execution failed @@ -63,10 +63,10 @@ consulted when reporting in ``verbose`` mode:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collecting ... collected 2 items - + test_simple.yml::hello FAILED [ 50%] test_simple.yml::ok PASSED [100%] - + ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ usecase execution failed @@ -87,5 +87,5 @@ interesting to just look at the collection tree:: - + ======================= no tests ran in 0.12 seconds ======================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 882700fec..49ffa7288 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -55,13 +55,13 @@ let's run the full monty:: ....F [100%] ================================= FAILURES ================================= _____________________________ test_compute[4] ______________________________ - + param1 = 4 - + def test_compute(param1): > assert param1 < 4 E assert 4 < 4 - + test_compute.py:3: AssertionError 1 failed, 4 passed in 0.12 seconds @@ -151,7 +151,7 @@ objects, they are still using the default pytest representation:: - + ======================= no tests ran in 0.12 seconds ======================= In ``test_timedistance_v3``, we used ``pytest.param`` to specify the test IDs @@ -198,9 +198,9 @@ this is a fully self-contained example which you can run with:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_scenarios.py .... [100%] - + ========================= 4 passed in 0.12 seconds ========================= If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function:: @@ -218,7 +218,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia - + ======================= no tests ran in 0.12 seconds ======================= Note that we told ``metafunc.parametrize()`` that your scenario values @@ -279,7 +279,7 @@ Let's first see how it looks like at collection time:: - + ======================= no tests ran in 0.12 seconds ======================= And then when we run the test:: @@ -288,15 +288,15 @@ And then when we run the test:: .F [100%] ================================= FAILURES ================================= _________________________ test_db_initialized[d2] __________________________ - + db = - + def test_db_initialized(db): # a dummy test if db.__class__.__name__ == "DB2": > pytest.fail("deliberately failing for demo purposes") E Failed: deliberately failing for demo purposes - + test_backends.py:6: Failed 1 failed, 1 passed in 0.12 seconds @@ -339,7 +339,7 @@ The result of this test will be successful:: collected 1 item - + ======================= no tests ran in 0.12 seconds ======================= .. regendoc:wipe @@ -384,13 +384,13 @@ argument sets to use for each test function. Let's run it:: F.. [100%] ================================= FAILURES ================================= ________________________ TestClass.test_equals[1-2] ________________________ - + self = , a = 1, b = 2 - + def test_equals(self, a, b): > assert a == b E assert 1 == 2 - + test_parametrize.py:18: AssertionError 1 failed, 2 passed in 0.12 seconds @@ -462,11 +462,11 @@ If you run this with reporting for skips enabled:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .s [100%] ========================= short test summary info ========================== SKIP [1] $REGENDOC_TMPDIR/conftest.py:11: could not import 'opt2' - + =================== 1 passed, 1 skipped in 0.12 seconds ==================== You'll see that we don't have an ``opt2`` module and thus the second test run diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 8e9d3ae62..58b4364b5 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -133,7 +133,7 @@ then the test collection looks like this:: - + ======================= no tests ran in 0.12 seconds ======================= .. note:: @@ -180,7 +180,7 @@ You can always peek at the collection tree without running tests like this:: - + ======================= no tests ran in 0.12 seconds ======================= .. _customizing-test-collection: @@ -243,5 +243,5 @@ file will be left out:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 9e9d65b6d..00aa3c842 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -14,83 +14,83 @@ get on the terminal - we are working on that):: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/assertion, inifile: collected 42 items - + failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF [100%] - + ================================= FAILURES ================================= ____________________________ test_generative[0] ____________________________ - + param1 = 3, param2 = 6 - + def test_generative(param1, param2): > assert param1 * 2 < param2 E assert (3 * 2) < 6 - + failure_demo.py:19: AssertionError _________________________ TestFailing.test_simple __________________________ - + self = - + def test_simple(self): - + def f(): return 42 - + def g(): return 43 - + > assert f() == g() E assert 42 == 43 E + where 42 = .f at 0xdeadbeef>() E + and 43 = .g at 0xdeadbeef>() - + failure_demo.py:37: AssertionError ____________________ TestFailing.test_simple_multiline _____________________ - + self = - + def test_simple_multiline(self): > otherfunc_multi(42, 6 * 9) - - failure_demo.py:40: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:40: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + a = 42, b = 54 - + def otherfunc_multi(a, b): > assert a == b E assert 42 == 54 - + failure_demo.py:15: AssertionError ___________________________ TestFailing.test_not ___________________________ - + self = - + def test_not(self): - + def f(): return 42 - + > assert not f() E assert not 42 E + where 42 = .f at 0xdeadbeef>() - + failure_demo.py:47: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ - + self = - + def test_eq_text(self): > assert "spam" == "eggs" E AssertionError: assert 'spam' == 'eggs' E - spam E + eggs - + failure_demo.py:53: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ - + self = - + def test_eq_similar_text(self): > assert "foo 1 bar" == "foo 2 bar" E AssertionError: assert 'foo 1 bar' == 'foo 2 bar' @@ -98,12 +98,12 @@ get on the terminal - we are working on that):: E ? ^ E + foo 2 bar E ? ^ - + failure_demo.py:56: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ - + self = - + def test_eq_multiline_text(self): > assert "foo\nspam\nbar" == "foo\neggs\nbar" E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar' @@ -111,12 +111,12 @@ get on the terminal - we are working on that):: E - spam E + eggs E bar - + failure_demo.py:59: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ - + self = - + def test_eq_long_text(self): a = "1" * 100 + "a" + "2" * 100 b = "1" * 100 + "b" + "2" * 100 @@ -128,12 +128,12 @@ get on the terminal - we are working on that):: E ? ^ E + 1111111111b222222222 E ? ^ - + failure_demo.py:64: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ - + self = - + def test_eq_long_text_multiline(self): a = "1\n" * 100 + "a" + "2\n" * 100 b = "1\n" * 100 + "b" + "2\n" * 100 @@ -146,25 +146,25 @@ get on the terminal - we are working on that):: E 1 E 1 E 1... - E + E E ...Full output truncated (7 lines hidden), use '-vv' to show - + failure_demo.py:69: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ - + self = - + def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] E assert [0, 1, 2] == [0, 1, 3] E At index 2 diff: 2 != 3 E Use -v to get the full diff - + failure_demo.py:72: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ - + self = - + def test_eq_list_long(self): a = [0] * 100 + [1] + [3] * 100 b = [0] * 100 + [2] + [3] * 100 @@ -172,12 +172,12 @@ get on the terminal - we are working on that):: E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...] E At index 100 diff: 1 != 2 E Use -v to get the full diff - + failure_demo.py:77: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ - + self = - + def test_eq_dict(self): > assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0} E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0} @@ -188,14 +188,14 @@ get on the terminal - we are working on that):: E {'c': 0} E Right contains more items: E {'d': 0}... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:80: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ - + self = - + def test_eq_set(self): > assert {0, 10, 11, 12} == {0, 20, 21} E AssertionError: assert {0, 10, 11, 12} == {0, 20, 21} @@ -206,34 +206,34 @@ get on the terminal - we are working on that):: E Extra items in the right set: E 20 E 21... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:83: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ - + self = - + def test_eq_longer_list(self): > assert [1, 2] == [1, 2, 3] E assert [1, 2] == [1, 2, 3] E Right contains more items, first extra item: 3 E Use -v to get the full diff - + failure_demo.py:86: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ - + self = - + def test_in_list(self): > assert 1 in [0, 2, 3, 4, 5] E assert 1 in [0, 2, 3, 4, 5] - + failure_demo.py:89: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ - + self = - + def test_not_in_text_multiline(self): text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail" > assert "foo" not in text @@ -245,14 +245,14 @@ get on the terminal - we are working on that):: E includes foo E ? +++ E and a... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:93: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ - + self = - + def test_not_in_text_single(self): text = "single foo line" > assert "foo" not in text @@ -260,172 +260,172 @@ get on the terminal - we are working on that):: E 'foo' is contained here: E single foo line E ? +++ - + failure_demo.py:97: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ - + self = - + def test_not_in_text_single_long(self): text = "head " * 50 + "foo " + "tail " * 20 > assert "foo" not in text E AssertionError: assert 'foo' not in 'head head head head hea...ail tail tail tail tail ' E 'foo' is contained here: - E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail + E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? +++ - + failure_demo.py:101: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ - + self = - + def test_not_in_text_single_long_term(self): text = "head " * 50 + "f" * 70 + "tail " * 20 > assert "f" * 70 not in text E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail ' E 'ffffffffffffffffff...fffffffffffffffffff' is contained here: - E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail + E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - + failure_demo.py:105: AssertionError ______________________________ test_attribute ______________________________ - + def test_attribute(): - + class Foo(object): b = 1 - + i = Foo() > assert i.b == 2 E assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b - + failure_demo.py:114: AssertionError _________________________ test_attribute_instance __________________________ - + def test_attribute_instance(): - + class Foo(object): b = 1 - + > assert Foo().b == 2 E AssertionError: assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b E + where .Foo object at 0xdeadbeef> = .Foo'>() - + failure_demo.py:122: AssertionError __________________________ test_attribute_failure __________________________ - + def test_attribute_failure(): - + class Foo(object): - + def _get_b(self): raise Exception("Failed to get attrib") - + b = property(_get_b) - + i = Foo() > assert i.b == 2 - - failure_demo.py:135: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:135: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + self = .Foo object at 0xdeadbeef> - + def _get_b(self): > raise Exception("Failed to get attrib") E Exception: Failed to get attrib - + failure_demo.py:130: Exception _________________________ test_attribute_multiple __________________________ - + def test_attribute_multiple(): - + class Foo(object): b = 1 - + class Bar(object): b = 2 - + > assert Foo().b == Bar().b E AssertionError: assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b E + where .Foo object at 0xdeadbeef> = .Foo'>() E + and 2 = .Bar object at 0xdeadbeef>.b E + where .Bar object at 0xdeadbeef> = .Bar'>() - + failure_demo.py:146: AssertionError __________________________ TestRaises.test_raises __________________________ - + self = - + def test_raises(self): s = "qwe" # NOQA > raises(TypeError, "int(s)") - - failure_demo.py:157: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:157: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + > int(s) E ValueError: invalid literal for int() with base 10: 'qwe' - + <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:634>:1: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ - + self = - + def test_raises_doesnt(self): > raises(IOError, "int('3')") E Failed: DID NOT RAISE - + failure_demo.py:160: Failed __________________________ TestRaises.test_raise ___________________________ - + self = - + def test_raise(self): > raise ValueError("demo error") E ValueError: demo error - + failure_demo.py:163: ValueError ________________________ TestRaises.test_tupleerror ________________________ - + self = - + def test_tupleerror(self): > a, b = [1] # NOQA E ValueError: not enough values to unpack (expected 2, got 1) - + failure_demo.py:166: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ - + self = - + def test_reinterpret_fails_with_print_for_the_fun_of_it(self): items = [1, 2, 3] print("items is %r" % items) > a, b = items.pop() E TypeError: 'int' object is not iterable - + failure_demo.py:171: TypeError --------------------------- Captured stdout call --------------------------- items is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ - + self = - + def test_some_error(self): > if namenotexi: # NOQA E NameError: name 'namenotexi' is not defined - + failure_demo.py:174: NameError ____________________ test_dynamic_compile_shows_nicely _____________________ - + def test_dynamic_compile_shows_nicely(): import imp import sys - + src = "def foo():\n assert 1 == 0\n" name = "abc-123" module = imp.new_module(name) @@ -433,66 +433,66 @@ get on the terminal - we are working on that):: py.builtin.exec_(code, module.__dict__) sys.modules[name] = module > module.foo() - - failure_demo.py:192: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:192: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + def foo(): > assert 1 == 0 E AssertionError - + <2-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:189>:2: AssertionError ____________________ TestMoreErrors.test_complex_error _____________________ - + self = - + def test_complex_error(self): - + def f(): return 44 - + def g(): return 43 - + > somefunc(f(), g()) - - failure_demo.py:205: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + failure_demo.py:205: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ failure_demo.py:11: in somefunc otherfunc(x, y) - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + a = 44, b = 43 - + def otherfunc(a, b): > assert a == b E assert 44 == 43 - + failure_demo.py:7: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ - + self = - + def test_z1_unpack_error(self): items = [] > a, b = items E ValueError: not enough values to unpack (expected 2, got 0) - + failure_demo.py:209: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ - + self = - + def test_z2_type_error(self): items = 3 > a, b = items E TypeError: 'int' object is not iterable - + failure_demo.py:213: TypeError ______________________ TestMoreErrors.test_startswith ______________________ - + self = - + def test_startswith(self): s = "123" g = "456" @@ -500,96 +500,96 @@ get on the terminal - we are working on that):: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - + failure_demo.py:218: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ - + self = - + def test_startswith_nested(self): - + def f(): return "123" - + def g(): return "456" - + > assert f().startswith(g()) E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith E + where '123' = .f at 0xdeadbeef>() E + and '456' = .g at 0xdeadbeef>() - + failure_demo.py:228: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - + self = - + def test_global_func(self): > assert isinstance(globf(42), float) E assert False E + where False = isinstance(43, float) E + where 43 = globf(42) - + failure_demo.py:231: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - + self = - + def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 E + where 42 = .x - + failure_demo.py:235: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - + self = - + def test_compare(self): > assert globf(10) < 5 E assert 11 < 5 E + where 11 = globf(10) - + failure_demo.py:238: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - + self = - + def test_try_finally(self): x = 1 try: > assert x == 0 E assert 1 == 0 - + failure_demo.py:243: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - + self = - + def test_single_line(self): - + class A(object): a = 1 - + b = 2 > assert A.a == b, "A.a appears not to be b" E AssertionError: A.a appears not to be b E assert 1 == 2 E + where 1 = .A'>.a - + failure_demo.py:256: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - + self = - + def test_multiline(self): - + class A(object): a = 1 - + b = 2 > assert ( A.a == b @@ -599,20 +599,20 @@ get on the terminal - we are working on that):: E one of those E assert 1 == 2 E + where 1 = .A'>.a - + failure_demo.py:264: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - + self = - + def test_custom_repr(self): - + class JSON(object): a = 1 - + def __repr__(self): return "This is JSON\n{\n 'foo': 'bar'\n}" - + a = JSON() b = 2 > assert a.a == b, a @@ -622,12 +622,12 @@ get on the terminal - we are working on that):: E } E assert 1 == 2 E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a - + failure_demo.py:278: AssertionError ============================= warnings summary ============================= - None + Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0. Please use Metafunc.parametrize instead. - + -- Docs: http://doc.pytest.org/en/latest/warnings.html ================== 42 failed, 1 warnings in 0.12 seconds =================== diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 180637ae9..b2fd8f8e8 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -49,9 +49,9 @@ Let's run this without supplying our new option:: F [100%] ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + cmdopt = 'type1' - + def test_answer(cmdopt): if cmdopt == "type1": print("first") @@ -59,7 +59,7 @@ Let's run this without supplying our new option:: print("second") > assert 0 # to see what was printed E assert 0 - + test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- first @@ -71,9 +71,9 @@ And now with supplying a command line option:: F [100%] ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + cmdopt = 'type2' - + def test_answer(cmdopt): if cmdopt == "type1": print("first") @@ -81,7 +81,7 @@ And now with supplying a command line option:: print("second") > assert 0 # to see what was printed E assert 0 - + test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- second @@ -124,7 +124,7 @@ directory with the above conftest.py:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= .. _`excontrolskip`: @@ -182,11 +182,11 @@ and when running it will see a skipped "slow" test:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .s [100%] ========================= short test summary info ========================== SKIP [1] test_module.py:8: need --runslow option to run - + =================== 1 passed, 1 skipped in 0.12 seconds ==================== Or run it including the ``slow`` marked test:: @@ -196,9 +196,9 @@ Or run it including the ``slow`` marked test:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .. [100%] - + ========================= 2 passed in 0.12 seconds ========================= Writing well integrated assertion helpers @@ -236,11 +236,11 @@ Let's run our little function:: F [100%] ================================= FAILURES ================================= ______________________________ test_something ______________________________ - + def test_something(): > checkconfig(42) E Failed: not configured: 42 - + test_checkconfig.py:11: Failed 1 failed in 0.12 seconds @@ -335,7 +335,7 @@ which will add the string to the test header accordingly:: project deps: mylib-1.1 rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= .. regendoc:wipe @@ -363,7 +363,7 @@ which will add info only when run with "--v":: did you? rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= and nothing when run plainly:: @@ -373,7 +373,7 @@ and nothing when run plainly:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= profiling test duration @@ -410,9 +410,9 @@ Now we can profile which test functions execute the slowest:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_some_are_slow.py ... [100%] - + ========================= slowest 3 test durations ========================= 0.30s call test_some_are_slow.py::test_funcslow2 0.20s call test_some_are_slow.py::test_funcslow1 @@ -482,18 +482,18 @@ If we run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_step.py .Fx. [100%] - + ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - + self = - + def test_modification(self): > assert 0 E assert 0 - + test_step.py:11: AssertionError ========================= short test summary info ========================== XFAIL test_step.py::TestUserHandling::()::test_deletion @@ -563,12 +563,12 @@ We can run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 7 items - + test_step.py .Fx. [ 57%] a/test_db.py F [ 71%] a/test_db2.py F [ 85%] b/test_error.py E [100%] - + ================================== ERRORS ================================== _______________________ ERROR at setup of test_root ________________________ file $REGENDOC_TMPDIR/b/test_error.py, line 1 @@ -576,37 +576,37 @@ We can run this:: E fixture 'db' not found > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. - + $REGENDOC_TMPDIR/b/test_error.py:1 ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - + self = - + def test_modification(self): > assert 0 E assert 0 - + test_step.py:11: AssertionError _________________________________ test_a1 __________________________________ - + db = - + def test_a1(db): > assert 0, db # to show value E AssertionError: E assert 0 - + a/test_db.py:2: AssertionError _________________________________ test_a2 __________________________________ - + db = - + def test_a2(db): > assert 0, db # to show value E AssertionError: E assert 0 - + a/test_db2.py:2: AssertionError ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.12 seconds ========== @@ -674,25 +674,25 @@ and run them:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py FF [100%] - + ================================= FAILURES ================================= ________________________________ test_fail1 ________________________________ - + tmpdir = local('PYTEST_TMPDIR/test_fail10') - + def test_fail1(tmpdir): > assert 0 E assert 0 - + test_module.py:2: AssertionError ________________________________ test_fail2 ________________________________ - + def test_fail2(): > assert 0 E assert 0 - + test_module.py:6: AssertionError ========================= 2 failed in 0.12 seconds ========================= @@ -773,36 +773,36 @@ and run it:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_module.py Esetting up a test failed! test_module.py::test_setup_fails Fexecuting test failed test_module.py::test_call_fails F - + ================================== ERRORS ================================== ____________________ ERROR at setup of test_setup_fails ____________________ - + @pytest.fixture def other(): > assert 0 E assert 0 - + test_module.py:7: AssertionError ================================= FAILURES ================================= _____________________________ test_call_fails ______________________________ - + something = None - + def test_call_fails(something): > assert 0 E assert 0 - + test_module.py:15: AssertionError ________________________________ test_fail2 ________________________________ - + def test_fail2(): > assert 0 E assert 0 - + test_module.py:19: AssertionError ==================== 2 failed, 1 error in 0.12 seconds ===================== diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index d4d386792..d236b480c 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -73,20 +73,20 @@ marked ``smtp`` fixture function. Running the test looks like this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_smtpsimple.py F [100%] - + ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_smtpsimple.py:11: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -209,32 +209,32 @@ inspect what is going on and can now run the tests:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py FF [100%] - + ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes E assert 0 - + test_module.py:6: AssertionError ________________________________ test_noop _________________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ========================= 2 failed in 0.12 seconds ========================= @@ -337,7 +337,7 @@ Let's execute it:: $ pytest -s -q --tb=no FFteardown smtp - + 2 failed in 0.12 seconds We see that the ``smtp`` instance is finalized after the two @@ -446,7 +446,7 @@ again, nothing much has changed:: $ pytest -s -q --tb=no FFfinalizing (smtp.gmail.com) - + 2 failed in 0.12 seconds Let's quickly create another test module that actually sets the @@ -567,51 +567,51 @@ So let's just do another run:: FFFF [100%] ================================= FAILURES ================================= ________________________ test_ehlo[smtp.gmail.com] _________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes E assert 0 - + test_module.py:6: AssertionError ________________________ test_noop[smtp.gmail.com] _________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ________________________ test_ehlo[mail.python.org] ________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 > assert b"smtp.gmail.com" in msg E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8' - + test_module.py:5: AssertionError -------------------------- Captured stdout setup --------------------------- finalizing ________________________ test_noop[mail.python.org] ________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ------------------------- Captured stdout teardown ------------------------- finalizing @@ -683,7 +683,7 @@ Running the above tests results in the following test IDs being used:: - + ======================= no tests ran in 0.12 seconds ======================= .. _`fixture-parametrize-marks`: @@ -713,11 +713,11 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 3 items - + test_fixture_marks.py::test_data[0] PASSED [ 33%] test_fixture_marks.py::test_data[1] PASSED [ 66%] test_fixture_marks.py::test_data[2] SKIPPED [100%] - + =================== 2 passed, 1 skipped in 0.12 seconds ==================== .. _`interdependent fixtures`: @@ -756,10 +756,10 @@ Here we declare an ``app`` fixture which receives the previously defined cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items - + test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED [ 50%] test_appsetup.py::test_smtp_exists[mail.python.org] PASSED [100%] - + ========================= 2 passed in 0.12 seconds ========================= Due to the parametrization of ``smtp`` the test will run twice with two @@ -825,26 +825,26 @@ Let's run the tests in verbose mode and with looking at the print-output:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items - + test_module.py::test_0[1] SETUP otherarg 1 RUN test0 with otherarg 1 PASSED TEARDOWN otherarg 1 - + test_module.py::test_0[2] SETUP otherarg 2 RUN test0 with otherarg 2 PASSED TEARDOWN otherarg 2 - + test_module.py::test_1[mod1] SETUP modarg mod1 RUN test1 with modarg mod1 PASSED test_module.py::test_2[mod1-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod1 PASSED TEARDOWN otherarg 1 - + test_module.py::test_2[mod1-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod1 PASSED TEARDOWN otherarg 2 - + test_module.py::test_1[mod2] TEARDOWN modarg mod1 SETUP modarg mod2 RUN test1 with modarg mod2 @@ -852,13 +852,13 @@ Let's run the tests in verbose mode and with looking at the print-output:: test_module.py::test_2[mod2-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod2 PASSED TEARDOWN otherarg 1 - + test_module.py::test_2[mod2-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod2 PASSED TEARDOWN otherarg 2 TEARDOWN modarg mod2 - - + + ========================= 8 passed in 0.12 seconds ========================= You can see that the parametrized module-scoped ``modarg`` resource caused an diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index f2dbec5e9..aae0bf971 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -50,17 +50,17 @@ That’s it. You can now execute the test function:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F [100%] - + ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + def test_answer(): > assert func(3) == 5 E assert 4 == 5 E + where 4 = func(3) - + test_sample.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -117,15 +117,15 @@ Once you develop multiple tests, you may want to group them into a class. pytest .F [100%] ================================= FAILURES ================================= ____________________________ TestClass.test_two ____________________________ - + self = - + def test_two(self): x = "hello" > assert hasattr(x, 'check') E AssertionError: assert False E + where False = hasattr('hello', 'check') - + test_class.py:8: AssertionError 1 failed, 1 passed in 0.12 seconds @@ -147,14 +147,14 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look F [100%] ================================= FAILURES ================================= _____________________________ test_needsfiles ______________________________ - + tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') - + def test_needsfiles(tmpdir): print (tmpdir) > assert 0 E assert 0 - + test_tmpdir.py:3: AssertionError --------------------------- Captured stdout call --------------------------- PYTEST_TMPDIR/test_needsfiles0 diff --git a/doc/en/index.rst b/doc/en/index.rst index 6a382e571..0539a1c55 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -29,17 +29,17 @@ To execute it:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F [100%] - + ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + def test_answer(): > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) - + test_sample.py:6: AssertionError ========================= 1 failed in 0.12 seconds ========================= diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index 693cf1913..f87f47d08 100644 --- a/doc/en/parametrize.rst +++ b/doc/en/parametrize.rst @@ -57,14 +57,14 @@ them in turn:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_expectation.py ..F [100%] - + ================================= FAILURES ================================= ____________________________ test_eval[6*9-42] _____________________________ - + test_input = '6*9', expected = 42 - + @pytest.mark.parametrize("test_input,expected", [ ("3+5", 8), ("2+4", 6), @@ -74,7 +74,7 @@ them in turn:: > assert eval(test_input) == expected E AssertionError: assert 54 == 42 E + where 54 = eval('6*9') - + test_expectation.py:8: AssertionError ==================== 1 failed, 2 passed in 0.12 seconds ==================== @@ -106,9 +106,9 @@ Let's run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_expectation.py ..x [100%] - + =================== 2 passed, 1 xfailed in 0.12 seconds ==================== The one parameter set which caused a failure previously now @@ -174,15 +174,15 @@ Let's also run with a stringinput that will lead to a failing test:: F [100%] ================================= FAILURES ================================= ___________________________ test_valid_string[!] ___________________________ - + stringinput = '!' - + def test_valid_string(stringinput): > assert stringinput.isalpha() E AssertionError: assert False E + where False = () E + where = '!'.isalpha - + test_strings.py:3: AssertionError 1 failed in 0.12 seconds diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index bfa6f3e75..a057d1d12 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -334,12 +334,12 @@ Running it with the report-on-xfail option gives this output:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/example, inifile: collected 7 items - + xfail_demo.py xxxxxxx [100%] ========================= short test summary info ========================== XFAIL xfail_demo.py::test_hello XFAIL xfail_demo.py::test_hello2 - reason: [NOTRUN] + reason: [NOTRUN] XFAIL xfail_demo.py::test_hello3 condition: hasattr(os, 'sep') XFAIL xfail_demo.py::test_hello4 @@ -349,7 +349,7 @@ Running it with the report-on-xfail option gives this output:: XFAIL xfail_demo.py::test_hello6 reason: reason XFAIL xfail_demo.py::test_hello7 - + ======================== 7 xfailed in 0.12 seconds ========================= .. _`skip/xfail with parametrize`: diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index 421b4c898..0171e3168 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -32,14 +32,14 @@ Running this would result in a passed test except for the last platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_tmpdir.py F [100%] - + ================================= FAILURES ================================= _____________________________ test_create_file _____________________________ - + tmpdir = local('PYTEST_TMPDIR/test_create_file0') - + def test_create_file(tmpdir): p = tmpdir.mkdir("sub").join("hello.txt") p.write("content") @@ -47,7 +47,7 @@ Running this would result in a passed test except for the last assert len(tmpdir.listdir()) == 1 > assert 0 E assert 0 - + test_tmpdir.py:7: AssertionError ========================= 1 failed in 0.12 seconds ========================= diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 53192b346..ec9f466b9 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -130,30 +130,30 @@ the ``self.db`` values in the traceback:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_unittest_db.py FF [100%] - + ================================= FAILURES ================================= ___________________________ MyTest.test_method1 ____________________________ - + self = - + def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef> E assert 0 - + test_unittest_db.py:9: AssertionError ___________________________ MyTest.test_method2 ____________________________ - + self = - + def test_method2(self): > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef> E assert 0 - + test_unittest_db.py:12: AssertionError ========================= 2 failed in 0.12 seconds ========================= diff --git a/doc/en/usage.rst b/doc/en/usage.rst index 25be54395..07077468a 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -502,7 +502,7 @@ hook was invoked:: $ python myinvoke.py . [100%]*** test run reporting finishing - + .. note:: diff --git a/doc/en/warnings.rst b/doc/en/warnings.rst index df93a02b5..62f96ccf7 100644 --- a/doc/en/warnings.rst +++ b/doc/en/warnings.rst @@ -25,14 +25,14 @@ Running pytest now produces this output:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_show_warnings.py . [100%] - + ============================= warnings summary ============================= test_show_warnings.py::test_one $REGENDOC_TMPDIR/test_show_warnings.py:4: UserWarning: api v1, should use functions from v2 warnings.warn(UserWarning("api v1, should use functions from v2")) - + -- Docs: http://doc.pytest.org/en/latest/warnings.html =================== 1 passed, 1 warnings in 0.12 seconds =================== @@ -45,17 +45,17 @@ them into errors:: F [100%] ================================= FAILURES ================================= _________________________________ test_one _________________________________ - + def test_one(): > assert api_v1() == 1 - - test_show_warnings.py:8: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + test_show_warnings.py:8: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + def api_v1(): > warnings.warn(UserWarning("api v1, should use functions from v2")) E UserWarning: api v1, should use functions from v2 - + test_show_warnings.py:4: UserWarning 1 failed in 0.12 seconds From 46aa18dfa7c46e70ae5c204667f3590181abe25f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 19 Jun 2018 21:34:03 -0300 Subject: [PATCH 16/31] Lint regendoc changes --- doc/en/assert.rst | 20 +- doc/en/builtin.rst | 28 +-- doc/en/cache.rst | 58 ++--- doc/en/capture.rst | 8 +- doc/en/doctest.rst | 4 +- doc/en/example/markers.rst | 92 +++---- doc/en/example/nonpython.rst | 10 +- doc/en/example/parametrize.rst | 34 +-- doc/en/example/pythoncollection.rst | 6 +- doc/en/example/reportingdemo.rst | 368 ++++++++++++++-------------- doc/en/example/simple.rst | 102 ++++---- doc/en/fixture.rst | 80 +++--- doc/en/getting-started.rst | 20 +- doc/en/index.rst | 8 +- doc/en/parametrize.rst | 20 +- doc/en/skipping.rst | 6 +- doc/en/tmpdir.rst | 10 +- doc/en/unittest.rst | 16 +- doc/en/usage.rst | 2 +- doc/en/warnings.rst | 18 +- 20 files changed, 455 insertions(+), 455 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index bcc0a28c9..e0e9b9305 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -29,17 +29,17 @@ you will see the return value of the function call:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_assert1.py F [100%] - + ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + def test_function(): > assert f() == 4 E assert 3 == 4 E + where 3 = f() - + test_assert1.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -172,12 +172,12 @@ if you run this module:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_assert2.py F [100%] - + ================================= FAILURES ================================= ___________________________ test_set_comparison ____________________________ - + def test_set_comparison(): set1 = set("1308") set2 = set("8035") @@ -188,7 +188,7 @@ if you run this module:: E Extra items in the right set: E '5' E Use -v to get the full diff - + test_assert2.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -241,14 +241,14 @@ the conftest file:: F [100%] ================================= FAILURES ================================= _______________________________ test_compare _______________________________ - + def test_compare(): f1 = Foo(1) f2 = Foo(2) > assert f1 == f2 E assert Comparing Foo instances: E vals: 1 != 2 - + test_foocompare.py:11: AssertionError 1 failed in 0.12 seconds diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index f5e1fd155..c2d23469b 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -17,13 +17,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a $ pytest -q --fixtures cache Return a cache object that can persist state between testing sessions. - + cache.get(key, default) cache.set(key, value) - + Keys must be a ``/`` separated value, where the first part is usually the name of your plugin or application to avoid clashes with other cache users. - + Values can be any object handled by the json stdlib module. capsys Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make @@ -49,9 +49,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. pytestconfig Session-scoped fixture that returns the :class:`_pytest.config.Config` object. - + Example:: - + def test_foo(pytestconfig): if pytestconfig.getoption("verbose"): ... @@ -61,9 +61,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a configured reporters, like JUnit XML. The fixture is callable with ``(name, value)``, with value being automatically xml-encoded. - + Example:: - + def test_function(record_property): record_property("example_key", 1) record_xml_property @@ -74,9 +74,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a automatically xml-encoded caplog Access and control log capturing. - + Captured logs are available through the following methods:: - + * caplog.text -> string containing formatted log output * caplog.records -> list of logging.LogRecord instances * caplog.record_tuples -> list of (logger_name, level, message) tuples @@ -84,7 +84,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch The returned ``monkeypatch`` fixture provides these helper methods to modify objects, dictionaries or os.environ:: - + monkeypatch.setattr(obj, name, value, raising=True) monkeypatch.delattr(obj, name, raising=True) monkeypatch.setitem(mapping, name, value) @@ -93,14 +93,14 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a monkeypatch.delenv(name, value, raising=True) monkeypatch.syspath_prepend(path) monkeypatch.chdir(path) - + All modifications will be undone after the requesting test function or fixture has finished. The ``raising`` parameter determines if a KeyError or AttributeError will be raised if the set/deletion operation has no target. recwarn Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. - + See http://docs.python.org/library/warnings.html for information on warning categories. tmpdir_factory @@ -111,9 +111,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a created as a sub directory of the base temporary directory. The returned object is a `py.path.local`_ path object. - + .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html - + no tests ran in 0.12 seconds You can also interactively ask for help, e.g. by typing on the Python interactive prompt something like:: diff --git a/doc/en/cache.rst b/doc/en/cache.rst index 437109db0..37bcf7070 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -49,26 +49,26 @@ If you run this for the first time you will see two failures:: .................F.......F........................ [100%] ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed 2 failed, 48 passed in 0.12 seconds @@ -80,31 +80,31 @@ If you then run it with ``--lf``:: rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items / 48 deselected run-last-failure: rerun previous 2 failures - + test_50.py FF [100%] - + ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed ================= 2 failed, 48 deselected in 0.12 seconds ================== @@ -121,31 +121,31 @@ of ``FF`` and dots):: rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items run-last-failure: rerun previous 2 failures first - + test_50.py FF................................................ [100%] - + ================================= FAILURES ================================= _______________________________ test_num[17] _______________________________ - + i = 17 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed _______________________________ test_num[25] _______________________________ - + i = 25 - + @pytest.mark.parametrize("i", range(50)) def test_num(i): if i in (17, 25): > pytest.fail("bad luck") E Failed: bad luck - + test_50.py:6: Failed =================== 2 failed, 48 passed in 0.12 seconds ==================== @@ -198,13 +198,13 @@ of the sleep:: F [100%] ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + mydata = 42 - + def test_function(mydata): > assert mydata == 23 E assert 42 == 23 - + test_caching.py:14: AssertionError 1 failed in 0.12 seconds @@ -215,13 +215,13 @@ the cache and this will be quick:: F [100%] ================================= FAILURES ================================= ______________________________ test_function _______________________________ - + mydata = 42 - + def test_function(mydata): > assert mydata == 23 E assert 42 == 23 - + test_caching.py:14: AssertionError 1 failed in 0.12 seconds @@ -246,7 +246,7 @@ You can always peek at the content of the cache using the ['test_caching.py::test_function'] example/value contains: 42 - + ======================= no tests ran in 0.12 seconds ======================= Clearing Cache content diff --git a/doc/en/capture.rst b/doc/en/capture.rst index 549845cc9..ab86fb55f 100644 --- a/doc/en/capture.rst +++ b/doc/en/capture.rst @@ -68,16 +68,16 @@ of the failing function and hide the other one:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .F [100%] - + ================================= FAILURES ================================= ________________________________ test_func2 ________________________________ - + def test_func2(): > assert False E assert False - + test_module.py:9: AssertionError -------------------------- Captured stdout setup --------------------------- setting up diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index ac470d105..9488ee826 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -65,9 +65,9 @@ then you can just invoke ``pytest`` without command line options:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 1 item - + mymodule.py . [100%] - + ========================= 1 passed in 0.12 seconds ========================= It is possible to use fixtures using the ``getfixture`` helper:: diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 176fdccdb..bf352bc81 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -35,9 +35,9 @@ You can then restrict a test run to only run tests marked with ``webtest``:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected - + test_server.py::test_send_http PASSED [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== Or the inverse, running all tests except the webtest ones:: @@ -48,11 +48,11 @@ Or the inverse, running all tests except the webtest ones:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected - + test_server.py::test_something_quick PASSED [ 33%] test_server.py::test_another PASSED [ 66%] test_server.py::TestClass::test_method PASSED [100%] - + ================== 3 passed, 1 deselected in 0.12 seconds ================== Selecting tests based on their node ID @@ -68,9 +68,9 @@ tests based on their module, class, method, or function name:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item - + test_server.py::TestClass::test_method PASSED [100%] - + ========================= 1 passed in 0.12 seconds ========================= You can also select on the class:: @@ -81,9 +81,9 @@ You can also select on the class:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item - + test_server.py::TestClass::test_method PASSED [100%] - + ========================= 1 passed in 0.12 seconds ========================= Or select multiple nodes:: @@ -94,10 +94,10 @@ Or select multiple nodes:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items - + test_server.py::TestClass::test_method PASSED [ 50%] test_server.py::test_send_http PASSED [100%] - + ========================= 2 passed in 0.12 seconds ========================= .. _node-id: @@ -132,9 +132,9 @@ select tests based on their names:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected - + test_server.py::test_send_http PASSED [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== And you can also run all tests except the ones that match the keyword:: @@ -145,11 +145,11 @@ And you can also run all tests except the ones that match the keyword:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected - + test_server.py::test_something_quick PASSED [ 33%] test_server.py::test_another PASSED [ 66%] test_server.py::TestClass::test_method PASSED [100%] - + ================== 3 passed, 1 deselected in 0.12 seconds ================== Or to select "http" and "quick" tests:: @@ -160,10 +160,10 @@ Or to select "http" and "quick" tests:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 2 deselected - + test_server.py::test_send_http PASSED [ 50%] test_server.py::test_something_quick PASSED [100%] - + ================== 2 passed, 2 deselected in 0.12 seconds ================== .. note:: @@ -199,21 +199,21 @@ You can ask which markers exist for your test suite - the list includes our just $ pytest --markers @pytest.mark.webtest: mark a test as a webtest. - + @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test. - + @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html - + @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. - - @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures - + + @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures + @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible. - + @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible. - + For an example on how to add and work with markers from a plugin, see :ref:`adding a custom marker from a plugin`. @@ -352,9 +352,9 @@ the test needs:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_someenv.py s [100%] - + ======================== 1 skipped in 0.12 seconds ========================= and here is one that specifies exactly the environment needed:: @@ -364,30 +364,30 @@ and here is one that specifies exactly the environment needed:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_someenv.py . [100%] - + ========================= 1 passed in 0.12 seconds ========================= The ``--markers`` option always gives you a list of available markers:: $ pytest --markers @pytest.mark.env(name): mark test to run only on named environment - + @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test. - + @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html - + @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. - - @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures - + + @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures + @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible. - + @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible. - + .. _`passing callables to custom markers`: @@ -523,11 +523,11 @@ then you will see two tests skipped and two executed tests as expected:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_plat.py s.s. [100%] ========================= short test summary info ========================== SKIP [2] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux - + =================== 2 passed, 2 skipped in 0.12 seconds ==================== Note that if you specify a platform via the marker-command line option like this:: @@ -537,9 +537,9 @@ Note that if you specify a platform via the marker-command line option like this platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 3 deselected - + test_plat.py . [100%] - + ================== 1 passed, 3 deselected in 0.12 seconds ================== then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests. @@ -588,9 +588,9 @@ We can now use the ``-m option`` to select one set:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 2 deselected - + test_module.py FF [100%] - + ================================= FAILURES ================================= __________________________ test_interface_simple ___________________________ test_module.py:3: in test_interface_simple @@ -609,9 +609,9 @@ or to select both "event" and "interface" tests:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items / 1 deselected - + test_module.py FFF [100%] - + ================================= FAILURES ================================= __________________________ test_interface_simple ___________________________ test_module.py:3: in test_interface_simple diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index ca7b2c8df..4f5adf63f 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -30,9 +30,9 @@ now execute the test specification:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collected 2 items - + test_simple.yml F. [100%] - + ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ usecase execution failed @@ -63,10 +63,10 @@ consulted when reporting in ``verbose`` mode:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collecting ... collected 2 items - + test_simple.yml::hello FAILED [ 50%] test_simple.yml::ok PASSED [100%] - + ================================= FAILURES ================================= ______________________________ usecase: hello ______________________________ usecase execution failed @@ -87,5 +87,5 @@ interesting to just look at the collection tree:: - + ======================= no tests ran in 0.12 seconds ======================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 49ffa7288..882700fec 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -55,13 +55,13 @@ let's run the full monty:: ....F [100%] ================================= FAILURES ================================= _____________________________ test_compute[4] ______________________________ - + param1 = 4 - + def test_compute(param1): > assert param1 < 4 E assert 4 < 4 - + test_compute.py:3: AssertionError 1 failed, 4 passed in 0.12 seconds @@ -151,7 +151,7 @@ objects, they are still using the default pytest representation:: - + ======================= no tests ran in 0.12 seconds ======================= In ``test_timedistance_v3``, we used ``pytest.param`` to specify the test IDs @@ -198,9 +198,9 @@ this is a fully self-contained example which you can run with:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_scenarios.py .... [100%] - + ========================= 4 passed in 0.12 seconds ========================= If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function:: @@ -218,7 +218,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia - + ======================= no tests ran in 0.12 seconds ======================= Note that we told ``metafunc.parametrize()`` that your scenario values @@ -279,7 +279,7 @@ Let's first see how it looks like at collection time:: - + ======================= no tests ran in 0.12 seconds ======================= And then when we run the test:: @@ -288,15 +288,15 @@ And then when we run the test:: .F [100%] ================================= FAILURES ================================= _________________________ test_db_initialized[d2] __________________________ - + db = - + def test_db_initialized(db): # a dummy test if db.__class__.__name__ == "DB2": > pytest.fail("deliberately failing for demo purposes") E Failed: deliberately failing for demo purposes - + test_backends.py:6: Failed 1 failed, 1 passed in 0.12 seconds @@ -339,7 +339,7 @@ The result of this test will be successful:: collected 1 item - + ======================= no tests ran in 0.12 seconds ======================= .. regendoc:wipe @@ -384,13 +384,13 @@ argument sets to use for each test function. Let's run it:: F.. [100%] ================================= FAILURES ================================= ________________________ TestClass.test_equals[1-2] ________________________ - + self = , a = 1, b = 2 - + def test_equals(self, a, b): > assert a == b E assert 1 == 2 - + test_parametrize.py:18: AssertionError 1 failed, 2 passed in 0.12 seconds @@ -462,11 +462,11 @@ If you run this with reporting for skips enabled:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .s [100%] ========================= short test summary info ========================== SKIP [1] $REGENDOC_TMPDIR/conftest.py:11: could not import 'opt2' - + =================== 1 passed, 1 skipped in 0.12 seconds ==================== You'll see that we don't have an ``opt2`` module and thus the second test run diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 58b4364b5..8e9d3ae62 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -133,7 +133,7 @@ then the test collection looks like this:: - + ======================= no tests ran in 0.12 seconds ======================= .. note:: @@ -180,7 +180,7 @@ You can always peek at the collection tree without running tests like this:: - + ======================= no tests ran in 0.12 seconds ======================= .. _customizing-test-collection: @@ -243,5 +243,5 @@ file will be left out:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 00aa3c842..4691b128b 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -14,83 +14,83 @@ get on the terminal - we are working on that):: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/assertion, inifile: collected 42 items - + failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF [100%] - + ================================= FAILURES ================================= ____________________________ test_generative[0] ____________________________ - + param1 = 3, param2 = 6 - + def test_generative(param1, param2): > assert param1 * 2 < param2 E assert (3 * 2) < 6 - + failure_demo.py:19: AssertionError _________________________ TestFailing.test_simple __________________________ - + self = - + def test_simple(self): - + def f(): return 42 - + def g(): return 43 - + > assert f() == g() E assert 42 == 43 E + where 42 = .f at 0xdeadbeef>() E + and 43 = .g at 0xdeadbeef>() - + failure_demo.py:37: AssertionError ____________________ TestFailing.test_simple_multiline _____________________ - + self = - + def test_simple_multiline(self): > otherfunc_multi(42, 6 * 9) - - failure_demo.py:40: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:40: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + a = 42, b = 54 - + def otherfunc_multi(a, b): > assert a == b E assert 42 == 54 - + failure_demo.py:15: AssertionError ___________________________ TestFailing.test_not ___________________________ - + self = - + def test_not(self): - + def f(): return 42 - + > assert not f() E assert not 42 E + where 42 = .f at 0xdeadbeef>() - + failure_demo.py:47: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ - + self = - + def test_eq_text(self): > assert "spam" == "eggs" E AssertionError: assert 'spam' == 'eggs' E - spam E + eggs - + failure_demo.py:53: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ - + self = - + def test_eq_similar_text(self): > assert "foo 1 bar" == "foo 2 bar" E AssertionError: assert 'foo 1 bar' == 'foo 2 bar' @@ -98,12 +98,12 @@ get on the terminal - we are working on that):: E ? ^ E + foo 2 bar E ? ^ - + failure_demo.py:56: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ - + self = - + def test_eq_multiline_text(self): > assert "foo\nspam\nbar" == "foo\neggs\nbar" E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar' @@ -111,12 +111,12 @@ get on the terminal - we are working on that):: E - spam E + eggs E bar - + failure_demo.py:59: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ - + self = - + def test_eq_long_text(self): a = "1" * 100 + "a" + "2" * 100 b = "1" * 100 + "b" + "2" * 100 @@ -128,12 +128,12 @@ get on the terminal - we are working on that):: E ? ^ E + 1111111111b222222222 E ? ^ - + failure_demo.py:64: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ - + self = - + def test_eq_long_text_multiline(self): a = "1\n" * 100 + "a" + "2\n" * 100 b = "1\n" * 100 + "b" + "2\n" * 100 @@ -146,25 +146,25 @@ get on the terminal - we are working on that):: E 1 E 1 E 1... - E + E E ...Full output truncated (7 lines hidden), use '-vv' to show - + failure_demo.py:69: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ - + self = - + def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] E assert [0, 1, 2] == [0, 1, 3] E At index 2 diff: 2 != 3 E Use -v to get the full diff - + failure_demo.py:72: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ - + self = - + def test_eq_list_long(self): a = [0] * 100 + [1] + [3] * 100 b = [0] * 100 + [2] + [3] * 100 @@ -172,12 +172,12 @@ get on the terminal - we are working on that):: E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...] E At index 100 diff: 1 != 2 E Use -v to get the full diff - + failure_demo.py:77: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ - + self = - + def test_eq_dict(self): > assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0} E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0} @@ -188,14 +188,14 @@ get on the terminal - we are working on that):: E {'c': 0} E Right contains more items: E {'d': 0}... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:80: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ - + self = - + def test_eq_set(self): > assert {0, 10, 11, 12} == {0, 20, 21} E AssertionError: assert {0, 10, 11, 12} == {0, 20, 21} @@ -206,34 +206,34 @@ get on the terminal - we are working on that):: E Extra items in the right set: E 20 E 21... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:83: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ - + self = - + def test_eq_longer_list(self): > assert [1, 2] == [1, 2, 3] E assert [1, 2] == [1, 2, 3] E Right contains more items, first extra item: 3 E Use -v to get the full diff - + failure_demo.py:86: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ - + self = - + def test_in_list(self): > assert 1 in [0, 2, 3, 4, 5] E assert 1 in [0, 2, 3, 4, 5] - + failure_demo.py:89: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ - + self = - + def test_not_in_text_multiline(self): text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail" > assert "foo" not in text @@ -245,14 +245,14 @@ get on the terminal - we are working on that):: E includes foo E ? +++ E and a... - E + E E ...Full output truncated (2 lines hidden), use '-vv' to show - + failure_demo.py:93: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ - + self = - + def test_not_in_text_single(self): text = "single foo line" > assert "foo" not in text @@ -260,172 +260,172 @@ get on the terminal - we are working on that):: E 'foo' is contained here: E single foo line E ? +++ - + failure_demo.py:97: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ - + self = - + def test_not_in_text_single_long(self): text = "head " * 50 + "foo " + "tail " * 20 > assert "foo" not in text E AssertionError: assert 'foo' not in 'head head head head hea...ail tail tail tail tail ' E 'foo' is contained here: - E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail + E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? +++ - + failure_demo.py:101: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ - + self = - + def test_not_in_text_single_long_term(self): text = "head " * 50 + "f" * 70 + "tail " * 20 > assert "f" * 70 not in text E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail ' E 'ffffffffffffffffff...fffffffffffffffffff' is contained here: - E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail + E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - + failure_demo.py:105: AssertionError ______________________________ test_attribute ______________________________ - + def test_attribute(): - + class Foo(object): b = 1 - + i = Foo() > assert i.b == 2 E assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b - + failure_demo.py:114: AssertionError _________________________ test_attribute_instance __________________________ - + def test_attribute_instance(): - + class Foo(object): b = 1 - + > assert Foo().b == 2 E AssertionError: assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b E + where .Foo object at 0xdeadbeef> = .Foo'>() - + failure_demo.py:122: AssertionError __________________________ test_attribute_failure __________________________ - + def test_attribute_failure(): - + class Foo(object): - + def _get_b(self): raise Exception("Failed to get attrib") - + b = property(_get_b) - + i = Foo() > assert i.b == 2 - - failure_demo.py:135: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:135: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + self = .Foo object at 0xdeadbeef> - + def _get_b(self): > raise Exception("Failed to get attrib") E Exception: Failed to get attrib - + failure_demo.py:130: Exception _________________________ test_attribute_multiple __________________________ - + def test_attribute_multiple(): - + class Foo(object): b = 1 - + class Bar(object): b = 2 - + > assert Foo().b == Bar().b E AssertionError: assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef>.b E + where .Foo object at 0xdeadbeef> = .Foo'>() E + and 2 = .Bar object at 0xdeadbeef>.b E + where .Bar object at 0xdeadbeef> = .Bar'>() - + failure_demo.py:146: AssertionError __________________________ TestRaises.test_raises __________________________ - + self = - + def test_raises(self): s = "qwe" # NOQA > raises(TypeError, "int(s)") - - failure_demo.py:157: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:157: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + > int(s) E ValueError: invalid literal for int() with base 10: 'qwe' - + <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:634>:1: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ - + self = - + def test_raises_doesnt(self): > raises(IOError, "int('3')") E Failed: DID NOT RAISE - + failure_demo.py:160: Failed __________________________ TestRaises.test_raise ___________________________ - + self = - + def test_raise(self): > raise ValueError("demo error") E ValueError: demo error - + failure_demo.py:163: ValueError ________________________ TestRaises.test_tupleerror ________________________ - + self = - + def test_tupleerror(self): > a, b = [1] # NOQA E ValueError: not enough values to unpack (expected 2, got 1) - + failure_demo.py:166: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ - + self = - + def test_reinterpret_fails_with_print_for_the_fun_of_it(self): items = [1, 2, 3] print("items is %r" % items) > a, b = items.pop() E TypeError: 'int' object is not iterable - + failure_demo.py:171: TypeError --------------------------- Captured stdout call --------------------------- items is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ - + self = - + def test_some_error(self): > if namenotexi: # NOQA E NameError: name 'namenotexi' is not defined - + failure_demo.py:174: NameError ____________________ test_dynamic_compile_shows_nicely _____________________ - + def test_dynamic_compile_shows_nicely(): import imp import sys - + src = "def foo():\n assert 1 == 0\n" name = "abc-123" module = imp.new_module(name) @@ -433,66 +433,66 @@ get on the terminal - we are working on that):: py.builtin.exec_(code, module.__dict__) sys.modules[name] = module > module.foo() - - failure_demo.py:192: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + failure_demo.py:192: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + def foo(): > assert 1 == 0 E AssertionError - + <2-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:189>:2: AssertionError ____________________ TestMoreErrors.test_complex_error _____________________ - + self = - + def test_complex_error(self): - + def f(): return 44 - + def g(): return 43 - + > somefunc(f(), g()) - - failure_demo.py:205: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + + failure_demo.py:205: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ failure_demo.py:11: in somefunc otherfunc(x, y) - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + a = 44, b = 43 - + def otherfunc(a, b): > assert a == b E assert 44 == 43 - + failure_demo.py:7: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ - + self = - + def test_z1_unpack_error(self): items = [] > a, b = items E ValueError: not enough values to unpack (expected 2, got 0) - + failure_demo.py:209: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ - + self = - + def test_z2_type_error(self): items = 3 > a, b = items E TypeError: 'int' object is not iterable - + failure_demo.py:213: TypeError ______________________ TestMoreErrors.test_startswith ______________________ - + self = - + def test_startswith(self): s = "123" g = "456" @@ -500,96 +500,96 @@ get on the terminal - we are working on that):: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - + failure_demo.py:218: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ - + self = - + def test_startswith_nested(self): - + def f(): return "123" - + def g(): return "456" - + > assert f().startswith(g()) E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith E + where '123' = .f at 0xdeadbeef>() E + and '456' = .g at 0xdeadbeef>() - + failure_demo.py:228: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - + self = - + def test_global_func(self): > assert isinstance(globf(42), float) E assert False E + where False = isinstance(43, float) E + where 43 = globf(42) - + failure_demo.py:231: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - + self = - + def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 E + where 42 = .x - + failure_demo.py:235: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - + self = - + def test_compare(self): > assert globf(10) < 5 E assert 11 < 5 E + where 11 = globf(10) - + failure_demo.py:238: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - + self = - + def test_try_finally(self): x = 1 try: > assert x == 0 E assert 1 == 0 - + failure_demo.py:243: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - + self = - + def test_single_line(self): - + class A(object): a = 1 - + b = 2 > assert A.a == b, "A.a appears not to be b" E AssertionError: A.a appears not to be b E assert 1 == 2 E + where 1 = .A'>.a - + failure_demo.py:256: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - + self = - + def test_multiline(self): - + class A(object): a = 1 - + b = 2 > assert ( A.a == b @@ -599,20 +599,20 @@ get on the terminal - we are working on that):: E one of those E assert 1 == 2 E + where 1 = .A'>.a - + failure_demo.py:264: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - + self = - + def test_custom_repr(self): - + class JSON(object): a = 1 - + def __repr__(self): return "This is JSON\n{\n 'foo': 'bar'\n}" - + a = JSON() b = 2 > assert a.a == b, a @@ -622,12 +622,12 @@ get on the terminal - we are working on that):: E } E assert 1 == 2 E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a - + failure_demo.py:278: AssertionError ============================= warnings summary ============================= Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0. Please use Metafunc.parametrize instead. - + -- Docs: http://doc.pytest.org/en/latest/warnings.html ================== 42 failed, 1 warnings in 0.12 seconds =================== diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index b2fd8f8e8..180637ae9 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -49,9 +49,9 @@ Let's run this without supplying our new option:: F [100%] ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + cmdopt = 'type1' - + def test_answer(cmdopt): if cmdopt == "type1": print("first") @@ -59,7 +59,7 @@ Let's run this without supplying our new option:: print("second") > assert 0 # to see what was printed E assert 0 - + test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- first @@ -71,9 +71,9 @@ And now with supplying a command line option:: F [100%] ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + cmdopt = 'type2' - + def test_answer(cmdopt): if cmdopt == "type1": print("first") @@ -81,7 +81,7 @@ And now with supplying a command line option:: print("second") > assert 0 # to see what was printed E assert 0 - + test_sample.py:6: AssertionError --------------------------- Captured stdout call --------------------------- second @@ -124,7 +124,7 @@ directory with the above conftest.py:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= .. _`excontrolskip`: @@ -182,11 +182,11 @@ and when running it will see a skipped "slow" test:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .s [100%] ========================= short test summary info ========================== SKIP [1] test_module.py:8: need --runslow option to run - + =================== 1 passed, 1 skipped in 0.12 seconds ==================== Or run it including the ``slow`` marked test:: @@ -196,9 +196,9 @@ Or run it including the ``slow`` marked test:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py .. [100%] - + ========================= 2 passed in 0.12 seconds ========================= Writing well integrated assertion helpers @@ -236,11 +236,11 @@ Let's run our little function:: F [100%] ================================= FAILURES ================================= ______________________________ test_something ______________________________ - + def test_something(): > checkconfig(42) E Failed: not configured: 42 - + test_checkconfig.py:11: Failed 1 failed in 0.12 seconds @@ -335,7 +335,7 @@ which will add the string to the test header accordingly:: project deps: mylib-1.1 rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= .. regendoc:wipe @@ -363,7 +363,7 @@ which will add info only when run with "--v":: did you? rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= and nothing when run plainly:: @@ -373,7 +373,7 @@ and nothing when run plainly:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items - + ======================= no tests ran in 0.12 seconds ======================= profiling test duration @@ -410,9 +410,9 @@ Now we can profile which test functions execute the slowest:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_some_are_slow.py ... [100%] - + ========================= slowest 3 test durations ========================= 0.30s call test_some_are_slow.py::test_funcslow2 0.20s call test_some_are_slow.py::test_funcslow1 @@ -482,18 +482,18 @@ If we run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - + test_step.py .Fx. [100%] - + ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - + self = - + def test_modification(self): > assert 0 E assert 0 - + test_step.py:11: AssertionError ========================= short test summary info ========================== XFAIL test_step.py::TestUserHandling::()::test_deletion @@ -563,12 +563,12 @@ We can run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 7 items - + test_step.py .Fx. [ 57%] a/test_db.py F [ 71%] a/test_db2.py F [ 85%] b/test_error.py E [100%] - + ================================== ERRORS ================================== _______________________ ERROR at setup of test_root ________________________ file $REGENDOC_TMPDIR/b/test_error.py, line 1 @@ -576,37 +576,37 @@ We can run this:: E fixture 'db' not found > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. - + $REGENDOC_TMPDIR/b/test_error.py:1 ================================= FAILURES ================================= ____________________ TestUserHandling.test_modification ____________________ - + self = - + def test_modification(self): > assert 0 E assert 0 - + test_step.py:11: AssertionError _________________________________ test_a1 __________________________________ - + db = - + def test_a1(db): > assert 0, db # to show value E AssertionError: E assert 0 - + a/test_db.py:2: AssertionError _________________________________ test_a2 __________________________________ - + db = - + def test_a2(db): > assert 0, db # to show value E AssertionError: E assert 0 - + a/test_db2.py:2: AssertionError ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.12 seconds ========== @@ -674,25 +674,25 @@ and run them:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py FF [100%] - + ================================= FAILURES ================================= ________________________________ test_fail1 ________________________________ - + tmpdir = local('PYTEST_TMPDIR/test_fail10') - + def test_fail1(tmpdir): > assert 0 E assert 0 - + test_module.py:2: AssertionError ________________________________ test_fail2 ________________________________ - + def test_fail2(): > assert 0 E assert 0 - + test_module.py:6: AssertionError ========================= 2 failed in 0.12 seconds ========================= @@ -773,36 +773,36 @@ and run it:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_module.py Esetting up a test failed! test_module.py::test_setup_fails Fexecuting test failed test_module.py::test_call_fails F - + ================================== ERRORS ================================== ____________________ ERROR at setup of test_setup_fails ____________________ - + @pytest.fixture def other(): > assert 0 E assert 0 - + test_module.py:7: AssertionError ================================= FAILURES ================================= _____________________________ test_call_fails ______________________________ - + something = None - + def test_call_fails(something): > assert 0 E assert 0 - + test_module.py:15: AssertionError ________________________________ test_fail2 ________________________________ - + def test_fail2(): > assert 0 E assert 0 - + test_module.py:19: AssertionError ==================== 2 failed, 1 error in 0.12 seconds ===================== diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index d236b480c..d4d386792 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -73,20 +73,20 @@ marked ``smtp`` fixture function. Running the test looks like this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_smtpsimple.py F [100%] - + ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_smtpsimple.py:11: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -209,32 +209,32 @@ inspect what is going on and can now run the tests:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_module.py FF [100%] - + ================================= FAILURES ================================= ________________________________ test_ehlo _________________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes E assert 0 - + test_module.py:6: AssertionError ________________________________ test_noop _________________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ========================= 2 failed in 0.12 seconds ========================= @@ -337,7 +337,7 @@ Let's execute it:: $ pytest -s -q --tb=no FFteardown smtp - + 2 failed in 0.12 seconds We see that the ``smtp`` instance is finalized after the two @@ -446,7 +446,7 @@ again, nothing much has changed:: $ pytest -s -q --tb=no FFfinalizing (smtp.gmail.com) - + 2 failed in 0.12 seconds Let's quickly create another test module that actually sets the @@ -567,51 +567,51 @@ So let's just do another run:: FFFF [100%] ================================= FAILURES ================================= ________________________ test_ehlo[smtp.gmail.com] _________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes E assert 0 - + test_module.py:6: AssertionError ________________________ test_noop[smtp.gmail.com] _________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ________________________ test_ehlo[mail.python.org] ________________________ - + smtp = - + def test_ehlo(smtp): response, msg = smtp.ehlo() assert response == 250 > assert b"smtp.gmail.com" in msg E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8' - + test_module.py:5: AssertionError -------------------------- Captured stdout setup --------------------------- finalizing ________________________ test_noop[mail.python.org] ________________________ - + smtp = - + def test_noop(smtp): response, msg = smtp.noop() assert response == 250 > assert 0 # for demo purposes E assert 0 - + test_module.py:11: AssertionError ------------------------- Captured stdout teardown ------------------------- finalizing @@ -683,7 +683,7 @@ Running the above tests results in the following test IDs being used:: - + ======================= no tests ran in 0.12 seconds ======================= .. _`fixture-parametrize-marks`: @@ -713,11 +713,11 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 3 items - + test_fixture_marks.py::test_data[0] PASSED [ 33%] test_fixture_marks.py::test_data[1] PASSED [ 66%] test_fixture_marks.py::test_data[2] SKIPPED [100%] - + =================== 2 passed, 1 skipped in 0.12 seconds ==================== .. _`interdependent fixtures`: @@ -756,10 +756,10 @@ Here we declare an ``app`` fixture which receives the previously defined cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items - + test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED [ 50%] test_appsetup.py::test_smtp_exists[mail.python.org] PASSED [100%] - + ========================= 2 passed in 0.12 seconds ========================= Due to the parametrization of ``smtp`` the test will run twice with two @@ -825,26 +825,26 @@ Let's run the tests in verbose mode and with looking at the print-output:: cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items - + test_module.py::test_0[1] SETUP otherarg 1 RUN test0 with otherarg 1 PASSED TEARDOWN otherarg 1 - + test_module.py::test_0[2] SETUP otherarg 2 RUN test0 with otherarg 2 PASSED TEARDOWN otherarg 2 - + test_module.py::test_1[mod1] SETUP modarg mod1 RUN test1 with modarg mod1 PASSED test_module.py::test_2[mod1-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod1 PASSED TEARDOWN otherarg 1 - + test_module.py::test_2[mod1-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod1 PASSED TEARDOWN otherarg 2 - + test_module.py::test_1[mod2] TEARDOWN modarg mod1 SETUP modarg mod2 RUN test1 with modarg mod2 @@ -852,13 +852,13 @@ Let's run the tests in verbose mode and with looking at the print-output:: test_module.py::test_2[mod2-1] SETUP otherarg 1 RUN test2 with otherarg 1 and modarg mod2 PASSED TEARDOWN otherarg 1 - + test_module.py::test_2[mod2-2] SETUP otherarg 2 RUN test2 with otherarg 2 and modarg mod2 PASSED TEARDOWN otherarg 2 TEARDOWN modarg mod2 - - + + ========================= 8 passed in 0.12 seconds ========================= You can see that the parametrized module-scoped ``modarg`` resource caused an diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index aae0bf971..f2dbec5e9 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -50,17 +50,17 @@ That’s it. You can now execute the test function:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F [100%] - + ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + def test_answer(): > assert func(3) == 5 E assert 4 == 5 E + where 4 = func(3) - + test_sample.py:5: AssertionError ========================= 1 failed in 0.12 seconds ========================= @@ -117,15 +117,15 @@ Once you develop multiple tests, you may want to group them into a class. pytest .F [100%] ================================= FAILURES ================================= ____________________________ TestClass.test_two ____________________________ - + self = - + def test_two(self): x = "hello" > assert hasattr(x, 'check') E AssertionError: assert False E + where False = hasattr('hello', 'check') - + test_class.py:8: AssertionError 1 failed, 1 passed in 0.12 seconds @@ -147,14 +147,14 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look F [100%] ================================= FAILURES ================================= _____________________________ test_needsfiles ______________________________ - + tmpdir = local('PYTEST_TMPDIR/test_needsfiles0') - + def test_needsfiles(tmpdir): print (tmpdir) > assert 0 E assert 0 - + test_tmpdir.py:3: AssertionError --------------------------- Captured stdout call --------------------------- PYTEST_TMPDIR/test_needsfiles0 diff --git a/doc/en/index.rst b/doc/en/index.rst index 0539a1c55..6a382e571 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -29,17 +29,17 @@ To execute it:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_sample.py F [100%] - + ================================= FAILURES ================================= _______________________________ test_answer ________________________________ - + def test_answer(): > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) - + test_sample.py:6: AssertionError ========================= 1 failed in 0.12 seconds ========================= diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index f87f47d08..693cf1913 100644 --- a/doc/en/parametrize.rst +++ b/doc/en/parametrize.rst @@ -57,14 +57,14 @@ them in turn:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_expectation.py ..F [100%] - + ================================= FAILURES ================================= ____________________________ test_eval[6*9-42] _____________________________ - + test_input = '6*9', expected = 42 - + @pytest.mark.parametrize("test_input,expected", [ ("3+5", 8), ("2+4", 6), @@ -74,7 +74,7 @@ them in turn:: > assert eval(test_input) == expected E AssertionError: assert 54 == 42 E + where 54 = eval('6*9') - + test_expectation.py:8: AssertionError ==================== 1 failed, 2 passed in 0.12 seconds ==================== @@ -106,9 +106,9 @@ Let's run this:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items - + test_expectation.py ..x [100%] - + =================== 2 passed, 1 xfailed in 0.12 seconds ==================== The one parameter set which caused a failure previously now @@ -174,15 +174,15 @@ Let's also run with a stringinput that will lead to a failing test:: F [100%] ================================= FAILURES ================================= ___________________________ test_valid_string[!] ___________________________ - + stringinput = '!' - + def test_valid_string(stringinput): > assert stringinput.isalpha() E AssertionError: assert False E + where False = () E + where = '!'.isalpha - + test_strings.py:3: AssertionError 1 failed in 0.12 seconds diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index a057d1d12..bfa6f3e75 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -334,12 +334,12 @@ Running it with the report-on-xfail option gives this output:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR/example, inifile: collected 7 items - + xfail_demo.py xxxxxxx [100%] ========================= short test summary info ========================== XFAIL xfail_demo.py::test_hello XFAIL xfail_demo.py::test_hello2 - reason: [NOTRUN] + reason: [NOTRUN] XFAIL xfail_demo.py::test_hello3 condition: hasattr(os, 'sep') XFAIL xfail_demo.py::test_hello4 @@ -349,7 +349,7 @@ Running it with the report-on-xfail option gives this output:: XFAIL xfail_demo.py::test_hello6 reason: reason XFAIL xfail_demo.py::test_hello7 - + ======================== 7 xfailed in 0.12 seconds ========================= .. _`skip/xfail with parametrize`: diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index 0171e3168..421b4c898 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -32,14 +32,14 @@ Running this would result in a passed test except for the last platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_tmpdir.py F [100%] - + ================================= FAILURES ================================= _____________________________ test_create_file _____________________________ - + tmpdir = local('PYTEST_TMPDIR/test_create_file0') - + def test_create_file(tmpdir): p = tmpdir.mkdir("sub").join("hello.txt") p.write("content") @@ -47,7 +47,7 @@ Running this would result in a passed test except for the last assert len(tmpdir.listdir()) == 1 > assert 0 E assert 0 - + test_tmpdir.py:7: AssertionError ========================= 1 failed in 0.12 seconds ========================= diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index ec9f466b9..53192b346 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -130,30 +130,30 @@ the ``self.db`` values in the traceback:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items - + test_unittest_db.py FF [100%] - + ================================= FAILURES ================================= ___________________________ MyTest.test_method1 ____________________________ - + self = - + def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef> E assert 0 - + test_unittest_db.py:9: AssertionError ___________________________ MyTest.test_method2 ____________________________ - + self = - + def test_method2(self): > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef> E assert 0 - + test_unittest_db.py:12: AssertionError ========================= 2 failed in 0.12 seconds ========================= diff --git a/doc/en/usage.rst b/doc/en/usage.rst index 07077468a..25be54395 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -502,7 +502,7 @@ hook was invoked:: $ python myinvoke.py . [100%]*** test run reporting finishing - + .. note:: diff --git a/doc/en/warnings.rst b/doc/en/warnings.rst index 62f96ccf7..df93a02b5 100644 --- a/doc/en/warnings.rst +++ b/doc/en/warnings.rst @@ -25,14 +25,14 @@ Running pytest now produces this output:: platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y rootdir: $REGENDOC_TMPDIR, inifile: collected 1 item - + test_show_warnings.py . [100%] - + ============================= warnings summary ============================= test_show_warnings.py::test_one $REGENDOC_TMPDIR/test_show_warnings.py:4: UserWarning: api v1, should use functions from v2 warnings.warn(UserWarning("api v1, should use functions from v2")) - + -- Docs: http://doc.pytest.org/en/latest/warnings.html =================== 1 passed, 1 warnings in 0.12 seconds =================== @@ -45,17 +45,17 @@ them into errors:: F [100%] ================================= FAILURES ================================= _________________________________ test_one _________________________________ - + def test_one(): > assert api_v1() == 1 - - test_show_warnings.py:8: - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - + + test_show_warnings.py:8: + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + def api_v1(): > warnings.warn(UserWarning("api v1, should use functions from v2")) E UserWarning: api v1, should use functions from v2 - + test_show_warnings.py:4: UserWarning 1 failed in 0.12 seconds From 130100bba1df6bf1776e77cc2d088d9dae347ddd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 20 Jun 2018 07:53:41 -0300 Subject: [PATCH 17/31] Fix reference to py36-freeze in travis and appveyor Travis and AppVeyor were executing "py35-freeze", which does not actually exist in tox.ini. --- .travis.yml | 4 ++-- appveyor.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d092149b..f2921e118 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,8 +37,8 @@ jobs: python: 'pypy-5.4' - env: TOXENV=py35 python: '3.5' - - env: TOXENV=py35-freeze - python: '3.5' + - env: TOXENV=py36-freeze + python: '3.6' - env: TOXENV=py37 python: 'nightly' diff --git a/appveyor.yml b/appveyor.yml index b808fa6d9..b30da5c58 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,7 +27,7 @@ environment: - TOXENV: "py36-pluggymaster" - TOXENV: "py27-nobyte" - TOXENV: "doctesting" - - TOXENV: "py35-freeze" + - TOXENV: "py36-freeze" - TOXENV: "docs" install: From 1ac1ee6fcb53751ae10f1b74f0fd8c51e15b5d50 Mon Sep 17 00:00:00 2001 From: AdamEr8 Date: Thu, 21 Jun 2018 12:09:56 +0300 Subject: [PATCH 18/31] Fixed text description above skipif's example @pytest.mark.skipif's example's description (above the code) was the opposite of the condition in the code, fixed the description to match the code. --- doc/en/skipping.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index bfa6f3e75..e1c348c08 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -80,7 +80,7 @@ during import time. If you wish to skip something conditionally then you can use ``skipif`` instead. Here is an example of marking a test function to be skipped -when run on a Python3.6 interpreter:: +when run on an interpreter earlier than Python3.6 :: import sys @pytest.mark.skipif(sys.version_info < (3,6), From 8b4c59e606285d76011934e61eb7b110262f37ff Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 21 Jun 2018 13:24:16 -0700 Subject: [PATCH 19/31] Silence usage of `reduce` warning in python 2 --- changelog/3609.trivial.rst | 1 + src/_pytest/mark/structures.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/3609.trivial.rst diff --git a/changelog/3609.trivial.rst b/changelog/3609.trivial.rst new file mode 100644 index 000000000..96e720d92 --- /dev/null +++ b/changelog/3609.trivial.rst @@ -0,0 +1 @@ +Silence usage of ``reduce`` warning in python 2 diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1a2bd73de..ceacc5c6b 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -1,13 +1,14 @@ import inspect import warnings from collections import namedtuple +from functools import reduce from operator import attrgetter import attr from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE from ..compat import NOTSET, getfslineno, MappingMixin -from six.moves import map, reduce +from six.moves import map EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark" From 5e56d775427808f3864d61637701380585c79f36 Mon Sep 17 00:00:00 2001 From: AdamEr8 Date: Fri, 22 Jun 2018 08:33:35 +0300 Subject: [PATCH 20/31] Create prnum.trivial.rst Added changelog file --- changelog/prnum.trivial.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/prnum.trivial.rst diff --git a/changelog/prnum.trivial.rst b/changelog/prnum.trivial.rst new file mode 100644 index 000000000..2fdff4dc5 --- /dev/null +++ b/changelog/prnum.trivial.rst @@ -0,0 +1 @@ +Minor Doc Fix: The description above the example for ``@pytest.fixture.skipif`` now matches the code From 40839b5a3a836c00611d6abc5706e7c7b82bef1a Mon Sep 17 00:00:00 2001 From: AdamEr8 Date: Fri, 22 Jun 2018 08:46:34 +0300 Subject: [PATCH 21/31] Rename prnum.trivial.rst to 3611.trivial.rst --- changelog/{prnum.trivial.rst => 3611.trivial.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{prnum.trivial.rst => 3611.trivial.rst} (100%) diff --git a/changelog/prnum.trivial.rst b/changelog/3611.trivial.rst similarity index 100% rename from changelog/prnum.trivial.rst rename to changelog/3611.trivial.rst From f883628939fa1ca5c3e2782030fc5b90a6e54b0c Mon Sep 17 00:00:00 2001 From: AdamEr8 Date: Fri, 22 Jun 2018 08:51:26 +0300 Subject: [PATCH 22/31] Changelog mistake Used pytest.fixture.skipif instead of pytest.mark.skipif --- changelog/3611.trivial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/3611.trivial.rst b/changelog/3611.trivial.rst index 2fdff4dc5..a768b4aa3 100644 --- a/changelog/3611.trivial.rst +++ b/changelog/3611.trivial.rst @@ -1 +1 @@ -Minor Doc Fix: The description above the example for ``@pytest.fixture.skipif`` now matches the code +Minor Doc Fix: The description above the example for ``@pytest.mark.skipif`` now matches the code From 4970f6d5c2303985934875b510dda2e85c4b77da Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 22 Jun 2018 09:14:12 -0300 Subject: [PATCH 23/31] Improve reason in skipif example --- doc/en/skipping.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index e1c348c08..cda67554d 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -84,7 +84,7 @@ when run on an interpreter earlier than Python3.6 :: import sys @pytest.mark.skipif(sys.version_info < (3,6), - reason="requires python3.6") + reason="requires python3.6 or higher") def test_function(): ... From 8cc210708cd7102017d0b1d206669166d28752e5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 22 Jun 2018 09:14:59 -0300 Subject: [PATCH 24/31] Improve changelog and change it to doc --- changelog/3611.doc.rst | 1 + changelog/3611.trivial.rst | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 changelog/3611.doc.rst delete mode 100644 changelog/3611.trivial.rst diff --git a/changelog/3611.doc.rst b/changelog/3611.doc.rst new file mode 100644 index 000000000..fe19cc025 --- /dev/null +++ b/changelog/3611.doc.rst @@ -0,0 +1 @@ +The description above the example for ``@pytest.mark.skipif`` now better matches the code. diff --git a/changelog/3611.trivial.rst b/changelog/3611.trivial.rst deleted file mode 100644 index a768b4aa3..000000000 --- a/changelog/3611.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Minor Doc Fix: The description above the example for ``@pytest.mark.skipif`` now matches the code From 1d55c49a9ae0e816af0442ab026ee2df57fa490c Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 23 Jun 2018 07:55:42 -0700 Subject: [PATCH 25/31] Fix `ImportWarning` triggered by explicit relative imports --- changelog/3061.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 changelog/3061.bugfix.rst diff --git a/changelog/3061.bugfix.rst b/changelog/3061.bugfix.rst new file mode 100644 index 000000000..1bdd1064e --- /dev/null +++ b/changelog/3061.bugfix.rst @@ -0,0 +1 @@ +Fix ``ImportWarning`` triggered by explicit relative imports in assertion-rewritten package modules. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index eceed611f..92f4ab10d 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -45,6 +45,14 @@ else: return ast.Call(a, b, c, None, None) +if sys.version_info >= (3, 4): + from importlib.util import spec_from_file_location +else: + + def spec_from_file_location(*_, **__): + return None + + class AssertionRewritingHook(object): """PEP302 Import hook which rewrites asserts.""" @@ -213,6 +221,8 @@ class AssertionRewritingHook(object): # Normally, this attribute is 3.2+. mod.__cached__ = pyc mod.__loader__ = self + # Normally, this attribute is 3.4+ + mod.__spec__ = spec_from_file_location(name, co.co_filename, loader=self) py.builtin.exec_(co, mod.__dict__) except: # noqa if name in sys.modules: From 17985b893d53961e5e3c861da5ec18a65e913454 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sat, 23 Jun 2018 10:22:09 -0700 Subject: [PATCH 26/31] Remove warning filter as well --- tox.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/tox.ini b/tox.ini index cb3846d54..810d5597f 100644 --- a/tox.ini +++ b/tox.ini @@ -204,9 +204,6 @@ filterwarnings = ignore:.*type argument to addoption.*:DeprecationWarning # produced by python >=3.5 on execnet (pytest-xdist) ignore:.*inspect.getargspec.*deprecated, use inspect.signature.*:DeprecationWarning - # ignore warning about package resolution using __spec__ or __package__ - # should be a temporary solution, see #3061 for discussion - ignore:.*can't resolve package from __spec__ or __package__.*:ImportWarning [flake8] max-line-length = 120 From deff54aae00fc9fd3f47a7e1a814b9acf872e4e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20S=C3=BAkup?= Date: Fri, 22 Jun 2018 22:58:16 +0200 Subject: [PATCH 27/31] Try import mock, but on python 3.3+ can use also stdlib unittest.mock From Python 3.3 is mock part of python standard library in unittest namespace --- AUTHORS | 1 + testing/test_mark.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 3edfdcf85..ebdcf728e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -157,6 +157,7 @@ Oleg Sushchenko Oliver Bestwalter Omar Kohl Omer Hadari +Ondřej Súkup Patrick Hayes Paweł Adamczak Pedro Algarvio diff --git a/testing/test_mark.py b/testing/test_mark.py index e2e7369dc..17349916e 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1,7 +1,11 @@ from __future__ import absolute_import, division, print_function import os import sys -import mock + +try: + import mock +except ImportError: + import unittest.mock as mock import pytest from _pytest.mark import ( MarkGenerator as Mark, From 0030ceb11cdd80a589bd1f47462cd887cfc2bb7e Mon Sep 17 00:00:00 2001 From: Marcelo Duarte Trevisani Date: Sun, 24 Jun 2018 19:31:13 +0200 Subject: [PATCH 28/31] Bug fix #3593 - approx method in a single element of numpy array If the user pass as a expected value a numpy array created like numpy.array(5); it will creates an array with one element without shape, when used with approx it will raise an error 'TypeError: iteration over a 0-d array' --- AUTHORS | 1 + changelog/3593.bugfix.rst | 5 +++++ src/_pytest/python_api.py | 8 +++++--- testing/python/approx.py | 19 +++++++++++++++++-- 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 changelog/3593.bugfix.rst diff --git a/AUTHORS b/AUTHORS index ebdcf728e..95e989306 100644 --- a/AUTHORS +++ b/AUTHORS @@ -126,6 +126,7 @@ Maik Figura Mandeep Bhutani Manuel Krebber Marc Schlaich +Marcelo Duarte Trevisani Marcin Bachry Mark Abramowitz Markus Unterwaditzer diff --git a/changelog/3593.bugfix.rst b/changelog/3593.bugfix.rst new file mode 100644 index 000000000..37aa30577 --- /dev/null +++ b/changelog/3593.bugfix.rst @@ -0,0 +1,5 @@ +If the user pass as a expected value a numpy array created like +numpy.array(5); it will creates an array with one element without shape, +when used with approx it will raise an error for the `repr` +'TypeError: iteration over a 0-d array'. With this PR pytest will iterate +properly in the numpy array even with 0 dimension. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 9257d210c..5ee16c2f8 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -86,9 +86,11 @@ class ApproxNumpy(ApproxBase): # shape of the array... import numpy as np - return "approx({!r})".format( - list(self._approx_scalar(x) for x in np.asarray(self.expected)) - ) + list_scalars = [] + for x in np.ndindex(self.expected.shape): + list_scalars.append(self._approx_scalar(np.asscalar(self.expected[x]))) + + return "approx({!r})".format(list_scalars) if sys.version_info[0] == 2: __cmp__ = _cmp_raises_type_error diff --git a/testing/python/approx.py b/testing/python/approx.py index 9e25feb0b..e65647897 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -27,8 +27,11 @@ class MyDocTestRunner(doctest.DocTestRunner): class TestApprox(object): - def test_repr_string(self): - plus_minus = u"\u00b1" if sys.version_info[0] > 2 else u"+-" + @pytest.fixture + def plus_minus(self): + return u"\u00b1" if sys.version_info[0] > 2 else u"+-" + + def test_repr_string(self, plus_minus): tol1, tol2, infr = "1.0e-06", "2.0e-06", "inf" assert repr(approx(1.0)) == "1.0 {pm} {tol1}".format(pm=plus_minus, tol1=tol1) assert ( @@ -61,6 +64,18 @@ class TestApprox(object): ), ) + def test_repr_0d_array(self, plus_minus): + np = pytest.importorskip("numpy") + np_array = np.array(5.) + assert approx(np_array) == 5.0 + string_expected = "approx([5.0 {} 5.0e-06])".format(plus_minus) + + assert repr(approx(np_array)) == string_expected + + np_array = np.array([5.]) + assert approx(np_array) == 5.0 + assert repr(approx(np_array)) == string_expected + def test_operator_overloading(self): assert 1 == approx(1, rel=1e-6, abs=1e-12) assert not (1 != approx(1, rel=1e-6, abs=1e-12)) From 1d5316a28b0a1f64c8ffc0051d95c449a843d9d0 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 25 Jun 2018 18:08:46 -0700 Subject: [PATCH 29/31] Update pypi.python.org URLs to pypi.org For details on the new PyPI, see the blog post: https://pythoninsider.blogspot.ca/2018/04/new-pypi-launched-legacy-pypi-shutting.html --- doc/en/announce/release-2.4.0.rst | 2 +- doc/en/fixture.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/announce/release-2.4.0.rst b/doc/en/announce/release-2.4.0.rst index 25f6254c5..1b0168841 100644 --- a/doc/en/announce/release-2.4.0.rst +++ b/doc/en/announce/release-2.4.0.rst @@ -23,7 +23,7 @@ a full list of details. A few feature highlights: called if the corresponding setup method succeeded. - integrate tab-completion on command line options if you - have `argcomplete `_ + have `argcomplete `_ configured. - allow boolean expression directly with skipif/xfail diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index d4d386792..e07d00eaa 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -154,7 +154,7 @@ This makes use of the automatic caching mechanisms of pytest. Another good approach is by adding the data files in the ``tests`` folder. There are also community plugins available to help managing this aspect of testing, e.g. `pytest-datadir `__ -and `pytest-datafiles `__. +and `pytest-datafiles `__. .. _smtpshared: From cbaa7dd56a685c887e25d4c94b62aa49e8a6a0ca Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Tue, 26 Jun 2018 06:35:27 -0700 Subject: [PATCH 30/31] Upgrade pre-commit hooks except pyupgrade --- .pre-commit-config.yaml | 8 +- doc/en/example/assertion/failure_demo.py | 17 ---- doc/en/example/assertion/test_failures.py | 2 +- .../assertion/test_setup_flow_example.py | 1 - doc/en/example/costlysetup/conftest.py | 1 - doc/en/example/multipython.py | 1 - doc/en/example/nonpython/conftest.py | 2 - doc/en/example/py2py3/conftest.py | 1 - doc/en/example/pythoncollection.py | 1 - src/_pytest/_code/code.py | 39 +++++---- src/_pytest/_code/source.py | 7 +- src/_pytest/assertion/rewrite.py | 2 +- src/_pytest/assertion/util.py | 2 +- src/_pytest/cacheprovider.py | 5 +- src/_pytest/capture.py | 2 - src/_pytest/compat.py | 20 ++--- src/_pytest/config/__init__.py | 25 +++--- src/_pytest/config/argparsing.py | 8 +- src/_pytest/config/exceptions.py | 1 + src/_pytest/config/findpaths.py | 1 - src/_pytest/debugging.py | 8 +- src/_pytest/deprecated.py | 4 +- src/_pytest/doctest.py | 15 +--- src/_pytest/fixtures.py | 14 ++- src/_pytest/helpconfig.py | 2 +- src/_pytest/junitxml.py | 7 +- src/_pytest/logging.py | 4 +- src/_pytest/main.py | 2 +- src/_pytest/mark/evaluate.py | 1 - src/_pytest/mark/structures.py | 20 +++-- src/_pytest/monkeypatch.py | 1 - src/_pytest/nodes.py | 4 +- src/_pytest/outcomes.py | 1 + src/_pytest/pytester.py | 21 ++--- src/_pytest/python.py | 29 +++---- src/_pytest/python_api.py | 6 +- src/_pytest/recwarn.py | 5 +- src/_pytest/resultlog.py | 1 - src/_pytest/runner.py | 21 +++-- src/_pytest/skipping.py | 9 +- src/_pytest/terminal.py | 27 +++--- src/_pytest/unittest.py | 12 ++- src/_pytest/warnings.py | 5 +- tasks/generate.py | 16 ++-- testing/acceptance_test.py | 11 +-- testing/code/test_code.py | 8 -- testing/code/test_excinfo.py | 15 ---- testing/code/test_source.py | 12 --- testing/code/test_source_multiline_block.py | 1 - testing/deprecated_test.py | 8 +- testing/logging/test_formatter.py | 6 +- testing/logging/test_reporting.py | 35 ++++---- testing/python/approx.py | 25 +++--- testing/python/collect.py | 15 +--- testing/python/fixture.py | 42 +++------ testing/python/integration.py | 8 -- testing/python/metafunc.py | 86 ++++++------------- testing/python/raises.py | 5 -- testing/test_argcomplete.py | 1 - testing/test_assertion.py | 37 +++----- testing/test_assertrewrite.py | 34 +------- testing/test_cacheprovider.py | 27 +++--- testing/test_capture.py | 6 -- testing/test_collection.py | 11 --- testing/test_compat.py | 4 - testing/test_config.py | 17 +--- testing/test_conftest.py | 4 - testing/test_doctest.py | 4 - testing/test_junitxml.py | 25 ++---- testing/test_mark.py | 6 -- testing/test_monkeypatch.py | 4 - testing/test_nose.py | 1 - testing/test_parseopt.py | 19 ++-- testing/test_pastebin.py | 3 - testing/test_pdb.py | 4 - testing/test_pluginmanager.py | 8 -- testing/test_pytester.py | 9 +- testing/test_recwarn.py | 2 - testing/test_runner.py | 26 ++---- testing/test_session.py | 2 - testing/test_skipping.py | 11 +-- testing/test_terminal.py | 8 -- testing/test_tmpdir.py | 2 - testing/test_unittest.py | 1 - testing/test_warnings.py | 5 +- tox.ini | 1 + 86 files changed, 309 insertions(+), 631 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e50891bbc..9e9549ed9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,19 @@ exclude: doc/en/example/py2py3/test_py2.py repos: - repo: https://github.com/ambv/black - rev: 18.4a4 + rev: 18.6b4 hooks: - id: black args: [--safe, --quiet] language_version: python3.6 - repo: https://github.com/asottile/blacken-docs - rev: v0.1.1 + rev: v0.2.0 hooks: - id: blacken-docs - additional_dependencies: [black==18.5b1] + additional_dependencies: [black==18.6b4] language_version: python3.6 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v1.2.3 + rev: v1.3.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index dc27f5dfb..0a104578c 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -25,9 +25,7 @@ def pytest_generate_tests(metafunc): class TestFailing(object): - def test_simple(self): - def f(): return 42 @@ -40,7 +38,6 @@ class TestFailing(object): otherfunc_multi(42, 6 * 9) def test_not(self): - def f(): return 42 @@ -48,7 +45,6 @@ class TestFailing(object): class TestSpecialisedExplanations(object): - def test_eq_text(self): assert "spam" == "eggs" @@ -106,7 +102,6 @@ class TestSpecialisedExplanations(object): def test_attribute(): - class Foo(object): b = 1 @@ -115,7 +110,6 @@ def test_attribute(): def test_attribute_instance(): - class Foo(object): b = 1 @@ -123,9 +117,7 @@ def test_attribute_instance(): def test_attribute_failure(): - class Foo(object): - def _get_b(self): raise Exception("Failed to get attrib") @@ -136,7 +128,6 @@ def test_attribute_failure(): def test_attribute_multiple(): - class Foo(object): b = 1 @@ -151,7 +142,6 @@ def globf(x): class TestRaises(object): - def test_raises(self): s = "qwe" # NOQA raises(TypeError, "int(s)") @@ -193,9 +183,7 @@ def test_dynamic_compile_shows_nicely(): class TestMoreErrors(object): - def test_complex_error(self): - def f(): return 44 @@ -218,7 +206,6 @@ class TestMoreErrors(object): assert s.startswith(g) def test_startswith_nested(self): - def f(): return "123" @@ -246,9 +233,7 @@ class TestMoreErrors(object): class TestCustomAssertMsg(object): - def test_single_line(self): - class A(object): a = 1 @@ -256,7 +241,6 @@ class TestCustomAssertMsg(object): assert A.a == b, "A.a appears not to be b" def test_multiline(self): - class A(object): a = 1 @@ -266,7 +250,6 @@ class TestCustomAssertMsg(object): ), "A.a appears not to be b\n" "or does not appear to be b\none of those" def test_custom_repr(self): - class JSON(object): a = 1 diff --git a/doc/en/example/assertion/test_failures.py b/doc/en/example/assertion/test_failures.py index 1150ec12f..43f748fa2 100644 --- a/doc/en/example/assertion/test_failures.py +++ b/doc/en/example/assertion/test_failures.py @@ -2,7 +2,7 @@ import py failure_demo = py.path.local(__file__).dirpath("failure_demo.py") -pytest_plugins = "pytester", +pytest_plugins = ("pytester",) def test_failure_demo_fails_properly(testdir): diff --git a/doc/en/example/assertion/test_setup_flow_example.py b/doc/en/example/assertion/test_setup_flow_example.py index c00711dc2..eb339f474 100644 --- a/doc/en/example/assertion/test_setup_flow_example.py +++ b/doc/en/example/assertion/test_setup_flow_example.py @@ -3,7 +3,6 @@ def setup_module(module): class TestStateFullThing(object): - def setup_class(cls): cls.classcount += 1 diff --git a/doc/en/example/costlysetup/conftest.py b/doc/en/example/costlysetup/conftest.py index 466c62c06..e41c4129c 100644 --- a/doc/en/example/costlysetup/conftest.py +++ b/doc/en/example/costlysetup/conftest.py @@ -10,7 +10,6 @@ def setup(request): class CostlySetup(object): - def __init__(self): import time diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 970800c7e..299833f71 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -21,7 +21,6 @@ def python2(request, python1): class Python(object): - def __init__(self, version, picklefile): self.pythonpath = py.path.local.sysfind(version) if not self.pythonpath: diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index 8429dd114..9732dc41b 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -9,7 +9,6 @@ def pytest_collect_file(parent, path): class YamlFile(pytest.File): - def collect(self): import yaml # we need a yaml parser, e.g. PyYAML @@ -19,7 +18,6 @@ class YamlFile(pytest.File): class YamlItem(pytest.Item): - def __init__(self, name, parent, spec): super(YamlItem, self).__init__(name, parent) self.spec = spec diff --git a/doc/en/example/py2py3/conftest.py b/doc/en/example/py2py3/conftest.py index 5d9a07e3e..9c1c6fa38 100644 --- a/doc/en/example/py2py3/conftest.py +++ b/doc/en/example/py2py3/conftest.py @@ -5,7 +5,6 @@ py3 = sys.version_info[0] >= 3 class DummyCollector(pytest.collect.File): - def collect(self): return [] diff --git a/doc/en/example/pythoncollection.py b/doc/en/example/pythoncollection.py index 3603361c3..b134d809d 100644 --- a/doc/en/example/pythoncollection.py +++ b/doc/en/example/pythoncollection.py @@ -7,7 +7,6 @@ def test_function(): class TestClass(object): - def test_method(self): pass diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index cb788c17f..0e5e580b6 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -274,6 +274,7 @@ class Traceback(list): """ Traceback objects encapsulate and offer higher level access to Traceback entries. """ + Entry = TracebackEntry def __init__(self, tb, excinfo=None): @@ -382,8 +383,11 @@ class ExceptionInfo(object): """ wraps sys.exc_info() objects and offers help for navigating the traceback. """ + _striptext = "" - _assert_start_repr = "AssertionError(u'assert " if _PY2 else "AssertionError('assert " + _assert_start_repr = ( + "AssertionError(u'assert " if _PY2 else "AssertionError('assert " + ) def __init__(self, tup=None, exprinfo=None): import _pytest._code @@ -424,7 +428,7 @@ class ExceptionInfo(object): text = text.rstrip() if tryshort: if text.startswith(self._striptext): - text = text[len(self._striptext):] + text = text[len(self._striptext) :] return text def errisinstance(self, exc): @@ -497,6 +501,7 @@ class ExceptionInfo(object): @attr.s class FormattedExcinfo(object): """ presenting information about failing Functions and Generators. """ + # for traceback entries flow_marker = ">" fail_marker = "E" @@ -556,7 +561,7 @@ class FormattedExcinfo(object): for line in source.lines[:line_index]: lines.append(space_prefix + line) lines.append(self.flow_marker + " " + source.lines[line_index]) - for line in source.lines[line_index + 1:]: + for line in source.lines[line_index + 1 :]: lines.append(space_prefix + line) if excinfo is not None: indent = 4 if short else self._getindent(source) @@ -691,7 +696,7 @@ class FormattedExcinfo(object): else: if recursionindex is not None: extraline = "!!! Recursion detected (same locals & position)" - traceback = traceback[:recursionindex + 1] + traceback = traceback[: recursionindex + 1] else: extraline = None @@ -722,15 +727,19 @@ class FormattedExcinfo(object): repr_chain += [(reprtraceback, reprcrash, descr)] if e.__cause__ is not None: e = e.__cause__ - excinfo = ExceptionInfo( - (type(e), e, e.__traceback__) - ) if e.__traceback__ else None + excinfo = ( + ExceptionInfo((type(e), e, e.__traceback__)) + if e.__traceback__ + else None + ) descr = "The above exception was the direct cause of the following exception:" - elif (e.__context__ is not None and not e.__suppress_context__): + elif e.__context__ is not None and not e.__suppress_context__: e = e.__context__ - excinfo = ExceptionInfo( - (type(e), e, e.__traceback__) - ) if e.__traceback__ else None + excinfo = ( + ExceptionInfo((type(e), e, e.__traceback__)) + if e.__traceback__ + else None + ) descr = "During handling of the above exception, another exception occurred:" else: e = None @@ -739,7 +748,6 @@ class FormattedExcinfo(object): class TerminalRepr(object): - def __str__(self): s = self.__unicode__() if _PY2: @@ -759,7 +767,6 @@ class TerminalRepr(object): class ExceptionRepr(TerminalRepr): - def __init__(self): self.sections = [] @@ -773,7 +780,6 @@ class ExceptionRepr(TerminalRepr): class ExceptionChainRepr(ExceptionRepr): - def __init__(self, chain): super(ExceptionChainRepr, self).__init__() self.chain = chain @@ -792,7 +798,6 @@ class ExceptionChainRepr(ExceptionRepr): class ReprExceptionInfo(ExceptionRepr): - def __init__(self, reprtraceback, reprcrash): super(ReprExceptionInfo, self).__init__() self.reprtraceback = reprtraceback @@ -831,7 +836,6 @@ class ReprTraceback(TerminalRepr): class ReprTracebackNative(ReprTraceback): - def __init__(self, tblines): self.style = "native" self.reprentries = [ReprEntryNative(tblines)] @@ -885,7 +889,6 @@ class ReprEntry(TerminalRepr): class ReprFileLocation(TerminalRepr): - def __init__(self, path, lineno, message): self.path = str(path) self.lineno = lineno @@ -903,7 +906,6 @@ class ReprFileLocation(TerminalRepr): class ReprLocals(TerminalRepr): - def __init__(self, lines): self.lines = lines @@ -913,7 +915,6 @@ class ReprLocals(TerminalRepr): class ReprFuncArgs(TerminalRepr): - def __init__(self, args): self.args = args diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 6b982a4ca..711408f61 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -17,6 +17,7 @@ class Source(object): """ an immutable object holding a source code fragment, possibly deindenting it. """ + _compilecounter = 0 def __init__(self, *parts, **kwargs): @@ -60,7 +61,7 @@ class Source(object): if key.step not in (None, 1): raise IndexError("cannot slice a Source with a step") newsource = Source() - newsource.lines = self.lines[key.start:key.stop] + newsource.lines = self.lines[key.start : key.stop] return newsource def __len__(self): @@ -178,7 +179,7 @@ class Source(object): except SyntaxError: ex = sys.exc_info()[1] # re-represent syntax errors from parsing python strings - msglines = self.lines[:ex.lineno] + msglines = self.lines[: ex.lineno] if ex.offset: msglines.append(" " * ex.offset + "^") msglines.append("(code was compiled probably from here: %s)" % filename) @@ -313,7 +314,7 @@ def deindent(lines, offset=None): except (IndentationError, tokenize.TokenError): pass # Add any lines we didn't see. E.g. if an exception was raised. - newlines.extend(lines[len(newlines):]) + newlines.extend(lines[len(newlines) :]) return newlines diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 92f4ab10d..bc18aa1fc 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -319,7 +319,7 @@ def _rewrite_test(config, fn): if ( not source.startswith(BOM_UTF8) and cookie_re.match(source[0:end1]) is None - and cookie_re.match(source[end1 + 1:end2]) is None + and cookie_re.match(source[end1 + 1 : end2]) is None ): if hasattr(state, "_indecode"): # encodings imported us again, so don't rewrite. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index bcb800a4a..08213c80e 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -322,7 +322,7 @@ def _compare_eq_dict(left, right, verbose=False): def _notin_text(term, text, verbose=False): index = text.find(term) head = text[:index] - tail = text[index + len(term):] + tail = text[index + len(term) :] correct_text = head + tail diff = _diff_text(correct_text, text, verbose) newdiff = [u("%s is contained here:") % py.io.saferepr(term, maxsize=42)] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index eb0fcc06f..53b6ebb61 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -18,7 +18,6 @@ from os.path import sep as _sep, altsep as _altsep class Cache(object): - def __init__(self, config): self.config = config self._cachedir = Cache.cache_dir_from_config(config) @@ -199,9 +198,7 @@ class NFPlugin(object): items[:] = self._get_increasing_order( six.itervalues(new_items) - ) + self._get_increasing_order( - six.itervalues(other_items) - ) + ) + self._get_increasing_order(six.itervalues(other_items)) self.cached_nodeids = [x.nodeid for x in items if isinstance(x, pytest.Item)] def _get_increasing_order(self, items): diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 7a57adb75..faa767a86 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -531,7 +531,6 @@ class FDCapture(FDCaptureBinary): class SysCapture(object): - def __init__(self, fd, tmpfile=None): name = patchsysdict[fd] self._old = getattr(sys, name) @@ -569,7 +568,6 @@ class SysCapture(object): class SysCaptureBinary(SysCapture): - def snap(self): res = self.tmpfile.buffer.getvalue() self.tmpfile.seek(0) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 7abd3d53f..3ca27fe60 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -72,12 +72,8 @@ def iscoroutinefunction(func): Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly, which in turns also initializes the "logging" module as side-effect (see issue #8). """ - return ( - getattr(func, "_is_coroutine", False) - or ( - hasattr(inspect, "iscoroutinefunction") - and inspect.iscoroutinefunction(func) - ) + return getattr(func, "_is_coroutine", False) or ( + hasattr(inspect, "iscoroutinefunction") and inspect.iscoroutinefunction(func) ) @@ -138,17 +134,13 @@ def getfuncargnames(function, is_method=False, cls=None): # If this function should be treated as a bound method even though # it's passed as an unbound method or function, remove the first # parameter name. - if ( - is_method - or ( - cls - and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod) - ) + if is_method or ( + cls and not isinstance(cls.__dict__.get(function.__name__, None), staticmethod) ): arg_names = arg_names[1:] # Remove any names that will be replaced with mocks. if hasattr(function, "__wrapped__"): - arg_names = arg_names[num_mock_patch_args(function):] + arg_names = arg_names[num_mock_patch_args(function) :] return arg_names @@ -340,7 +332,6 @@ if _PY2: from py.io import TextIO class CaptureIO(TextIO): - @property def encoding(self): return getattr(self, "_encoding", "UTF-8") @@ -350,7 +341,6 @@ else: import io class CaptureIO(io.TextIOWrapper): - def __init__(self): super(CaptureIO, self).__init__( io.BytesIO(), encoding="UTF-8", newline="", write_through=True diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 11348b80d..7e7f3b6d2 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -30,7 +30,6 @@ hookspec = HookspecMarker("pytest") class ConftestImportFailure(Exception): - def __init__(self, path, excinfo): Exception.__init__(self, path, excinfo) self.path = path @@ -318,9 +317,11 @@ class PytestPluginManager(PluginManager): self._configured = True def _warn(self, message): - kwargs = message if isinstance(message, dict) else { - "code": "I1", "message": message, "fslocation": None, "nodeid": None - } + kwargs = ( + message + if isinstance(message, dict) + else {"code": "I1", "message": message, "fslocation": None, "nodeid": None} + ) self.hook.pytest_logwarning.call_historic(kwargs=kwargs) # @@ -335,9 +336,11 @@ class PytestPluginManager(PluginManager): here. """ current = py.path.local() - self._confcutdir = current.join( - namespace.confcutdir, abs=True - ) if namespace.confcutdir else None + self._confcutdir = ( + current.join(namespace.confcutdir, abs=True) + if namespace.confcutdir + else None + ) self._noconftest = namespace.noconftest testpaths = namespace.file_or_dir foundanchor = False @@ -405,7 +408,9 @@ class PytestPluginManager(PluginManager): try: mod = conftestpath.pyimport() if hasattr(mod, "pytest_plugins") and self._configured: - from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST + from _pytest.deprecated import ( + PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST + ) warnings.warn(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST) except Exception: @@ -477,7 +482,8 @@ class PytestPluginManager(PluginManager): except ImportError as e: new_exc_type = ImportError new_exc_message = 'Error importing plugin "%s": %s' % ( - modname, safe_str(e.args[0]) + modname, + safe_str(e.args[0]), ) new_exc = new_exc_type(new_exc_message) @@ -518,7 +524,6 @@ def _ensure_removed_sysmodule(modname): class Notset(object): - def __repr__(self): return "" diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 781d8e8c4..21d99b0ce 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -149,6 +149,7 @@ class Argument(object): and ignoring choices and integer prefixes https://docs.python.org/3/library/optparse.html#optparse-standard-option-types """ + _typ_map = {"int": int, "string": str, "float": float, "complex": complex} def __init__(self, *names, **attrs): @@ -274,7 +275,6 @@ class Argument(object): class OptionGroup(object): - def __init__(self, name, description="", parser=None): self.name = name self.description = description @@ -312,7 +312,6 @@ class OptionGroup(object): class MyOptionParser(argparse.ArgumentParser): - def __init__(self, parser, extra_info=None): if not extra_info: extra_info = {} @@ -378,9 +377,8 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter): xxoption = option[2:] if xxoption.split()[0] not in option_map: shortened = xxoption.replace("-", "") - if ( - shortened not in short_long - or len(short_long[shortened]) < len(xxoption) + if shortened not in short_long or len(short_long[shortened]) < len( + xxoption ): short_long[shortened] = xxoption # now short_long has been filled out to the longest with dashes diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py index 64bae834d..19fe5cb08 100644 --- a/src/_pytest/config/exceptions.py +++ b/src/_pytest/config/exceptions.py @@ -5,4 +5,5 @@ class UsageError(Exception): class PrintHelp(Exception): """Raised when pytest should print it's help to skip the rest of the argument parsing and validation.""" + pass diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index fde7bddb9..234aa69c7 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -74,7 +74,6 @@ def get_common_ancestor(paths): def get_dirs_from_args(args): - def is_option(x): return str(x).startswith("-") diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 2e253aaa2..3fc3eb552 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -65,6 +65,7 @@ def pytest_configure(config): class pytestPDB(object): """ Pseudo PDB that defers to the real pdb. """ + _pluginmanager = None _config = None _pdb_cls = pdb.Pdb @@ -87,7 +88,6 @@ class pytestPDB(object): class PdbInvoke(object): - def pytest_exception_interact(self, node, call, report): capman = node.config.pluginmanager.getplugin("capturemanager") if capman: @@ -114,7 +114,9 @@ def _enter_pdb(node, excinfo, rep): showcapture = node.config.option.showcapture for sectionname, content in ( - ("stdout", rep.capstdout), ("stderr", rep.capstderr), ("log", rep.caplog) + ("stdout", rep.capstdout), + ("stderr", rep.capstderr), + ("log", rep.caplog), ): if showcapture in (sectionname, "all") and content: tw.sep(">", "captured " + sectionname) @@ -148,9 +150,7 @@ def _find_last_non_hidden_frame(stack): def post_mortem(t): - class Pdb(pytestPDB._pdb_cls): - def get_stack(self, f, t): stack, i = pdb.Pdb.get_stack(self, f, t) if f is None: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 7ebdcf999..b3c40c2ae 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -22,7 +22,9 @@ FUNCARG_PREFIX = ( "Please remove the prefix and use the @pytest.fixture decorator instead." ) -CFG_PYTEST_SECTION = "[pytest] section in {filename} files is deprecated, use [tool:pytest] instead." +CFG_PYTEST_SECTION = ( + "[pytest] section in {filename} files is deprecated, use [tool:pytest] instead." +) GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue" diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index b0a3ad08d..57d3367e4 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -105,7 +105,6 @@ def _is_doctest(config, path, parent): class ReprFailDoctest(TerminalRepr): - def __init__(self, reprlocation_lines): # List of (reprlocation, lines) tuples self.reprlocation_lines = reprlocation_lines @@ -118,7 +117,6 @@ class ReprFailDoctest(TerminalRepr): class MultipleDoctestFailures(Exception): - def __init__(self, failures): super(MultipleDoctestFailures, self).__init__() self.failures = failures @@ -172,7 +170,6 @@ def _get_runner(checker=None, verbose=None, optionflags=0, continue_on_failure=T class DoctestItem(pytest.Item): - def __init__(self, name, parent, runner=None, dtest=None): super(DoctestItem, self).__init__(name, parent) self.runner = runner @@ -243,7 +240,7 @@ class DoctestItem(pytest.Item): for (i, x) in enumerate(lines) ] # trim docstring error lines to 10 - lines = lines[max(example.lineno - 9, 0):example.lineno + 1] + lines = lines[max(example.lineno - 9, 0) : example.lineno + 1] else: lines = [ "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example" @@ -255,9 +252,7 @@ class DoctestItem(pytest.Item): if isinstance(failure, doctest.DocTestFailure): lines += checker.output_difference( example, failure.got, report_choice - ).split( - "\n" - ) + ).split("\n") else: inner_excinfo = ExceptionInfo(failure.exc_info) lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)] @@ -347,7 +342,6 @@ def _check_all_skipped(test): class DoctestModule(pytest.Module): - def collect(self): import doctest @@ -480,9 +474,7 @@ def _get_report_choice(key): DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF, DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE, DOCTEST_REPORT_CHOICE_NONE: 0, - }[ - key - ] + }[key] def _fix_spoof_python2(runner, encoding): @@ -502,7 +494,6 @@ def _fix_spoof_python2(runner, encoding): from doctest import _SpoofOut class UnicodeSpoof(_SpoofOut): - def getvalue(self): result = _SpoofOut.getvalue(self) if encoding and isinstance(result, bytes): diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 495e6b9b3..151346413 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -65,7 +65,6 @@ scope2props["function"] = scope2props["instance"] + ("function", "keywords") def scopeproperty(name=None, doc=None): - def decoratescope(func): scopename = name or func.__name__ @@ -276,7 +275,6 @@ def get_direct_param_fixture_func(request): class FuncFixtureInfo(object): - def __init__(self, argnames, names_closure, name2fixturedefs): self.argnames = argnames self.names_closure = names_closure @@ -698,7 +696,6 @@ class FixtureLookupError(LookupError): class FixtureLookupErrorRepr(TerminalRepr): - def __init__(self, filename, firstlineno, tblines, errorstring, argname): self.tblines = tblines self.errorstring = errorstring @@ -837,9 +834,10 @@ class FixtureDef(object): return hook.pytest_fixture_setup(fixturedef=self, request=request) def __repr__(self): - return ( - "" - % (self.argname, self.scope, self.baseid) + return "" % ( + self.argname, + self.scope, + self.baseid, ) @@ -1064,7 +1062,7 @@ class FixtureManager(object): if nodeid.startswith(baseid): if baseid: i = len(baseid) - nextchar = nodeid[i:i + 1] + nextchar = nodeid[i : i + 1] if nextchar and nextchar not in ":/": continue autousenames.extend(basenames) @@ -1171,7 +1169,7 @@ class FixtureManager(object): self.config.warn( "C1", deprecated.FUNCARG_PREFIX.format(name=name), nodeid=nodeid ) - name = name[len(self._argprefix):] + name = name[len(self._argprefix) :] elif not isinstance(marker, FixtureFunctionMarker): # magic globals with __getattr__ might have got us a wrong # fixture attribute diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 5514fec40..12c3339c6 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -149,7 +149,7 @@ def showhelp(config): type = "string" spec = "%s (%s)" % (name, type) line = " %-24s %s" % (spec, help) - tw.line(line[:tw.fullwidth]) + tw.line(line[: tw.fullwidth]) tw.line() tw.line("environment variables:") diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 29da27de7..86aad69bb 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -55,7 +55,6 @@ _py_ext_re = re.compile(r"\.py$") def bin_xml_escape(arg): - def repl(matchobj): i = ord(matchobj.group()) if i <= 0xFF: @@ -67,7 +66,6 @@ def bin_xml_escape(arg): class _NodeReporter(object): - def __init__(self, nodeid, xml): self.id = nodeid @@ -358,7 +356,6 @@ def mangle_test_address(address): class LogXML(object): - def __init__(self, logfile, prefix, suite_name="pytest", logging="no"): logfile = os.path.expanduser(os.path.expandvars(logfile)) self.logfile = os.path.normpath(os.path.abspath(logfile)) @@ -544,9 +541,7 @@ class LogXML(object): skips=self.stats["skipped"], tests=numtests, time="%.3f" % suite_time_delta, - ).unicode( - indent=0 - ) + ).unicode(indent=0) ) logfile.close() diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 00bb9aeb5..70b6592c4 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -409,9 +409,7 @@ class LoggingPlugin(object): """ return self._config.getoption( "--log-cli-level" - ) is not None or self._config.getini( - "log_cli" - ) + ) is not None or self._config.getini("log_cli") @contextmanager def _runtest_for(self, item, when): diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 23562358d..7feeaf8cf 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -343,7 +343,6 @@ def _patched_find_module(): class FSHookProxy(object): - def __init__(self, fspath, pm, remove_mods): self.fspath = fspath self.pm = pm @@ -361,6 +360,7 @@ class NoMatch(Exception): class Interrupted(KeyboardInterrupt): """ signals an interrupted test run. """ + __module__ = "builtins" # for py3 diff --git a/src/_pytest/mark/evaluate.py b/src/_pytest/mark/evaluate.py index a3d11ee0f..d4bfdaf34 100644 --- a/src/_pytest/mark/evaluate.py +++ b/src/_pytest/mark/evaluate.py @@ -21,7 +21,6 @@ def cached_eval(config, expr, d): class MarkEvaluator(object): - def __init__(self, item, name): self.item = item self._marks = None diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index ceacc5c6b..eb0349c2f 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -25,9 +25,10 @@ def alias(name, warning=None): def istestfunc(func): - return hasattr(func, "__call__") and getattr( - func, "__name__", "" - ) != "" + return ( + hasattr(func, "__call__") + and getattr(func, "__name__", "") != "" + ) def get_empty_parameterset_mark(config, argnames, func): @@ -40,18 +41,20 @@ def get_empty_parameterset_mark(config, argnames, func): raise LookupError(requested_mark) fs, lineno = getfslineno(func) reason = "got empty parameter set %r, function %s at %s:%d" % ( - argnames, func.__name__, fs, lineno + argnames, + func.__name__, + fs, + lineno, ) return mark(reason=reason) class ParameterSet(namedtuple("ParameterSet", "values, marks, id")): - @classmethod def param(cls, *values, **kw): marks = kw.pop("marks", ()) if isinstance(marks, MarkDecorator): - marks = marks, + marks = (marks,) else: assert isinstance(marks, (tuple, list, set)) @@ -88,7 +91,7 @@ class ParameterSet(namedtuple("ParameterSet", "values, marks, id")): argval = argval.args[-1] assert not isinstance(argval, ParameterSet) if legacy_force_tuple: - argval = argval, + argval = (argval,) if newmarks: warnings.warn(MARK_PARAMETERSET_UNPACKING) @@ -333,6 +336,7 @@ class MarkGenerator(object): will set a 'slowtest' :class:`MarkInfo` object on the ``test_function`` object. """ + _config = None def __getattr__(self, name): @@ -362,7 +366,6 @@ MARK_GEN = MarkGenerator() class NodeKeywords(MappingMixin): - def __init__(self, node): self.node = node self.parent = node.parent @@ -409,6 +412,7 @@ class NodeMarkers(object): unstable api """ + own_markers = attr.ib(default=attr.Factory(list)) def update(self, add_markers): diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 16080b5d5..e6928f96b 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -86,7 +86,6 @@ def derive_importpath(import_path, raising): class Notset(object): - def __repr__(self): return "" diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index ef74c53eb..e4b10fe66 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -48,7 +48,7 @@ def ischildnode(baseid, nodeid): node_parts = _splitnode(nodeid) if len(node_parts) < len(base_parts): return False - return node_parts[:len(base_parts)] == base_parts + return node_parts[: len(base_parts)] == base_parts @attr.s @@ -335,7 +335,6 @@ def _check_initialpaths_for_relpath(session, fspath): class FSCollector(Collector): - def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None): fspath = py.path.local(fspath) # xxx only for test_resultlog.py? name = fspath.basename @@ -369,6 +368,7 @@ class Item(Node): """ a basic test invocation item. Note that for a single function there might be multiple test invocation items. """ + nextitem = None def __init__(self, name, parent=None, config=None, session=None, nodeid=None): diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 8a3662e1b..63b8453b7 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -43,6 +43,7 @@ class Skipped(OutcomeException): class Failed(OutcomeException): """ raised from an explicit call to pytest.fail() """ + __module__ = "builtins" diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index c9defe03a..ce1c8ea1c 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -62,7 +62,6 @@ def pytest_configure(config): class LsofFdLeakChecker(object): - def get_open_files(self): out = self._exec_lsof() open_files = self._parse_lsof_output(out) @@ -73,7 +72,6 @@ class LsofFdLeakChecker(object): return py.process.cmdexec("lsof -Ffn0 -p %d" % pid) def _parse_lsof_output(self, out): - def isopen(line): return line.startswith("f") and ( "deleted" not in line @@ -195,7 +193,6 @@ def _pytest(request): class PytestArg(object): - def __init__(self, request): self.request = request @@ -211,7 +208,6 @@ def get_public_names(values): class ParsedCall(object): - def __init__(self, name, kwargs): self.__dict__.update(kwargs) self._name = name @@ -423,13 +419,12 @@ class RunResult(object): "failed": d.get("failed", 0), "error": d.get("error", 0), } - assert ( - obtained == dict(passed=passed, skipped=skipped, failed=failed, error=error) + assert obtained == dict( + passed=passed, skipped=skipped, failed=failed, error=error ) class CwdSnapshot(object): - def __init__(self): self.__saved = os.getcwd() @@ -438,7 +433,6 @@ class CwdSnapshot(object): class SysModulesSnapshot(object): - def __init__(self, preserve=None): self.__preserve = preserve self.__saved = dict(sys.modules) @@ -453,7 +447,6 @@ class SysModulesSnapshot(object): class SysPathsSnapshot(object): - def __init__(self): self.__saved = list(sys.path), list(sys.meta_path) @@ -778,7 +771,6 @@ class Testdir(object): rec = [] class Collect(object): - def pytest_configure(x, config): rec.append(self.make_hook_recorder(config.pluginmanager)) @@ -910,8 +902,10 @@ class Testdir(object): for item in items: if item.name == funcname: return item - assert 0, ( - "%r item not found in module:\n%s\nitems: %s" % (funcname, source, items) + assert 0, "%r item not found in module:\n%s\nitems: %s" % ( + funcname, + source, + items, ) def getitems(self, source): @@ -1115,7 +1109,6 @@ def getdecoded(out): class LineComp(object): - def __init__(self): self.stringio = py.io.TextIO() @@ -1202,7 +1195,7 @@ class LineMatcher(object): """ for i, line in enumerate(self.lines): if fnline == line or fnmatch(line, fnline): - return self.lines[i + 1:] + return self.lines[i + 1 :] raise ValueError("line %r not found in output" % fnline) def _log(self, *args): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 0dcecdd55..8a9c15dc2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -69,13 +69,12 @@ def filter_traceback(entry): # entry.path might point to a non-existing file, in which case it will # also return a str object. see #1133 p = py.path.local(entry.path) - return not p.relto(_pluggy_dir) and not p.relto(_pytest_dir) and not p.relto( - _py_dir + return ( + not p.relto(_pluggy_dir) and not p.relto(_pytest_dir) and not p.relto(_py_dir) ) def pyobj_property(name): - def get(self): node = self.getparent(getattr(__import__("pytest"), name)) if node is not None: @@ -258,7 +257,6 @@ class PyobjMixin(PyobjContext): super(PyobjMixin, self).__init__(*k, **kw) def obj(): - def fget(self): obj = getattr(self, "_obj", None) if obj is None: @@ -320,7 +318,6 @@ class PyobjMixin(PyobjContext): class PyCollector(PyobjMixin, nodes.Collector): - def funcnamefilter(self, name): return self._matches_prefix_or_glob_option("python_functions", name) @@ -487,9 +484,11 @@ class Module(nodes.File, PyCollector): exc_info = ExceptionInfo() if self.config.getoption("verbose") < 2: exc_info.traceback = exc_info.traceback.filter(filter_traceback) - exc_repr = exc_info.getrepr( - style="short" - ) if exc_info.traceback else exc_info.exconly() + exc_repr = ( + exc_info.getrepr(style="short") + if exc_info.traceback + else exc_info.exconly() + ) formatted_tb = safe_str(exc_repr) raise self.CollectError( "ImportError while importing test module '{fspath}'.\n" @@ -673,7 +672,6 @@ class FunctionMixin(PyobjMixin): class Generator(FunctionMixin, PyCollector): - def collect(self): # test generators are seen as collectors but they also # invoke setup/teardown on popular request @@ -728,7 +726,6 @@ def hasnew(obj): class CallSpec2(object): - def __init__(self, metafunc): self.metafunc = metafunc self.funcargs = {} @@ -1002,9 +999,9 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect): from _pytest.fixtures import scopes indirect_as_list = isinstance(indirect, (list, tuple)) - all_arguments_are_fixtures = indirect is True or indirect_as_list and len( - indirect - ) == argnames + all_arguments_are_fixtures = ( + indirect is True or indirect_as_list and len(indirect) == argnames + ) if all_arguments_are_fixtures: fixturedefs = arg2fixturedefs or {} used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()] @@ -1026,8 +1023,9 @@ def _idval(val, argname, idx, idfn, config=None): # See issue https://github.com/pytest-dev/pytest/issues/2169 import warnings - msg = "Raised while trying to determine id of parameter %s at position %d." % ( - argname, idx + msg = ( + "Raised while trying to determine id of parameter %s at position %d." + % (argname, idx) ) msg += "\nUpdate your code as this will raise an error in pytest-4.0." warnings.warn(msg, DeprecationWarning) @@ -1222,6 +1220,7 @@ class Function(FunctionMixin, nodes.Item, fixtures.FuncargnamesCompatAttr): """ a Function Item is responsible for setting up and executing a Python test function. """ + _genid = None # disable since functions handle it themselfes _ALLOW_MARKERS = False diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 5ee16c2f8..d88d1c88b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -174,6 +174,7 @@ class ApproxScalar(ApproxBase): """ Perform approximate comparisons for single numbers only. """ + DEFAULT_ABSOLUTE_TOLERANCE = 1e-12 DEFAULT_RELATIVE_TOLERANCE = 1e-6 @@ -271,9 +272,7 @@ class ApproxScalar(ApproxBase): # we aren't even going to use it. relative_tolerance = set_default( self.rel, self.DEFAULT_RELATIVE_TOLERANCE - ) * abs( - self.expected - ) + ) * abs(self.expected) if relative_tolerance < 0: raise ValueError( @@ -652,7 +651,6 @@ raises.Exception = fail.Exception class RaisesContext(object): - def __init__(self, expected_exception, message, match_expr): self.expected_exception = expected_exception self.message = message diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 7839f5700..177757f27 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -193,13 +193,10 @@ class WarningsRecorder(warnings.catch_warnings): class WarningsChecker(WarningsRecorder): - def __init__(self, expected_warning=None, match_expr=None): super(WarningsChecker, self).__init__() - msg = ( - "exceptions must be old-style classes or " "derived from Warning, not %s" - ) + msg = "exceptions must be old-style classes or " "derived from Warning, not %s" if isinstance(expected_warning, tuple): for exc in expected_warning: if not inspect.isclass(exc): diff --git a/src/_pytest/resultlog.py b/src/_pytest/resultlog.py index 8f300c983..0ad31b8bc 100644 --- a/src/_pytest/resultlog.py +++ b/src/_pytest/resultlog.py @@ -68,7 +68,6 @@ def generic_path(item): class ResultLog(object): - def __init__(self, config, logfile): self.config = config self.logfile = logfile # preferably line buffered diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 18e925509..ee53642c7 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -186,6 +186,7 @@ def call_runtest_hook(item, when, **kwds): class CallInfo(object): """ Result/Exception info a function invocation. """ + #: None or ExceptionInfo object. excinfo = None @@ -221,13 +222,15 @@ def getslaveinfoline(node): d = node.slaveinfo ver = "%s.%s.%s" % d["version_info"][:3] node._slaveinfocache = s = "[%s] %s -- Python %s %s" % ( - d["id"], d["sysplatform"], ver, d["executable"] + d["id"], + d["sysplatform"], + ver, + d["executable"], ) return s class BaseReport(object): - def __init__(self, **kw): self.__dict__.update(kw) @@ -401,7 +404,9 @@ class TestReport(BaseReport): def __repr__(self): return "" % ( - self.nodeid, self.when, self.outcome + self.nodeid, + self.when, + self.outcome, ) @@ -442,7 +447,6 @@ def pytest_make_collect_report(collector): class CollectReport(BaseReport): - def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra): self.nodeid = nodeid self.outcome = outcome @@ -457,12 +461,13 @@ class CollectReport(BaseReport): def __repr__(self): return "" % ( - self.nodeid, len(self.result), self.outcome + self.nodeid, + len(self.result), + self.outcome, ) class CollectErrorRepr(TerminalRepr): - def __init__(self, msg): self.longrepr = msg @@ -529,7 +534,7 @@ class SetupState(object): def _teardown_towards(self, needed_collectors): exc = None while self.stack: - if self.stack == needed_collectors[:len(self.stack)]: + if self.stack == needed_collectors[: len(self.stack)]: break try: self._pop_and_teardown() @@ -551,7 +556,7 @@ class SetupState(object): for col in self.stack: if hasattr(col, "_prepare_exc"): py.builtin._reraise(*col._prepare_exc) - for col in needed_collectors[len(self.stack):]: + for col in needed_collectors[len(self.stack) :]: self.stack.append(col) try: col.setup() diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index a348d5484..64bc770ae 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -157,9 +157,11 @@ def pytest_runtest_makereport(item, call): else: rep.outcome = "passed" rep.wasxfail = explanation - elif getattr(item, "_skipped_by_mark", False) and rep.skipped and type( - rep.longrepr - ) is tuple: + elif ( + getattr(item, "_skipped_by_mark", False) + and rep.skipped + and type(rep.longrepr) is tuple + ): # skipped by mark.skipif; change the location of the failure # to point to the item definition, otherwise it will display # the location of where the skip exception was raised within pytest @@ -274,7 +276,6 @@ def show_skipped(terminalreporter, lines): def shower(stat, format): - def show_(terminalreporter, lines): return show_simple(terminalreporter, lines, stat, format) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 9c4eec753..7dd2edd6f 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -220,7 +220,6 @@ class WarningReport(object): class TerminalReporter(object): - def __init__(self, config, file=None): import _pytest.config @@ -407,13 +406,16 @@ class TerminalReporter(object): def pytest_runtest_logfinish(self, nodeid): if self.verbosity <= 0 and self._show_progress_info: self._progress_nodeids_reported.add(nodeid) - last_item = len( - self._progress_nodeids_reported - ) == self._session.testscollected + last_item = ( + len(self._progress_nodeids_reported) == self._session.testscollected + ) if last_item: self._write_progress_information_filling_space() else: - past_edge = self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width + past_edge = ( + self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 + >= self._screen_width + ) if past_edge: msg = self._get_progress_information_message() self._tw.write(msg + "\n", cyan=True) @@ -462,8 +464,8 @@ class TerminalReporter(object): line = "collected " else: line = "collecting " - line += str(self._numcollected) + " item" + ( - "" if self._numcollected == 1 else "s" + line += ( + str(self._numcollected) + " item" + ("" if self._numcollected == 1 else "s") ) if errors: line += " / %d errors" % errors @@ -495,7 +497,9 @@ class TerminalReporter(object): verinfo = ".".join(map(str, sys.pypy_version_info[:3])) msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3]) msg += ", pytest-%s, py-%s, pluggy-%s" % ( - pytest.__version__, py.__version__, pluggy.__version__ + pytest.__version__, + py.__version__, + pluggy.__version__, ) if ( self.verbosity > 0 @@ -563,10 +567,10 @@ class TerminalReporter(object): for item in items: needed_collectors = item.listchain()[1:] # strip root node while stack: - if stack == needed_collectors[:len(stack)]: + if stack == needed_collectors[: len(stack)]: break stack.pop() - for col in needed_collectors[len(stack):]: + for col in needed_collectors[len(stack) :]: stack.append(col) # if col.name == "()": # continue @@ -624,11 +628,10 @@ class TerminalReporter(object): ) def _locationline(self, nodeid, fspath, lineno, domain): - def mkrel(nodeid): line = self.config.cwd_relative_nodeid(nodeid) if domain and line.endswith(domain): - line = line[:-len(domain)] + line = line[: -len(domain)] values = domain.split("[") values[0] = values[0].replace(".", "::") # don't replace '.' in params line += "[".join(values) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 6ad9fda88..d6e7cb272 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -163,15 +163,13 @@ class TestCaseFunction(Function): # implements the skipping machinery (see #2137) # analog to pythons Lib/unittest/case.py:run testMethod = getattr(self._testcase, self._testcase._testMethodName) - if ( - getattr(self._testcase.__class__, "__unittest_skip__", False) - or getattr(testMethod, "__unittest_skip__", False) + if getattr(self._testcase.__class__, "__unittest_skip__", False) or getattr( + testMethod, "__unittest_skip__", False ): # If the class or method was skipped. - skip_why = ( - getattr(self._testcase.__class__, "__unittest_skip_why__", "") - or getattr(testMethod, "__unittest_skip_why__", "") - ) + skip_why = getattr( + self._testcase.__class__, "__unittest_skip_why__", "" + ) or getattr(testMethod, "__unittest_skip_why__", "") try: # PY3, unittest2 on PY2 self._testcase._addSkip(self, self._testcase, skip_why) except TypeError: # PY2 diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index e023d0ab4..abd04801b 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -75,9 +75,8 @@ def catch_warnings_for_item(item): warn_msg = warning.message unicode_warning = False - if ( - compat._PY2 - and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args) + if compat._PY2 and any( + isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args ): new_args = [] for m in warn_msg.args: diff --git a/tasks/generate.py b/tasks/generate.py index 398af70c9..89452aa5c 100644 --- a/tasks/generate.py +++ b/tasks/generate.py @@ -22,16 +22,16 @@ def announce(ctx, version): contributors = set(stdout.splitlines()) - template_name = "release.minor.rst" if version.endswith( - ".0" - ) else "release.patch.rst" - template_text = Path(__file__).parent.joinpath(template_name).read_text( - encoding="UTF-8" + template_name = ( + "release.minor.rst" if version.endswith(".0") else "release.patch.rst" + ) + template_text = ( + Path(__file__).parent.joinpath(template_name).read_text(encoding="UTF-8") ) - contributors_text = "\n".join( - "* {}".format(name) for name in sorted(contributors) - ) + "\n" + contributors_text = ( + "\n".join("* {}".format(name) for name in sorted(contributors)) + "\n" + ) text = template_text.format(version=version, contributors=contributors_text) target = Path(__file__).parent.joinpath( diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index c2eed419c..88c1f8740 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -13,7 +13,6 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR class TestGeneralUsage(object): - def test_config_error(self, testdir): testdir.makeconftest( """ @@ -458,7 +457,6 @@ class TestGeneralUsage(object): class TestInvocationVariants(object): - def test_earlyinit(self, testdir): p = testdir.makepyfile( """ @@ -557,9 +555,7 @@ class TestInvocationVariants(object): out, err = capsys.readouterr() def test_invoke_plugin_api(self, testdir, capsys): - class MyPlugin(object): - def pytest_addoption(self, parser): parser.addoption("--myopt") @@ -798,9 +794,10 @@ class TestInvocationVariants(object): """Test backward compatibility for get_plugin_manager function. See #787.""" import _pytest.config - assert type( - _pytest.config.get_plugin_manager() - ) is _pytest.config.PytestPluginManager + assert ( + type(_pytest.config.get_plugin_manager()) + is _pytest.config.PytestPluginManager + ) def test_has_plugin(self, request): """Test hasplugin function of the plugin manager (#932).""" diff --git a/testing/code/test_code.py b/testing/code/test_code.py index bfae36918..e098f136d 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -26,7 +26,6 @@ def test_code_gives_back_name_for_not_existing_file(): def test_code_with_class(): - class A(object): pass @@ -54,7 +53,6 @@ def test_code_source(): def test_frame_getsourcelineno_myself(): - def func(): return sys._getframe(0) @@ -65,7 +63,6 @@ def test_frame_getsourcelineno_myself(): def test_getstatement_empty_fullsource(): - def func(): return sys._getframe(0) @@ -111,7 +108,6 @@ def test_unicode_handling_syntax_error(): def test_code_getargs(): - def f1(x): pass @@ -138,7 +134,6 @@ def test_code_getargs(): def test_frame_getargs(): - def f1(x): return sys._getframe(0) @@ -165,7 +160,6 @@ def test_frame_getargs(): class TestExceptionInfo(object): - def test_bad_getsource(self): try: if False: @@ -178,7 +172,6 @@ class TestExceptionInfo(object): class TestTracebackEntry(object): - def test_getsource(self): try: if False: @@ -194,7 +187,6 @@ class TestTracebackEntry(object): class TestReprFuncArgs(object): - def test_not_raise_exception_with_mixed_encoding(self): from _pytest._code.code import ReprFuncArgs diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index f4044b6ec..4bac7ba4c 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -65,7 +65,6 @@ def test_excinfo_simple(): def test_excinfo_getstatement(): - def g(): raise ValueError @@ -112,7 +111,6 @@ def h(): class TestTraceback_f_g_h(object): - def setup_method(self, method): try: h() @@ -194,7 +192,6 @@ class TestTraceback_f_g_h(object): ], ) def test_traceback_filter_selective(self, tracebackhide, matching): - def f(): # raise ValueError @@ -224,7 +221,6 @@ class TestTraceback_f_g_h(object): assert len(ntraceback) == len(traceback) - 1 def test_traceback_recursion_index(self): - def f(n): if n < 10: n += 1 @@ -236,7 +232,6 @@ class TestTraceback_f_g_h(object): assert recindex == 3 def test_traceback_only_specific_recursion_errors(self, monkeypatch): - def f(n): if n == 0: raise RuntimeError("hello") @@ -248,7 +243,6 @@ class TestTraceback_f_g_h(object): assert "RuntimeError: hello" in str(repr.reprcrash) def test_traceback_no_recursion_index(self): - def do_stuff(): raise RuntimeError @@ -288,7 +282,6 @@ class TestTraceback_f_g_h(object): assert excinfo.traceback.recursionindex() is None def test_traceback_getcrashentry(self): - def i(): __tracebackhide__ = True raise ValueError @@ -312,7 +305,6 @@ class TestTraceback_f_g_h(object): assert entry.frame.code.name == "h" def test_traceback_getcrashentry_empty(self): - def g(): __tracebackhide__ = True raise ValueError @@ -429,10 +421,8 @@ def test_match_raises_error(testdir): class TestFormattedExcinfo(object): - @pytest.fixture def importasmod(self, request): - def importasmod(source): source = _pytest._code.Source(source) tmpdir = request.getfixturevalue("tmpdir") @@ -519,7 +509,6 @@ raise ValueError() pr = FormattedExcinfo() class FakeCode(object): - class raw(object): co_filename = "?" @@ -537,7 +526,6 @@ raise ValueError() f_globals = {} class FakeTracebackEntry(_pytest._code.Traceback.Entry): - def __init__(self, tb, excinfo=None): self.lineno = 5 + 3 @@ -882,7 +870,6 @@ raise ValueError() from _pytest._code.code import TerminalRepr class MyRepr(TerminalRepr): - def toterminal(self, tw): tw.line(py.builtin._totext("я", "utf-8")) @@ -1303,7 +1290,6 @@ def test_exception_repr_extraction_error_on_recursion(): """ class numpy_like(object): - def __eq__(self, other): if type(other) is numpy_like: raise ValueError( @@ -1343,7 +1329,6 @@ def test_no_recursion_index_on_recursion_error(): try: class RecursionDepthError(object): - def __getattr__(self, attr): return getattr(self, "_" + attr) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 56dad7567..34a6dc5d1 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -58,9 +58,7 @@ def test_source_from_function(): def test_source_from_method(): - class TestClass(object): - def test_method(self): pass @@ -75,7 +73,6 @@ def test_source_from_lines(): def test_source_from_inner_function(): - def f(): pass @@ -199,7 +196,6 @@ class TestSourceParsingAndCompiling(object): assert str(source) == "x=3" def test_compile_and_getsource_through_same_function(self): - def gensource(source): return _pytest._code.compile(source) @@ -337,7 +333,6 @@ class TestSourceParsingAndCompiling(object): @pytest.mark.parametrize("name", ["", None, "my"]) def test_compilefuncs_and_path_sanity(self, name): - def check(comp, name): co = comp(self.source, name) if not name: @@ -359,9 +354,7 @@ class TestSourceParsingAndCompiling(object): def test_getstartingblock_singleline(): - class A(object): - def __init__(self, *args): frame = sys._getframe(1) self.source = _pytest._code.Frame(frame).statement @@ -373,7 +366,6 @@ def test_getstartingblock_singleline(): def test_getline_finally(): - def c(): pass @@ -406,7 +398,6 @@ def test_getfuncsource_dynamic(): def test_getfuncsource_with_multine_string(): - def f(): c = """while True: pass @@ -538,14 +529,12 @@ def test_getfslineno(): def test_code_of_object_instance_with_call(): - class A(object): pass pytest.raises(TypeError, lambda: _pytest._code.Source(A())) class WithCall(object): - def __call__(self): pass @@ -553,7 +542,6 @@ def test_code_of_object_instance_with_call(): assert "pass" in str(code.source()) class Hello(object): - def __call__(self): pass diff --git a/testing/code/test_source_multiline_block.py b/testing/code/test_source_multiline_block.py index 92f7412eb..009bb87ae 100644 --- a/testing/code/test_source_multiline_block.py +++ b/testing/code/test_source_multiline_block.py @@ -14,7 +14,6 @@ def test_getstartingblock_multiline(): """ class A(object): - def __init__(self, *args): frame = sys._getframe(1) self.source = _pytest._code.Frame(frame).statement diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 39ff1f1fc..b82dbcf7d 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -84,7 +84,6 @@ def test_str_args_deprecated(tmpdir, testdir): warnings = [] class Collect(object): - def pytest_logwarning(self, message): warnings.append(message) @@ -260,6 +259,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives( ) res = testdir.runpytest_subprocess() assert res.ret == 0 - assert str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[ - 0 - ] not in res.stderr.str() + assert ( + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] + not in res.stderr.str() + ) diff --git a/testing/logging/test_formatter.py b/testing/logging/test_formatter.py index ca2a41065..0348b215c 100644 --- a/testing/logging/test_formatter.py +++ b/testing/logging/test_formatter.py @@ -18,7 +18,6 @@ def test_coloredlogformatter(): ) class ColorConfig(object): - class option(object): pass @@ -26,9 +25,8 @@ def test_coloredlogformatter(): tw.hasmarkup = True formatter = ColoredLevelFormatter(tw, logfmt) output = formatter.format(record) - assert ( - output - == ("dummypath 10 " "\x1b[32mINFO \x1b[0m Test Message") + assert output == ( + "dummypath 10 " "\x1b[32mINFO \x1b[0m Test Message" ) tw.hasmarkup = False diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 91ed2e475..0a8a58506 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -520,16 +520,22 @@ def test_sections_single_new_line_after_test_outcome(testdir, request): "=* 1 passed in *=", ] ) - assert re.search( - r"(.+)live log teardown(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)", - result.stdout.str(), - re.MULTILINE, - ) is not None - assert re.search( - r"(.+)live log finish(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)", - result.stdout.str(), - re.MULTILINE, - ) is not None + assert ( + re.search( + r"(.+)live log teardown(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)", + result.stdout.str(), + re.MULTILINE, + ) + is not None + ) + assert ( + re.search( + r"(.+)live log finish(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)", + result.stdout.str(), + re.MULTILINE, + ) + is not None + ) def test_log_cli_level(testdir): @@ -850,7 +856,6 @@ def test_live_logging_suspends_capture(has_capture_manager, request): assert CaptureManager.resume_global_capture class DummyTerminal(six.StringIO): - def section(self, *args, **kwargs): pass @@ -865,10 +870,10 @@ def test_live_logging_suspends_capture(has_capture_manager, request): logger.critical("some message") if has_capture_manager: - assert ( - MockCaptureManager.calls - == ["suspend_global_capture", "resume_global_capture"] - ) + assert MockCaptureManager.calls == [ + "suspend_global_capture", + "resume_global_capture", + ] else: assert MockCaptureManager.calls == [] assert out_file.getvalue() == "\nsome message\n" diff --git a/testing/python/approx.py b/testing/python/approx.py index e65647897..39f10a821 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -13,7 +13,6 @@ inf, nan = float("inf"), float("nan") class MyDocTestRunner(doctest.DocTestRunner): - def __init__(self): doctest.DocTestRunner.__init__(self) @@ -26,7 +25,6 @@ class MyDocTestRunner(doctest.DocTestRunner): class TestApprox(object): - @pytest.fixture def plus_minus(self): return u"\u00b1" if sys.version_info[0] > 2 else u"+-" @@ -34,23 +32,20 @@ class TestApprox(object): def test_repr_string(self, plus_minus): tol1, tol2, infr = "1.0e-06", "2.0e-06", "inf" assert repr(approx(1.0)) == "1.0 {pm} {tol1}".format(pm=plus_minus, tol1=tol1) - assert ( - repr(approx([1.0, 2.0])) - == "approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])".format( - pm=plus_minus, tol1=tol1, tol2=tol2 - ) + assert repr( + approx([1.0, 2.0]) + ) == "approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])".format( + pm=plus_minus, tol1=tol1, tol2=tol2 ) - assert ( - repr(approx((1.0, 2.0))) - == "approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))".format( - pm=plus_minus, tol1=tol1, tol2=tol2 - ) + assert repr( + approx((1.0, 2.0)) + ) == "approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))".format( + pm=plus_minus, tol1=tol1, tol2=tol2 ) assert repr(approx(inf)) == "inf" assert repr(approx(1.0, rel=nan)) == "1.0 {pm} ???".format(pm=plus_minus) - assert ( - repr(approx(1.0, rel=inf)) - == "1.0 {pm} {infr}".format(pm=plus_minus, infr=infr) + assert repr(approx(1.0, rel=inf)) == "1.0 {pm} {infr}".format( + pm=plus_minus, infr=infr ) assert repr(approx(1.0j, rel=inf)) == "1j" diff --git a/testing/python/collect.py b/testing/python/collect.py index 724504b1a..46694f2d8 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -14,7 +14,6 @@ ignore_parametrized_marks = pytest.mark.filterwarnings( class TestModule(object): - def test_failing_import(self, testdir): modcol = testdir.getmodulecol("import alksdjalskdjalkjals") pytest.raises(Collector.CollectError, modcol.collect) @@ -141,7 +140,6 @@ class TestModule(object): class TestClass(object): - def test_class_with_init_warning(self, testdir): testdir.makepyfile( """ @@ -246,7 +244,6 @@ class TestClass(object): class TestGenerator(object): - def test_generative_functions(self, testdir): modcol = testdir.getmodulecol( """ @@ -458,7 +455,6 @@ class TestGenerator(object): class TestFunction(object): - def test_getmodulecollector(self, testdir): item = testdir.getitem("def test_func(): pass") modcol = item.getparent(pytest.Module) @@ -673,12 +669,10 @@ class TestFunction(object): config = item.config class MyPlugin1(object): - def pytest_pyfunc_call(self, pyfuncitem): raise ValueError class MyPlugin2(object): - def pytest_pyfunc_call(self, pyfuncitem): return True @@ -831,7 +825,6 @@ class TestFunction(object): class TestSorting(object): - def test_check_equality(self, testdir): modcol = testdir.getmodulecol( """ @@ -886,7 +879,6 @@ class TestSorting(object): class TestConftestCustomization(object): - def test_pytest_pycollect_module(self, testdir): testdir.makeconftest( """ @@ -1062,7 +1054,6 @@ def test_modulecol_roundtrip(testdir): class TestTracebackCutting(object): - def test_skip_simple(self): excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")') assert excinfo.traceback[-1].frame.code.name == "skip" @@ -1191,7 +1182,6 @@ class TestTracebackCutting(object): class TestReportInfo(object): - def test_itemreport_reportinfo(self, testdir, linecomp): testdir.makeconftest( """ @@ -1497,7 +1487,10 @@ def test_class_injection_does_not_break_collection(testdir): ''' ) result = testdir.runpytest() - assert "RuntimeError: dictionary changed size during iteration" not in result.stdout.str() + assert ( + "RuntimeError: dictionary changed size during iteration" + not in result.stdout.str() + ) result.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/python/fixture.py b/testing/python/fixture.py index 6d2bb663b..9cc3b6890 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -8,7 +8,6 @@ from _pytest import fixtures def test_getfuncargnames(): - def f(): pass @@ -30,7 +29,6 @@ def test_getfuncargnames(): assert fixtures.getfuncargnames(h) == ("arg1", "arg2") class A(object): - def f(self, arg1, arg2="hello"): pass @@ -43,7 +41,6 @@ def test_getfuncargnames(): class TestFillFixtures(object): - def test_fillfuncargs_exposed(self): # used by oejskit, kept for compatibility assert pytest._fillfuncargs == fixtures.fillfixtures @@ -570,7 +567,6 @@ class TestFillFixtures(object): class TestRequestBasic(object): - def test_request_attributes(self, testdir): item = testdir.getitem( """ @@ -1003,7 +999,6 @@ class TestRequestBasic(object): class TestRequestMarking(object): - def test_applymarker(self, testdir): item1, item2 = testdir.getitems( """ @@ -1073,7 +1068,6 @@ class TestRequestMarking(object): class TestRequestCachedSetup(object): - def test_request_cachedsetup_defaultmodule(self, testdir): reprec = testdir.inline_runsource( """ @@ -1245,7 +1239,6 @@ class TestRequestCachedSetup(object): class TestFixtureUsages(object): - def test_noargfixturedec(self, testdir): testdir.makepyfile( """ @@ -1540,7 +1533,6 @@ class TestFixtureUsages(object): class TestFixtureManagerParseFactories(object): - @pytest.fixture def testdir(self, request): testdir = request.getfixturevalue("testdir") @@ -1668,7 +1660,6 @@ class TestFixtureManagerParseFactories(object): class TestAutouseDiscovery(object): - @pytest.fixture def testdir(self, testdir): testdir.makeconftest( @@ -1845,7 +1836,6 @@ class TestAutouseDiscovery(object): class TestAutouseManagement(object): - def test_autouse_conftest_mid_directory(self, testdir): pkgdir = testdir.mkpydir("xyz123") pkgdir.join("conftest.py").write( @@ -2112,7 +2102,6 @@ class TestAutouseManagement(object): class TestFixtureMarker(object): - def test_parametrize(self, testdir): testdir.makepyfile( """ @@ -2938,21 +2927,18 @@ class TestFixtureMarker(object): reprec = testdir.inline_run() reprec.assertoutcome(passed=6) values = reprec.getcalls("pytest_runtest_call")[0].item.module.values - assert ( - values - == [ - "test_hello", - "fin John", - "test_hello", - "fin Doe", - "test_name", - "test_population", - "fin John", - "test_name", - "test_population", - "fin Doe", - ] - ) + assert values == [ + "test_hello", + "fin John", + "test_hello", + "fin Doe", + "test_name", + "test_population", + "fin John", + "test_name", + "test_population", + "fin Doe", + ] def test_parametrize_setup_function(self, testdir): testdir.makepyfile( @@ -3135,7 +3121,6 @@ class TestRequestScopeAccess(object): class TestErrors(object): - def test_subfactory_missing_funcarg(self, testdir): testdir.makepyfile( """ @@ -3203,7 +3188,6 @@ class TestErrors(object): class TestShowFixtures(object): - def test_funcarg_compat(self, testdir): config = testdir.parseconfigure("--funcargs") assert config.option.showfixtures @@ -3480,7 +3464,6 @@ class TestShowFixtures(object): @pytest.mark.parametrize("flavor", ["fixture", "yield_fixture"]) class TestContextManagerFixtureFuncs(object): - def test_simple(self, testdir, flavor): testdir.makepyfile( """ @@ -3622,7 +3605,6 @@ class TestContextManagerFixtureFuncs(object): class TestParameterizedSubRequest(object): - def test_call_from_fixture(self, testdir): testfile = testdir.makepyfile( """ diff --git a/testing/python/integration.py b/testing/python/integration.py index f348fdc29..a6fb93bfb 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -4,7 +4,6 @@ from _pytest import runner class TestOEJSKITSpecials(object): - def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage testdir.makeconftest( """ @@ -70,7 +69,6 @@ class TestOEJSKITSpecials(object): def test_wrapped_getfslineno(): - def func(): pass @@ -89,12 +87,10 @@ def test_wrapped_getfslineno(): class TestMockDecoration(object): - def test_wrapped_getfuncargnames(self): from _pytest.compat import getfuncargnames def wrap(f): - def func(): pass @@ -115,7 +111,6 @@ class TestMockDecoration(object): from _pytest.compat import getfuncargnames def wrap(f): - def func(): pass @@ -269,7 +264,6 @@ class TestMockDecoration(object): class TestReRunTests(object): - def test_rerun(self, testdir): testdir.makeconftest( """ @@ -316,7 +310,6 @@ def test_pytestconfig_is_session_scoped(): class TestNoselikeTestAttribute(object): - def test_module_with_global_test(self, testdir): testdir.makepyfile( """ @@ -402,7 +395,6 @@ class TestNoselikeTestAttribute(object): @pytest.mark.issue351 class TestParameterize(object): - def test_idfn_marker(self, testdir): testdir.makepyfile( """ diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e181d3131..9f425821b 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -14,7 +14,6 @@ PY3 = sys.version_info >= (3, 0) class TestMetafunc(object): - def Metafunc(self, func, config=None): # the unit tests of this class check if things work correctly # on the funcarg level, so we don't need a full blown @@ -35,7 +34,6 @@ class TestMetafunc(object): return python.Metafunc(definition, fixtureinfo, config) def test_no_funcargs(self, testdir): - def function(): pass @@ -44,7 +42,6 @@ class TestMetafunc(object): repr(metafunc._calls) def test_function_basic(self): - def func(arg1, arg2="qwe"): pass @@ -55,7 +52,6 @@ class TestMetafunc(object): assert metafunc.cls is None def test_addcall_no_args(self): - def func(arg1): pass @@ -67,7 +63,6 @@ class TestMetafunc(object): assert not hasattr(call, "param") def test_addcall_id(self): - def func(arg1): pass @@ -83,7 +78,6 @@ class TestMetafunc(object): assert metafunc._calls[1].id == "2" def test_addcall_param(self): - def func(arg1): pass @@ -101,7 +95,6 @@ class TestMetafunc(object): assert metafunc._calls[2].getparam("arg1") == 1 def test_addcall_funcargs(self): - def func(x): pass @@ -119,7 +112,6 @@ class TestMetafunc(object): assert not hasattr(metafunc._calls[1], "param") def test_parametrize_error(self): - def func(x, y): pass @@ -132,7 +124,6 @@ class TestMetafunc(object): pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) def test_parametrize_bad_scope(self, testdir): - def func(x): pass @@ -143,7 +134,6 @@ class TestMetafunc(object): assert "has an unsupported scope value 'doggy'" in str(ve) def test_parametrize_and_id(self): - def func(x, y): pass @@ -166,7 +156,6 @@ class TestMetafunc(object): assert ids == [u"basic", u"advanced"] def test_parametrize_with_wrong_number_of_ids(self, testdir): - def func(x, y): pass @@ -185,12 +174,10 @@ class TestMetafunc(object): @pytest.mark.issue510 def test_parametrize_empty_list(self): - def func(y): pass class MockConfig(object): - def getini(self, name): return "" @@ -206,7 +193,6 @@ class TestMetafunc(object): assert "skip" == metafunc._calls[0].marks[0].name def test_parametrize_with_userobjects(self): - def func(x, y): pass @@ -338,23 +324,20 @@ class TestMetafunc(object): pytest.param(b"\xc3\xb4", totext("other")), ], ) - assert ( - result - == [ - "1.0--1.1", - "2--202", - "three-three hundred", - "True-False", - "None-None", - "foo-bar", - "str-int", - "a7-b7", - "a8-b8", - "a9-b9", - "\\xc3\\xb4-name", - "\\xc3\\xb4-other", - ] - ) + assert result == [ + "1.0--1.1", + "2--202", + "three-three hundred", + "True-False", + "None-None", + "foo-bar", + "str-int", + "a7-b7", + "a8-b8", + "a9-b9", + "\\xc3\\xb4-name", + "\\xc3\\xb4-other", + ] def test_idmaker_enum(self): from _pytest.python import idmaker @@ -424,23 +407,20 @@ class TestMetafunc(object): idfn=ids, ) - assert ( - [str(i.message) for i in rec.list] - == [ - "Raised while trying to determine id of parameter a at position 0." - "\nUpdate your code as this will raise an error in pytest-4.0.", - "Raised while trying to determine id of parameter b at position 0." - "\nUpdate your code as this will raise an error in pytest-4.0.", - "Raised while trying to determine id of parameter a at position 1." - "\nUpdate your code as this will raise an error in pytest-4.0.", - "Raised while trying to determine id of parameter b at position 1." - "\nUpdate your code as this will raise an error in pytest-4.0.", - "Raised while trying to determine id of parameter a at position 2." - "\nUpdate your code as this will raise an error in pytest-4.0.", - "Raised while trying to determine id of parameter b at position 2." - "\nUpdate your code as this will raise an error in pytest-4.0.", - ] - ) + assert [str(i.message) for i in rec.list] == [ + "Raised while trying to determine id of parameter a at position 0." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 0." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter a at position 1." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 1." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter a at position 2." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 2." + "\nUpdate your code as this will raise an error in pytest-4.0.", + ] def test_parametrize_ids_exception(self, testdir): """ @@ -496,7 +476,6 @@ class TestMetafunc(object): assert result == ["a0", "a1", "b0", "c", "b1"] def test_addcall_and_parametrize(self): - def func(x, y): pass @@ -511,7 +490,6 @@ class TestMetafunc(object): @pytest.mark.issue714 def test_parametrize_indirect(self): - def func(x, y): pass @@ -526,7 +504,6 @@ class TestMetafunc(object): @pytest.mark.issue714 def test_parametrize_indirect_list(self): - def func(x, y): pass @@ -537,7 +514,6 @@ class TestMetafunc(object): @pytest.mark.issue714 def test_parametrize_indirect_list_all(self): - def func(x, y): pass @@ -548,7 +524,6 @@ class TestMetafunc(object): @pytest.mark.issue714 def test_parametrize_indirect_list_empty(self): - def func(x, y): pass @@ -588,7 +563,6 @@ class TestMetafunc(object): @pytest.mark.issue714 def test_parametrize_indirect_list_error(self, testdir): - def func(x, y): pass @@ -704,7 +678,6 @@ class TestMetafunc(object): ) def test_addcalls_and_parametrize_indirect(self): - def func(x, y): pass @@ -837,7 +810,6 @@ class TestMetafunc(object): ) def test_format_args(self): - def function1(): pass @@ -860,7 +832,6 @@ class TestMetafunc(object): class TestMetafuncFunctional(object): - def test_attributes(self, testdir): p = testdir.makepyfile( """ @@ -1494,7 +1465,6 @@ class TestMetafuncFunctionalAuto(object): @pytest.mark.filterwarnings("ignore:Applying marks directly to parameters") @pytest.mark.issue308 class TestMarkersWithParametrization(object): - def test_simple_mark(self, testdir): s = """ import pytest diff --git a/testing/python/raises.py b/testing/python/raises.py index 64199c3b6..99aeffdf2 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -4,7 +4,6 @@ import sys class TestRaises(object): - def test_raises(self): source = "int('qwe')" excinfo = pytest.raises(ValueError, source) @@ -22,9 +21,7 @@ class TestRaises(object): pytest.raises(ValueError, int, "hello") def test_raises_callable_no_exception(self): - class A(object): - def __call__(self): pass @@ -109,7 +106,6 @@ class TestRaises(object): import gc class T(object): - def __call__(self): raise ValueError @@ -160,7 +156,6 @@ class TestRaises(object): from six import add_metaclass class Meta(type(object)): - def __getitem__(self, item): return 1 / 0 diff --git a/testing/test_argcomplete.py b/testing/test_argcomplete.py index b042de5ce..9e6b711a2 100644 --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -86,7 +86,6 @@ class FilesCompleter(object): class TestArgComplete(object): - @pytest.mark.skipif("sys.platform in ('win32', 'darwin')") def test_compare_with_compgen(self): from _pytest._argcomplete import FastFilesCompleter diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 393cf817c..aff644ee7 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -14,7 +14,6 @@ PY3 = sys.version_info >= (3, 0) @pytest.fixture def mock_config(): - class Config(object): verbose = False @@ -27,7 +26,6 @@ def mock_config(): class TestImportHookInstallation(object): - @pytest.mark.parametrize("initial_conftest", [True, False]) @pytest.mark.parametrize("mode", ["plain", "rewrite"]) def test_conftest_assertion_rewrite(self, testdir, initial_conftest, mode): @@ -288,7 +286,6 @@ class TestImportHookInstallation(object): class TestBinReprIntegration(object): - def test_pytest_assertrepr_compare_called(self, testdir): testdir.makeconftest( """ @@ -321,7 +318,6 @@ def callequal(left, right, verbose=False): class TestAssert_reprcompare(object): - def test_different_types(self): assert callequal([0, 1], "foo") is None @@ -459,7 +455,6 @@ class TestAssert_reprcompare(object): MutableSequence = col.MutableSequence class TestSequence(MutableSequence): # works with a Sequence subclass - def __init__(self, iterable): self.elements = list(iterable) @@ -488,9 +483,7 @@ class TestAssert_reprcompare(object): assert len(expl) > 1 def test_list_bad_repr(self): - class A(object): - def __repr__(self): raise ValueError(42) @@ -506,7 +499,6 @@ class TestAssert_reprcompare(object): """ class A(str): - def __repr__(self): return "" @@ -532,7 +524,6 @@ class TestAssert_reprcompare(object): """ class A(str): - def __repr__(self): return "\xff" @@ -557,7 +548,6 @@ class TestAssert_reprcompare(object): class TestFormatExplanation(object): - def test_special_chars_full(self, testdir): # Issue 453, for the bug this would raise IndexError testdir.makepyfile( @@ -781,24 +771,19 @@ def test_rewritten(testdir): def test_reprcompare_notin(mock_config): detail = plugin.pytest_assertrepr_compare( mock_config, "not in", "foo", "aaafoobbb" - )[ - 1: - ] + )[1:] assert detail == ["'foo' is contained here:", " aaafoobbb", "? +++"] def test_reprcompare_whitespaces(mock_config): detail = plugin.pytest_assertrepr_compare(mock_config, "==", "\r\n", "\n") - assert ( - detail - == [ - r"'\r\n' == '\n'", - r"Strings contain only whitespace, escaping them using repr()", - r"- '\r\n'", - r"? --", - r"+ '\n'", - ] - ) + assert detail == [ + r"'\r\n' == '\n'", + r"Strings contain only whitespace, escaping them using repr()", + r"- '\r\n'", + r"? --", + r"+ '\n'", + ] def test_pytest_assertrepr_compare_integration(testdir): @@ -1036,7 +1021,6 @@ def test_AssertionError_message(testdir): def test_set_with_unsortable_elements(): # issue #718 class UnsortableKey(object): - def __init__(self, name): self.name = name @@ -1169,4 +1153,7 @@ def test_issue_1944(testdir): ) result = testdir.runpytest() result.stdout.fnmatch_lines(["*1 error*"]) - assert "AttributeError: 'Module' object has no attribute '_obj'" not in result.stdout.str() + assert ( + "AttributeError: 'Module' object has no attribute '_obj'" + not in result.stdout.str() + ) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 144f625bc..20cc476d8 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -78,9 +78,8 @@ def adjust_body_for_new_docstring_in_module_node(m): various Python 3.7 versions, but we should remove the 3.7 check after 3.7 is released as stable to make this check more straightforward. """ - if ( - sys.version_info < (3, 8) - and not ((3, 7) <= sys.version_info <= (3, 7, 0, "beta", 4)) + if sys.version_info < (3, 8) and not ( + (3, 7) <= sys.version_info <= (3, 7, 0, "beta", 4) ): assert len(m.body) > 1 assert isinstance(m.body[0], ast.Expr) @@ -89,7 +88,6 @@ def adjust_body_for_new_docstring_in_module_node(m): class TestAssertionRewrite(object): - def test_place_initial_imports(self): s = """'Doc string'\nother = stuff""" m = rewrite(s) @@ -150,7 +148,6 @@ class TestAssertionRewrite(object): assert "warnings" not in "".join(result.outlines) def test_name(self): - def f(): assert False @@ -181,7 +178,6 @@ class TestAssertionRewrite(object): assert getmsg(f, {"cls": X}) == "assert cls == 42" def test_assert_already_has_message(self): - def f(): assert False, "something bad!" @@ -251,7 +247,6 @@ class TestAssertionRewrite(object): ) def test_boolop(self): - def f(): f = g = False assert f and g @@ -331,7 +326,6 @@ class TestAssertionRewrite(object): getmsg(f, must_pass=True) def test_short_circuit_evaluation(self): - def f(): assert True or explode # noqa @@ -344,7 +338,6 @@ class TestAssertionRewrite(object): getmsg(f, must_pass=True) def test_unary_op(self): - def f(): x = True assert not x @@ -370,7 +363,6 @@ class TestAssertionRewrite(object): assert getmsg(f) == "assert (+0 + 0)" def test_binary_op(self): - def f(): x = 1 y = -1 @@ -384,7 +376,6 @@ class TestAssertionRewrite(object): assert getmsg(f) == "assert not (5 % 4)" def test_boolop_percent(self): - def f(): assert 3 % 2 and False @@ -411,7 +402,6 @@ class TestAssertionRewrite(object): testdir.runpytest().assert_outcomes(passed=1) def test_call(self): - def g(a=42, *args, **kwargs): return False @@ -483,7 +473,6 @@ class TestAssertionRewrite(object): ) def test_attribute(self): - class X(object): g = 3 @@ -509,7 +498,6 @@ class TestAssertionRewrite(object): ) def test_comparisons(self): - def f(): a, b = range(2) assert b < a @@ -542,7 +530,6 @@ class TestAssertionRewrite(object): getmsg(f, must_pass=True) def test_len(self): - def f(): values = list(range(10)) assert len(values) == 11 @@ -553,7 +540,6 @@ class TestAssertionRewrite(object): ) def test_custom_reprcompare(self, monkeypatch): - def my_reprcompare(op, left, right): return "42" @@ -575,11 +561,8 @@ class TestAssertionRewrite(object): assert getmsg(f) == "assert 5 <= 4" def test_assert_raising_nonzero_in_comparison(self): - def f(): - class A(object): - def __nonzero__(self): raise ValueError(42) @@ -597,16 +580,13 @@ class TestAssertionRewrite(object): assert " < 0" in getmsg(f) def test_formatchar(self): - def f(): assert "%test" == "test" assert getmsg(f).startswith("assert '%test' == 'test'") def test_custom_repr(self): - def f(): - class Foo(object): a = 1 @@ -620,7 +600,6 @@ class TestAssertionRewrite(object): class TestRewriteOnImport(object): - def test_pycache_is_a_file(self, testdir): testdir.tmpdir.join("__pycache__").write("Hello") testdir.makepyfile( @@ -671,9 +650,7 @@ class TestRewriteOnImport(object): def test_rewritten(): assert "@py_builtins" in globals() """ - ).encode( - "utf-8" - ), + ).encode("utf-8"), "wb", ) old_mode = sub.stat().mode @@ -870,7 +847,6 @@ def test_rewritten(): class TestAssertionRewriteHookDetails(object): - def test_loader_is_package_false_for_module(self, testdir): testdir.makepyfile( test_fun=""" @@ -1090,7 +1066,6 @@ def test_issue731(testdir): class TestIssue925(object): - def test_simple_case(self, testdir): testdir.makepyfile( """ @@ -1122,8 +1097,7 @@ class TestIssue925(object): result.stdout.fnmatch_lines("*E*assert True == ((False == True) == True)") -class TestIssue2121(): - +class TestIssue2121: def test_simple(self, testdir): testdir.tmpdir.join("tests/file.py").ensure().write( """ diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 33d1dd844..fcf3eaf75 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -6,11 +6,10 @@ import pytest import os import shutil -pytest_plugins = "pytester", +pytest_plugins = ("pytester",) class TestNewAPI(object): - def test_config_cache_makedir(self, testdir): testdir.makeini("[pytest]") config = testdir.parseconfigure() @@ -182,7 +181,6 @@ def test_cache_show(testdir): class TestLastFailed(object): - def test_lastfailed_usecase(self, testdir, monkeypatch): monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) p = testdir.makepyfile( @@ -557,10 +555,9 @@ class TestLastFailed(object): ) result = testdir.runpytest() result.stdout.fnmatch_lines("*1 failed*") - assert ( - self.get_cached_last_failed(testdir) - == ["test_xfail_strict_considered_failure.py::test"] - ) + assert self.get_cached_last_failed(testdir) == [ + "test_xfail_strict_considered_failure.py::test" + ] @pytest.mark.parametrize("mark", ["mark.xfail", "mark.skip"]) def test_failed_changed_to_xfail_or_skip(self, testdir, mark): @@ -572,10 +569,9 @@ class TestLastFailed(object): """ ) result = testdir.runpytest() - assert ( - self.get_cached_last_failed(testdir) - == ["test_failed_changed_to_xfail_or_skip.py::test"] - ) + assert self.get_cached_last_failed(testdir) == [ + "test_failed_changed_to_xfail_or_skip.py::test" + ] assert result.ret == 1 testdir.makepyfile( @@ -619,10 +615,10 @@ class TestLastFailed(object): """ ) testdir.runpytest() - assert ( - self.get_cached_last_failed(testdir) - == ["test_bar.py::test_bar_2", "test_foo.py::test_foo_4"] - ) + assert self.get_cached_last_failed(testdir) == [ + "test_bar.py::test_bar_2", + "test_foo.py::test_foo_4", + ] # 2. fix test_bar_2, run only test_bar.py testdir.makepyfile( @@ -695,7 +691,6 @@ class TestLastFailed(object): class TestNewFirst(object): - def test_newfirst_usecase(self, testdir): testdir.makepyfile( **{ diff --git a/testing/test_capture.py b/testing/test_capture.py index e14b3af78..54f0fbc44 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -48,7 +48,6 @@ def StdCapture(out=True, err=True, in_=True): class TestCaptureManager(object): - def test_getmethod_default_no_fd(self, monkeypatch): from _pytest.capture import pytest_addoption from _pytest.config.argparsing import Parser @@ -150,7 +149,6 @@ def test_collect_capturing(testdir): class TestPerTestCapturing(object): - def test_capture_and_fixtures(self, testdir): p = testdir.makepyfile( """ @@ -294,7 +292,6 @@ class TestPerTestCapturing(object): class TestLoggingInteraction(object): - def test_logging_stream_ownership(self, testdir): p = testdir.makepyfile( """ @@ -399,7 +396,6 @@ class TestLoggingInteraction(object): class TestCaptureFixture(object): - @pytest.mark.parametrize("opt", [[], ["-s"]]) def test_std_functional(self, testdir, opt): reprec = testdir.inline_runsource( @@ -771,7 +767,6 @@ def test_error_during_readouterr(testdir): class TestCaptureIO(object): - def test_text(self): f = capture.CaptureIO() f.write("hello") @@ -1337,7 +1332,6 @@ def test_py36_windowsconsoleio_workaround_non_standard_streams(): from _pytest.capture import _py36_windowsconsoleio_workaround class DummyStream(object): - def write(self, s): pass diff --git a/testing/test_collection.py b/testing/test_collection.py index 657d64c74..e12e788b4 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -8,7 +8,6 @@ from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv class TestCollector(object): - def test_collect_versus_item(self): from pytest import Collector, Item @@ -115,7 +114,6 @@ class TestCollector(object): class TestCollectFS(object): - def test_ignored_certain_directories(self, testdir): tmpdir = testdir.tmpdir tmpdir.ensure("build", "test_notfound.py") @@ -253,12 +251,10 @@ class TestCollectFS(object): class TestCollectPluginHookRelay(object): - def test_pytest_collect_file(self, testdir): wascalled = [] class Plugin(object): - def pytest_collect_file(self, path, parent): if not path.basename.startswith("."): # Ignore hidden files, e.g. .testmondata. @@ -273,7 +269,6 @@ class TestCollectPluginHookRelay(object): wascalled = [] class Plugin(object): - def pytest_collect_directory(self, path, parent): wascalled.append(path.basename) @@ -285,7 +280,6 @@ class TestCollectPluginHookRelay(object): class TestPrunetraceback(object): - def test_custom_repr_failure(self, testdir): p = testdir.makepyfile( """ @@ -335,7 +329,6 @@ class TestPrunetraceback(object): class TestCustomConftests(object): - def test_ignore_collect_path(self, testdir): testdir.makeconftest( """ @@ -437,7 +430,6 @@ class TestCustomConftests(object): class TestSession(object): - def test_parsearg(self, testdir): p = testdir.makepyfile("def test_func(): pass") subdir = testdir.mkdir("sub") @@ -634,7 +626,6 @@ class TestSession(object): class Test_getinitialnodes(object): - def test_global_file(self, testdir, tmpdir): x = tmpdir.ensure("x.py") with tmpdir.as_cwd(): @@ -662,7 +653,6 @@ class Test_getinitialnodes(object): class Test_genitems(object): - def test_check_collect_hashes(self, testdir): p = testdir.makepyfile( """ @@ -776,7 +766,6 @@ def test_matchnodes_two_collections_same_file(testdir): class TestNodekeywords(object): - def test_no_under(self, testdir): modcol = testdir.getmodulecol( """ diff --git a/testing/test_compat.py b/testing/test_compat.py index 550a8f1b3..399b0d342 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -7,7 +7,6 @@ from _pytest.outcomes import OutcomeException def test_is_generator(): - def zap(): yield @@ -19,9 +18,7 @@ def test_is_generator(): def test_real_func_loop_limit(): - class Evil(object): - def __init__(self): self.left = 1000 @@ -86,7 +83,6 @@ def test_is_generator_async_syntax(testdir): class ErrorsHelper(object): - @property def raise_exception(self): raise Exception("exception should be catched") diff --git a/testing/test_config.py b/testing/test_config.py index 5fb048364..b507bb8e8 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -10,7 +10,6 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED class TestParseIni(object): - @pytest.mark.parametrize( "section, filename", [("pytest", "pytest.ini"), ("tool:pytest", "setup.cfg")] ) @@ -118,7 +117,6 @@ class TestParseIni(object): class TestConfigCmdlineParsing(object): - def test_parsing_again_fails(self, testdir): config = testdir.parseconfig() pytest.raises(AssertionError, lambda: config.parse([])) @@ -172,7 +170,6 @@ class TestConfigCmdlineParsing(object): class TestConfigAPI(object): - def test_config_trace(self, testdir): config = testdir.parseconfig() values = [] @@ -412,7 +409,6 @@ class TestConfigAPI(object): class TestConfigFromdictargs(object): - def test_basic_behavior(self): from _pytest.config import Config @@ -479,7 +475,6 @@ class TestConfigFromdictargs(object): def test_options_on_small_file_do_not_blow_up(testdir): - def runfiletest(opts): reprec = testdir.inline_run(*opts) passed, skipped, failed = reprec.countoutcomes() @@ -526,7 +521,6 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch): dist = Dist() def load(self): - class PseudoPlugin(object): x = 42 @@ -606,9 +600,9 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block assert "mytestplugin" not in sys.modules assert config.pluginmanager.get_plugin("mytestplugin") is None else: - assert config.pluginmanager.get_plugin( - "mytestplugin" - ) is plugin_module_placeholder + assert ( + config.pluginmanager.get_plugin("mytestplugin") is plugin_module_placeholder + ) def test_cmdline_processargs_simple(testdir): @@ -709,7 +703,6 @@ def test_notify_exception(testdir, capfd): assert "ValueError" in err class A(object): - def pytest_internalerror(self, excrepr): return True @@ -725,7 +718,6 @@ def test_load_initial_conftest_last_ordering(testdir): pm = get_config().pluginmanager class My(object): - def pytest_load_initial_conftests(self): pass @@ -754,7 +746,6 @@ def test_get_plugin_specs_as_list(): class TestWarning(object): - def test_warn_config(self, testdir): testdir.makeconftest( """ @@ -804,7 +795,6 @@ class TestWarning(object): class TestRootdir(object): - def test_simple_noini(self, tmpdir): assert get_common_ancestor([tmpdir]) == tmpdir a = tmpdir.mkdir("a") @@ -863,7 +853,6 @@ class TestRootdir(object): class TestOverrideIniArgs(object): - @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) def test_override_ini_names(self, testdir, name): testdir.tmpdir.join(name).write( diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 61b640976..4b80f1f56 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -28,9 +28,7 @@ def ConftestWithSetinitial(path): def conftest_setinitial(conftest, args, confcutdir=None): - class Namespace(object): - def __init__(self): self.file_or_dir = args self.confcutdir = str(confcutdir) @@ -40,7 +38,6 @@ def conftest_setinitial(conftest, args, confcutdir=None): class TestConftestValueAccessGlobal(object): - def test_basic_init(self, basedir): conftest = PytestPluginManager() p = basedir.join("adir") @@ -311,7 +308,6 @@ def test_conftest_found_with_double_dash(testdir): class TestConftestVisibility(object): - def _setup_tree(self, testdir): # for issue616 # example mostly taken from: # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 7f3aff3b0..6a84c5feb 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -8,7 +8,6 @@ import pytest class TestDoctests(object): - def test_collect_testtextfile(self, testdir): w = testdir.maketxtfile(whatever="") checkfile = testdir.maketxtfile( @@ -723,7 +722,6 @@ class TestDoctests(object): class TestLiterals(object): - @pytest.mark.parametrize("config_mode", ["ini", "comment"]) def test_allow_unicode(self, testdir, config_mode): """Test that doctests which output unicode work in all python versions @@ -841,7 +839,6 @@ class TestDoctestSkips(object): @pytest.fixture(params=["text", "module"]) def makedoctest(self, testdir, request): - def makeit(doctest): mode = request.param if mode == "text": @@ -1122,7 +1119,6 @@ class TestDoctestNamespaceFixture(object): class TestDoctestReportingOption(object): - def _run_doctest_report(self, testdir, format): testdir.makepyfile( """ diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index d0be5f267..aa6b9a120 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -29,7 +29,6 @@ def assert_attr(node, **kwargs): class DomNode(object): - def __init__(self, dom): self.__node = dom @@ -81,7 +80,6 @@ class DomNode(object): class TestPython(object): - def test_summing_simple(self, testdir): testdir.makepyfile( """ @@ -713,7 +711,6 @@ def test_dont_configure_on_slaves(tmpdir): gotten = [] class FakeConfig(object): - def __init__(self): self.pluginmanager = self self.option = self @@ -737,7 +734,6 @@ def test_dont_configure_on_slaves(tmpdir): class TestNonPython(object): - def test_summing_simple(self, testdir): testdir.makeconftest( """ @@ -1127,18 +1123,15 @@ def test_fancy_items_regression(testdir): import pprint pprint.pprint(items) - assert ( - items - == [ - u"conftest a conftest.py", - u"conftest a conftest.py", - u"conftest b conftest.py", - u"test_fancy_items_regression a test_fancy_items_regression.py", - u"test_fancy_items_regression a test_fancy_items_regression.py", - u"test_fancy_items_regression b test_fancy_items_regression.py", - u"test_fancy_items_regression test_pass" u" test_fancy_items_regression.py", - ] - ) + assert items == [ + u"conftest a conftest.py", + u"conftest a conftest.py", + u"conftest b conftest.py", + u"test_fancy_items_regression a test_fancy_items_regression.py", + u"test_fancy_items_regression a test_fancy_items_regression.py", + u"test_fancy_items_regression b test_fancy_items_regression.py", + u"test_fancy_items_regression test_pass" u" test_fancy_items_regression.py", + ] def test_global_properties(testdir): diff --git a/testing/test_mark.py b/testing/test_mark.py index 17349916e..084e3c3a5 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -21,7 +21,6 @@ ignore_markinfo = pytest.mark.filterwarnings( class TestMark(object): - def test_markinfo_repr(self): from _pytest.mark import MarkInfo, Mark @@ -39,7 +38,6 @@ class TestMark(object): pytest.raises((AttributeError, TypeError), mark) def test_mark_with_param(self): - def some_function(abc): pass @@ -487,7 +485,6 @@ def test_parametrized_with_kwargs(testdir): class TestFunctional(object): - def test_mark_per_function(self, testdir): p = testdir.makepyfile( """ @@ -884,7 +881,6 @@ class TestFunctional(object): class TestKeywordSelection(object): - def test_select_simple(self, testdir): file_test = testdir.makepyfile( """ @@ -1037,7 +1033,6 @@ def test_parameterset_extractfrom(argval, expected): def test_legacy_transfer(): - class FakeModule(object): pytestmark = [] @@ -1058,7 +1053,6 @@ def test_legacy_transfer(): class TestMarkDecorator(object): - @pytest.mark.parametrize( "lhs, rhs, expected", [ diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index c298ce0d9..c47d10de2 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -17,7 +17,6 @@ def mp(): def test_setattr(): - class A(object): x = 1 @@ -42,7 +41,6 @@ def test_setattr(): class TestSetattrWithImportPath(object): - def test_string_expression(self, monkeypatch): monkeypatch.setattr("os.path.abspath", lambda x: "hello2") assert os.path.abspath("123") == "hello2" @@ -84,7 +82,6 @@ class TestSetattrWithImportPath(object): def test_delattr(): - class A(object): x = 1 @@ -311,7 +308,6 @@ def test_importerror(testdir): class SampleNew(object): - @staticmethod def hello(): return True diff --git a/testing/test_nose.py b/testing/test_nose.py index abe732375..d63b30584 100644 --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -33,7 +33,6 @@ def test_setup_func_with_setup_decorator(): values = [] class A(object): - @pytest.fixture(autouse=True) def f(self): values.append(1) diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 79076cafd..3870ad419 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -13,7 +13,6 @@ def parser(): class TestParser(object): - def test_no_help_by_default(self, capsys): parser = parseopt.Parser(usage="xyz") pytest.raises(SystemExit, lambda: parser.parse(["-h"])) @@ -34,9 +33,8 @@ class TestParser(object): assert argument.dest == "test" argument = parseopt.Argument("-t", "--test", dest="abc") assert argument.dest == "abc" - assert ( - str(argument) - == ("Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')") + assert str(argument) == ( + "Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')" ) def test_argument_type(self): @@ -180,7 +178,6 @@ class TestParser(object): assert args.S is False def test_parse_defaultgetter(self): - def defaultget(option): if not hasattr(option, "type"): return @@ -204,15 +201,11 @@ class TestParser(object): ) parser.add_argument( "-t", "--twoword", "--duo", "--two-word", "--two", help="foo" - ).map_long_option = { - "two": "two-word" - } + ).map_long_option = {"two": "two-word"} # throws error on --deux only! parser.add_argument( "-d", "--deuxmots", "--deux-mots", action="store_true", help="foo" - ).map_long_option = { - "deux": "deux-mots" - } + ).map_long_option = {"deux": "deux-mots"} parser.add_argument("-s", action="store_true", help="single short") parser.add_argument("--abc", "-a", action="store_true", help="bar") parser.add_argument("--klm", "-k", "--kl-m", action="store_true", help="bar") @@ -224,9 +217,7 @@ class TestParser(object): ) parser.add_argument( "-x", "--exit-on-first", "--exitfirst", action="store_true", help="spam" - ).map_long_option = { - "exitfirst": "exit-on-first" - } + ).map_long_option = {"exitfirst": "exit-on-first"} parser.add_argument("files_and_dirs", nargs="*") args = parser.parse_args(["-k", "--duo", "hallo", "--exitfirst"]) assert args.twoword == "hallo" diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index ad7c4d0c1..1005dcba4 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -5,7 +5,6 @@ import pytest class TestPasteCapture(object): - @pytest.fixture def pastebinlist(self, monkeypatch, request): pastebinlist = [] @@ -85,7 +84,6 @@ class TestPasteCapture(object): class TestPaste(object): - @pytest.fixture def pastebin(self, request): return request.config.pluginmanager.getplugin("pastebin") @@ -102,7 +100,6 @@ class TestPaste(object): calls.append((url, data)) class DummyFile(object): - def read(self): # part of html of a normal response return b'View raw.' diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 615d52e83..08be812a2 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -25,7 +25,6 @@ def custom_pdb_calls(): # install dummy debugger class and track which methods were called on it class _CustomPdb(object): - def __init__(self, *args, **kwargs): called.append("init") @@ -45,7 +44,6 @@ def custom_debugger_hook(): # install dummy debugger class and track which methods were called on it class _CustomDebugger(object): - def __init__(self, *args, **kwargs): called.append("init") @@ -65,7 +63,6 @@ def custom_debugger_hook(): class TestPDB(object): - @pytest.fixture def pdblist(self, request): monkeypatch = request.getfixturevalue("monkeypatch") @@ -563,7 +560,6 @@ class TestPDB(object): class TestDebuggingBreakpoints(object): - def test_supports_breakpoint_module_global(self): """ Test that supports breakpoint global marks on Python 3.7+ and not on diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 22cea4207..c24314d22 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -16,7 +16,6 @@ def pytestpm(): class TestPytestPluginInteractions(object): - def test_addhooks_conftestplugin(self, testdir): testdir.makepyfile( newhooks=""" @@ -104,7 +103,6 @@ class TestPytestPluginInteractions(object): values = [] class A(object): - def pytest_configure(self, config): values.append(self) @@ -125,12 +123,10 @@ class TestPytestPluginInteractions(object): saveindent = [] class api1(object): - def pytest_plugin_registered(self): saveindent.append(pytestpm.trace.root.indent) class api2(object): - def pytest_plugin_registered(self): saveindent.append(pytestpm.trace.root.indent) raise ValueError() @@ -175,12 +171,10 @@ class TestPytestPluginInteractions(object): warnings = [] class get_warnings(object): - def pytest_logwarning(self, code, fslocation, message, nodeid): warnings.append(message) class Plugin(object): - def pytest_testhook(): pass @@ -232,7 +226,6 @@ def test_importplugin_error_message(testdir, pytestpm): class TestPytestPluginManager(object): - def test_register_imported_modules(self): pm = PytestPluginManager() mod = types.ModuleType("x.y.pytest_hello") @@ -363,7 +356,6 @@ class TestPytestPluginManager(object): class TestPytestPluginManagerBootstrapming(object): - def test_preparse_args(self, pytestpm): pytest.raises( ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"]) diff --git a/testing/test_pytester.py b/testing/test_pytester.py index b74c0b7f7..195f2c7f1 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -84,9 +84,7 @@ def test_testdir_runs_with_plugin(testdir): def make_holder(): - class apiclass(object): - def pytest_xyz(self, arg): "x" @@ -143,7 +141,6 @@ def test_makepyfile_utf8(testdir): class TestInlineRunModulesCleanup(object): - def test_inline_run_test_module_not_cleaned_up(self, testdir): test_mod = testdir.makepyfile("def test_foo(): assert True") result = testdir.inline_run(str(test_mod)) @@ -154,7 +151,6 @@ class TestInlineRunModulesCleanup(object): assert result2.ret == EXIT_TESTSFAILED def spy_factory(self): - class SysModulesSnapshotSpy(object): instances = [] @@ -220,7 +216,6 @@ class TestInlineRunModulesCleanup(object): def test_inline_run_clean_sys_paths(testdir): - def test_sys_path_change_cleanup(self, testdir): test_path1 = testdir.tmpdir.join("boink1").strpath test_path2 = testdir.tmpdir.join("boink2").strpath @@ -245,7 +240,6 @@ def test_inline_run_clean_sys_paths(testdir): assert sys.meta_path == original_meta_path def spy_factory(self): - class SysPathsSnapshotSpy(object): instances = [] @@ -371,7 +365,8 @@ class TestSysPathsSnapshot(object): original_other = list(getattr(sys, other_path_type)) snapshot = SysPathsSnapshot() transformation = { - "source": (0, 1, 2, 3, 4, 5), "target": (6, 2, 9, 7, 5, 8) + "source": (0, 1, 2, 3, 4, 5), + "target": (6, 2, 9, 7, 5, 8), } # noqa: E201 assert sys_path == [self.path(x) for x in transformation["source"]] sys_path[1] = self.path(6) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index a8e2fb803..f81d27889 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -21,7 +21,6 @@ def test_recwarn_functional(testdir): class TestWarningsRecorderChecker(object): - def test_recording(self): rec = WarningsRecorder() with rec: @@ -188,7 +187,6 @@ class TestDeprecatedCall(object): class TestWarns(object): - def test_strings(self): # different messages, b/c Python suppresses multiple identical warnings source1 = "warnings.warn('w1', RuntimeWarning)" diff --git a/testing/test_runner.py b/testing/test_runner.py index f5430a90d..a78d4de31 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -12,7 +12,6 @@ from _pytest import runner, main, outcomes class TestSetupState(object): - def test_setup(self, testdir): ss = runner.SetupState() item = testdir.getitem("def test_func(): pass") @@ -101,7 +100,6 @@ class TestSetupState(object): class BaseFunctionalTests(object): - def test_passfunction(self, testdir): reports = testdir.runitem( """ @@ -253,10 +251,10 @@ class BaseFunctionalTests(object): """ ) reps = rec.getcalls("pytest_runtest_logstart pytest_runtest_logfinish") - assert ( - [x._name for x in reps] - == ["pytest_runtest_logstart", "pytest_runtest_logfinish"] - ) + assert [x._name for x in reps] == [ + "pytest_runtest_logstart", + "pytest_runtest_logfinish", + ] for rep in reps: assert rep.nodeid == "test_logstart_logfinish_hooks.py::test_func" assert rep.location == ("test_logstart_logfinish_hooks.py", 1, "test_func") @@ -395,9 +393,7 @@ class BaseFunctionalTests(object): class TestExecutionNonForked(BaseFunctionalTests): - def getrunner(self): - def f(item): return runner.runtestprotocol(item, log=False) @@ -439,7 +435,6 @@ class TestExecutionForked(BaseFunctionalTests): class TestSessionReports(object): - def test_collect_result(self, testdir): col = testdir.getmodulecol( """ @@ -869,14 +864,11 @@ def test_current_test_env_var(testdir, monkeypatch): result = testdir.runpytest_inprocess() assert result.ret == 0 test_id = "test_current_test_env_var.py::test" - assert ( - pytest_current_test_vars - == [ - ("setup", test_id + " (setup)"), - ("call", test_id + " (call)"), - ("teardown", test_id + " (teardown)"), - ] - ) + assert pytest_current_test_vars == [ + ("setup", test_id + " (setup)"), + ("call", test_id + " (call)"), + ("teardown", test_id + " (teardown)"), + ] assert "PYTEST_CURRENT_TEST" not in os.environ diff --git a/testing/test_session.py b/testing/test_session.py index 4a594009b..50ce91534 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -6,7 +6,6 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED class SessionTests(object): - def test_basic_testitem_events(self, testdir): tfile = testdir.makepyfile( """ @@ -168,7 +167,6 @@ class SessionTests(object): class TestNewSession(SessionTests): - def test_order_of_execution(self, testdir): reprec = testdir.inline_runsource( """ diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 5d970e2fe..507ce126a 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -7,7 +7,6 @@ from _pytest.runner import runtestprotocol class TestEvaluator(object): - def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") evalskipif = MarkEvaluator(item, "skipif") @@ -126,7 +125,10 @@ class TestEvaluator(object): ) ev = MarkEvaluator(item, "skipif") exc = pytest.raises(pytest.fail.Exception, ev.istrue) - assert """Failed: you need to specify reason=STRING when using booleans as conditions.""" in exc.value.msg + assert ( + """Failed: you need to specify reason=STRING when using booleans as conditions.""" + in exc.value.msg + ) def test_skipif_class(self, testdir): item, = testdir.getitems( @@ -146,7 +148,6 @@ class TestEvaluator(object): class TestXFail(object): - @pytest.mark.parametrize("strict", [True, False]) def test_xfail_simple(self, testdir, strict): item = testdir.getitem( @@ -514,7 +515,6 @@ class TestXFail(object): class TestXFailwithSetupTeardown(object): - def test_failing_setup_issue9(self, testdir): testdir.makepyfile( """ @@ -547,7 +547,6 @@ class TestXFailwithSetupTeardown(object): class TestSkip(object): - def test_skip_class(self, testdir): testdir.makepyfile( """ @@ -645,7 +644,6 @@ class TestSkip(object): class TestSkipif(object): - def test_skipif_conditional(self, testdir): item = testdir.getitem( """ @@ -1023,7 +1021,6 @@ def test_imperativeskip_on_xfail_test(testdir): class TestBooleanCondition(object): - def test_skipif(self, testdir): testdir.makepyfile( """ diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 8f08ad34f..a9da27980 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -18,7 +18,6 @@ DistInfo = collections.namedtuple("DistInfo", ["project_name", "version"]) class Option(object): - def __init__(self, verbose=False, fulltrace=False): self.verbose = verbose self.fulltrace = fulltrace @@ -68,7 +67,6 @@ def test_plugin_nameversion(input, expected): class TestTerminal(object): - def test_pass_skip_fail(self, testdir, option): testdir.makepyfile( """ @@ -248,7 +246,6 @@ class TestTerminal(object): class TestCollectonly(object): - def test_collectonly_basic(self, testdir): testdir.makepyfile( """ @@ -356,7 +353,6 @@ def test_repr_python_version(monkeypatch): class TestFixtureReporting(object): - def test_setup_fixture_error(self, testdir): testdir.makepyfile( """ @@ -457,7 +453,6 @@ class TestFixtureReporting(object): class TestTerminalFunctional(object): - def test_deselected(self, testdir): testpath = testdir.makepyfile( """ @@ -735,9 +730,7 @@ def test_color_yes_collection_on_non_atty(testdir, verbose): def test_getreportopt(): - class Config(object): - class Option(object): reportchars = "" disable_warnings = True @@ -1102,7 +1095,6 @@ def test_no_trailing_whitespace_after_inifile_word(testdir): class TestProgress(object): - @pytest.fixture def many_tests_files(self, testdir): testdir.makepyfile( diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 336249094..db6e68674 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -42,7 +42,6 @@ def test_ensuretemp(recwarn): class TestTempdirHandler(object): - def test_mktemp(self, testdir): from _pytest.tmpdir import TempdirFactory @@ -59,7 +58,6 @@ class TestTempdirHandler(object): class TestConfigTmpdir(object): - def test_getbasetemp_custom_removes_old(self, testdir): mytemp = testdir.tmpdir.join("xyz") p = testdir.makepyfile( diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 65ffdb975..482e89280 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -389,7 +389,6 @@ def test_module_level_pytestmark(testdir): class TestTrialUnittest(object): - def setup_class(cls): cls.ut = pytest.importorskip("twisted.trial.unittest") # on windows trial uses a socket for a reactor and apparently doesn't close it properly diff --git a/testing/test_warnings.py b/testing/test_warnings.py index c5bea052a..15ec36600 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -160,9 +160,8 @@ def test_unicode(testdir, pyfile_with_warnings): reason="warnings message is broken as it is not str instance", ) def test_py2_unicode(testdir, pyfile_with_warnings): - if ( - getattr(sys, "pypy_version_info", ())[:2] == (5, 9) - and sys.platform.startswith("win") + if getattr(sys, "pypy_version_info", ())[:2] == (5, 9) and sys.platform.startswith( + "win" ): pytest.xfail("fails with unicode error on PyPy2 5.9 and Windows (#2905)") testdir.makepyfile( diff --git a/tox.ini b/tox.ini index 810d5597f..adc4e9746 100644 --- a/tox.ini +++ b/tox.ini @@ -207,3 +207,4 @@ filterwarnings = [flake8] max-line-length = 120 +ignore = E203,W503 From f940967e232c42fb4d091aba514f44e115bcc40f Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 24 Jun 2018 19:09:09 -0700 Subject: [PATCH 31/31] Fix test offset after black moved code --- testing/code/test_source.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 34a6dc5d1..7982cfa35 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -336,9 +336,9 @@ class TestSourceParsingAndCompiling(object): def check(comp, name): co = comp(self.source, name) if not name: - expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 3) + expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 2) else: - expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 3) + expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 2) fn = co.co_filename assert fn.endswith(expected)